• ベストアンサー

文字列の検索

先日同じ質問をして、プログラムの内容を修正したのですが、今度は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と出力

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

  • ベストアンサー
  • yama5140
  • ベストアンサー率54% (136/250)
回答No.6

結論: No.4 さんのとおりです。 (以降、年寄りならではの・・) ☆コンパイラは、重大な疑念で「警告」を発します。  なかには、  ・int main() に return 文が無いという警告もあります。   これは、「排便後に紙がない」と同じで、生死に関係ありません。   (年寄りは、void main() で「紙」不要)     しかし、他の警告は、無視してはいけません。 ☆無視は、「一方通行路の逆走」と思ったほうがよろしいかと。  今回のように、対向車が見えないから、なんて考えてはいけません。 (質問主旨の整理) ×「0が無限にでてきます」 ←(警告を撲滅後だったら○) ○「警告がたくさんでてきます」 ++++++++++++++++++++++++++++++++++++++ ・模範解答ではない。「勉強」の参考に・・・ ・文字列の入力に見かけない fgets() を用いている ☆これらから、ひとつの「警告」も出ないソースを投稿します。  参考にはならないか・・平易に書いたつもりなんだけど(残念)。    (BorlandC++5.6.4)  小難しくなりますが、文字列終端 ( '\0' )の前に、'\n' があります。 #include <stdio.h> #define OWARI ('\n') // ('\0') と変えて試行? int myStrFin( char *a, char *b ) {  char *c, *d;  c = a; // 検索対象文字列  d = b; // 検索文字列  while( OWARI != *c ){   if( *c != *d ){ // 不一致    c++;    d = b; // 検索文字列リセット    continue;   }   c++; // 次の文字は?   d++;   if( OWARI == *d ){ // 検索文字列終わり    printf( "1\n" );    return( 1 );   }   if( *c != *d ){    d = b; // 検索文字列リセット    c++;    if( OWARI != *c ) continue;    break; // 検索対象文字列終わり   }  }  printf( "0\n" );  return( 0 ); } int main( void ) {  char str1[100], str2[100];  printf( "検索対象文字列:" );  fgets( str1, 100, stdin );  printf( "検索文字列:" );  fgets( str2, 100, stdin );  myStrFin( str1, str2 );  return( 0 ); // トイレットペーパー? } 注:インデントに全角空白を用いています。タブに一括変換して下さい。

その他の回答 (5)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.5

お示しのコードをインデントしてみると下記のようになります #include<stdio.h> // char型のポインタを返す関数 mystrfinの定義 // 引数は char型のポインタ変数を2個必要とする char *mystrfin(char *a, char *b); int main(void) {   // char型のポインタ変数を宣言   char *c,*d;   // char型の配列を宣言   char str1[100],str2[100];   //プロンプトを表示して入力を待つ   printf("1>>");   fgets(str1,100,stdin);   printf("2>>");   fgets(str2,100,stdin);   // メインの処理を行う   // 未初期化の変数を使うのはなぜか?   // 関数の先頭の『*』は必要なのか?   // 先に入力された str1,str2を使うのでないのか ・・・   *mystrfin(c,d); } char *mystrfin(char *a,char *b){   // char型のポインタ変数を宣言   char *c,*d;   // char型ポインタ と 文字定数'\0'の比較は正当な結果をもたらすのか   // ポインタcが 0x123456のアドレスを保持していた場合   // c!='\0' は 0x123456 != 0x00 と等価である これに意味があるのか   // 0x123456はアドレスであり文字ではない   // また 宣言されただけのポインタ変数はどこのアドレスを指しているかは   // 不明である   // そのような不明なものを比較に使えるのか   while(c!='\0'){     // この初期化はここでよいのか     c=a;     d=b;     // ここも ポインタと文字定数の比較をしているがこれに意味があるのか     while(c!='\0' && d!='\0'){       // if文の有効範囲は 次のブロックまでである       // ifの影響範囲がprintfまでしか及ばない これは意図したことなのか       // c!=d はポインタの比較なので保持しているアドレスが式の値になる       // c= 0x123456、 d=0x456789なら 0x123456 != 0x456789と等価である       // ポインタが指す先の文字の比較を意図したのであれば       // この式では期待する結果が得られない       if(c!=d)         printf("0");       // このbreakは無条件に実行されるこれは意図したことか       break;       // この2つは実行される機会が無い       c++;       d++;     }   }   // d = '\0' はポインタdが示すアドレスへの代入になる   // これは意図した動作か   if(d='\0')    printf("1");   // ここはもはやif文の影響範囲ではない   // a++としているがこれは何を意図するものか   a++;   // ここが無条件に実行されるので return NULLは決して実行されない   return a;   return NULL; }

  • S117
  • ベストアンサー率40% (18/45)
回答No.4

QNo.4433291からの続きですね? 上記回答1について修正した後が見られません。どのような修正としましたか? また、2の修正についてもたしかにエラーは出ないでしょうけど、何の解決にもなっていません。 また、なぜか以前のソースよりも誤りが増えています。コンパイラのエラーが出ないからといって、問題がなくなったわけではありません。 全体としてご自身で何がしたいのか分かっていないように思えます。この回答から見るに、模範解答の提示では本質的な問題解決は難しいでしょう。 ここまでに学習した内容が間違いなく身につくよう復習されたほうが、おそらく理解するのは早いでしょう。 今後の学習の役に立つよう、復習したほうがよさそうなものを列挙しておきます。 ・条件分岐 ・ループ ・比較演算 ・変数について全般(特に初期化とスコープ) ・ポインタについて全般 ・関数について全般(特に引数) ・型 ほかにも、すでに学習した箇所を一度総点検したほうが良いでしょう。

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

> char str1[100],str2[100]; > printf("1>>"); > fgets(str1,100,stdin); > printf("2>>"); > fgets(str2,100,stdin); > > *mystrfin(c,d); せっかく入力した str1 と str2 を使っていないのは何故ですか? また、mystrfin 関数呼び出しの先頭にある * の意味は何ですか?

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

if文がどこまでが有効範囲かをよく考えましょう if ( c != d )   printf("0"); break; c++; d++; と記述した際と if ( c != d ) {   printf("0");   break; } c++; d++; と記述した際とで どこまで実行されるか ・・・ if文で c!=d と比較しているがこの比較は何を期待しているのか ポインタc および dが保持しているアドレスの比較なのか ポインタが指す先の文字を比較したいのか mystrfinの呼び出しに使う引数の変数は本当にそれ(c,d)で大丈夫なのか mystrfinの呼び出し方の記述は *mystrfin( c, d ); で本当に良いのか ・・・ while(c!='\0'){ と記述しているが cは初期化されていないのにこの比較はしてもよいのか また 文字'\0'と charポインタを比較しているが本当に妥当なのか

346mouse
質問者

補足

>mystrfinの呼び出しに使う引数の変数は本当にそれ(c,d)で大丈夫なのか mystrfinの呼び出し方の記述は *mystrfin( c, d ); で本当に良いのか ・・・ >while(c!='\0'){ と記述しているが cは初期化されていないのにこの比較はしてもよいのか また 文字'\0'と charポインタを比較しているが本当に妥当なのか ここの2つがよくわかりません… どなたか解説をおねがいします…

noname#88772
noname#88772
回答No.1

こんにちは。  コンパイルで警告が出ていませんか? 変数の c, d に着目すれば解決します。 main() と mystrfin() の両方です。 ご参考までに。

関連するQ&A

専門家に質問してみよう