• ベストアンサー

for文の中のscanfにスペースが必要な理由を教えてください。

for文の中のscanfにスペースが必要な理由を教えてください。 以下のようなプログラムを作りました。 10 #include <stdio.h> 20 int main() 30 { 40 printf("入力された英字とその次の英字を出力するプログラムである。\n"); 50 char a; 60 for(;;) 70 {scanf(" %c",&a); 80 if(a=='z'||a=='Z') break;else printf("入力された英字は%cで次の英字は%cです。\n",a,a+1);} 90 printf("終了\n"); 100 } というプログラムを作りました。 70の行のscanfの%cの前にスペースを空けないと実行結果が 「入力された英字とその次の英字を出力するプログラムである。  k  入力された英字はkで次の英字はlです。  入力された英字は  で英字は(よく分からない文字) です。」 という結果になります。 半角スペースを空けると、正常に実行されて 「入力された英字とその次の英字を出力するプログラムである。  k  入力された英字はkで次の英字はlです。」 となります。半角スペース以外もいろいろ試したのですが、どれも正常に実行されませんでした。  この半角スペースはどういう意味なのでしょうか、また、どういう時にこの半角スペースが必要になるのでしょうか、ぜひ教えてください。

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

  • ベストアンサー
  • notnot
  • ベストアンサー率47% (4857/10273)
回答No.2

