我试图自己学习C,我有一些Matlab和Python的经验。我试图创建一个简单的猜谜游戏,你给出一个数字,计算机猜测一个数字,你必须告诉它是否更高或更低。我已经编写了一些代码,但它不起作用(例如,尝试输入30)。代码很丑陋,但我只是想了解发生了什么。
我尝试使用case语句编写它,但结果相同。
另外,当您用yy回答y / n问题时会发生什么?这些数字突然上升了吗?
#include "stdio.h"
#include "stdlib.h"
int main(void) {
int a;
int i = 1;
int b = 50;
int temp;
int last = 0;
char ans = ' ';
printf("Enter value for computer to guess (0-100): ");
scanf("%d", &a);
while (a - b) {
printf("Is the number larger than %i (y/n): ", b);
scanf("%s", &ans);
if (ans == 'y') {
temp = b;
b = b + ((b + last) / 2);
last = temp;
} else {
temp = b;
b = b - ((b + last) / 2);
last = temp;
}
i++;
}
printf("Your number was: %i. Number of guesses was: %i \n", b, i);
return 0;
}
答案 0 :(得分:3)
在您的代码中
scanf("%s",&ans);
在您超出分配的内存时调用undefined behavior。
要使用%s
格式说明符,您需要一个数组作为参数(指向数组的第一个元素的指针,具体而言)。
但是,在您的情况下,更改
scanf("%s",&ans);
到
scanf(" %c",&ans); // note the space
可能会解决这个问题。 (可选)要处理 extra 输入(如yyy
),您可以在读取每个输入后考虑清除输入缓冲区,例如
while (getchar() != '\n');
或同样。
答案 1 :(得分:0)
您可能希望计算机二进制搜索答案并有效地到达目的地。您需要跟踪您正在搜索的上边界和下边界。试试这样的事情;
int main(void){
int a;
int i = 1;
int b = 50;
int lower = 0;
int upper = 100;
char ans[256] = {0};
printf("Enter value for computer to guess (0-100): ");
scanf("%d", &a);
while (a-b) {
printf("Is the number larger than %i (y/n): ",b);
scanf("%s",ans);
if (ans[0] == 'y') {
lower = b;
b = b + ((upper-lower)/2);
printf("Last: %d - %d\n",lower, upper);
}
else {
upper = b;
b = b - ((upper-lower)/2);
printf("Last: %d - %d\n",lower, upper);
}
i++;
}
printf("Your number was: %i. Number of guesses was: %i \n",b,i);
return 0;
}
答案 2 :(得分:0)
这就是问题所在。
char ans = ' ';
...
scanf("%s",&ans);
ans
只有一个字节的内存,但您已向scanf
询问了整个字符串。所以它尽职尽责地将整个字符串填充到ans
的单个字节中。由于这包括空字节,即使输入y
或n
也会写入一个额外的字节。 yy
写入三个字节。
这会导致ans
静默溢出其内存,破坏相邻变量。这就是yy
混淆事物的原因,你将3个字节(2个字符加上一个空字节)放入1个溢出2个字节的字节中。它会使用last
字符y
覆盖121
。您可以通过一些调试printf
来看到这一点。
printf("b = %d, last = %d\n", b, last);
printf("Is the number larger than %i (y/n): ",b);
scanf("%s",&ans);
printf("b = %d, last = %d\n", b, last);
Enter value for computer to guess (0-100): 30
b = 50, last = 0
Is the number larger than 50 (y/n): yy
b = 50, last = 121
相反,您希望使用%c
来读取单个字符。但这有其自身的问题,scanf("%d", &a)
在STDIN上留下换行符,scanf("%c", &ans)
将首先读取该换行符。
这就是为什么scanf
是一个问题,应该避免,它可以在流中留下意外的输入。这里有很多关于SO推荐scanf
的答案。而是使用fgets
或getline
来读取整行,然后使用sscanf
来读取字符串。我更喜欢getline
因为它处理为你分配行内存。
这是一个如何做的草图。
char *line = NULL;
size_t linelen = 0;
printf("Enter value for computer to guess (0-100): ");
getline(&line, &linelen, stdin);
sscanf(line, "%d", &a);
printf("You entered %d\n", a);
printf("Is the number larger than %i (y/n): ",b);
getline(&line, &linelen, stdin);
sscanf(line, "%c", &ans);
switch(ans) {
case 'y':
...
break;
case 'n':
...
break;
default:
printf("I don't understand '%c', try again.\n", ans);
}
free(line);