【问题标题】:calculator in C - input a whole formulaC中的计算器 - 输入整个公式
【发布时间】:2023-03-07 09:40:01
【问题描述】:

我正在尝试用 C 编写一个计算器,并希望制作一个可以计算多个输入的计算器,例如 (5*9 + 1 -2)。这些输入可以是完全随机的,我不知道该怎么做。

我知道如何初始化一个变量,并要求用户输入一个数字等等,但如果用户想将 50 个随机数相加,那计算器将无法做到这一点。

希望您能提供帮助,或分享一些技巧

谢谢!

【问题讨论】:

  • 到目前为止你尝试了什么?
  • 您需要实现一些算法才能正确执行此操作,请参阅answer 以获取有关从何处开始的一些提示
  • 要计算任意表达式,您需要一些数据结构,如堆栈或表达式树来存储表达式节点,然后遍历它们并计算。您应该首先尝试计算不带括号的表达式,然后您需要使用空格和数学运算符号 (+ - * /) 作为分隔符来拆分字符串。然后根据当前操作,您只需将当前值添加到总和或使用乘数/除数修改它。
  • @L.Butz 我不知道从哪里开始。我想将输入保存到一个字符串中,然后使用 for 循环遍历该字符串并取出每个值和算术符号,但我不知道该去哪里

标签: c calculator


【解决方案1】:

这不是一个完整的解决方案,但嘿,它是…… 试试这个代码:

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

#define MAX_SIZE (1000)

static char tempNumStr[50] = {0};
static double parsedDoubleArr[5] = {0};
static char parsedOperators[5] = {0};

void flushTempArr(char tmpArr[50]){
    for(int i=0; i< 50; i++)
        tmpArr[i]  = 0 ;
}

int tempNumStrIterator=0;

int parsedDoubleArrIterator=0;
int parsedOperatorsIterator=0;


int main(void)
{


    char operator;
    char sourceStr[] = "(17.5 + 8)";

    for(int i = 0; sourceStr[i] != '\0'; ++i) /*iterate over string till \0 */
    {
        if (IsDigit(sourceStr[i]))
        {
            while(sourceStr[i] != '\0' && IsDigit(sourceStr[i]))
            {
                tempNumStr[tempNumStrIterator++] = sourceStr[i];
                ++i;
            }

            sscanf(tempNumStr, "%lf", &parsedDoubleArr[parsedDoubleArrIterator++]);
            flushTempArr(tempNumStr);
            tempNumStrIterator = 0;
        }

        if (IsCalcOperator(sourceStr[i]))
        {
            parsedOperators[parsedOperatorsIterator++] = sourceStr[i];
        }

        else if (IsBracket(sourceStr[i]))
        {
            //do something
            continue;
        }
    }

    //do what you want with parsedDoubleArr and parsedOperators

    return EXIT_SUCCESS;
}

【讨论】:

    【解决方案2】:

    为了做到这一点,您需要阅读整行(应该不会太难), 那么你需要解析它并将其存储到一些数据结构中。

    我知道有两种存储和使用它的方法:

    • 第一个:容易做,好用,不美观也不快: 一个双链表,每个链接包含一个运算符一个数字和一个优先级,如果它是一个运算符(如果你想要更简洁的东西,你可以使用枚举+联合):

      struct list {
          struct list *prev;
          struct list *next;
          char operator;
          int number;
          unsigned int priority;
      }
      

      你遍历你的字符串并应用一个简单的优先级算法(伪代码):

      var priority = 0
      var array = cut string // ["5", "+", "3", "*", "(", "6", "-", "2", ")"]
      
      check string // verify the string is correct
      
      for each element of array :
          if (element is number)
              store in list
      
          else if (element is operator)
              store in list
              if (element is '*' or '/' or '%')
                  set his priority to priority + 1
              else
                  set his priority to priority
      
          else if (element is open parenthesis)
              priority += 2
      
          else if (element is close parenthesis)
              priority -= 2
      

      例如:

      字符串:

      5 + 3 * (6 - 2) - 1
      

      优先级:

        0   1    2    0
      

      然后,进行计算:

      while list isn't empty:
          find operator with the highest priority // if there is more than one, take the first
          calculate this operator // with the element prev and next
          replace by result in list // operator, but also prev and next
      

      再举一个例子,5 + 3 * (6 - 2) - 1

      第一次迭代:

      5 + 3 * 4 - 1
      

      然后

      5 + 12 - 1
      

      然后

      17 - 1       
      

      然后

      16
      
    • 另一个(更好,即使如果你不熟悉递归会有点困难)一个:使用reverse polish notation 的二叉树 (见herehere

      这个比较常见,我就不解释了。

    【讨论】:

    • 还有 1 个问题,对于 'var array = cut string' 行,我如何剪切字符串。另外,我不明白你所说的“检查字符串”是什么意思,看看它是否正确,是否有执行此操作的功能,或者其他部分是否已经检查过?
    • @Cray 为了剪切字符串,你必须做一点解析,但你可以先用空格剪切它(3 + 4变成["3", "+", "4"]),使用@ 987654324@。 (如果这样做,每个字符都必须用空格分隔...)“检查字符串”检查语法错误,例如不匹配的括号或连续的两个运算符(或数字)(3 + * 4 不是有效的操作,3 4 + 5 也不是),未知字符(3 + 4NINJA 也无效)等等......
    【解决方案3】:

    您可以在阅读时使用一个字符串,当您找到{+,-,*,/}. 时,您可以使用该字符串并在它们之间找到您的数字。

    尝试添加您的代码!

    祝你好运!

    【讨论】:

    • 我想将输入保存到一个字符串中,然后使用 for 循环遍历该字符串并取出每个值和算术符号,但我不知道该去哪里。这是最有效的方法吗?
    • 简单..首先您必须选择第一个值并保存到 X 中,比如说(在第一个算术符号之前),然后在您找到的每个符号处取其后面的值并执行该符号的含义与 X .
    【解决方案4】:

    您需要实现一个将运算符优先级考虑在内的表达式解析器。对我来说,最简单的两种方法是实现递归体面解析器或实现Shunting yard algorithm

    有关示例,请参阅 this

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-09
      • 2014-04-01
      • 1970-01-01
      • 2012-12-18
      • 2018-11-03
      • 1970-01-01
      • 1970-01-01
      • 2020-05-24
      相关资源
      最近更新 更多