我正在制作一个输入三个数字的程序,然后计算一些不同的东西(每个东西都必须是它自己的功能)。该程序开始告诉用户他们的选择并等待他们的输入。在任何情况执行后,程序将再次打印菜单,除非它将使用默认情况,然后它将打印菜单并要求输入。任何帮助将不胜感激。
#include <stdio.h>
#include <stdlib.h>
void greeting() {
printf("Welcome to Dr. Computer's Mathatorium \n"); // this is a seperate function just because
printf("Remember to use capital letters when selecting \n");
}
//This getNum function is used to the get the number
int getNum ()
{
int a;
printf("Enter your first integer:"); //tells user to input number
scanf("%i", &a); //input
return a;
}
// gets the sum of the numbers
int getSum (int f, int g, int h)
{
return (f + g + h);
}
// gets the sum of the numbers
int getPro (int f, int g, int h)
{
return (f * g * h);
}
// gets the sum of the numbers
int getAvg (int f, int g, int h)
{
return (f * g * h)/3;
}
// gets the sum of the numbers
int getLow (int f, int g, int h)
{
return (f + g + h); //NEEDS ADJUSTING
}
main()
{
int first, second, third, sum, pro, avg, low;
char choice;
greeting ();
do {
printf("Main Menu\n");
printf("A) Get Three Integers\n");
printf("B) Display the Sum\n");
printf("C) Display the Product\n");
printf("D) Display the Average\n");
printf("E) Display the lowest\n");
printf("F) Quit\n");
scanf("%c", &choice);
//here comes the switches to route the choices
switch(choice){
case 'A':
first = getNum ();
second = getNum ();
third = getNum ();
printf("first is: %i\n", first);
printf("second is: %i\n", second);
printf("third is: %i\n", third);
break;
case 'B':
sum = getSum (first, second, third);
printf("sum is: %i\n", sum);
break;
case 'C':
pro = getPro (first, second, third);
printf("product is: %i\n", pro);
break;
case 'D':
avg = getAvg (first, second, third);
printf("average is: %i\n", avg);
break;
case 'E':
avg = getAvg (first, second, third); //NOT DONE YET
printf("average is: %i\n", avg); //REMEMBER TO FIX
break;
default:
printf("INVALID CHOICE!\n");
break;
}
} while (choice != 'F');
return 0;
}
试试这段代码,这是你的程序,有一些变化:
#include <stdio.h>
void greeting() {
printf("Welcome to Dr. Computer's Mathatorium \n"); // this is a seperate function just because
printf("Remember to use capital letters when selecting \n");
}
int getNum () //This getNum function is used to the get the number
{
int a;
printf("Enter your first integer:"); //tells user to input number
scanf("%i", &a); //input
return a;
}
int getSum (int f, int g, int h) // gets the sum of the numbers
{ return (f + g + h);
}
int getPro (int f, int g, int h) // gets the sum of the numbers
{ return (f * g * h);
}
int getAvg (int f, int g, int h) // gets the sum of the numbers
{ return (f * g * h)/3;
}
int getLow (int f, int g, int h) // gets the sum of the numbers
{ return (f + g + h); //NEEDS ADJUSTING
}
int main(void)
{
int first, second, third, sum, pro, avg;
char choice;
greeting ();
do {
printf("Main Menu\n");
printf("A) Get Three Integers\n");
printf("B) Display the Sum\n");
printf("C) Display the Product\n");
printf("D) Display the Average\n");
printf("E) Display the lowest\n");
printf("F) Quit\n");
fseek(stdin,0,SEEK_END); // change
choice = getc(stdin); // change
//scanf("%c", &choice);
//here comes the switches to route the choices
switch(choice){
case 'A':
case 'a': // change
first = getNum ();
second = getNum ();
third = getNum ();
printf("first is: %i\n", first);
printf("second is: %i\n", second);
printf("third is: %i\n", third);
break;
case 'B':
case 'b': // change
sum = getSum (first, second, third);
printf("sum is: %i\n", sum);
break;
case 'C':
case 'c': // change
pro = getPro (first, second, third);
printf("product is: %i\n", pro);
break;
case 'D':
case 'd': // change
avg = getAvg (first, second, third);
printf("average is: %i\n", avg);
break;
case 'E':
case 'e': // change
avg = getAvg (first, second, third); //NOT DONE YET
printf("average is: %i\n", avg); //REMEMBER TO FIX
break;
default:
printf("INVALID CHOICE!\n");
break;
}
} while (choice != 'F' && choice != 'f'); // change
return 0;
}
有很多方法可以解决这个问题。这是一个适用于这种有限环境的解决方案 - 将第58行更改为:
scanf(" %c", &choice);
我在%
说明符之前添加了一个空格。这意味着“跳过stdin中的任何空白字符,然后读取下一个非空白字符并将其存储在'choice'变量的内存地址中”。
值得指出的是,选择'F'将导致程序打印“INVALID CHOICE!”在结束之前。这是因为没有'F'的开关大小写,所以它在退出do-while循环之前落到了默认的无效大小写。
我们来做桌面检查。假设你有一个输入流,例如:
{ 'A', '\n', '1', '\n', '2', '\n', '3', '\n', 'B', '\n', 'F', '\n', '\0' }
您会注意到每个输入格式正确 - 只有一个字符后跟换行符,并且该流在终止字符之前有一个换行符。如果你想处理未格式化的输入,我建议不要使用scanf()
开头,因为scanf
代表扫描格式化的字符串。
原始海报代码中输入流的第一个读数是第58行的声明:
scanf("%c", &choice);
这意味着“从stdin中读取下一个字符并将其存储在'choice'变量的内存地址中”。
在该行之后,choice ='A',您的输入流如下所示:
{ '\n', '1', '\n', '2', '\n', '3', '\n', 'B', '\n', 'F', '\n', '\0' }
如果我们遵循代码,则switch语句在'A'的情况下停止,下一次读取在第63行的getNum()
函数调用期间。这跳转到第15行,我们看到语句:
scanf("%i", &a); //input
这意味着“从stdin读取下一个整数并将其存储在'a'变量的内存地址”。当我说“读取下一个整数”时,我的意思是“跳过任何空格字符,然后读取'+'或' - '符号(如果存在),然后继续读取字符,直到找到与字符集不匹配的字符{'0 ','1','2','3','4','5','6','7','8','9'},然后转换为整数“[1]。
如果我们遵循这个半复杂的过程,我们跳过'\ n',因为它是一个空白字符,读取'1',然后停止并将'1'字符转换为数值1
并将其存储在变量a
中。
所以现在输入流看起来像这样:
{ '\n', '2', '\n', '3', '\n', 'B', '\n', 'F', '\n', '\0' }
main()
函数中的局部变量是:
choice = 'A'
first = 1
接下来我们看到getNum()
在第64和65行被调用了两次。继续关注,你将有一个这样的输入流:
{ '\n', 'B', '\n', 'F', '\n', '\0' }
而main函数中的局部变量如下:
choice = 'A'
first = 1
second = 2
third = 3
下一个读取是在我们循环回到第58行之后:
scanf("%c", &choice);
如果你还记得,这意味着“从stdin中读取下一个字符并将其存储在'choice'变量的内存地址中”。下一个字符是'\n'
,因此在此行之后输入流如下所示:
{ 'B', '\n', 'F', '\n', '\0' }
main()
函数的局部变量如下:
choice = '\n'
first = 1
second = 2
third = 3
现在我们遇到了问题!如果我们按照代码,switch语句在case default
停止,程序打印“INVALID CHOICE!”。我们不想在第58行读取换行符,而是跳过任何空格,然后读取第一个字符。请参阅上面的一个解决方案
[1] ISO / IEC9899-1990§7.9.6.2(第135-136页)