• ベストアンサー

strstr()を使ったプログラムについて

上のプログラムでは正しい結果がでて、下のプログラムでは正しい結果がでない理由を教えてください。 <上のプログラム> #include<stdio.h> #include<string.h> main() { char *str = "Apple,Lemmon,Apple,Orange,Grape,Apple,Lemmon"; int i = 0;     while((str = strstr(str,"Apple")) != NULL){ str++; i++; }     printf("文字列の中にAppleは%d個含まれます。",i); return 0; } <下のプログラム> #include<stdio.h> #include<string.h> main() { char *str = "Apple,Lemmon,Apple,Orange,Grape,Apple,Lemmon"; int i = 0;     while(strstr(str,"Apple") != NULL){      str++; i++; } printf("文字列の中にAppleは%d個含まれます。",i); return 0; } 実行環境はBorland C++、上のプログラムでは正しく3と表示されますが、 下のプログラムでは33と表示されてしまいます。

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

  • ベストアンサー
  • chie65535
  • ベストアンサー率43% (8481/19299)
回答No.2

上のプログラム 1回目のstrstr "Apple,Lemmon,Apple,Orange,Grape,Apple,Lemmon"から"Apple"を探す。 見付かるので "Apple,Lemmon,Apple,Orange,Grape,Apple,Lemmon" の中にある最初の"Apple"の位置が返され、それがstrになる。 strは "Apple,Lemmon,Apple,Orange,Grape,Apple,Lemmon" を指す。 strとiがインクリメントされる。 結果、strは "pple,Lemmon,Apple,Orange,Grape,Apple,Lemmon" を指す。 2回目のstrstr "pple,Lemmon,Apple,Orange,Grape,Apple,Lemmon"から"Apple"を探す。 見付かるので "pple,Lemmon,Apple,Orange,Grape,Apple,Lemmon" の中にある最初の"Apple"の位置が返され、それがstrになる。 strは "Apple,Orange,Grape,Apple,Lemmon" を指す。 strとiがインクリメントされる。 結果、strは "pple,Orange,Grape,Apple,Lemmon" を指す。 3回目のstrstr "pple,Orange,Grape,Apple,Lemmon"から"Apple"を探す。 見付かるので "pple,Orange,Grape,Apple,Lemmon" の中にある最初の"Apple"の位置が返され、それがstrになる。 strは "Apple,Lemmon" を指す。 strとiがインクリメントされる。 結果、strは "pple,Lemmon" を指す。 4回目のstrstr "pple,Lemmon"から"Apple"を探す。 見付からないのでNULLが返る。 NULLが返るとwhile文をやめる。 iは3回インクリメントされているので 「文字列の中にAppleは3個含まれます。」 と表示される。 下のプログラム 1回目のstrstr "Apple,Lemmon,Apple,Orange,Grape,Apple,Lemmon"から"Apple"を探す。 見付かるので "Apple,Lemmon,Apple,Orange,Grape,Apple,Lemmon" の中にある最初の"Apple"の位置が返される。 strとiがインクリメントされる。 結果、strは "pple,Lemmon,Apple,Orange,Grape,Apple,Lemmon" を指す。 2回目のstrstr "pple,Lemmon,Apple,Orange,Grape,Apple,Lemmon"から"Apple"を探す。 見付かるので "pple,Lemmon,Apple,Orange,Grape,Apple,Lemmon" の中にある最初の"Apple"の位置が返される。 strとiがインクリメントされる。 結果、strは "ple,Lemmon,Apple,Orange,Grape,Apple,Lemmon" を指す。 3回目のstrstr "ple,Lemmon,Apple,Orange,Grape,Apple,Lemmon"から"Apple"を探す。 2回目で見付かった"Apple"がまた見付かるので "ple,Lemmon,Apple,Orange,Grape,Apple,Lemmon" の中にある最初の"Apple"の位置が返される。 strとiがインクリメントされる。 結果、strは "le,Lemmon,Apple,Orange,Grape,Apple,Lemmon" を指す。 4回目のstrstr "le,Lemmon,Apple,Orange,Grape,Apple,Lemmon"から"Apple"を探す。 2、3回目で見付かった"Apple"がまた見付かるので "le,Lemmon,Apple,Orange,Grape,Apple,Lemmon" の中にある最初の"Apple"の位置が返される。 strとiがインクリメントされる。 結果、strは "e,Lemmon,Apple,Orange,Grape,Apple,Lemmon" を指す。 5回目のstrstr "e,Lemmon,Apple,Orange,Grape,Apple,Lemmon"から"Apple"を探す(以下同文) 6回目のstrstr ",Lemmon,Apple,Orange,Grape,Apple,Lemmon"から"Apple"を探す(以下同文) 7回目のstrstr "Lemmon,Apple,Orange,Grape,Apple,Lemmon"から"Apple"を探す(以下同文) 8回目のstrstr "emmon,Apple,Orange,Grape,Apple,Lemmon"から"Apple"を探す(以下同文) 9回目のstrstr "mmon,Apple,Orange,Grape,Apple,Lemmon"から"Apple"を探す(以下同文) (中略) 32回目のstrstr ",Apple,Lemmon"から"Apple"を探す(以下同文) 33回目のstrstr "Apple,Lemmon"から"Apple"を探す(以下同文) 34回目のstrstr "pple,Lemmon"から"Apple"を探し、見付からないのでwhile文をやめる。 iは33回インクリメントされているので 「文字列の中にAppleは33個含まれます。」 と表示される。

