我正在用 C 编写一个 super 简单的基于命令行的程序。这只是一个小测试,代码非常简单。所以它的目的是询问用户的姓名、数学成绩、英语成绩、计算成绩。然后计算出他们的平均成绩,并告诉他们输入的名字。是的,我知道这是一个非常简单的程序,但我还是做错了。
问题是,我的代码的一部分将首先运行,告诉用户输入他们的名字,然后一旦他们这样做并按下回车键,我的代码的其余部分将立即运行,然后停止工作。很奇怪,我就是不明白哪里出了问题。
#include <stdio.h>
int main(int argc, const char * argv[])
{
char chr;
char firstname;
int mathsmark, englishmark, computingmark, averagemark;
printf("What is your name?\n");
scanf("%c", &firstname);
printf("\n");
printf("What is your maths mark?\n");
scanf("%d", &mathsmark);
printf("\n");
printf("What is your english mark?\n");
scanf("%d", &englishmark);
printf("\n");
printf("What is your computing mark?\n");
scanf("%d", &computingmark);
printf("\n");
printf("Your name is: %c", firstname);
printf("\n");
averagemark = (mathsmark + englishmark + computingmark) / 3;
printf("%d", averagemark);
printf("\n");
chr = '\0';
while (chr != '\n') {
chr = getchar ();
}
return 0;
}
最佳答案
一个主要问题是您已将 firstname
声明为单个字符长,并且当您尝试从控制台读取名称时,您使用的是 %c
转换说明符,它从输入流中读取下一个单个字符并将其存储到 firstname
。名称的其余部分留在输入流中,以破坏剩余的 scanf
调用。
例如,如果您键入“Jacob”作为名字,那么第一个 scanf
调用会将 J
分配给 firstname
,留下 "acob\n"
在输入流中。
下一个 scanf
调用尝试将 "acob\n"
转换为整数值并将其保存到 mathsmark
,但失败了 ("acob\n"
不是有效的整数字符串)。接下来的两个 scanf
调用也会发生同样的事情。
最后一个循环
while (chr != '\n')
{
chr = getchar();
}
最终消耗了 "acob\n"
的剩余部分,其中包含换行符(因为您在键入名称后按了 Enter),导致循环和程序退出。
你如何解决这个问题?
首先,您需要将firstname
声明为char
的数组:
char firstname[SOME_SIZE] = {0};
其中 SOME_SIZE
足够大以处理您的所有情况。您需要将 scanf
调用更改为
scanf("%s", firstname);
这告诉 scanf
从输入流中读取字符直到下一个空白字符,并将结果存储到 firstname
数组中。请注意,您不需要在此处使用 &
运算符;在大多数情况下,数组类型的表达式将被转换(“衰减”)为指针类型的表达式,表达式的值将是数组中第一个元素的地址。
请注意,scanf
不是很安全,也不是很健壮。如果您输入的字符多于缓冲区的容量,scanf
会很乐意将这些额外的字符存储到数组后面的内存中,这可能会破坏一些重要的东西。您可以通过在转换说明符中使用显式字段宽度来防止这种情况,例如
scanf(*%29s", firstname);
但总的来说这很痛苦。
scanf
也不太擅长检测错误输入。如果您输入“12er”作为您的标记之一,scanf
将转换并分配 “12”
,将 “er”
留在流弄脏了下一个阅读。
scanf
返回成功赋值的次数,因此防止错误输入的一种方法是检查返回值,如下所示:
if (scanf("%d", &mathmarks) != 1)
{
printf("Bad input detected for math marks\n");
}
不幸的是,scanf
不会从流中删除坏字符;你必须自己使用 getchar
或类似的方法来完成。
关于c - 我的 SIMPLE C 程序有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12803254/