2016-04-26 2 views
2

私は典型的な "y/n" char関数をif/else文で必要とする長いプログラムを構築していますが、うまくいきますが、ユーザが何か無効なものを入れた場合、 "Invalid answer" %cの代わりに "%1s"を実行しようとしましたが、暴走入力を止めません。cのcharに対する繰り返しの無効な回答を停止する方法は?

#include<stdio.h> 

int main() 
{ 
printf("Welcome.I can predict the future\n" 
    "I learned this gift from someone in the future.\n" 
    "A bright creature with green eyes taught me how.\n" 
"It appeared to me on a Sunday without enthusiam\n" 
    "and told me I would end up trapped in a computer,\n" 
"and there was nothing I could do about it.\n" 

"It was really cruel of it to do that.\n" 
"I could have enjoyed the rest of my days\n" 
"without being depressed having known that...\n" 
"I also didn't need to know so many other things I\n" 
"now have learned.\n\n" 

"Having said this, would you like me to predict you\n" 
    "future?y/n\n"); 

char ansr; 
scanf("%1s", &ansr); 


while (ansr != 'y' && ansr != 'n'){ 

printf("Invalid answer, Please try again."); 
scanf("%1s", &ansr); 
} 

if (ansr == 'y') { 
printf("You've been warned.\n\n"); 
} 
else if (ansr == 'n') { 
printf("Goodbye Then.\n\n"); 
} 




return 0; 

} 
+0

'char ansr [2]; scanf( "%1s"、ansr); ながら(* ANSR = 'Y' && * ANSR = 'N'!){ '使用 – BLUEPIXY

+0

:'チャーANSRと、 のscanf(「%の1」、&ansr);が '間違っている;'%の1s'は2つの文字、文字列の最後の文字用とヌルのための1つのポインタを必要とたぶんあなたは 'char型の答えを求めていました;。(scanfの場合( "%c"、&answer)== 1){... OK ...} else {... EOFまたはエラー...} 'フォーマット文字列の先頭の空白には空白または空白がなく、どちらも重要です。 –

答えて

1

まず、あなたは、この書式指定子が配列を想定しているためchar%1sを使用する必要はありません。 ansrのメモリ位置に1文字を書き込んだ後、次のメモリ位置にヌルバイトを書き込みます。これにより未定義の動作が発生しました。 %cを使用してスティックします。

余分な文字をクリアするには、あなたはそれが改行を見つけるまで、文字を読むためにループ内でgetcharを使用したいです。それはバッファをフラッシュします。

while (ansr != 'y' && ansr != 'n') { 
    printf("Invalid answer, Please try again."); 
    while (getchar() != '\n'); 
    scanf("%c", &ansr); 
} 

出力:

... 
Having said this, would you like me to predict you 
future?y/n 
bogus 
Invalid answer, Please try again.wrong 
Invalid answer, Please try again.yep 
You've been warned. 
0

あなたの入力中の文字列を処理するには、次のようにあなたのansrバッファに標準入力からの読み込みしようとした後、文字列の比較を行うことができます。 stdinの残りの部分を%*[^\n]に投げ捨てることで、スキャンは空白または複数の文字の影響を受けず、希望するy/n文字を取得します。また、閉じ括弧を忘れずに、mainにゼロを戻してください。

#include <stdio.h> 
#include <string.h> 
#define buffLen 32 

int main() {   

    char ansr[buffLen] = ""; 

    printf("...would you like me to predict your future? (y/n) \n"); 

    while (strcmp(ansr, "y") != 0 && strcmp(ansr, "n") != 0){ 

     // Read the string, and throw away the rest up to the newline char. 
     scanf("%s%*[^\n]", &ansr); 

     if (strcmp(ansr, "y") == 0) { 
      printf("You've been warned.\n"); 
     } else if (strcmp(ansr, "n") == 0) { 
      printf("Goodbye Then.\n"); 
     } else { 
      printf("Invalid answer, Please try again.\n"); 
     } 
    } 

    return 0; 
} 

EDIT:条件がある前にdoブロックがバッファを初期化しているため、ダミーのものでバッファansrを初期化するから私たちを救うために、DO-whileループを使用するには、コメントでは良い提案がありました評価される。私はこれらを使用することはめったにないので、私はこれが好きですが、これはいつ使うのが大好きですか?

#include <stdio.h> 
#include <string.h> 
#define buffLen 32 

int main() { 

    char ansr[strLen]; 

    printf("...would you like me to predict your future? (y/n) \n"); 

    do { 
     // Read the string, and throw away the rest up to the newline char. 
     scanf("%s%*[^\n]", &ansr); 

     if (strcmp(ansr, "y") == 0) { 
      printf("You've been warned.\n"); 
     } else if (strcmp(ansr, "n") == 0) { 
      printf("Goodbye Then.\n"); 
     } else { 
      printf("Invalid answer, Please try again.\n"); 
     } 
    } while (strcmp(ansr, "y") != 0 && strcmp(ansr, "n") != 0); 

    return 0; 
} 
+0

書かれているように、このプログラムは、 'ansr'の内容が初期化される前に、' strcmp() 'を呼び出すので、未定義の振る舞いをまったく実行しないか、まったく実行しないことがあります。 – duskwuff

+0

OPPS、素敵なキャッチ、私はそれを初期化するためのもの。 – nigel

+0

バッファオーバーフロー、このプログラムは、人は簡単、scanf関数呼び出しで、発見それを長さを与えるか、あるいは脆弱でいる。オーバーフローに関する –

関連する問題