eques130
質問者

お礼

とてもよく分かる回答ありがとうございました。

その他の回答 (2)

  • php504
  • ベストアンサー率42% (926/2160)
回答No.3

思った動作にならないときは printf("%d回目のstr=%s\n", i, str); とか書いて確認してみましょう。

eques130
質問者

お礼

そうすることでプログラムの動きが分かるんですね。 ありがとうございました。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

「正しい結果が出ない」のは「正しい結果が出ないプログラムを書いたから」ですね. どっちもプログラムに書いてある通りの動作をしてます. strstr がどのような動作をするかがわかれば明らかだと思う.

関連するQ&A

  • 結果が不安定なプログラム

    配列に入れられた文字列を、別の配列に逆にして入れ、表示するというプログラムを作っています。 #include<stdio.h> #include<string.h> #include<stdlib.h> void main() {   char str1[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", str2[] = "";   int i = 0, len = strlen(str1);   char *p1 = str1 + len - 1, *p2 = str2;   while(*(p1 - i) != str1[0] - 1) *(p2 + i) = *(p1 - i++);   printf("str1 = %s\n",p1 = str1);   printf("str2 = %s\n",p2); } 実行結果: str1 = ABCDEFGHIJKLMNOPQRSTUVWXYZ str2 = ZYXWVUTSRQPONMLKJIHGFEDCBA と出るのですが、この文字列を例えば"TANGOHYOJI"とかに変えてみると、実行は出来るんですがprintfの部分が表示されません。 また表示できても、文字が違う文字になって表示されたりします。 あと、この場合に使われている<stdlib.h>はどういった役割を果たしているのでしょうか?これがないとこのプログラムは動かなかったのですが・・。 どうかよろしくお願いします。

  • strstrを利用しない文字列検索について

    キーボードから入力した文字列 str に対し, This is~の文字列中に str が出現するかどうかを判定して表示するプログラムを作成したいのですが、うまくコンパイルができません。 条件ですが、、、 ・forループを利用し、0文字目、1文字目と順に検索していく ・strstr関数およびstring.hを利用しない です。このプログラムをいじって教えてほしいです。 ややこしくて答えづらい質問かと思いますが、有識者の知恵を拝借したいです。よろしくお願いします。 #include <stdio.h> int main(void) { char str[256]; char s[] = "This is a pen. That is an apple."; int i,j,k,checker; printf("This is a pen. That is an apple.\n\n"); gets(str); for(j=0;j<256;j++) { for(i=j,k=0;str[k]!='\0';k++,i++) { if(str[k]==s[i]) { checker=1; } else { checker=0; } } } if(checker==0) { printf("NG!その文字列は含まれていません。\n"); } else { printf("OK!その文字列は含まれています。\n"); } }

  • C言語に詳しい方お願い致しいます

    文字列Aから文字列Bを除いた結果を表示するプログラムなのですが 一ヶ所分からない部分があります。 #include <stdio.h> #include <string.h> int main(void){  char str1[] = "abcdefg";  char str2[] = "cde";  char str3[128] = "";  char *p1 = str1, *p2;  size_t len;  len = strlen(str2);  while((p2 = strstr(p1,str2)) != NULL) {   strncat(str3,p1,p2 - p1);   p1 = p2 + len;   printf("----\n");   printf("p2=%s\n", p2);   printf("str3=%s\n", str3);   printf("p1=%s\n", p1);  }  strcat(str3,p1);  printf("%s\n",str3);  return 0; } while文中の p1 = p2 + len; なのですが、何故これでp1の内容が「fg」になるのでしょう。

  • ポインタ勉強中です。しかも実行するとおかしいです。

    <本に載ってたソース> #include<stdio.h> #include<string.h> int main() { char msg[20]; char *str=NULL; int i; int cnt; str=&msg[0]; printf("文字を入力してください"); scanf("%s",&str); cnt=strlen(msg); str=msg+cnt; for(i=cnt;i>=0;i--){ printf("%c",*(str--)); } printf("\n"); return 0; } char *str=NULL;は、ポインタstrを空にするということでしょうか? いつもながらstrlenとsizeofが混じります。 sizeofがバイトの大きさで、strlenが、文字数でしたっけ?

  • どこがちがうのでしょうか?

    以下の二つのプログラムはユーザーが文字を入力し、80文字以下なら ピリオドを追加して表示するというものです。上はうまくいきますが、下はうまくいきません。なぜでしょうか? #include<string.h> #include<stdlib.h> int main() { char str[80]; int i; printf("文字列を入力してください。\n"); gets(str); if(strlen(str)<80) { for(i=strlen(str);i<79;i++) strcat(str,"."); } printf("%s",str); } #include<stdio.h> #include<string.h> #include<stdlib.h> int main() { char str[80]; int i; printf("文字列を入力してください。\n"); gets(str); if(strlen(str)<80) { for(i=strlen(str)+1;i<79;i++) str[i] = "."; } printf("%s",str); }

  • 数式を読みこんで答えをかえすプログラム

    C言語で、「キーボードから入力された数式(加法、減法限定)の答えをかえすプログラム」をつくりたいのですが。。。 ※4+35+287-43など #include<stdio.h> #include<string.h> #define NUM 40 int main(void){ char str[NUM]; int i, result, x; printf("Please input an expression:\n"); scanf("%s", str); x = strlen(str); result = 0; for(i=0; i<=x; i++){ if((str[i] == '+') || (str[i] == '-')){ // printf(","); } printf("%c", str[i]); } } printfで+と-を「,」で区切って、それをヒントにそれぞれ配列の中に入れるのかな、というところまでは出来たのですが。。。 解り易い解説をつけて下さるとありがたいです。よろしくお願いします。

  • abcdとキーボードで打ったらdcbaと表示されるプログラム

    C言語に関しては初心者です。 メイン関数は変更せずに行います。 /* reverse.c: reverse a given string */ #include <stdio.h> #include <string.h> void reverse(char *); /* プロトタイプ宣言 */ int main(void) { char str[100]; scanf("%s", str); reverse(str); printf("%s\n", str); return (0); } void reverse(char *s) { char n; int i; char str; n = strlen(str) - 1; for(i=0,i++,i<=100) { s[i] = *s[n-i]; printf("%s\"s[i]); } }

  • ファイルの入出力プログラムについて

    san.txtに(I can do it )と書いて以下のプログラムを実行したらメ噫|リ メ噫|リ メ噫|リ メ噫|リ メ噫|リ メ噫| とバグってしまいました。なぜですか? #include <stdio.h> #include <stdlib.h> main () { FILE *outfp; char str[256];    if (( outfp = fopen("san.txt", "w"))       ==NULL) { printf("ファイルオープンエラー\n"); exit(1); } while(fputs(str, outfp)){ printf("%s", str); } fclose(outfp); return 0; }

  • 配列のコピー

    配列bufの内容をstrにコピーしてgetsを使い 表示させたいのですが、うまくいかず 余計な文字まで出力されます、どのようにすれば うまくいくでしょうか? どなたかアドバイスよろしくお願いしますm(_ _)m #include <stdio.h> void main(){ char buf[256]="message"; char str[256]; int i = 0; while(buf[i] != NULL){ str[i] = buf[i]; i++; } printf(str); }

  • C言語でファイルの内容を strtok関数 を使って数字と文字を分けて

    C言語でファイルの内容を strtok関数 を使って数字と文字を分けて配列に格納したいのですが、うまくできません。 どこが駄目なのかご指摘をお願いします! ファイル内容 20 田中 10 鈴木 #include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc,char *argv[]) { FILE *fp; char str[256]; char *tp; int i=0; int num[10]; char na[10]; fp=fopen(argv[1],"r"); while(fgets(str,sizeof str,fp)!=NULL); tp = strtok ( str, " " ); while(tp != NULL ) { num[i]=atoi(tp); tp = strtok( NULL," "); if ( tp != NULL ){ na[i]=*tp; } i++; } printf("%d\n%s",num[0],na[0]); printf("%d\n%s",num[1],na[1]); fclose(fp); return 0; }