Проблема с калькулятором с++

Если ввести 5*2+1 = 11 (нормально), если со скобками (5*2)+1 = 11 (тоже нормально), а если 5*(2+1) = 0. Что не так?

И если вводить числа и любое выражение через пробел тоже выдаёт 0 подскажите что не так

#include <iostream>

using namespace std;
 
float num()
{
    int result = 0;
    for (;; )
    {
        char c = cin.get();
        if (c >= '0' && c <= '9')
            result = result * 10 + c - '0';
        else
        {
            cin.putback(c);
            return result;
        }
    }
}
 
 
float plusMinus();
 
float skobki()
{
    char c = cin.get();
    if (c == '(')
    {
        float x = plusMinus();
        cin.get();
        return x;
    }
    else
    {
        cin.putback(c);
        return num();
    }
}
 
 
float umnojDel()
{
    float x = skobki();
    for (;; )
    {
        char c = cin.get();
        switch (c)
        {
        case '*':
            x *= num();
            break;
        case '/':
            x /= num();
            break;
        default:
            cin.putback(c);
            return x;
        }
    }
}
 
float plusMinus()
{
    float x = umnojDel();
    for (;; )
    {
        char c = cin.get();
        switch (c)
        {
        case '+':
            x += umnojDel();
            break;
        case '-':
            x -= umnojDel();
            break;
        default:
            cin.putback(c);
            return x;
        }
    }
}
 
 
int main()
{
    cout << "Calculator: ";
    float result = plusMinus();
    cout << "Result: " << result << endl;
}

Ответы (1 шт):

Автор решения: KoVadim

Конечно не будет работать - Вы же пробелы никак не обрабатываете. Давайте будем их обрабатывать. Для начала добавим код туда, где скобочки обрабатываем, всего одну строку

float skobki()
{
    char c = cin.get();
    while (c == ' ') {c = cin.get();} // вот эту
    if (c == '(')
    {
        float x = plusMinus();

И ещё нужно пробелы пропускать в умножении

    case '*':
        x *= num();
        break;
    case '/':
        x /= num();
        break;
    case ' ': // вот эта и следующая строка
      break;
    default:

и при чтении числа тоже, но тут три строки:

float num()
{
    char c = cin.get();
    while (c == ' ') {c = cin.get();}
    cin.putback(c);

и все, теперь все работает с пробелами.

В целом, при написании такого парсера обычно пишется функция skipspace(), которую вставляют почти везде (в Вашей реализации парсера).

А вот такое 5*(2+1) пока ещё не работает. Почему? да просто у Вас такая грамматика - первым множителем может быть выражение в скобках, а последующие - только числом. Поправим

float umnojDel()
{
    float x = skobki();
    for (;; )
    {
        char c = cin.get();
        switch (c)
        {
        case '*':
            x *= skobki();
            break;
        case '/':
            x /= skobki();
            break;
        case ' ':
          break;
        default:
            cin.putback(c);
            return x;
        }
    }
}

Теперь даже вложенные скобочки работают. Правда проверки на правильность выражения все ещё нет, но это тема отдельной большой книги, например, книги дракона.

→ Ссылка