• ベストアンサー

スキャン集合に関して

#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のスキャン集合に原因があるのでしょうか?

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

  • ベストアンサー
  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.4

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に備えてくれます。

yamada11
質問者

お礼

ありがとうございます。丁寧に教えていただき大変勉強になりました。 しかも分かりやすい解決方法で助かりました。

その他の回答 (4)

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.5

念のため。 私が紹介したスキャン集合 >scanf("%127s%*[^\n]%*c", str ); とNo4さんがおっしゃっている方法 >scanf( "%[^\n]", str ); >getchar(); は必ずしも等価ではありません。 私が紹介した方法では、 空入力を許可しない為、 Enterを入力しても継続します。 本題です。 >が分からない状態です。立て続けで申し訳ございません。 えっと、何が分からないのかが分かりません。 結局、int tan_kansu(char *sp)という関数は何をするんでしょうか? 与えられた文字列と入力した文字列を使って何をするかを 補足してもらえないでしょうか。。。?

yamada11
質問者

お礼

すいません、最終的に分からないのはバッファに情報が残るケースの対処方法です。(というと大きすぎますが) scanf、gets,fgetsの三つにおいて、空白を含めて入力してファイルの中身を読み込み、加工して別なファイルに保存するといった事がしたいのですが、なかなかうまくいかず悩んでいました。

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.3

いきなり、what.txtなる物が出てきましたが、 一番最初の質問内容と異なっているように思います。 貴方がどんな結果を期待しているのか分かりかねます。 元の質問内容と異なるようなら、 新たに質問することをお勧めします。

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.2

原因はNo1の方が最初に仰っている通りです。 バッファオーバランを防ぐ為に私なら、 以下のようなスキャン集合を指定します。 #改行も読み捨てるはず char str[128]; printf("文字列を入力してください>\n"); scanf("%127s%*[^\n]%*c", str ); > scanf( "%s\*c", str, &ch ); %*c のミスでしょうか? *(代入抑止)を指定しているので&chは不要に思います。

yamada11
質問者

お礼

ありがとうございます。今はこちらのソース #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); } が分からない状態です。立て続けで申し訳ございません。

yamada11
質問者

補足

入力後に気づきましたが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)
回答No.1

原因は 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 ); といった具合にして見ましょう

yamada11
質問者

お礼

ありがとうございます。色々サイトを見てまわったのですが、似たような解説のサイトが多数ありました。しかし、 #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); } これも似たような事態になるのですが、解決するにはどうしたらよいのでしょう?たて続けの質問で申し訳ございません。

