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

时间:2012-01-05 01:23:46

标签: c while-loop

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

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

“100 S”打印“= 100.000000”

“2 /”打印“= 50.000000”

“10 *”打印“= 500.000000”

它还可以检测零除以及未知运算符。

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

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

// Write a program that acts as a simple "printing" calculator

#include <stdio.h>

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)...

7 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

我想退出你需要输入一个浮点+'E'(0.0 E)而不只是'E'。那会是你要问的吗?

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

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

答案 4 :(得分:0)

它不是“卡在一个循环中”,它正在等待操作员这一行:

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

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

(顺便说一句,您应该在operator之前将while ( operator != 'E') {初始化为特定内容,因为据您所知,operator可能恰好以{{1}开头另外,正如Mysticial所说,'E'不是C标识符的好名字,因为它在C ++中的用途。)

答案 5 :(得分:0)

问题是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 */
  }

答案 6 :(得分:0)

  

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

     

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

您可能想要读取整个表达式,然后解析它是否正确。有各种表达式表示方法(infixpostfix (also known as reverse polish notation)prefix (otherwise known as polish notation)),这使得验证和评估它们的任务变得更加容易。

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