- ベストアンサー
スキャン集合に関して
#include <stdio.h> int main() { char str[128]; printf("文字列を入力してください>\n"); scanf("%[^\n]" , str); printf("入力された値 = %s\n" , str); can_kansu(str); return 0; } int can_kansu(char *sp) { char strs[128]; printf("%sとは違う文字を入力して下さい。\n", sp); scanf("%[^\n]" , strs); printf("入力された値 = %s\n" , strs); return (0); } このプログラムでは、mainでは正常に入力表示が可能なのに、can_kansuにいくと勝手に入力、表示され、しかもその文字は文字化けして表示されてしまいます。 <実際の入力例> 文字列を入力してください> kkk 入力された値 = kkk kkkとは違う文字を入力して下さい。 入力された値 = �p "kkkとは違う文字を入力して下さい。"の所で入力出来ずにつぎに勝手に進んでしまい、入力されている文字はこの通りです。 原因は何でしょうか?scanfのスキャン集合に原因があるのでしょうか?
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
scanf("%[^\n]" , str); を実行すると、キー入力待ちになり、ここで abcd<ENTER> と入力すると、標準入力のストリームに 'a' 'b' 'c' 'd' '\n' が送り込まれます。 そしてscanfは、標準入力のストリームから1文字づつ取り出し、\nの手前までをstrに格納します。つまり、strには「abcd+ヌル文字」が入ります。 そして、標準入力のストリームには、貴方が押した<ENTER>が、つまり'\n'が残ります。 標準入力のストリームの先頭に'\n'が残ったまま、次の scanf("%[^\n]" , strs); を実行すると、先頭に'\n'がありますから、scanfは何も入力しないで終了します。貴方は「\nが来るまでstrsに読め」って言ってるのですから、いきなり\nが来れば、scanfは何もしません。strsは未初期化のままです。strsが未初期化のままなら、何が表示されるか判らないので、メモリ上にあったゴミが表示され、文字化けしたようになります。 「\nの手前まで、\nが来るまで読み込んだら、\nは読み込まれずに残る」のです。 だったら「\nの手前まで、\nが来るまで読み込んだら、読み込まれずに残った\nを読み捨てれば良い」のです。 プログラム内の、すべての scanf("%[^\n]" , ほげほげ); の直後に getchar(); を入れて下さい。余さず全部です。どこの関数にあるかも関係なく、全部のscanf("%[^\n]" , ほげほげ);の直後に入れて下さい。 getcharが、標準入力のストリームに残った'\n'を読み捨て、その後に呼び出されるscanfに備えてくれます。
その他の回答 (4)
- aris-wiz
- ベストアンサー率38% (96/252)
念のため。 私が紹介したスキャン集合 >scanf("%127s%*[^\n]%*c", str ); とNo4さんがおっしゃっている方法 >scanf( "%[^\n]", str ); >getchar(); は必ずしも等価ではありません。 私が紹介した方法では、 空入力を許可しない為、 Enterを入力しても継続します。 本題です。 >が分からない状態です。立て続けで申し訳ございません。 えっと、何が分からないのかが分かりません。 結局、int tan_kansu(char *sp)という関数は何をするんでしょうか? 与えられた文字列と入力した文字列を使って何をするかを 補足してもらえないでしょうか。。。?
お礼
すいません、最終的に分からないのはバッファに情報が残るケースの対処方法です。(というと大きすぎますが) scanf、gets,fgetsの三つにおいて、空白を含めて入力してファイルの中身を読み込み、加工して別なファイルに保存するといった事がしたいのですが、なかなかうまくいかず悩んでいました。
- aris-wiz
- ベストアンサー率38% (96/252)
いきなり、what.txtなる物が出てきましたが、 一番最初の質問内容と異なっているように思います。 貴方がどんな結果を期待しているのか分かりかねます。 元の質問内容と異なるようなら、 新たに質問することをお勧めします。
- aris-wiz
- ベストアンサー率38% (96/252)
原因はNo1の方が最初に仰っている通りです。 バッファオーバランを防ぐ為に私なら、 以下のようなスキャン集合を指定します。 #改行も読み捨てるはず char str[128]; printf("文字列を入力してください>\n"); scanf("%127s%*[^\n]%*c", str ); > scanf( "%s\*c", str, &ch ); %*c のミスでしょうか? *(代入抑止)を指定しているので&chは不要に思います。
お礼
ありがとうございます。今はこちらのソース #include <stdio.h> #include <string.h> #define STR_MAX 256 int main(void) { FILE *fp; int dore; char str[6000]; fp = fopen("what.txt", "r"); while (fgets(str, STR_MAX, fp) != 0){ str[strlen(str) - 1] = '\0'; printf(" %s\n", str); tan_kansu(str); fclose(fp); return (0); } int tan_kansu(char *sp) { char tan[6000]; char tekitou1[6000]; printf("%s以外のものを入力して下さい。\n", sp); scanf("%[^\n]" , tan); printf("入力したもの=%s\n", tan); return (0); } が分からない状態です。立て続けで申し訳ございません。
補足
入力後に気づきましたがwhat.txtの中身はこれです。 #include <stdio.h> int main() { char str[128]; printf("文字列を入力してください>\n"); scanf("%[^\n]" , str); printf("入力された値 = %s\n" , str); can_kansu(str); return 0; } int can_kansu(char *sp) { char strs[128]; printf("%sとは違う文字を入力して下さい。\n", sp); scanf("%[^\n]" , strs); printf("入力された値 = %s\n" , strs); return (0); } これを読み込んでいます。
- redfox63
- ベストアンサー率71% (1325/1856)
原因は main側で実行された scanfの入力時の改行が処理されずに残ったままのため can_kansu側のscanfが失敗しているためです main側のscanfを int ch = 0; scanf( "%s\*c", str, &ch ); といった具合に '\n'を吐き出してやるか can_kansu側で int ch = 0; // バッファの先頭が '\n'ならば scanfは失敗して 0を返す while( 1 != scanf( "%[^\n]s", strs ) ) scanf( "%*c", &ch ); といった具合にして見ましょう
お礼
ありがとうございます。色々サイトを見てまわったのですが、似たような解説のサイトが多数ありました。しかし、 #include <stdio.h> #include <string.h> #define STR_MAX 256 int main(void) { FILE *fp; int dore; char str[6000]; fp = fopen("what.txt", "r"); while (fgets(str, STR_MAX, fp) != 0){ str[strlen(str) - 1] = '\0'; printf(" %s\n", str); tan_kansu(str); fclose(fp); return (0); } int tan_kansu(char *sp) { char tan[6000]; char tekitou1[6000]; printf("%s以外のものを入力して下さい。\n", sp); scanf("%[^\n]" , tan); printf("入力したもの=%s\n", tan); return (0); } これも似たような事態になるのですが、解決するにはどうしたらよいのでしょう?たて続けの質問で申し訳ございません。
お礼
ありがとうございます。丁寧に教えていただき大変勉強になりました。 しかも分かりやすい解決方法で助かりました。