{a,b,c,x,d,x,x,e,x,f,\0}
という文字型配列があったとして、xを取り除いて{a,b,c,d,e,f,\0}という配列にしたいのです。
その場合、例えば'd'の前にはxが1つ、'e' の前にはxが3つ、'f'の前にはxが4つありますよね?
その数だけそれぞれの位置を左へずらせばxを取り除ける処理ができると思うのですが、その場合どのようにすれば実現できるでしょうか。
forでループをするというのは何となく分かるのですが、何分初心者なもので、見当がつきません。
文字型配列の指定文字の削除について
Re: 文字型配列の指定文字の削除について
ずらす方法では無いですが、参考にどうぞ。
新たに配列を作って’x’以外の文字をコピーしてます。
<出力>
abcdef
新たに配列を作って’x’以外の文字をコピーしてます。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i;
int cnt; // 文字数
int p;
char *str = "abcxdxxexf";
char *ans;
/* 'x' 以外の文字数を数える*/
cnt = 0;
for(i = 0; str[i] != NULL; i++){
if(str[i] != 'x') cnt++;
}
/* 文字数分のメモリ確保 */
ans = (char*)calloc(cnt, sizeof(char));
if(ans == NULL){// メモリ確保できなかったら。
printf("メモリ確保失敗\n");
return 1;
}
/* 文字列のコピー */
p = 0;
for(i = 0; i < cnt; i++){
while(str[p] == 'x') p++; // 'x'の部分を飛ばす。
ans[i] = str[p];
p++;
}
printf("%s\n", ans);
return 0;
}
abcdef
Re: 文字型配列の指定文字の削除について
アルゴリズムを正直にコードにすると以下のようになります(Cでのコードです)
説明します。
まずchar str[] = 云々は大丈夫ですね。単純に文字列をchar型配列に押し込んだだけです。
具体的なアルゴリズムですが、strのn文字目(これは0から始まるとします)におけるそれまでに出たxの個数をcounter[n]に格納します
この時どうせ消えてなくなるstr[n] == 'x'の文字に対応するcounter[n]には値を何も代入しません
これは後々楽にもなります。つまりずらすべき文字にはカウンタがありxにはないのです。自動的にxの部分を上書きできます
最初のwhileループでこれを行いもう一方のwhileループでおっしゃられたように一気に文字をずらして
表示します
現在n文字目のカウンターがkならばその文字はn-k文字目にずらされるはずです
kは先に求めてあります。k == counter[n]です。
最後に終端処理が正しくされることを確かめましょう
前処理ではヌル文字にもカウンターが付けられます。
つまり後のループではヌル文字もほかの文字同様にずらされます。
よってこのコードは正しく動きます。
こんなのでどうでしょう?^^;
#include <stdio.h>
#include <string.h>
char str[] = "abcxdxxexfgxxx";
int main(){
int counter[100];
int numX = 0;
int i = 0, j = 0;
memset(counter,0,sizeof(counter));
do{
if(str[i] == 'x'){
++numX;
continue;
}
counter[i] = numX;
}while(str[i++] != '\0');
do{
if(counter[j])str[j-counter[j]] = str[j];
}while(str[j++] != '\0');
printf(str);
return 0;
}
説明します。
まずchar str[] = 云々は大丈夫ですね。単純に文字列をchar型配列に押し込んだだけです。
具体的なアルゴリズムですが、strのn文字目(これは0から始まるとします)におけるそれまでに出たxの個数をcounter[n]に格納します
この時どうせ消えてなくなるstr[n] == 'x'の文字に対応するcounter[n]には値を何も代入しません
これは後々楽にもなります。つまりずらすべき文字にはカウンタがありxにはないのです。自動的にxの部分を上書きできます
最初のwhileループでこれを行いもう一方のwhileループでおっしゃられたように一気に文字をずらして
表示します
現在n文字目のカウンターがkならばその文字はn-k文字目にずらされるはずです
kは先に求めてあります。k == counter[n]です。
最後に終端処理が正しくされることを確かめましょう
前処理ではヌル文字にもカウンターが付けられます。
つまり後のループではヌル文字もほかの文字同様にずらされます。
よってこのコードは正しく動きます。
こんなのでどうでしょう?^^;
Re: 文字型配列の指定文字の削除について
Cでの正規表現はめんどくさかったりしますからね。
すごく適当にですが書いてみました。
指定した文字を消す関数を作って実装してみた形です。
基本的には適当なサイズなバッファでいいと思いますが、どうしても
きっちりと文字列数分のサイズしかとりたくない場合はdefineを1にした時のポインタバージョンを。
適当に書いただけなので、あまり参考にはならないかも・・
すごく適当にですが書いてみました。
#define GETPOINTERMODE ( 0 )
#if GETPOINTERMODE == 0
static void DeleteTargetStr( char* pDst, char* pSrc, char TargetStrCode )
{
int Cnt = 0;
for( int i = 0; i < strlen( pSrc ); i++ )
{
if( pSrc[ i ] != TargetStrCode )
pDst[ Cnt++ ] = pSrc[ i ];
}
}
#else
static void DeleteTargetStr( char** ppDst, char* pSrc, char TargetStrCode )
{
int Cnt = 0;
char Temp[ 0x100 ] = { 0, };
for( int i = 0; i < strlen( pSrc ); i++ )
{
if( pSrc[ i ] != TargetStrCode )
Temp[ Cnt++ ] = pSrc[ i ];
}
int Length = strlen( Temp );
char* pTemp = new char[ Length + 1 ];
strcpy( pTemp, Temp );
pTemp[ Length ] = 0; // NULL文字忘れずに
*ppDst = pTemp; // 最後にアドレスメモ
}
#endif
void main()
{
char* str = "abcxdxxefxf";
#if GETPOINTERMODE == 0
char Dst[ 0x100 ] = { 0, };
DeleteTargetStr( Dst, str, 'x' );
printf( "%s\n", Dst );
#else
char* pDst;
DeleteTargetStr( &pDst, str, 'x' );
printf( "%s\n", pDst );
#endif
// ポインタ取得の場合は解放をお忘れなく
#if GETPOINTERMODE == 1
delete[] pDst;
#endif
}
指定した文字を消す関数を作って実装してみた形です。
基本的には適当なサイズなバッファでいいと思いますが、どうしても
きっちりと文字列数分のサイズしかとりたくない場合はdefineを1にした時のポインタバージョンを。
適当に書いただけなので、あまり参考にはならないかも・・
Re: 文字型配列の指定文字の削除について
ちなみにですが、よりコンパクトにまとめることができます
実はcounterはなくなっても問題ありません、numXはその位置での個数を格納しているからです
よって二つのwhileは一つに集約されます
memsetもつかわないためもはやstring.hも必要ありません
コードはこうなります。(直観性は幾分失われる気がしますが)
実はcounterはなくなっても問題ありません、numXはその位置での個数を格納しているからです
よって二つのwhileは一つに集約されます
memsetもつかわないためもはやstring.hも必要ありません
コードはこうなります。(直観性は幾分失われる気がしますが)
Re: 文字型配列の指定文字の削除について
みなさん本当にありがとうございます^^
ちなみに新しく代入する配列を用意しないで同じ処理をすることはできませんか?
関数なら sakujo(char * str, char sakujo_moji)で受け取った文字型配列自体に削除文字を消した文字列を代入したいです。
ちなみに新しく代入する配列を用意しないで同じ処理をすることはできませんか?
関数なら sakujo(char * str, char sakujo_moji)で受け取った文字型配列自体に削除文字を消した文字列を代入したいです。