【问题标题】:Rearrange array for calculator BODMAS重新排列计算器 BODMAS 的数组
【发布时间】:2016-10-07 20:43:03
【问题描述】:

我试图重新排列我的计算器数组以逃避 BODMAS 条件。基本上,我读取一个字符串,将数字和运算符添加到不同的数组中,然后尝试重新排列每个数组以使操作具有优先级(从数组中的右到左)。我对“priorizar”功能进行了更改。我猜重新排列不起作用。我的代码有问题吗?提前致谢

#include <stdio.h>

#define MAX 100

struct stacknum{
    float nums[MAX];
    int topnum;
}sn;    //'stack' de numeros - nao prioritaria

struct stackops{
    char ops[MAX];
    int topop;
}so;    // 'stack' de operadores - nao prioritaria

struct stacknum1{
    float nums1[MAX];
    int topnum1;
}sn1;  // 'stack' de numeros - prioritaria

struct stackops1{
    char ops1[MAX];
    int topop1;
}so1;  // 'stack' de operadores - prioritaria

float calculo(float vlr, float vlr2, char op)  // funçao de operaçoes
{
    if ('+' == op)
        return vlr + vlr2;

    if ( '-' == op)
        return vlr2 - vlr;

    if ( '*' == op)
        return  vlr * vlr2;

    if ('/' == op)
        return vlr2 / vlr;
    else
        return 0;
}

void priorizar()
{
    int i, k = 0;
    char aux;
    float aux1, aux2;

    for (i = 0; i < MAX; i++)
    {
        if (so.ops[i] == '*' || so.ops[i] == '/')
        {
            aux = so.ops[so.topop - k];
            so.ops[so.topop - k] = so.ops[i];
            so.ops[i] = aux;
            aux1 = sn.nums[sn.topnum - (k + 1)];
            aux2 = sn.nums[sn.topnum - k];
            sn.nums[sn.topnum - (k + 1)] = sn.nums[i];
            sn.nums[sn.topnum - k] = sn.nums[i + 1];
            sn.nums[i] = aux2;
            sn.nums[i + 1] = aux1;
            k++;
        }
    }
}

float emptystack(int k)   // faz operaçoes a partir da stack , esvazia-a     fazendo todas as operaçoes dentro dela
{ // buffer size excedido quando 20+20*30 ????
    float v1, v2;
    char op;

    if (k == 0)
    {
        while (so.topop != 0)  // esvaziar stack  
        {
            v1 = sn.nums[--(sn.topnum)];
            v2 = sn.nums[--(sn.topnum)];
            op = so.ops[--(so.topop)];
            sn.nums[sn.topnum++] = calculo(v1, v2, op);
        }

        return sn.nums[sn.topnum - 1];
    }
    else
    {
        while(so1.topop1!=0)  // esvaziar stack prioritaria
        {
            v1 = sn1.nums1[--(sn1.topnum1)];
            v2 = sn1.nums1[--(sn1.topnum1)];
            op = so1.ops1[--(so1.topop1)];
            sn1.nums1[sn1.topnum1++] = calculo(v1, v2, op);
        }

        return 0;
    }
}

int IsDigit(char str[], int i)  // se é digito ou nao lel kek
{
    if(str[i] >= '0' && str[i] <= '9')
        return 1;
    else return 0;
}

float analisa(char str[])   // analise de string, BODMAS + parenteses
{
    int i;
    float valor;
    char op;

    for (i = 0; str[i] != '\0'; i++)   
    {
        if (IsDigit(str, i))   // Ñ PARENTESES
        {
            sscanf(str + i, "%f", &valor);  // le e passa para float
            sn.nums[sn.topnum++] = valor;  // empilha numero

            while (str[i + 1] == '.' || (str[i + 1] >= '0' && str[i + 1] <= '9'))
                i++;
        } else if (str[i] == '+' || str[i] == '-' || str[i]=='*' || str[i] == '/')     // empilha se for operaçao nao prioritaria
            so.ops[so.topop++] = str[i];
    }

    priorizar();
    return emptystack(0);   // esvazia stack nao prioritaria e retorna o resultado final
}

int main()
{
    char str[100] = "3*3+2";
    float resultado;
    //printf("Expressao: ");
    //scanf("%s",str);
    resultado = analisa(str);
    printf("%g\n",resultado);
    return 0;
}

【问题讨论】:

  • 如果它不起作用,那么是的,您的代码有问题。要知道什么,您需要提供一些示例,说明预期的、实际的和似乎错误的。
  • 事后像这样重新排列是很困难的,你现在知道了。我建议您查找其他解析表达式的技术。例如基于operator precedence parsing 的一个(有几个非常简单的基于堆栈的变体)。
  • @EugeneSh。如果我执行 3*3+2,则返回 0。看起来 sn.nums[0] 始终为零,但它被认为是最终结果。虽然 sn.nums[1] 给出 9,但这是第一次操作的结果
  • @JoachimPileborg 我试图避免这种情况,因为我的目标是不使用它>.>

标签: c arrays sorting for-loop struct


【解决方案1】:

低级问题是priorizar() 函数没有正确管理堆栈——它在错误的地方寻找东西:

aux = so.ops[so.topop - k];

k = 0时,这是垃圾内存,应该是:

aux = so.ops[so.topop - k - 1];

这是堆栈中的顶部项目。并且它没有正确解释sn 堆栈与so 堆栈相比以不同的速度增长的事实,有时速度是两倍,有时速度相同。所以你不能使用固定的偏移量来索引两者:

sn.nums[i] = aux2;
sn.nums[i + 1] = aux1;

有时会是:

sn.nums[2 * i] = aux2;
sn.nums[2 * i + 1] = aux1;

在其他情况下,只有一个数字可以操作,因为等式的另一半是表达式。

高级问题是逻辑错误。如果我们可视化堆栈:

so: * +
sn: 3 3 2

那么priorizar()首先要做的是:

so: + *
sn: 3 2 3

这给了我们 9 ((2 * 3) + 3) 而不是期望的 11。但是由于搜索操作符堆栈一直在继续,它再次遇到 '*' 并再次错误地转换它:

so: * +
sn: 3 garbage 3

给我们 (3 + 垃圾) * 3)。即使您改正错误并阻止i 和so.topop - k 交叉,您仍然会得到错误的答案。

您可以根据需要重新排列priorizar() 中的代码,但我不相信您可以从这里到达那里。

【讨论】:

  • 感谢您的回答和解释。我想我没有意识到堆栈以不同的速度增长。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-22
  • 1970-01-01
  • 1970-01-01
  • 2013-03-22
相关资源
最近更新 更多