试图学习C语言,但我';我遇到了奇怪的虫子(至少对我来说)
我正在努力自学C语言,我以前在Matlab和Python方面有一些经验。我正在尝试创建一个简单的猜测游戏,在这个游戏中,你给出一个数字,计算机猜测一个数字,你必须告诉它是高还是低。我已经写了一些代码,但它就是不起作用(例如,试着输入30)。代码很难看,但我只是想了解发生了什么 我试着用case语句来写,但结果是一样的 还有,当你用yy回答y/n问题时发生了什么?数字突然上升试图学习C语言,但我';我遇到了奇怪的虫子(至少对我来说),c,char,scanf,C,Char,Scanf,我正在努力自学C语言,我以前在Matlab和Python方面有一些经验。我正在尝试创建一个简单的猜测游戏,在这个游戏中,你给出一个数字,计算机猜测一个数字,你必须告诉它是高还是低。我已经写了一些代码,但它就是不起作用(例如,试着输入30)。代码很难看,但我只是想了解发生了什么 我试着用case语句来写,但结果是一样的 还有,当你用yy回答y/n问题时发生了什么?数字突然上升 #include "stdio.h" #include "stdlib.h" int main(void) {
#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;
}
在代码中
scanf("%s",&ans);
在超出分配的内存时调用
要使用%s
格式说明符,您需要一个数组作为参数(具体来说,指向数组的第一个元素的指针)
然而,在你的情况下,改变
scanf("%s",&ans);
到
有可能解决这个问题。可选地,为了处理额外的输入,(如<代码> yyy ),您可以考虑在读取每个输入之后清除输入缓冲区,如
while (getchar() != '\n');
或者类似地。在代码中
scanf("%s",&ans);
在超出分配的内存时调用
要使用%s
格式说明符,您需要一个数组作为参数(具体来说,指向数组的第一个元素的指针)
然而,在你的情况下,改变
scanf("%s",&ans);
到
有可能解决这个问题。可选地,为了处理额外的输入,(如<代码> yyy ),您可以考虑在读取每个输入之后清除输入缓冲区,如
while (getchar() != '\n');
或者类似地。您可能希望计算机对答案进行二进制搜索并高效地到达那里。您需要跟踪搜索的上下边界。试试这样的东西
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;
}
您可能希望计算机对答案进行二进制搜索并高效地到达那里。您需要跟踪搜索的上下边界。试试这样的东西
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;
}
这就是问题所在
char ans = ' ';
...
scanf("%s",&ans);
ans
只有一个字节的内存,但您要求scanf
获取整个字符串。因此,它会尽职尽责地将整个字符串填充到ans
的单个字节中。由于这包括一个空字节,因此即使输入y
或n
也会写入一个额外的字节yy
写入三个字节
这会导致ans
悄悄地溢出其内存,破坏相邻变量。这就是为什么yy
会把事情弄得一团糟,你把3个字节(2个字符加上一个空字节)放到一个分配的字节中,溢出2个字节。它用字符y
覆盖last
,该字符是编号121
。您可以通过一些调试printf
s看到这一点
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
是一个问题,应该避免,因为它会在流中留下意外的输入。这里有很多答案,因此建议不要使用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);
这就是问题所在
char ans = ' ';
...
scanf("%s",&ans);
ans
只有一个字节的内存,但您要求scanf
获取整个字符串。因此,它会尽职尽责地将整个字符串填充到ans
的单个字节中。由于这包括一个空字节,因此即使输入y
或n
也会写入一个额外的字节yy
写入三个字节
这会导致ans
悄悄地溢出其内存,破坏相邻变量。这就是为什么yy
会把事情弄得一团糟,你把3个字节(2个字符加上一个空字节)放到一个分配的字节中,溢出2个字节。它用字符y
覆盖last
,该字符是编号121
。您可以通过一些调试printf
s看到这一点
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
是一个问题,应该避免,因为它会在流中留下意外的输入。这里有很多答案,因此建议不要使用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);
char-ans='''''。。。scanf(“%s”、&ans)代码>-->scanf(“%c”和&ans)
如果输入yy
,则第一个y
将由第一个scanf
读取,然后下次转到scanf
时,将读取第二个y
。(scanf的意思是“从输入缓冲区提取字符并仅在缓冲区为空时等待”,而不是“等待输入”)注意,您应该使用而不是“包括”来包括非用户定义的库(例如:#包括)。注意,您也将使enter键不被处理。您需要使用“%s”(注意前导空格)以确保已使用空格。@DavidHoelzer%s
已使用前导空格char ans='''''。。。scanf(“%s”、&ans)代码>-->scanf(“%c”和&ans)
如果输入yy
,则第一个y
将由第一个scanf
读取,然后下次转到scanf
时,将读取第二个y
。(scanf表示“从输入缓冲区和wai中提取字符