• ベストアンサー

文字列から空白を取り除きたいのですが

C言語を勉強しはじめて間もない者です。 文字列から空白を取り除く(空白は左に詰めることで埋める)処理をしたいのですが、下記のようなやり方でうまくできなくて困っています。 ↓を実行すると" 1234"なら"12344"になるはずだったのですが、うまくいきません。何がおかしいのでしょうか?? よろしければご教授願います。 ※文字列は半角のみ想定しています。 int i = 0; char str[] = " 1 23 4 5"; char *p; p = str;   while( *p != '\0' ){     if ( isspace(*p) != 0 ){       while( *(p + i + 1) != '\0' ){         *(p + i) = *(p + i + 1);         i++;       }     }     p++;   }  

質問者が選んだベストアンサー

  • ベストアンサー
  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.4

#3です。 先の回答と全く同じ動作をするコードです。 コメントを付けましたので、読んでみてください。 #include <stdio.h> #include <ctype.h> void TrimSpace(char *str) { char *p = str; // 当該文字列の先頭を指すポインターを用意する while (*str != '\0') { // 当該文字列の末尾に到達しない間、処理を続ける if (!isspace(*str)) { // 着目している文字が空白でなければ *p = *str; // その文字を答えに格納する p++; // 答えのポインターを1つ進める } str++; // 当該文字列用のポインターは、とにかく1つ進める } *p = '\0'; // 答えの文字列を終端させる } int main(void) { char str[] = " 1 23 4 5"; printf("空白を詰める前:\"%s\"\n", str); TrimSpace(str); printf("空白を詰めた後:\"%s\"\n", str); return 0; }

yucchi1114
質問者

お礼

ご丁寧にありがとございます! 凄くわかりやすいです。 これからも勉強に勤しもうと思います。 ありがとうございました!

その他の回答 (3)

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.3

> 詰める過程で"123455555"とまず表示させたかったのです。 これがなぜ必要なのかわかりませんが、省略してもよいのであれば、 こんなのでどうでしょう。 #include <stdio.h> #include <ctype.h> void TrimSpace(char *str) { char *p; for (p = str; *str; str++) { if (!isspace(*str)) { *p++ = *str; } } *p = '\0'; } int main(void) { char str[] = " 1 23 4 5"; printf("空白を詰める前:\"%s\"\n", str); TrimSpace(str); printf("空白を詰めた後:\"%s\"\n", str); return 0; }

yucchi1114
質問者

お礼

ご回答ありがとうございます。 >> 詰める過程で"123455555"とまず表示させたかったのです。 > >これがなぜ必要なのかわかりませんが、省略してもよいのであれば、 >こんなのでどうでしょう。 詰める工程を確認しようと思いまして…。 ふむふむ。。 も、もう少し簡単というか易しい書き方にできませんか?(._.) ってちょっとずうずうしいですよね。 自分で書いた物と比べてドコがダメだったのか探したかったのですが、ちょっと難しいです。。

回答No.2

