質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

3回答

5011閲覧

C言語 数字以外を入力すると無限ループしてしまいます。。。

alice331

総合スコア11

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2020/07/06 14:28

じゃんけんゲームを作成したのですが、手を入力する際と再度挑戦する際に数字以外の文字を入力すると無限ループしてしまいます。
数字以外が入力されていますと、エラー出力したのですがどのようにすればよろしいでしょうか?
よろしくお願い致します。

c

1#include <time.h> 2#include <stdio.h> 3#include <stdlib.h> 4 5int human; /*人間の手*/ 6int com; /*コンピュータの手*/ 7int win_no; /*勝った回数*/ 8int lose_no; /*負けた回数*/ 9int draw_no; /*引き分けの回数*/ 10/* 手 */ 11char *hand[] = {"グー","チョキ","パー"}; 12 13/* 初期化処理 */ 14void initialize(void) 15{ 16 win_no = 0; 17 lose_no =0; 18 draw_no =0; 19 20 srand(time(NULL)); 21 printf("じゃんけんゲーム開始です\n"); 22} 23 24/* じゃんけん実行(手の読み込み/生成) */ 25void jyanken(void) 26{ 27 int i; 28 /* コンピュータの手(0~2)を乱数で生成 */ 29 com = rand()%3; 30 31 while(1) 32 { 33 printf("じゃんけんポン…"); 34 for(i = 0; i < 3; i++) 35 { 36 printf("(%d)%s", i, hand[i]); 37 } 38 printf(":"); 39 /* 人間の手を読み込む */ 40 scanf("%d",&human); 41 if(0 <= human && human <=2) 42 { 43 break; 44 } 45 printf("0~2の数字を再度入力して下さい\n"); 46 } 47} 48/* 勝ち/負け/引き分け回数を更新 */ 49void count_no(int result) 50{ 51 switch(result) 52 { 53 /* 引き分け */ 54 case 0: draw_no++; 55 break; 56 57 /* 負け */ 58 case 1: lose_no++; 59 break; 60 61 /* 勝ち */ 62 case 2: win_no++; 63 break; 64 } 65} 66 67/* 判定結果を表示 */ 68void disp_result(int result) 69{ 70 switch(result) 71 { 72 case 0: printf("引き分け"); 73 break; 74 75 case 1: printf("あなたの負けです"); 76 break; 77 78 case 2: printf("あなたの勝ちです"); 79 break; 80 } 81} 82 83/* 再挑戦するかを確認 */ 84int Retry(void) 85{ 86 int x; 87 printf("もう一度しますか""(0)いいえ (1)はい :"); 88 scanf("%d", &x); 89 90 return x; 91} 92 93int main(void) 94{ 95 int judge; /* 勝敗 */ 96 int retry; /* もう一度 */ 97 98 /* 初期化処理 */ 99 initialize(); 100 101 do 102 { 103 /* じゃんけんの実行 */ 104 jyanken(); 105 /* コンピュータと人間の手を表示 */ 106 printf("私は%sで、あなたは%sです。\n",hand[com],hand[human]); 107 /* 勝敗判定 */ 108 judge = (human - com + 3)%3; 109 /* 勝ち、負け、引き分け回数を更新 */ 110 count_no(judge); 111 /* 判定結果を表示 */ 112 disp_result(judge); 113 /* 再挑戦するか確認 */ 114 while(1) 115 { 116 retry = Retry(); 117 if( retry == 0 ) 118 { 119 printf("%d勝%d敗%d分けでした。",win_no,lose_no,draw_no); 120 break; 121 } 122 else if (retry == 1) 123 { 124 break; 125 } 126 else 127 { 128 printf("0~1の数字を再度入力して下さい\n"); 129 } 130 } 131 } 132 while(retry == 1); 133 return 0; 134} 135

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

scanfを使わないようにしてはどうかな。
fgetsで1行読んで、strtolで整数値を生成して、そいつを使う。

C

1 /* 人間の手を読み込む */ 2 // scanf("%d", &human); 3 char humanstr[80]; 4 char *endptr; 5 fgets(humanstr, sizeof(humanstr), stdin); 6 human = strtol(humanstr, &endptr, 10); 7 if (endptr != humanstr && 0 <= human && human <= 2) { 8 break; 9 }

C

1 printf( 2 "もう一度しますか" 3 "(0)いいえ (1)はい :"); 4 // scanf("%d", &x); 5 char answer[80]; 6 fgets(answer, sizeof(answer), stdin); 7 x = strtol(answer, NULL, 10); 8 9 return x;

投稿2020/07/06 15:10

Daregada

総合スコア11990

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

scanfは書式文字列に合わない入力は読み取らずに入力バッファに残したしたままとします。
そのため数字以外の文字を入力し、scanf("%d", &変数)を呼び続けると無限ループとなります。
scanfの戻り値を見て入力を読み捨てるか、文字列として読み込んでから数値変換するなどの対応が必要となります、

scanf 異常な入力が行われた時の処理

投稿2020/07/06 14:39

SHOMI

総合スコア4079

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

こんなのはいかがでしょうか?

diff

1 } 2 printf(":"); 3 /* 人間の手を読み込む */ 4- scanf("%d",&human); 5- if(0 <= human && human <=2) 6+ if (scanf("%d",&human) == 1 && 0 <= human && human <=2) 7 { 8 break; 9 } 10+ scanf("%*[^\n]"); // 行末まで不正な文字を読み飛ばす 11 printf("0~2の数字を再度入力して下さい\n"); 12 } 13 }

追記
scanf は、もう一つあったんですね。

diff

1 { 2 int x; 3 printf("もう一度しますか""(0)いいえ (1)はい :"); 4- scanf("%d", &x); 5- 6- return x; 7+ if (scanf("%d", &x) == 1) return x; 8+ scanf("%*[^\n]"); // 行末まで不正な文字を読み飛ばす 9+ return 2; 10 } 11 12 int main(void)

追記2
この scanf("%*[^\n]"); による現在の行の不正文字の読み飛ばしには
注意しなければならないことがあります。
それは行末の '\n' が入力バッファに残っているということです。

次の入力処理が scanf("%d" や scanf("%s などであれば、
その '\n' を呼び飛ばしてくれるので問題ありません。

しかし、scanf("%c" や scanf("%[ では、'\n' を読み込んでしまいます。
また、getchar() や fgets でも '\n' を文字として読み込んでしまいます。

投稿2020/07/06 14:38

編集2020/07/08 00:24
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問