【问题标题】:How to properly parse numbers in an arithmetic expression, differentiating positive and negative ones?如何正确解析算术表达式中的数字,区分正数和负数?
【发布时间】:2017-01-04 22:12:51
【问题描述】:

我的数据结构类中有一个作业,我必须在其中编写一个计算器,用 4 个基本运算和括号来求解算术表达式,输入是通过标准输入缓冲区完成的,输出也是如此。

一开始很容易,老师为我们提供了算法(如何将表达式从中缀转换为后缀以及如何评估它),唯一的目标是让我们实现自己的堆栈并使用它,但是计算器本身并不能很好地工作,我认为是因为我的解析器。

This is the algorithm 和我的代码,用于解析数字、运算符和括号,同时将它们放入数组中,以便以后更容易评估的方式存储表达式。

// saida is an array of pairs of integers, the first value of the pair is the value of the info (the number itself or the ASCII value of the operator)
// The second value is an indicator of whether it is a number or a operator
for (i = 0; i < exp_size; i++) {
    c = expression[i];

    // If the current char is a digit, store it into a helper string and keep going until a non-digit is found
    // Then atoi() is used to transform this string into an int and then store it.
    if (c >= '0' && c <= '9') {
        j = 1, k = i+1;
        tempInt[0] = c;
        while(expression[k] >= '0' && expression[k] <= '9') {
            tempInt[j++] = expression[k];
            k++;
        }
        tempInt[j] = '\0';
        saida[saidaIndex][0] = atoi(tempInt);
        saida[saidaIndex++][1] = 0;
        i = k-1;
    }

    // If the character is an operator, the algorithm is followed.
    else if (c == '+' || c == '-' || c == '*' || c == '/') {
        while(pilha->size > 0 && isOpBigger( stack_top(pilha), c )) {
            saida[saidaIndex][0] = stack_pop(pilha);
            saida[saidaIndex++][1] = 1;
        }
        stack_push(c, pilha);
    }
    else if (c == '(') stack_push(c, pilha);
    else if (c == ')') {
        j = stack_pop(pilha);
        while(j != '(') {
            saida[saidaIndex][0] = j;
            saida[saidaIndex++][1] = 1;
            j = stack_pop(pilha);
        }
    }
}

问题是,在这段代码中,我无法判断减号是表示减法运算符还是负数(我知道减号运算符是负数的和,但它并没有帮助我解决这个问题),我想到了以下,没有成功:

  • 每次出现减号时,存储一个加号并让下一个数字本身为 * -1。如果下一个数字已经是负数,或者如果减号位于带括号的表达式之前,例如 1 + 2 - (3 * 4),则不起作用。
  • 如果减号后面有空格,则为运算符,否则为负数。不起作用,因为输入中没有这些规则。

我在口译方面没有任何经验,我真的不知道如何进行。该代码可以完美地处理没有负数的有效表达式,但不能处理像 () + 3 - () 这样的奇怪表达式,但这是另一个问题。

感谢您的帮助。

【问题讨论】:

  • 代替for (i = 0; i &lt; exp_size; i++)(每次迭代仅强制增加1)尝试char *p = expression; while (*p) { test/increment as needed },它允许您根据需要向前读取和使用表达式中的字符.例如if (*p == '-') while (isblank (*p)) p++;(或其他类似的测试,例如(0-9 等)让您在表达式中向前阅读以确定您正在处理什么?
  • 我从来没有想过这样遍历一个字符串,去试试,谢谢!
  • 在解析任何字符串时,这增加了很大的灵活性。你知道你会在每个字符串的末尾有一个 nul-byte ,所以只需使用 while (*p) 沿着字符串向下走并根据需要读取/检查就可以让你做各种各样的事情,比如@ 987654330@ 提前(或后面)阅读。您甚至可以使用多个指针将字符串中的 sub-expressions 括起来,例如 char *sp, *ep; 用于 startend 指针,它允许您设置if (*p == '(') sp = p; 并继续直到if (*p = ')') ep = p; 然后处理spep 之间的内容。
  • 这真的为我打开了新的视野,再次感谢你,会记住这一点!

标签: c string parsing calculator arithmetic-expressions


【解决方案1】:

这就是所谓的“一元减号”问题,在您的情况下(无变量)可以通过替换来解决。

如果是运算符-,则为一元减号

  • 前面有一个左括号
  • 前面有另一个运算符
  • 输入的第一个字符

现在不是存储-,而是存储一个不同的字符,比如m,并为其分配比其他运算符更高的优先级(如果有,则与幂运算符相同)。

另一个提示:不要使用空格来表示任何东西,算术表达式必须在没有空格的情况下工作,否则它是不正确的。

【讨论】:

  • 谢谢,我要试试。我也应该用加号来实现它吗?
  • 不,通常不需要。
  • @MikaelMello,因为你有一元减号运算符,你也有一元加号运算符。这是不必要的,但它可以作为+3(在表达式的开头)进入输入或重复,如++3。检查您是否可以输入像+++-+++-+-+-++3+-+-+-+5 这样的输入并且它们是有效的。一元运算符的优先级应高于二元算术运算符,以允许像 5 * - 3-5 * +3 这样的表达式(被解释为 5 * (-3)(-5) * (+3))或至少比加法运算符 + 和 @ 更多987654332@(在这种情况下,第二个-5 * +3 不正确)
  • 你是对的,我已经添加了一个一元加任何一种方式,以及对多个一元运算符的支持,比如你的第二个和第三个例子。我使用“布尔”变量来指示一元运算符是否处于活动状态并且它工作正常,但我选择将++3 指示为无效表达式,因为它看起来不正确。因此,如果这些示例是有效的表达式,我将回到我最初实现的方式,即 -+3+-3 导致 -3。感谢您对这种情况有所了解。
  • @MikaelMello 很好,现在实现阶乘:10! ;-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-02
  • 2014-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多