Программа-калькулятор, в которой вычисления могут храниться в переменной

#c

#c

Вопрос:

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

 a = 1   2
b = 6 - 5
c = 20 * a
d = a / b
exit
  

Тогда вывод должен быть:

 3
1
60
3
  

Посмотрите, как программа сохраняет значение a = 1 2 as a = 3 . Затем пользователь может свободно использовать a в другом вычислении. Например, 20 * a . С a = 3 этого момента 20 * a должно быть равно 60 .

Однако в моей программе есть проблема. Если я введу следующее:

 a = 1   2
b = a   3
c = a   b
d = 20 * a
  

Затем я получаю проблему с выводом для строк 3 и 4. Результат, который я получаю, выглядит следующим образом:

 3
6
55

  

Как вы можете видеть, он говорит, что a b = 55 , когда это необходимо 9 . И когда я пытаюсь умножить 20 * a , я даже не получаю результат. Я предполагаю, что для этой последней строки нет выходных данных, потому что она даже не вводит случай умножения в коде. Но понятия не имею, откуда 55 берется.

Вот мой код (я знаю, что он грязный, но это потому, что я перепробовал все, чтобы исправить это, и мне не повезло):

 #include <iostream>
#include <cmath>
#include <stdlib.h>
#include <sstream>
#include <string>

using namespace std;

    char op='a';
    double num1, num2, num3=0;
    int sub1, sub2=0;
    std::string temp;

int main() {

    double var[26];
    
    bool flag = false;
    
    char eq[5];
    
    while (true) {
        
        getline(cin, temp);
        
        if (temp.compare("exit") == 0) {
            break;
        }
        
        std::stringstream os(temp);
        
        int count = 0;
        
        for(charamp; c : temp) {
            if(c != ' '){
                eq[count] = c;
                count  ;
            }
        }
        
        /* for(std::string::size_type i = 0; i < temp.size();   i){
            if(temp[i] != ' '){
                eq[count] = temp[i];
                count  ;
            }
        }
         */
    
        
        if(eq[0] >= 97 amp;amp; eq[0] <= 122){
            num1 = eq[2] - 48;
            op = eq[3];
            num2 = eq[4] - 48;
            flag = true;
        }
        else{
            num1 = eq[0] - 48;
            op = eq[1];
            num2 = eq[2] - 48;
        }
        
        
        
        switch (op) {
        case ' ':
            if(flag == true){
                var[eq[0] - 97] = num1   num2;
            }
            if((int)num1 >= 48 amp;amp; (int)num1 <= 57){
                num1 = var[(int)num1   48 - 97];
            }
            if((int)num2 >= 48 amp;amp; (int)num2 <= 57){
                num2 = var[(int)num2   48 - 97];
            }
            cout << num1   num2 << endl;
            break;

        case '-':
            if(flag == true){
                var[eq[0] - 97] = num1 - num2;
            }
            if((int)num1 >= 48 amp;amp; (int)num1 <= 57){
                num1 = var[(int)num1   48- 97];
            }
            if((int)num2 >= 48 amp;amp; (int)num2 <= 57){
                num2 = var[(int)num2   48- 97];
            }
            cout << num1 - num2 << endl;
            break;

        case '*':
            if(flag == true){
                var[eq[0] - 97] = num1 * num2;
            }
            if((int)num1 >= 48 amp;amp; (int)num1 <= 57){
                num1 = var[(int)num1   48- 97];
            }
            if((int)num2 >= 48 amp;amp; (int)num2 <= 57){
                num2 = var[(int)num2   48- 97];
            }
            cout << num1 * num2 << endl;
            break;

        case '/':
            if(flag == true){
                var[eq[0] - 97] = num1 / num2;
            }
            if((int)num1 >= 48 amp;amp; (int)num1 <= 57){
                num1 = var[(int)num1   48- 97];
            }
            if((int)num2 >= 48 amp;amp; (int)num2 <= 57){
                num2 = var[(int)num2   48- 97];
            }
            cout << num1 / num2 << endl;
            break;

        case '%':
            sub1 = num1;
            sub2 = num2;
            if(flag == true){
                var[eq[0] - 97] = sub1 % sub2;
            }
            if((int)num1 >= 48 amp;amp; (int)num1 <= 57){
                num1 = var[(int)num1   48- 97];
            }
            if((int)num2 >= 48 amp;amp; (int)num2 <= 57){
                num2 = var[(int)num2   48- 97];
            }
            cout << sub1 % sub2 << endl;
            break;

        case '^':
            if(flag == true){
                var[eq[0] - 97] = pow(num1, num2);
            }
            if((int)num1 >= 48 amp;amp; (int)num1 <= 57){
                num1 = var[(int)num1   48- 97];
            }
            if((int)num2 >= 48 amp;amp; (int)num2 <= 57){
                num2 = var[(int)num2   48- 97];
            }
            cout << pow(num1, num2) << endl;
            break;
        }
    }

    return 0;
}
  

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

