为什么以下程序陷入循环?

我写了一个练习的解决方案,要求编写一个程序,作为一个简单的“打印”计算器,并检测除零并检查未知操作符。

当输入预期的运算符时,程序按预期工作。 例如:

“100 S”打印“= 100.000000”

“2 /”打印“= 50.000000”

“10 *”打印“= 500.000000”

它还检测零除和未知运算符。

但是,当我以错误的顺序输入运算符时,如:“/ 2”或“* 10”,程序陷入循环。

如何修复此错误,以便在错误的顺序输入运算符时,它只打印“未知运算符”?

// Write a program that acts as a simple "printing" calculator #include  int main (void) { float acc, b; char operator; printf ("Begin Calculations\n"); while ( operator != 'E') { scanf ("%f %c", &b, &operator); switch (operator) { case 'S': // set accumulator case 's': acc = b; printf ("= %f\n", acc); break; case 'E': // end program case 'e': printf ("= %f\nEnd of Calculations.\n", acc); break; case '+': printf ("= %f\n", acc += b); break; case '-': printf ("= %f\n", acc -= b); break; case '*': printf ("= %f\n", acc *= b); break; case '/': if ( b == 0 ) printf ("Can't divide by zero.\n"); else printf ("= %f\n", acc /= b); break; default: printf ("Unknown operator.\n"); break; } } return 0; } 

更新 :我找到了解决方案

 while ( operator != 'E' && operator != 'e' ) { if ( scanf ("%f %c", &b, &operator ) < 2 ) { printf ("Error. You need to enter a number.\n"); break; } else { switch (operator)... 

scanf的结果是分配的字段数。 如果scanf返回0,则每次调用它时,它将为相同的格式字符串返回0 。 因为scanf推回它读取的最后一个与输入序列( %f )不匹配的字符,它会反复尝试反复转换相同的字符串。

这就是你无限循环的原因。 您可能想检查scanf的结果。 如果小于2,则输出错误。

我认为你需要让你的输入例程比scanf(显然)更强大。 例如,如果您以整行读取输入,则可以解析它们(例如,使用sscanf)以获取组件而不会弄乱输入流。

scanf正在读取,直到它可以解析浮点数。 尝试使用gets来读取字符串,然后从那里解析该字符串。

http://www.cplusplus.com/reference/clibrary/cstdio/gets/

我想退出你需要输入一个浮点+’E’(0.0 E)而不只是’E’。 这就是你要问的问题吗?

啊! 我看到你提到放下东西。 是。 scanf()永远不会检测到它。

如果你在Linux下,请检查lex和yacc(或者说flex和bison是准确的。)要做这些事情,它会好很多,你可以做得更好(支持括号,减号和加号运算符,而不是只是加减法等)

它不是“卡在一个循环中”,它正在等待运营商这条线:

  scanf ("%f %c", &b, &operator); 

承诺。 该行读取直到它收到一个浮点数,然后它读取一个运算符。 如果你先给它一个操作员,它就会忽略它。

(顺便说一下,你应该在运行之前将operator初始化为特定的东西,然后while ( operator != 'E') { ,因为众所周知, operator可能恰好以'E'开头。另外,正如Mysticial所说, operator不是C标识符的一个很好的名称,因为它在C ++中的用途。)

问题是scanf()试图读取你告诉它的内容,即浮点数和字符。 当你输入scanf返回的另一种方式,因为它不是你告诉它的格式,但不幸的是它WONT刷新缓冲区,所以while会再次进行,scanf会再次尝试读取,依此类推。

删除scanf,虽然如果这只是作业,你可以尝试:

  if (!scanf ("%f %c", &b, &operator)) { scanf ("%*[^\n]"); /* TRY to flush stdin */ printf("Incorrect input!"); incorrect_input++; continue; } else { incorrect_input = 0; } if (incorrect_input > 5) { break; /* Very simple measure to avoid getting stuck in the loop */ } 

但是,当我以错误的顺序输入运算符时,如:“/ 2”或“* 10”,程序陷入循环。

如何修复此错误,以便在错误的顺序输入运算符时,它只打印“未知运算符”?

您可能希望读取整个表达式,然后解析它的正确性。 有各种表达式表示方法(中缀 , 后缀(也称为反向抛光表示法)和前缀(也称为波兰表示法) ),这使得validation和评估它们的任务更容易。

此外,如果您已经或可以掌握由Dennis Ritchie和Brian Kernighan编写的“ The C Programming Language ”一书,请转到第4章并阅读指导您完成计算器程序设计和实现的部分。