関連するQ&A

  • C言語、スキャン集合について

    下記のプログラムはスキャン集合を使って入力された文字列の先頭に 並んでいる数字を読み込んで捨て、その後に続く文字列を読み込んで 表示するものです。 #include <stdio.h> int main(void) { char str[80]; printf("数字に続けて文字列を入力してください\n"); scanf("%*[0-9]%s", str); printf("%s", str); return 0; } 【質問】%*[0-9] を %[^0-9] に置き換えてコンパイルして実行すると、 意味不明の文字列が出力されるのはなぜでしょうか? 置き換えても同じ結果になる気がするのですが…

  • ポインタについて

    #include<stdio.h> int main(void) { char str[10]; char *ptr = str; printf("文字列を入力してください。\n"); scanf("%s",ptr); printf("文字列は%sです。",str); return 0; } 上記のプログラムのscanf("%s",ptr);の ptrに&をつけるとなぜ先頭の4文字は入力しても 表示されなくなってしまうのでしょうか? よろしくお願いします。

  • 要素数を100個にしろといわれたのですが

    要素数を100個にしろといわれたのですが int main(void){ char str="100"; printf("文字列を入力してください:"); scanf_s("%s",str); put_string(str); putchar('n'); return (0); } この『char str="100";』の部分を『char str[100];』にしたらいいんでしょうか? 教科書をみてやってみたのですがイマイチ理解できずお手上げ状態です 因みに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言語文字数4つカウント

    こんにちは。大学の課題で「キーボードから入力した文字数に含まれる'h''o''g''e'の4つの文字数をカウントする関数を含むプログラムを完成させよ」という課題がありました。なかなかできず現段階では以下のようになっています。どうすれば問題文のように実行できますか? #include <stdio.h> char str_chnum(const char str[], int ch) { int count = 0; int i; for(i = 0; str[i] != '\0'; i++) { if(str[i] == ch) count++; } return(count); } int main(void) { char str[128]; int ch; printf("文字列を入力してください:"); scanf("%s", str); printf("検索する文字を入力してください:"); scanf(" %c", &ch); printf("%cは%d個ありました。\n", ch, str_chnum(str, ch)); return(0); }

  • C言語 文字列の操作

    文字Cが含まれる個数を求めたいです #include <stdio.h> int str_chnum(const char str[],int c) { int i; int count=0; for(i=0;str[i]!="\0";i++) if (str[i]==c) count++; return(count); } int main(void) { char st[100]; printf("検索文字列を入力してください:"); scanf("%s",st) ; printf("検索文字列数は%uです。\n",st,int str_chnum(const str[],int c)); return(0); } コンパイルできません。なぜですか?printfの行がたぶん間違っていると思うんですが。。。

  • C言語 ポインタと配列

    #include <stdio.h> /* scanf("%c", &search); ではなく scanf(" %c", &search); であることに注意する */ char *str_chr(const char *str, char c) { char *find; find = NULL; do { if(*str == c) { find = (char*)str; break; } } while(*str++); return(find); } int main(void) { char str[100] = {0}; char search; char *find; printf("文字列を入力してください:"); scanf("%s", str); printf("検索する文字を入力してください:"); scanf(" %c", &search); find = str_chr(str, search); if(find == NULL) { puts("検索した文字は見つかりませんでした。"); } else { printf("検索した文字 %c は\"%p\"にあります。\n", *find , find); } return(0); } このコードのfind = (char*)str;の (char*)str;の部分がどうなっているのかわかりません。 あとこのfindというのは&find[0]という解釈でいいでしょうか? 教えてくださいm(_ _ )m

  • ポインタ

    質問なのですが、このソースのchar *str_copy(char *d, const char *s)関数内のchar *p=d;はなんで、*pにdを入れるか分かりません。それと、このdは、*dなのですか?どうして、while (*d++ = *s++) みたいに*dをつけないんですか?教えてください。宜しくお願いします。 #include <stdio.h> char *str_copy(char *d, const char *s) { char *p=d; while (*d++ = *s++) ; return (p); } int main(void) { char tmp[100]; char st1[100], st2[100],st3[100]; printf("文字列を入力してください:"); scanf("%s",tmp); str_copy(st1,str_copy(st2,tmp)); printf("文字列st1は%sです。\n", st1); printf("文字列st2は%sです。\n", st2); printf("文字列st3は%sです。\n", str_copy(st3,tmp)); return (0); }

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

    <本に載ってたソース> #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が、文字数でしたっけ?

  • C言語 無効な例外ハンドラー ルーチン

    失礼します現在C言語を書籍にて勉強しておりますが、エラーが出てしまいすすめません正誤表などがなくこまっています現在のソースは #include <stdio.h> int str_char(const char str[], int c) { int i; for (i = 0; str[i] != '\0'; i++) if (str[i] == c) return (i); return(-1); } int main(void) { int no; char ch[10]; printf("英文字を入力してください"); scanf_s("%s", ch); no = str_char("ABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwxyz", ch[0]); if (no >= 0 && no <= 25) printf("それは英大文字の%dです\n", no + 1); else if (no >= 26 && no <= 51) printf("それは英小文字の%dです\n", no - 25); else printf("それは英文字ではありません\n"); return(0); } で、出てくるエラーメッセージは ハンドルされない例外が 0xFEFEFEFE (helloworld.exe) で発生しました: 0xC00001A5: 無効な例外ハンドラー ルーチンが検出されました。 (パラメーター: 0x00000003)。 です。 よろしくお願いします

専門家に質問してみよう