Комментарии:

1. небольшой совет. if(флаг == true) -> просто измените на if(флаг). Намного чище.

2. кроме того … в вашем коде огромное количество магических чисел … что очень затрудняет понимание того, что вы делаете. Что такое «48» / «97» / «57»? Вы должны использовать фактический символ. например, ‘a’ для представления 97

3. @Ilan Keshet Они должны были представлять символы через их ASCII. Могу ли я просто поменять их местами с реальными символами?

4. ДА. если вы напрямую заменяете их ascii, это лучшая практика

5. Micronag: C автоматически преобразует его для вас в значение ascii int . Хорошо… Не совсем. Он преобразует символ в значение символа в кодировке символов, используемой компилятором, которая, вероятно, является ASCII, но стандарт C не требует кодировки. Это еще одна причина не использовать здесь магические числа. 'a' всегда 'a' , но 'a' не всегда 97.

Ответ №1:

Загрузка значений из вашего var массива должна быть выполнена до выполнения дальнейших операций, поэтому сразу после синтаксического анализа строки загрузите их следующим образом

 if(eq[0] >= 97 amp;amp; eq[0] <= 122){
    num1 = eq[2] - 48;
    op = eq[3];
    num2 = eq[4] - 48;
    flag = true;
}
else{
    num1 = eq[0] - 48;
    op = eq[1];
    num2 = eq[2] - 48;
}

if((int)num1 >= 48 amp;amp; (int)num1 <= 57){
        num1 = var[(int)num1   48 - 97];
}

if((int)num2 >= 48 amp;amp; (int)num2 <= 57){
        num2 = var[(int)num2   48 - 97];
}
  

Внутри вашего блока switch вы можете просто напрямую выполнить операцию, например. для ‘ ‘ регистр :

 case ' ':
        
    if(flag == true){
       var[eq[0] - 97] = num1   num2;
    }
        
    cout << num1   num2 << endl;
    break;
  

Комментарии:

1. Большое вам спасибо. Я действительно ценю это. Но почему код прерывается, когда я пытаюсь умножить? Например, если я сделаю a = 1 2, а затем c = 20 * a, это не сработает. Как вы упоминали ранее, некоторые операции деления также не работают.

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

3. Я думаю, я знаю, что происходит. Когда я загружаю подобные переменные num1 = eq[2] - 48; , я присваиваю только то, что находится внутри eq[2] num1 . Однако eq[2] правильна ли однозначная цифра? Поэтому, если я ввожу двузначное число, например 20, eq[2] оно содержит не обе цифры, а только одну.

4. Потому что я попытался сделать b = 3 * 5 , что означало b = 15 бы, а затем я сделал c = b 10 , и ответ вышел в 16, а не в 26. Поэтому я думаю, что он считывает только первую цифру 10, которая будет равна 1. Он не считывает обе цифры 1 и 0, чтобы получить 10. И опять же, я думаю, это потому num2 , что загружается как num2 = eq[4] - 48; where eq[4 ] именно там, где находится 1 из 10.

5. Довольно много. Вы можете перебирать строку вручную и постепенно * = 10 старого значения и добавлять новое (или просто добавлять новое, деленное на коэффициент progressive / = 10, как только вы встретите десятичную точку), но вам лучше просто использовать надлежащую функциональность синтаксического анализа, встроенную в STL