我是一名C编程入门者,试图在这里编写一个原始数字猜谜游戏。 (这不是我保证的学校作业)。但是因为我在尝试完成整个功能时遇到了一些麻烦,我想也许我需要一些帮助。所以基本上我已经完成了该程序的主要猜测部分:向用户表明他的猜测太高或太低或者是正确的答案。但是,如果用户输入一些无效值,如字符或小数(它们应该只输入1-100的整数),我的程序只会提示用户猜测超出范围并自动循环此消息直到猜测时间用完了。我检查了我的代码,但无法弄明白。如果有人能给我一个帖子,我将不胜感激! 这是代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_NUMBER 100
int main(void) {
int randNum;
srand((int)time(0));
randNum = rand() % 100 + 1;
long guessNum;
char guessStr[80];
guessNum = atoi(guessStr);
int count = 0;
do {
printf("\nplz enter a guess from integer 1 to 100: %d", randNum);
scanf("%ld", &guessNum);
if (guessNum < randNum && guessNum >= 1) {
printf("your guess is lower than the selected number");
count++;
printf("\nyou have %d times left to try", 100 - count);
}
if (guessNum > randNum && guessNum <= 100) {
printf("your guess is higher than the selected number");
count++;
printf("\nyou have %d times left to try", 100 - count);
}
if (guessNum < 1 || guessNum > 100) {
printf("your guess is out of the range, plz pick between 1-100");
count++;
printf("\nyou have %d times left to try", 100 - count);
}
if (guessNum == randNum) {
printf("congrats you got the right answer");
count++;
printf("\nyou used %d times to make the right guess", count);
}
} while (count < MAX_NUMBER);
printf("\nthe guess time is used out!");
return 0;
}
答案 0 :(得分:1)
如果scanf
检测到与转换说明符不匹配的输入(例如查看字母所需的数字),它将在该点停止扫描并将该字符保留在输入流中,将在下一次阅读中弄清楚,然后在下一次阅读。
有几种方法可以解决这个问题。
首先,scanf
返回成功转化和分配的数量;例如,如果scanf( "%d", &value );
能够从输入流中读取整数值,则scanf
将返回1。首先,我们可以检查一下:
if ( scanf( "%d", &guessNum ) == 1 )
{
// test the value of guessNum
}
else
{
// input wasn't a valid integer; consume input until we see a newline
char c;
while ( ( c = getchar() ) != '\n' )
;
}
问题在于,如果您输入12r
之类的内容,scanf
将转换并分配12
,同时在输入流中保留r
。理想情况下,您希望拒绝整个输入。您可以在输入后立即阅读该字符,如下所示:
char follow;
int itemsRead = scanf( "%d%c", &guessNum, &follow );
if ( itemsRead == 2 && isspace( follow ) )
{
// test value of guessNum
}
else
{
// input was not an integer followed by a newline
while ( getchar() != '\n' )
;
}
这可以保护您免受12r
等情况的侵害。但是,仍然存在缺陷。信不信由你,scanf( "%d" )
不会阻塞像
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
即使这样的值无法用原生int
类型表示。再一次,你希望能够完全拒绝这种糟糕的输入。
第三种方法是将输入作为文本读取,然后使用atoi
,strtol
或sscanf
之类的内容进行转换。我首选的方法是使用strtol
,如下所示:
char input[MAX_INPUT_LEN]; // where MAX_INPUT_LEN is appropriate for a signed
// integer value; a 32-bit int can represent up to
// 10 decimal digits, plus the sign, plus the
// 0 terminator.
if ( fgets( input, sizeof input, stdin ) )
{
if ( !strchr( input, '\n' ) ) // if newline is not present in the input buffer
{
fprintf( stderr, "Input too long!\n" );
while ( getchar() != '\n' )
;
}
else
{
char *follow; // will point to first non-digit character in input
int tmp = strtol( input, &follow, 10 ); // convert input string to equivalent
// integer value;
if ( !isspace( *follow ) && *follow != 0 )
{
fprintf( stderr, "%s is not a valid integer value\n", input );
}
else
{
guessNum = tmp;
// test value of guessNum
}
}
}
你需要根据自己的需要进行调整(最好将大部分垃圾隐藏在自己的功能中),但你应该明白这一点。
答案 1 :(得分:0)
你应该使用这样的循环:
for (int readNums = 0; readNums == 0; ) {
printf("plz enter a guess from integer 1 to 100: %d\n", randNum);
readNums = scanf("%ld", &guessNum);
}
您可以删除guessStr
及其所有引用,因为您实际上并未使用它。另外,通常的C语言是将循环退出条件置于循环的顶部。对于您的程序,这意味着您现有的do ... while()
循环将变为:
while(count < MAX_NUMBER)
{
/* your code here */
}
最后,在比赛结束时,你想要一种实际退出的方法。你可以这样做:
/* other guess handling code here... */
if(guessNum == randNum)
{
printf("congrats you got the right answer\n");
count++;
printf("you used %d times to make the right guess\n", count);
break;
}
}
if (guessNum != randNum)
printf("the guess time is used out!\n");
另请注意,我使用了另一个C语言,即将\n
放在字符串的末尾而不是开头。