Как просканировать ряд чисел и операторов, используя цикл while? - PullRequest
0 голосов
/ 24 декабря 2011

У меня есть ввод stdin, например, «33 44 55 + 66 * + =» (т. Е. Обратная польская запись , RPN), и я использую следующие коды для его анализа.Но scanf ("% d") читает '+' и отбрасывает его, как отменить оператор и заставить его читать scanf ("% c")?Каков наилучший способ решения проблемы.Спасибо.

while ((reta = scanf("%d", &operand)) == 1 || (retb = scanf(" %c ", &operator)) == 1) {
  if (reta == 1) push(exprStack, operand);
  else if (retb == 1) {
    operand = pop(exprStack);
    /* function pmtd executes some basic calculation, i.e., plus, minus, times and divide */
    push(exprStack, pmtd(operator, pop(exprStack), operand));
  }
} 

Ответы [ 4 ]

1 голос
/ 24 декабря 2011

Лучший способ решить эту проблему - использовать генератор синтаксического анализатора, такой как ANTLR . Это займет немного времени, если вы не использовали его раньше, но есть примеры и учебные пособия для арифметических вычислений, например, то, что вы хотите сделать, и ANTLR генерирует код на C, который будет выполнять правильную и правильную работу синтаксического анализа в соответствии с определяемая вами грамматика (в отличие от рукописного кода синтаксического анализа, который обычно имеет причуды, если не явные ошибки).

Если вы используете ANTLR, он может анализировать входные данные в "абстрактном синтаксическом дереве" или AST. Если вы тщательно определите свою грамматику, этот AST может быть пройден простой рекурсией для выполнения вычислений, один за другим, что делает этот вид оценщика довольно простым и надежным.

0 голосов
/ 25 декабря 2011

Я рекомендую вам использовать Bison (генератор парсера).
В руководстве приведен прекрасный пример калькулятора RPN.Этот пример используется во всем руководстве.

http://www.gnu.org/software/bison/manual/html_node/RPN-Calc.html#RPN-Calc

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

0 голосов
/ 25 декабря 2011

Сильное предложение:

  1. Получить строку с помощью fgets (). Есть много, много веских причин для этого.

  2. Как только вы получили строку, попробуйте ее проанализировать с помощью sscanf (), если хотите.

    "sscanf ()" это то же самое, что и "scanf" - за исключением того, что он работает со строками в памяти (вместо непосредственного чтения стандартного ввода).

  3. Или используйте strtok (), если хотите. Или напишите свои собственные функции для анализа и интерпретации строки.

  4. Я подозреваю, что sscanf () слишком ограничен для ваших целей. Но если вы хотите попробовать - если только из любопытства - круто. Просто сделайте себе одолжение и используйте «fgets ()», чтобы сначала получить информацию от stdin.

ИМХО .. PSM

0 голосов
/ 25 декабря 2011

Невозможно отключить по scanf. снова используйте sscanf для той же точки или scanf ("% s") -> проверьте строку и конвертируйте.

* 1003 Е.Г. *

#include <stdio.h>
#include <stdlib.h>

int main(){
    int reta=0,retb=0;
    int operand;
    char operator;
    char token[16];

    token[15] = '\0';
    while (0 != scanf(" %15s", token)) {
        if(1 == (reta = sscanf(token, "%d", &operand)))
            printf("operand : %d\n", operand);
        else if(1 == (retb = sscanf(token, "%c", &operator))){
            printf("operator : %c\n", operator);
            if(operator == '=') break;
        } else
            printf("else\n");
        reta=retb=0;
    }
    return 0;
}
...