身近にC言語の実行環境がないので試してないのですが、 プログラムを見る限り"i"の初期化の位置が悪いです。 プログラムの先頭では初期化せず int i; と宣言のみにしてif文の下にi=0を入れると良いと思います。 yucchi1114さんのプログラムだと、最初の空白が見つかったときは、後ろ文字を前に詰めますが、二つ目の空白が見つかり再びif文の中に入ってきたときは、iは初期化されていないので、前回の数からプラスされていきます。   while( *p != '\0' ){     if ( isspace(*p) != 0 ){       i=0;  /* ここでiを初期化 */       while( *(p + i + 1) != '\0' ){ 以上

yucchi1114
質問者

お礼

ご回答ありがとうございます。 うっかりミスです。 実際にはその位置でiを初期化していたんですが、投稿の際に打ち損ねてしまいました。 (ソースは投稿しているPCに無く、手元の印刷したソースを見ながら打っていたので。)

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.1

> " 1234"なら"12344"になるはずだった "1234" ではなくて、"12344" という結果を望んでいるのですか? だとすると、 > char str[] = " 1 23 4 5"; この場合はどういう結果を望んでいるのですか? ところで、コードを載せるときは、ここを見ている人たちが 「そのまま」コピー&ペーストしてコンパイルできるよう、 ヘッダーファイルのインクルードや関数定義など、 「全文を」載せてくださいませんか?

yucchi1114
質問者

補足

失礼いたしました。 詰める過程で"123455555"とまず表示させたかったのです。 最終的には"12345"を望みます。 この処理は後々関数化して、void TrimSpace(char str[])で渡すとスペースを除いた文字列になるようにしたい思っています。 以下が現状のソースになります。 よろしくお願いします。 #include <stdio.h> #include <stdlib.> #include <string.h> #include <ctype.h> int main(void) { int i = 0; char str[] = " 1 23 4 5"; char *p; p = str; while( *p != '\0' ){ if ( isspace(*p) != 0 ){ while( *(p + i + 1) != '\0' ){ *(p + i) = *(p + i + 1); i++; } } p++; } printf("%s\n",str); return 0; }

関連するQ&A

  • 文字列の扱い方

    初歩的な質問ですみません… str文字列からcという文字を見つけたら添字を返すという関数を作ったのですが、 iにこの関数を代入して、if文の制御式にiを使って比較するまでは正常なのですが、 真文にiを使うと何故か偽文(という言い方でいいのでしょうか…この場合("そんな値はありません。"というところです)が実行されてしまいます。 よろしければご教授お願い致します。 #include <stdio.h> int str_char(const char str[],int c) { int len = strlen(str); int i; for (i = 0;i < len;i++) { if (str[i] == c) return i; } return -1; } int main() { char str[64] = "Fucking Brutal Death Metal"; int ch,i; printf("どの文字を調べますか?"); scanf("%c",&ch); i = str_char(str,ch); if (i >= 0) printf("その文字は%d番目にあります。",str_char(str,ch) + 1); //何故かiだと動かない else printf("そんな値はありません。"); return 0; }

  • C言語のポインタと配列について

    下のコードについて2つ質問があります。 (1) char *p; p = str; ならわかるのですが、なぜ型が違う char *p = str; のような代入がOKなのでしょうか。文字列をコピーするときの   *p = *str; と比較して、とても違和感があります。  str は引数で受けた文字列の先頭アドレス。 (2)   char *str;   str = " 1 23 4 5"; と   char str[] = " 1 23 4 5"; との違いがよくわかりません。 #include <stdio.h> #include <ctype.h> void TrimSpace(char *str) {   char *p = str;        // (1)型が違うのになぜこんな代入をするのか?      while (*str != '\0') {     if ( !isspace(*str) ) {       *p = *str;      // この代入は自然       p++;     }     str++;   }   *p = '\0'; } int main(void) {      //char *str;   //str = " 1 23 4 5";     (2)これでは空白を詰めた後の文字列が表示されないのはなぜか?      char str[] = " 1 23 4 5"; //これで OK   printf("空白を詰める前:\"%s\"\n", str);   TrimSpace(str);   printf("空白を詰めた後:\"%s\"\n", str);   return 0; }

  • 文字列に関する関数

    現在C言語の勉強をしております。 そこで、以下の関数の作成について質問させてください。 【関数の仕様】 引数の文字列から、'-'(ハイフン)と'P'以降を排除した文字列を返す。 自分なりに作成してみたのですが、コンパイルで警告が出てしまう状況です・・・。 もっとスマートに書けるんだろうとは思っているんですが、精一杯でした・・・。 どなたか教えていただけませんでしょうか? char *getDelStr(char *str) { int len = strlen(str); int count; char targetStr[32]; for(count = 0; count < len; count++){ if(str[count] != 'P'){ if(str[count] != '-'){ strcat(targetStr,str[count]); } }else{ return targetStr; } } return str; } 以上、よろしくお願いいたします。

  • C言語 文字列操作

    トリム関数とリムーブ関数を作成してみました。改良点はありますでしょうか? ~~~~以下ソース~~~~ #include <stdio.h> #include <stdlib.h> #include <string.h> char *Trim(char *str); char *Remove(char *str, char *rmv); void main(void) {  char str[10], rmv[10], *p;  int c;  /* " abcd "をトリムする */  strcpy(str, " abcd ");  printf("トリム前 |%s|\n", str);  p = Trim(str);  printf("トリム後 |%s|\n", str);  /* 指定文字列を削除する */  printf("削除する文字列を入力してください :");  scanf("%s", rmv);  Remove(str, rmv);  printf("削除後 |%s|\n", str);  exit(0); } char *Trim(char *str) {  char space[] = " ";  char null[] = "";  int index = 0;  while(1){   if(strcmp(&(str[index]), null) == 0){    index--;    if(strncmp(&(str[index]), space, 1) == 0){     strcpy(&(str[index]), &(str[index]) + 1);    }else{     break;    }   }else{    if(strncmp(&(str[index]), space, 1) == 0 && index == 0){     strcpy(&(str[index]), &(str[index]) + 1);    }else{     index++;    }   }  }  return str; } char *Remove(char *str, char *rmv) {  int c, size, i;  char *p;  c = '\0';  p = strchr(rmv, c);  size = p - rmv;  for(i = 0; i < size; i++){   c = (int)rmv[i];   p = strchr(str, c);   if (p != NULL) {    strcpy(&(str[p-str]), p + 1);   }   else{    printf("""%c""は見つかりませんでした\n", c);   }  }  return str; }

  • abcが、入力された文字列内にあるかどうかを表示するプログラム

    文字列strの中にabcが含まれていれば、1を返し、含まれていなければ0を返すプログラムが分かりません。 C言語の問題で下記のものが分かりません。どなたか知恵を貸してください。 ユーザが文字を入力し、CTRL+Zが押されるまで、半角英数字の入力(最大でも1000文字)を受け付ける。文字列「abc」が、入力された文字列内にあるかどうかを表示するプログラムを作成する。ユーザが入力した文字列が3文字未満はabcがありませんと表示させる。 そのプログラム内で以下の関数を完成させる。 int str_srch_abc(char str []) 文字列strの中にabcが含まれていれば、1を返し、含まれていなければ0を返す関数とする。 (例えばabcは連続でabcの時だけ1を返し、asbscなどはoを返します。) ちなみに自分なりにやってみたのですが、ここまでしかできませんでした。 #include<stdio.h> int main() { int str_srch_abc(char str []); char str[1000]; int ch=0, j=0; printf("半角英数字を入力してください"); scanf("%s",str); while((ch=getchar())!=EOF){ str[j]=ch; j++; } str[j]='\0'; printf("%s",str); return(0); }

  • 文字列中に含まれる文字の個数をカウントするプログラムについて…

    文字列、1文字が与えられたとき、これをポインタで入力し文字列中に含まれる文字の個数を計算するプログラムを作成せよ。 と、いう課題がだされたんですけど、ユーザが任意の文字列と1文字を入力できるようにすることができません…。 多分main関数の部分をちょっといじくればよいと思うのですが…。 どなたかアドバイスをお願いします。 #include <stdio.h> int count(const char *str, const char ch) { int cnt=0; while (*str!='\0') { if (*str==ch) cnt++; str++; } return cnt; } int main() { const char *str="hello,world!"; const ch='o'; int cnt; cnt=count(str, ch); printf("%s中に%cは%d個です\n", str, ch, cnt); return 0; }

  • ポインタと文字列

    最近やっとポインタを理解できるようになってしきました。 でも、ちょっとわからない問題があるので質問させていただきます。 問)a~z,A~Z及び,.?空白などで構成される文字列を入力して、大文字と小文字を区別しないでa~zの出現頻度をポインタを使ってそれぞれ表しなさい。 ※文字列のほうはこちらで用意させていただきました。リダイレクトを使用してください。単語数は250です。 http://ayumuatsuco.fc2web.com/mit.htm 一応途中まで作ってある私のプログラムを参考にしてみてください。実行結果が変ですが。。。 #include <stdio.h> int main(void) { char buffer[250], hindo[26], *p; int i; while(1){ if(gets(buffer)==NULL) break; p=buffer; while(*p!='\0'){ hindo[*p-'a']++; for(i=0; i<10; i++){ if('a'<=*(p+i)) *(p+i)=*(p+i)-32 } for(i=0; i<26; i++){ printf("hindo[%d]=%d\n",i,*(p+i)); } } } return 0; }

  • 入力された文字列の中の数字を全てを削除するプログラム(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; }

  • プログラミング ポインタを使った文字列比較

    プログラミング ポインタを使った文字列比較 2つの文字列str1, str2を入力し,それらが等しければ0,等しくなければ1を返す関数str_compareを作り、返り値によって以下のように表示するプログラムを作れ。ただし,関数strcmpを使ってはならない。 文字列の入出力はmain関数で行い,関数str_compareの仮引数にはポインタ変数を宣言し,ポインタと間接演算子*を用いた処理を行うこと。 % ./a.out input str1 = Worldcup input str2 = Worldcup same strings % ./a.out input str1 = World input str2 = cup different strings この問題に私は次のようにプログラミングしました。 #include <stdio.h> #define MAX 100 int str_compare(char *, char *); main() { char str1[MAX], str2[MAX]; printf("input str1 = %s", str1); scanf("%s", str1); printf("input str2 = %s", str2); scanf("%s", str2); str_compare(str1, str2); if (str_compare(str1, str2) == 0) printf("same strings\n"); else if (str_compare(str1, str2) == 1) printf("different strings\n"); } int str_compare(char *s1, char *s2) { int i; for (i = 0; s1[i] != '\0'; i++) { if (s1[i] != s2[i]) { break; } } if (s1[i] == s2[i]) { return 0; } else { return 1; } } これで実行したところ、「input str1 =」の右のスペースが文字化け?してしまいます。(半角カタカナや記号が出る)ただ、その後に文字列を入力すると、正しく機能します。 これは何が悪いなのでしょうか、どなたか教えてください。

  • 文字列

    下のプログラムは何をするためのプログラムなのか教えてください。 個人的には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; }

専門家に質問してみよう