Почему следующая программа застряла в цикле? - PullRequest
0 голосов
/ 05 января 2012

Я написал решение для упражнения, в котором предлагается написать программу, которая действует как простой «печатный» калькулятор, а также обнаруживает деление на ноль и проверяет неизвестные операторы.

Программа работает, как предполагалось, когда вводятся ожидаемые операторы. Например:

"100 S" печатает "= 100.000000"

"2 /" prints "= 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 ]

1 голос
/ 05 января 2012

Результатом scanf является количество назначенных полей.Если scanf возвращает 0, он будет возвращать 0 для одной и той же строки формата каждый раз, когда вы ее вызываете.Поскольку scanf возвращает последний прочитанный символ, который не соответствует входной последовательности (%f), он будет неоднократно пытаться преобразовывать одну и ту же строку снова и снова.

Именно поэтому вы выполняете бесконечный цикл.Возможно, вы захотите проверить результат scanf.Если оно меньше 2, выдается ошибка.

0 голосов
/ 05 января 2012

Однако, когда я вводю операторы в неправильном порядке, например: "/ 2" или "* 10", программа застревает в цикле.

Как мне исправить эту ошибку, чтобычто когда операторы вводятся в неправильном порядке, он просто печатает «Неизвестный оператор»?

Возможно, вы захотите прочитать все выражение, а затем проанализировать его на предмет правильности.Существуют различные методы обозначения выражений ( infix , postfix (также известный как обратная польская запись) и prefix (также известный как польская запись) ), которые делают задачуоблегчить их проверку и оценку.

Также, если у вас есть или вы можете получить книгу " Язык программирования C * ", написанную Деннисом Ричи и Брайаном Керниганом, обратитесь к главе 4 и прочитайтераздел, в котором рассказывается о разработке и реализации программы калькулятора.

0 голосов
/ 05 января 2012

Проблема в том, что scanf () пытается прочитать то, что вы ему сказали, то есть число с плавающей запятой и символ.Когда вы печатаете наоборот, scanf возвращается, потому что это не тот формат, который вы ему сказали, но, к сожалению, он НЕ БУДЕТ очищать буфер, поэтому время снова будет идти, и scanf попытается снова прочитать и так далее.

Drop 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 */
  }
0 голосов
/ 05 января 2012

Это не «застрял в цикле», это ждет оператора, что эта строка:

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

обещания. Эта строка читает, пока не получит число с плавающей запятой, а затем читает оператор. Если вы сначала дадите ему оператор, он просто проигнорирует его.

(Между прочим, вы должны инициализировать operator чем-то конкретным, прежде чем перейти к строке while ( operator != 'E') {, потому что, насколько вы знаете, operator может начаться как 'E'. Также, как говорит Mysticial , operator не является хорошим именем для идентификатора C, поскольку он используется в C ++.)

0 голосов
/ 05 января 2012

Я думаю, что для выхода вам нужно ввести число с плавающей запятой + «E» (0,0 E), а не просто «E». Это то, о чем ты спрашиваешь?

Ах! Я вижу, вы упомянули о том, что все ставится задом наперед. Да. scanf () никогда этого не обнаружит.

Если вы работаете в Linux, посмотрите lex и yacc (или, если быть точным, flex и bison). Чтобы делать такие вещи, это намного лучше, и вы можете сделать вещи намного лучше (поддержка скобок, минус и плюс оператор, а не просто сложение и вычитание и т. д.)

0 голосов
/ 05 января 2012

scanf читает, пока не сможет проанализировать число с плавающей запятой. Попробуйте использовать get для чтения строки, а затем проанализируйте эту строку.

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

0 голосов
/ 05 января 2012

Я думаю, вам нужно сделать вашу процедуру ввода более надежной, чем scanf (по-видимому). Например, если вы читаете входные данные целыми строками, вы можете проанализировать их (скажем, используя sscanf), чтобы получить компоненты без путаницы во входном потоке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...