Cの初心者ないしプログラミングの初心者とお見受けします。 まず、scanf関数は、非常に使い方が難しい関数で、上級者でないと使ってはいけません。もし、入門書にscanfを使う例が載っていたら、その本はまともじゃないので、別の本を探しましょう。 難しさは今回実感しましたね? 元に戻って、なぜ空白が必要かですが、man scanfには、 >ホワイトスペース (スペース、タブ、改行など; isspace(3) 参照) の列。この命令は、入力中の任意の個数のホワイトスペースに一致する。 (「何もなし」にも一致する)。 と書いてあります。 以下の説明では、\n が改行であると知っていることが前提です。 kを入力したときに、kのキーだけでなく、Enterも押しているはずです。 つまり、入力されたのは、"k\n" という文字列なわけです。 これを、scanf(" %c",&a)で読むと、%c が k を読み取り、データとして、\n が残ります。ループの次の繰り返しでは、" %c"の空白が \n に対応して、%c に対応する物が無くなってしまいますので、また次の行を読み取ります。次の行は、z Enterだとすると、"z\n" になります。で、%c に z が対応して読み込まれ、ループが終了。 今度は、scanf("%c",&a)で読む場合。 "k\n" をまず、%c が k を読み取り、\n が残ります。ループの次の繰り返しで、%c が \n に対応して読み取ります。そのため、「入力された英字は」のあとで、\n のために改行されます。また、'\n'+1 が、「よくわからない文字」として表示されたのでしょう。ループの次の繰り返しでようやく "z\n" の z が %c に対応して読み込まれます。 以上の説明を一読して「なるほど」と内容が理解できなければ、scanfを使うのをやめましょう。 この例だと、 案1: for(;;){ a=getchar();/*1文字入力して*/ if(!isalpha(a)) continue; /*英字以外を読み飛ばす*/ if(a=='z'||a=='Z') ..... 案2: char line[1000]; for(;;){ fgets(line,sizeof line,stdin);/*1行入力して*/ a=line[0];/*先頭文字を取り出す*/ if(a=='z'||a=='Z') ..... 案3: char line[1000]; for(;;){ fgets(line,sizeof line,stdin); sscanf(line,"%c",&a); if(a=='z'||a=='Z') .....

gokugokuR
質問者

お礼

大変勉強になりました。参考のプログラムはなんとか理解できました。 案1の場合のみ何文字か入力した場合、1文字目以降も残って次のループで実行されていることが分かりました。他の案は1文字目だけを選ぶというプログラムが記載されていて、そういうプログラムがなければ入力した文字は残ることが分かりました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (2)

  • chie65535
  • ベストアンサー率44% (8567/19468)
回答No.3

ANo.1の >fflush(stdin); >とするのも良い。 は大間違い。 「標準入力がリダイレクトされていると、fflush(stdin);の挙動は不定」となる為「fflush(stdin);はやってはいけない」のです。 多分、fflush(stdin);で入力バッファを捨てようとすると、入力がリダイレクトされた場合に「無限ループしたり、予期せぬ動作をする」でしょう。 LSIC-86のようにユーザーズマニュアルに「標準入力がキーボードになっている場合に限りやっても良い」と記されている場合のみ使用すべきです。 但し「標準入力がリダイレクトされているかどうかは、プログラム自身には判らない」ので、やはりLSIC-86であっても「やってはいけない」のです。 正しく動作させたいのであれば scanf("%c%*[^\n]%*c",&a); のように「1文字読み取って、それ以降の改行文字以外を読み捨てて、さらに改行を読み捨てる」と言う書き方をしないとなりません。

gokugokuR
質問者

補足

回答ありがとうございました。 いろいろ考えたのですが、初心者なものですから、scanf("%c%*[^\n]%*c",&a);のプログラムの意味がよく分かりません。 ぜひよければもう少し詳しく教えてください。

全文を見る
すると、全ての回答が全文表示されます。
  • f272
  • ベストアンサー率46% (8111/17329)
回答No.1

入力の際に押されるリターンキーが入力バッファに残っている。それを読み飛ばすのが半角スペースの役割です。 scanf("%c",&a); としているときに、k[RETURN]とすると%cにkがマッチするけど、次に[RETURN]が%cにマッチするのです。 対処法は scanf(" %c",&a); でもいいけれど scanf("%c",&a); fflush(stdin); とするのも良い。

gokugokuR
質問者

お礼

早速の回答ありがとうございます。 よくわからない文字というのがアスキーコードで11の文字(ENTERの次の値の文字)でしたので、ENTERが行われて改行されて次の番号の文字が出力されていることが分かりました。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • for文,scanfについて

    以下のプログラムを実行したのですが #include<stdio.h> #include<math.h> main(){ int i,b=5; char c; for(i=0;i<=9;++i){ printf("%d\n",b); scanf("%c",c);←入力は自由 } return 0; } 結果 | 予想 5  |  5 a   |  a 5  |  5 5  |  a a   |  5 5  |  a 5  |  5 a   |  a と予想と違う結果が繰り返されるんですが なぜか分かりません。アドバイスを頂けな いでしょうか?

  • scanf文がうまくいかないのですが・・・

    下のようなプログラムを実行するとうまくいかないのですが、何故なのでしょう。 どうかお教えください。 #include<stdio.h> int main(void) { int i; char n; for(i = 0; i < 10; i++) { printf("nを入力してください>>>"); scanf("%c",&n); printf("%c\n",n); } return 0; }

  • switch文とscanfについて

    ソースコード------------------------------------- #include <stdio.h> void main(){ int i; char s, ch; while(1){ printf("Input 1 or 2\n"); scanf("%c", &s); switch(s){ case '1' : printf("Input a number\n"); scanf("%d", &i); printf("You input '%d'\n", i); break; case '2' : printf("Input a character\n"); scanf("%c", &ch); printf("You input '%c'\n", ch); break; } } } ----------------------------------------------- 実行例----------------------------------------- Input 1 or 2 1 Input a number 4 You input '4' Input 1 or 2 Input 1 or 2 //------(1) 2 Input a character You input ' //------(2) ' Input 1 or 2 ----------------------------------------------- (1)について。 なぜ"Input 1 or 2"が二回繰り返されているのですか。 (2)について。 scanfが呼び出されて入力待ちになることを期待しているのですが、 なぜ(2)のようになってしまうのでしょうか。

  • if~else文の中にまたif~else文をいれるには。

     このプログラムを思うように実行したいのですが、できません。 コンパイルはできるのですが、警告が4つほど出て、結果も自分が思ってるのとは違います。 プログラムのどこを改善すべきか教えてください。 OSはWindows XPで、コンパイラはボーランドのフリーコンパイラを使用しています。 #include<stdio.h> int main(){ int a,b,c,d; printf("1か0を入力してください。\n"); scanf("%d",&a); if(a=0) { printf("2か3を入力してください。\n"); scanf("%d",&b); if(b=2){ printf("今まで合計は%dです。\n",a+b); } if(b=3){ printf("今まで合計は%dです。\n",a+b); } else { printf("指定した数字を入力して下さい。\n"); } } else if(a=1) { printf("あなたは%dを入力しました。\n",a); } else { printf("指定した数字を入力してください。\n"); } return 0; }

  • scanf文で入力した値の計算がうまくいきません

    2つの少数を含む数字を入力し計算して出力するプログラムを作っているのですがうまくいきません。下がそのプログラムです。 #include<stdio.h> int main(void) { int ver1,ver2; printf("1つ目の実数を入力して下さい\n"); scanf("%f",&ver1); printf("2つ目の実数を入力して下さい\n"); scanf("%f",&ver2); printf("%f+%f=%f\n",ver1,ver2,ver1+ver2); printf("%f-%f=%f\n",ver1,ver2,ver1-ver2); printf("%f×%f=%f\n",ver1,ver2,ver1*ver2); return 0; }

  • for文のループがされません

    #include <stdio.h> main() { int n, count, c; int d = 50000; printf("整数を入力:"); scanf("%d",&n); for(count = 1; count <= n; count++){ c = d * (16 / 100); d += c; } printf("%d回目の数はは%dです\n",n,d); } というプログラムを作ったのですが、for文のところが実行されずに、 1回目ならば58000となるはずなのに初期値のまま50000と表示されてしまいます。 どなたかご指摘お願いします。

  • Cの問題について。

    下の問題の時、 y、zが入力された時に暗号化された文字をa、bへ戻す方法がわかりません。 わかる方がいたら、ヒントだけでもいいので、よろしくお願いします。 適当な1文字を入力し、それが元が何であったかが分からないように何文字かずらして暗号化し、また元に戻すようなプログラムを作りなさい。文字としては英字小文字のみと仮定します。 例を以下に示します。作成するプログラムも同じような出力形式にしてください。 [ 例 ] 入力文字 = x 暗号化された文字 = b 復号化された文字 = x 何文字ずらすか?については、各自で適当に設定して構いません。 ただし、暗号化された文字も、英字小文字でなければなりません。 例えば、zに2を足すと、そのままでは英字でない記号になってしまいますが、これを z+1 -> a, z+2 -> b, z+3 -> c, … のようにアルファベットの先頭に戻してやる処理が必要です。 この点を工夫して下さい。 #include <stdio.h> void main(){ char moji; int a; printf("入力文字:"); scanf("%c",&moji); a=2; moji += a; printf("暗号化された文字= %c \n",moji); moji -= a; printf("複合化された文字= %c \n\n",moji); }

  • プログラミング for文

    プログラミング for文 プログラミングの問題です。 「自然数nを入力し、以下のようなパターンが出力されるようなプログラムをfor文を使って作成せよ。」 (例:n=3のとき) % ./a.out n: 3 * ** *** *__* **_** ****** *__*__* **_**_** ********* (例:n=4のとき) % ./a.out n: 4 * ** *** **** *___* **__** ***_*** ******** *___*___* **__**__** ***_***_*** ************ *___*___*___* **__**__**__** ***_***_***_*** **************** (_で空白を表しましたが、上手く見られないかもしれません…。小さい直角三角形が下に行くにつれ1個ずつ増え、全体的にみると大きい直角三角形が見えるイメージです。) つまり、n=3なら、 * ** *** を単位として、1~3行目にはこれが1つ、4~6行目にはこれが2つ、7~9行目にはこれが3つあります。 一般に、 * ** *** … ********(←n個) を単位とし、n^2-2~n^2行目にこれがn個あるようなパターンです。 私はまず、単位パターンをプログラムしました。 #include <stdio.h> main() { ___int n, i, j; ___printf("n: "); ___scanf("%d", &n); ___for (i=1; i<=n; i++) { ______for (j=1; j<=i; j++) { _________printf("*"); ______} ______printf("\n"); ___} } (_は空白です) しかし、単位パターンを横に2個、3個と並べるプログラムが分かりません。 さらにfor文を使い、3重、4重にするのですか?どなたか教えてください。

  • C言語でfor文を用いたプログラミングについてです。

    C言語のプログラミングの課題で以下のような表をfor文を用いて作るというものが出ました。 商品名 単価(円)個数(円) 計  A  50   20   ***  B  90   30   ***  C  30   80   ***        合計金額   *** A,B,C及びそれぞれの単価、個数の値はキーボードからの入力で、***は演算によりその結果を出力するようにします。つまり、商品名(1文字)と単価、そしてその個数をキーボードから入力すると、単価と個数をかけた値と、それら全ての合計が出力されるようなプログラムを作るということです。 私は以下のようなプログラムを作りました #include<stdio.h> int main(void) { int a,b,c,sum,allsum,i; printf("商品名 単価 個数 計\n"); for(i=1;i<=3;i++) { a=getchar(); scanf("%d %d",&b,&c);  sum=b*c; allsum +=sum; putchar(a); printf(" %d %d %d \n",b,c,sum); } printf("合計金額 %d\n",allsum); return 0; } しかしこれでは合計金額がちゃんと表示されなかったりしてうまくいきません。おそらくfor文の中身に問題があると思うんですが…。どうか正しいプログラムと、なぜこのプログラムではうまくいかないのかを教えていただきたいです。なにぶん初心者なもんで、よろしくお願いします。

  • 簡単なscanf文が、わかりません。

    #include <stdio.h> int main(void) { int data; scanf("%d",&data); /*入力部分*/ printf("%d\n",data); return 0; } 参考書には、キーで入力、enterキー押すと、はじめて文字が画面に表示されるとなってましたが。 実際は、enter押さずに、キーボードでキー入力した時点で文字が表示されますが、 どこが間違っているんでしょうか? コンパイラは、 Borland C++ Compiler です。 お願いします。

印刷できません
このQ&Aのポイント
  • オフライン状態で印刷が急に出来なくなった
  • パソコンもしくはスマートフォンのOSはWindowsです
  • 接続は無線LANで、Wi-Fiルーターの機種名はバッファローです
回答を見る