• 締切済み

文字列str内の全ての数字を削除する関数

文字列str内の全ての数字を削除する関数 void del_digit(char str[]) を作成。 (例えば、"ab1C9"を受け取ったら、"ABC"にする) という関数を作りたいのですが、うまくいきません。 過去に似たような『文字列内の数字削除』の質問をされた方が いましたが、ポインタを使っていました。 http://okwave.jp/qa1775576.html ポインタを使わずにするには、どうしたらよいのでしょうか? 途中まで作ってみたのですが、うまく動きません。 #include <stdio.h> #include <ctype.h> void del_digit(char str[]) {     unsigned i = 0, j = 0;     char ctr[] = {'0'};     while (str[i] != '\0') {           ctr[i] = str[i];           i++;     }     i = 0;     while (ctr[i] != '\0') {           if (ctr[i] < '0' || ctr[i] > '9') {              str[j] = toupper(ctr[i]);              j++;           }           i++;     }     str[j] = '\0'; } int main(void) {     char str[100];     printf("文字列を入力してください:");     scanf("%s", str);     del_digit(str);     printf("%s\n", str);     return (0); }

みんなの回答

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.8

★追記。 ・一時コピーする領域は『buff』を用意しなくても引数『str』に上書きしてもいいですよ。  今回の場合は文字の削除ですから。→挿入して領域が増加する場合は『buff』などを用意する  必要があります。 ・以上。おわり。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.7

★たくさん回答がありますが、もう一つサンプルを付けます。 ・実現方法ですが、引数の『str』から数字部分以外を別領域へコピーする仕組みがメインです。 ・そして、別領域にコピーするときに英字の『小文字』を『大文字』に変換する方法も一緒に  記述すれば良いと思います。 ・あと数字文字の判定は『isdigit』関数で行い、小文字ならば大文字に変換するには知っての  通り『toupper』関数を使います。 ・最後に別領域へコピーした内容を引数『str』にコピーしなおせば完成です。 サンプル: void del_digit( char str[] ) {  char buff[ 256 ]; ←一時コピーする別領域  int i; ←コピー先の配列の添え字カウンタ  int j; ←コピー元の配列の添え字カウンタ    for ( i = j = 0 ; str[j] != '\0' ; j++ ){   if ( !isdigit(str[j]) ){ ←数字以外を処理    buff[ i++ ] = (char)toupper( str[j] ); ←大文字変換してコピー   }  }  buff[ i ] = '\0'; ←最後にNULL文字をセット  strcpy( str, buff ); ←引数 str にコピー  /*  for ( i = j = 0 ; buff[j] != '\0' ; i++, j++ ){   str[ i ] = buff[ j ];  }  str[ i ] = '\0'; ←最後にNULL文字をセット  */ } 最後に: ・上記のサンプルは『del_digit』関数の部分のみです。main 関数は質問者さんのものでいいです。 ・また、引数 str の文字列に漢字文字が含まれると文字化けを起します。つまり、漢字非対応です。 ・あと『strcpy』の部分を自分でコピーする場合は、『/*』…『*/』の部分になります。 ・これで『数字』部分を取り除いて、『小文字』を『大文字』に変換する『del_digit』関数の完成  です。あまり、難しく考えすぎない方ないいでしょう。→コピーと文字変換を組合わせただけです。 ・以上。おわり。

回答No.6

   ごめん、訂正。 void del_digit(char *str) { int i, j; for(i = j = 0; str[i] != '\0'; i ++){ if(!isdigit(str[i])){ str[j] = toupper(str[i]); j ++; } } str[j] = '\0'; return; }  

回答No.5

   文字列を扱う時点で、"ポインタを使わずに"というのは無理だけど、 #include <stdio.h> #include <ctype.h> void del_digit(char *str) { int i, j; for(i = j = 0; str[i] != '\0'; i ++){ str[j] = toupper(str[i]); j += !isdigit(str[i]); } str[j] = '\0'; return; } int main(void) { char str[] = "a1b2c3d4e5"; puts(str); del_digit(str); puts(str); return 0; }  

回答No.4

まずC言語には、『文字列そのもの』という概念はなく、変わりに『1文字を表現するchar型の配列で文字列を表現する』という考え方があります。なので、文字列操作をしようと思うと、文字列を成す各char型の配列を操作しなければなりません。配列の先頭はポインタ変数です。char型の文字列の場合だと、先頭のデータを表現するchar*型の変数だけということになります。通常は、このchar*変数にインクリメントしたりデクリメントしたりして、配列内の要素にchar*変数を移動させて各要素を操作しますが、それがトリッキー見にえて嫌なら、文字列の先頭を指すchar*変数に添え字を付けても配列の各要素を操作することが出来ます。いかがその関数です。適当に書きましたので参考までに。 void hoge(char*str){ int a,s; //a番目の文字が終端文字'\0'でないならば、 //aを++して繰り返し for(a=0;str[a];++a){ //a番目の文字が数値ならば if(str[a]>='0'&&str[a]<='9'){ //数値の削除 for(s=a;str[s];++s) str[s]=str[s+1]; --a; } } return; }

noname#26650
noname#26650
回答No.3

コードの途中に、途中経過を確認するための printf関数を適宜入れてみましょう。 ところで、del_digit関数の仕様は 「文字列str内の全ての数字を削除する」だけではないですよね。 「結果をすべて大文字にする」も含んでいてよいのですね?

  • yukimican
  • ベストアンサー率70% (112/159)
回答No.2

質問に書かれている方法だと、  char ctr[] = {'0'}; はサイズ1の配列(ctr[1]と同じ)になってしまいますので その後のループで配列の範囲外にアクセスしてエラーになります。 なので、配列ctrのサイズは、入力された文字数よりも大きくしないといけません。 とりあえず、512や1024といった数字で試してみてください。 あと、最初のwhileループ内で文字チェックをするように変えれば 2番目のループの回数が減りますよ。 それをさらにステップアップさせたのが、No.1さんの方法ですね。 こちらは 文字列が (結果の文字数)≦(入力文字数) となることを利用していますが、 処理を1ステップずつ紙に書いていけば理解しやすいと思います。

ki_c
質問者

お礼

回答ありがとうございました。 配列の範囲を広げたら、おしいところまでいきました! ただそれだけだと、sacanfでstr[0]に数字を入力すると 文字バケの表示が文字列の最後についてしまったため? ctr[i] = '\0'; を追加したらうまくいきました。 まだ、おかしいところあるかもしれませんが、大変参考に なりました。ありがとうございます。 void del_digit(char str[]) {     unsigned i = 0, j = 0;     char ctr[1000];     while (str[i] != '\0') {           ctr[i] = str[i];           i++;     }     ctr[i] = '\0';     i = 0;     while (ctr[i] != '\0') {          if (ctr[i] < '0' || ctr[i] > '9') {              str[j] = toupper(ctr[i]);              j++;           }           i++;     }     str[j] = '\0';

  • alphion
  • ベストアンサー率19% (27/136)
回答No.1

そのような形にしたいなら、 void del_digit(char str[]) { unsigned i = 0, j = 0; while (str[i] != '\0') { if (str[i] < '0' || str[i] > '9') { str[j] = str[i]; j++; } i++; } str[j] = '\0'; } みたいにしますけど…(参考まで)

ki_c
質問者

お礼

回答ありがとうございました。 処理も少なくてスムーズに、きれいにできました。 ありがとうございます。