我正在使用C编写一个简单的程序,我需要计算平均值等。我的第一个函数是提示用户参数(我假设)存储在全局变量中以便我可以使用它们在其他功能中,例如"计算MIPS"等
我的问题是,当我调用该函数来收集用户的输入时,程序会在第一次提示后停止。共有7个提示。有谁知道我做错了什么?我可以做些什么建议,以便能够询问我的所有提示和存储值?我在考虑使用while循环,但是我不确定当值全部存储在全局变量中时如何终止循环。我确定我在解决一个简单的问题。
我的节目如下:
#include <stdio.h>
#include <stdlib.h>
/* declare global var's */
int intr_class = 0;
int freq = 0;
int class1 = 0;
int cpi_1 = 0;
int class2 = 0;
int cpi_2 = 0;
int class3 = 0;
int cpi_3 = 0;
void params(){
printf("Enter the number of instruction classes: ");
scanf("%s", intr_class);
printf("Enter the frequency of the machine (MHz): ");
scanf("%s", freq);
printf("Enter CPI of class 1: ");
scanf("%s", cpi_1);
printf("Enter instruction count of class 1 (millions): ");
scanf("%s", class1);
printf("Enter CPI of class 2: ");
scanf("%s", cpi_2);
printf("Enter instruction count of class 2 (millions): ");
scanf("%s", class2);
printf("Enter CPI of class 3: ");
scanf("%s", cpi_3);
printf("Enter instruction count of class 3 (millions): ");
scanf("%s", class3);
}
int main() {
/* declare local var's */
char menuChoice[0];
/* until user quits, loop */
/* print out menu list */
printf("Menu of Options:\n______________\n"
"a) Enter Parameters\n"
"b) Calculate average CPI of a sequence of instructions\n"
"c) Calculate total execution time of a sequence of instructions\n"
"d) Calculate MIPS of a sequence of instructions\n"
"e) Quit\n\n"
"Enter selection: ");
scanf("%s", menuChoice);
/* prompt for selection & choose appropriate procedure using either a case statement of if-else if-else statements or switch scanf for character input */
while(menuChoice[0] != 'e'){
switch(menuChoice[0]){
case 'a':
params();
break;
case 'b':
//avgCPI();
break;
case 'c':
//calcExTime();
break;
case 'd':
//calcMIPS();
break;
case 'e':
exit(0);
default:
printf("Menu of Options:\n______________\na) Enter Parameters\nb) Calculate average CPI of a sequence of instructions\nc) Calculate total execution time of a sequence of instructions\nd) Calculate MIPS of a sequence of instructions\ne) Quit\n\nEnter selection: ");
}
}
return(0);
}
答案 0 :(得分:2)
您遇到UB,因为这不是使用scanf
的方式。
scanf ("%d", &variable_name)
用于整数,但就这样做,你使用错误的格式("%s"
)+传递变量值(... variable_name
)而不是变量adrress( &variable_name
请注意&amp; )
答案 1 :(得分:2)
虽然您发现错误地使用格式说明符并且需要指向scanf
中变量的指针是您的主要问题,但使用{{1>还有另一个方面还没有解决。
如果没有验证返回,您不能简单地编写scanf
来接收用户输入,以确保成功转换为发生的整数。您必须这样做才能确信scanf ("%d", &intr_class);
完全拥有有效值。 (在您尝试使用intr_class
之前,如果您有任何此类要求,您还需要确保该值在可接受的范围内)
这适用于所有用户输入,无论您使用哪种功能,但它尤其适用于intr_class
。如果响应您的提示,用户输错了怎么办?例如
scanf
然后呢?除非您检查返回,否则永远不会知道Enter the number of instruction classes: rabbits
未设置,如果未初始化,任何访问该值的尝试都是未定义行为。
此外,intr_class
在遇到错误时会停止阅读,而scanf
中仍然无法读取任何字符。那么当你尝试阅读其他内容时会发生什么?让我们考虑一个例子:
stdin
此条目是成功还是失败? (答案:失败)为什么? Enter the frequency of the machine (MHz): 800
仍然包含stdin
(每次用户按 Enter 时都会添加"rabbits\n800\n"
,并且每次输入都不会失败的唯一原因是{'\n'
1}}格式说明符使用前导空格),但'%d'
不是空格...)
因此,使用"rabbits"
进行用户输入时,必须非常小心,不仅要考虑转换是成功还是失败,还要考虑输入缓冲区中剩余的任何字符(scanf
如果你的话下一类输入不会消耗前导空格,也不会消耗转换失败后输入缓冲区中剩余的任何字符。
您管理此方法的一种方法是在每次调用'\n'
后手动删除stdin
中保留的所有字符。 (注意:应该检查返回值是否也不是scanf
)。在您致电EOF
并检查返回不是scanf
之后,您只需调用一个简单的函数来读取并丢弃所有剩余的字符,例如:
EOF
避免使用全局变量以及使用/* function to empty remaining characters in stdin before next input
* to help avoid the pitfalls associated with using scanf for user input.
*/
void emptystdin()
{
int c = getchar();
for (; c != '\n' && c != EOF; c = getchar()) {}
}
保存所有参数的非常好的建议也应该得到解决。如果你定义一个struct(称之为struct
),在struct parameters_t
中创建并声明它的一个实例(比如一个叫main()
),那么你需要做的就是传递地址将parameters
添加到parameters
函数中,并填写params()
中的值。您只需更改函数声明,以包含指向结构类型的指针params
,然后在void params (stuct parameters_t *p)
函数中提示并填充p->intr_class
等。
为了简单起见(并且不必一直为类型键入params
,您只需创建一个struct parameters_t
(别名),将typedef
定义为{的别名{1}}减少打字。
您还应该将返回类型从parameters_t
更改为可以在struct parameters_t
在一个简短的例子中将这些部分放在一起,你可以做类似以下的事情:
void
示例使用/输出
params
看看结束了。当你刚刚学习时,有很多东西需要消化。如果您有任何问题,请发表评论,我很乐意进一步提供帮助。
答案 2 :(得分:1)
https://www.tutorialspoint.com/c_standard_library/c_function_scanf.htm
这应该可以帮助您了解scanf的工作原理。正如另外两个人所说,你应该使用%d
而不是%s
,并且在变量之前需要一个&符号。如果你已经学过指针,你就会知道为什么你需要&符号,如果不是现在不担心它,你以后会学到它。
我给你的链接也为你提供了其他数据类型的%命令。大多数数据类型都有不同的字母,例如%s
用于字符串(字符数组),而您将%lf
用于双字母。
希望这有帮助!
答案 3 :(得分:0)
对整数使用scanf("%d",&VariableName)
,对字符数组(字符串)使用scanf(" %s",&arrCHar)
。
此外,您必须在调用函数之前声明函数原型。