- 締切済み
文字列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); }
- ki_c
- お礼率63% (28/44)
- C・C++・C#
- 回答数8
- ありがとう数5
- みんなの回答 (8)
- 専門家の回答
みんなの回答
- Oh-Orange
- ベストアンサー率63% (854/1345)
★追記。 ・一時コピーする領域は『buff』を用意しなくても引数『str』に上書きしてもいいですよ。 今回の場合は文字の削除ですから。→挿入して領域が増加する場合は『buff』などを用意する 必要があります。 ・以上。おわり。
- Oh-Orange
- ベストアンサー率63% (854/1345)
★たくさん回答がありますが、もう一つサンプルを付けます。 ・実現方法ですが、引数の『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』関数の完成 です。あまり、難しく考えすぎない方ないいでしょう。→コピーと文字変換を組合わせただけです。 ・以上。おわり。
- yaemon_2006
- ベストアンサー率22% (50/220)
ごめん、訂正。 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; }
- yaemon_2006
- ベストアンサー率22% (50/220)
文字列を扱う時点で、"ポインタを使わずに"というのは無理だけど、 #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; }
- tutemarihu
- ベストアンサー率0% (0/1)
まず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; }
コードの途中に、途中経過を確認するための printf関数を適宜入れてみましょう。 ところで、del_digit関数の仕様は 「文字列str内の全ての数字を削除する」だけではないですよね。 「結果をすべて大文字にする」も含んでいてよいのですね?
- yukimican
- ベストアンサー率70% (112/159)
質問に書かれている方法だと、 char ctr[] = {'0'}; はサイズ1の配列(ctr[1]と同じ)になってしまいますので その後のループで配列の範囲外にアクセスしてエラーになります。 なので、配列ctrのサイズは、入力された文字数よりも大きくしないといけません。 とりあえず、512や1024といった数字で試してみてください。 あと、最初のwhileループ内で文字チェックをするように変えれば 2番目のループの回数が減りますよ。 それをさらにステップアップさせたのが、No.1さんの方法ですね。 こちらは 文字列が (結果の文字数)≦(入力文字数) となることを利用していますが、 処理を1ステップずつ紙に書いていけば理解しやすいと思います。
- alphion
- ベストアンサー率19% (27/136)
そのような形にしたいなら、 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'; } みたいにしますけど…(参考まで)
お礼
回答ありがとうございました。 処理も少なくてスムーズに、きれいにできました。 ありがとうございます。
関連するQ&A
- 入力された文字列の中の数字を全てを削除するプログラム(C言語)
入力された文字列の中の数字を全てを削除するプログラム(C言語) 柴田望洋さんの「明解C言語入門編」という本の演習11-5に当たるこのプログラムの作り方がどうしてもわかりません。 なんとか書いてみましたが、実行してもうまくいきません。 どこが悪いのか自分でもわかりません。 誰か教えてくださいお願いします。 以下が僕が書いたコードです。 #include<stdio.h> void del_digit(char *str){ unsigned i=0; char *a; while(*(str+i)){ if(*(str+i)<0 || *(str+i)>9) *a++=*(str+i); i++; } printf("%s",a); } int main(){ char *str; scanf(" %s",str); del_digit(str); return 0; }
- 締切済み
- C・C++・C#
- 二次元配列による文字列の配列の受渡しについての質問です。
二次元配列による文字列の配列の受渡しについての質問です。 #include <stdio.h> void print_pname(char str[][5], int n) { int i, j; for (i = 0; i < n; i++) { printf("str[%d] = \"", i); for (j = 0; str[i][j] != '\0'; j++) putchar(str[i][j]); printf("\"\n"); } } int main(void) { char ary[][5] = {"Lisp", "C", "Ada"}; print_pname(ary, sizeof(ary) / sizeof(ary[0])); return 0; } 上のプログラム中の関数print_pnameの引数char str[][5]についてですが char (*str)[5](配列のポインタ)と変更した場合にwarningが多数発生します。 これはどうしてでしょうか? また、上のプログラムを配列のポインタを使って変更することは可能でしょうか? 以上、よろしくお願いします。
- ベストアンサー
- C・C++・C#
- 文字列の検索
プログラミングの勉強の際に下のプログラムを作りました。 最初にある文字列を入力して、その後別の文字列を入力して、 後に入力した文字列が最初に入力した文字列に含まれていれば1、 含まれていなければ0と表示するプログラムです。 コンパイルは通るのですが、文字列を2つ入力すると 「セグメンテーション違反です」と表記されます… どこが悪いのでしょうか? どなたか解説・指摘・模範解答などおねがいします。 (使用するのは#include<stdio.h>のみ、ポインタ変数必須です) #include<stdio.h> char *mystrfin(char *a, char *b); int main(void) { char str1[100],str2[100]; printf("1>>"); fgets(str1,100,stdin); printf("2>>"); fgets(str2,100,stdin); *mystrfin(c,d); } char *mystrfin(char *a,char *b){ char *c,*d; while(*c!='\0'){ c=a; d=b; while(*c!='\0' && *d!='\0') if(*c!=*d) printf("0"); break; c++; d++; } if(*d='\0') printf("1"); a++; return a; return NULL; }
- ベストアンサー
- C・C++・C#
- 文字列のコピー
C言語で、文字列をコピーする関数で、処理が止まってしまいます。 以下が実行したプログラムです。 #include<stdio.h> #include<string.h> void copy(char *str2 ,char *str3){ strcpy(str2,str3); } void input(char* str){ scanf("%s",str); } int main (void){ char *a; char *b="TEST"; printf("%s\n",b); input(a); copy(b,a); printf("%s",b); return(0);} copy(b,a);で処理が止まってしまいます。入力した文字列を表示できるように、御指摘お願いします。
- 締切済み
- 情報工学
- C言語 数字を削除する関数
#include <stdio.h> void del_digit(char str[]) { unsigned i = 0, count = 0; while (str[i]) { if(str[i] >= '0' && str[i] <= '9') { count++; } else { str[i - count] = str[i]; } i++; } str[i - count] = '\0'; } str内の全ての数字を削除する関数です。 AB1C9と入力するとABCと表示されます。 まずwhile (str[i])のとこのiは5までいくと思います。 5まで行った時にstr[5]は\0だからelseのほうに行ってstr[5- 2] = str[5];という風に処理されると思います。 その段階でstr[3]には¥0が入っていると思うのですが最後に str[5- 2] = '\0';でまたstr[3]に\0を入れる処理をしているのはなぜなんでしょうか? 最後のstr[i - count] = '\0';を消して実行してみると 「ABCC9」と表示されてしまいます。 教えてくださいm(_ _ )m
- ベストアンサー
- C・C++・C#
- 文字列を関数に渡すぷろぐらむなのですがおかしいです。
<ソース> #include<stdio.h> #include<stdlib.h> void str(char a[]); int main() { char st[10]="abcde"; str(st); str("ABCabc123"); return 0; } void str(char a[]) { int i; printf("%s\n",a); i=0; while(a[i]){ a[i]=toupper(a[i]); putchar(a[i]); i++; } putchar('\n'); } 分からないところがあるので質問します。 toupperは、大文字にするんですよね。 putcharは、基本的にchar型でしたっけ? putsとgetsは、int型でしたっけ? 後、プログラムが暴走してます。 どこがおかしいんでしょう?
- ベストアンサー
- C・C++・C#
- 文字列をうまく返してくれない
数値を文字列として呼び出し元に渡し、呼び出し元で文字列を数値に変えようとしたのですがatoi関数(strtolを使うと最初の文字のみ帰ってくるため2桁以上の数値に対応できない)を使うとうまく行きませんでした。 どのように変更したらatoiが使える文字列になりますか? #include <stdio.h> #include <stdlib.h> static struct{ char *name; }kuda[5]={ { "もも" , "りんご" , "みかん" , "バナナ" , "パイナップル" } } char *re_3( void ){ int a = 3; char str_h[100]; char *str; sprintf_s( str_h , 100 , "%d" , a ); *str = *str_h; //原因はおそらくここ return str; } void main( void ){ printf( "%s" , kuda[ atoi( re_3() ) ].name ); }
- ベストアンサー
- C・C++・C#
- 文字列
下のプログラムは何をするためのプログラムなのか教えてください。 個人的にはJISコードに関係していると思うのですがさっぱりわかりません。 どなたか詳しい説明お願いします。 #include <stdio.h> #define LEN 255 int main(void) { char str[LEN]; char cipher[LEN]; int ikey; int i,n; printf("文字列を入力せよ : "); scanf("%s", str); printf("鍵を入力 : "); scanf("%d", &ikey); i = 0; while (str[i]!='\0') { n = (str[i]-'A'+ikey)%26; cipher[i] = 'A'+n; ++i; } cipher[i] = '\0'; printf("%s\n", cipher); return 0; }
- ベストアンサー
- C・C++・C#
- 文字列の検索
先日同じ質問をして、プログラムの内容を修正したのですが、今度は2つ文字列を入力した後0が無限にでてきます… どなたか解説・指摘・模範解答などおねがいします。 内容は最初にある文字列を入力して、その後別の文字列を入力して、 後に入力した文字列が最初に入力した文字列に含まれていれば1、 含まれていなければ0と表示するプログラムです。 (使用するのは#include<stdio.h>のみ、ポインタ変数必須です) #include<stdio.h> char *mystrfin(char *a, char *b); int main(void) { char *c,*d; char str1[100],str2[100]; printf("1>>"); fgets(str1,100,stdin); printf("2>>"); fgets(str2,100,stdin); *mystrfin(c,d); } char *mystrfin(char *a,char *b){ char *c,*d; while(c!='\0'){ c=a; d=b; while(c!='\0' && d!='\0'){ if(c!=d) printf("0"); break; c++; d++; } } if(d='\0') printf("1"); a++; return a; return NULL; } 例 検索対象文字列:asdfghjkl 検索文字列:sdf 1と出力 検索対象文字列:asdfghjkl 検索文字列:qwer 0と出力
- ベストアンサー
- C・C++・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';