当前位置: 首页 > 知识库问答 >
问题:

使用堆栈将中缀表达式转换为后缀(C)

穆子琪
2023-03-14

我的讲师给了我一个任务,让我创建一个程序,使用堆栈将表达式和中缀转换为后缀。我制作了堆栈类和一些函数来读取中缀表达式。

但是这个函数,叫做transtToPostfix(char*const inFix,char*const postFix),它负责使用堆栈将数组inFix中的inFix表达式转换为数组postFix中的postfix表达式,并没有做它应该做的事情...你们能帮帮我告诉我哪里做错了吗?

下面是从中缀转换为后缀的函数的代码,convertToPostfix(char*const-inFix,char*const-postFix)是我需要帮助修复的代码:

 void ArithmeticExpression::inputAndConvertToPostfix()
    {
       char inputChar; //declaring inputChar
       int i = 0; //inizalize i to 0

       cout << "Enter the Arithmetic Expression(No Spaces): ";

       while( ( inputChar = static_cast<char>( cin.get() ) ) != '\n' )
       {
          if (i >= MAXSIZE) break; //exits program if i is greater than or equal to 100

          if(isdigit(inputChar) || isOperator(inputChar))
          {
             inFix[i] = inputChar; //copies each char to inFix array
             cout << inFix[i] << endl;
          }
          else
             cout << "You entered an invalid Arithmetic Expression\n\n" ;

          }

          // increment i;
          i++;
          convertToPostfix(inFix, postFix);


       }




    bool ArithmeticExpression::isOperator(char currentChar)
    {

        if(currentChar == '+')
            return true;
        else if(currentChar == '-')
            return true;
        else if(currentChar == '*')
            return true;
        else if(currentChar == '/')
            return true;
        else if(currentChar == '^')
            return true;
        else if(currentChar == '%')
            return true;
        else
            return false;
    }

    bool ArithmeticExpression::precedence(char operator1, char operator2)
    {
        if ( operator1 == '^' )
           return true;
        else if ( operator2 == '^' )
           return false;
        else if ( operator1 == '*' || operator1 == '/' )
           return true;
        else if ( operator1 == '+' || operator1 == '-' )
           if ( operator2 == '*' || operator2 == '/' )
              return false;
           else
              return true;

        return false;
    }

   void ArithmeticExpression::convertToPostfix(char * const inFix, char * const postFix)
        {
           Stack2<char> stack;

           const char lp = '(';

           stack.push(lp); //Push a left parenthesis ‘(‘ onto the stack.

           strcat(inFix,")");//Appends a right parenthesis ‘)’ to the end of infix.

          // int i = 0;
           int j = 0;

           if(!stack.isEmpty())
           {

               for(int i = 0;i < 100;){

                   if(isdigit(inFix[i]))
                   {
                        postFix[j] = inFix[i];
                        cout << "This is Post Fix for the first If: " << postFix[j] << endl;
                        i++;
                        j++;
                   }

                    if(inFix[i] == '(')
                   {
                       stack.push(inFix[i]);
                       cout << "The InFix was a (" << endl;
                       i++;
                       //j++;
                   }

                    if(isOperator(inFix[i]))
                               {
                            char operator1 = inFix[i];

                            cout << "CUrrent inFix is a operator" << endl;
                                   if(isOperator(stack.getTopPtr()->getData()))
                                       {
                                       cout << "The stack top ptr is a operator1" << endl;
                                       char operator2 = stack.getTopPtr()->getData();
                                           if(precedence(operator1,operator2))
                                           {
                                               //if(isOperator(stack.getTopPtr()->getData())){
                                                   cout << "The stack top ptr is a operato2" << endl;
                                                   postFix[j] = stack.pop();
                                                   cout << "this is post fix " << postFix[j] << endl;
                                                   i++;
                                                   j++;
                                              // }

                                           }

                                       }
                                   else

                                       stack.push(inFix[i]);
                                   // cout << "Top Ptr is a: "<< stack.getTopPtr()->getData() << endl;



                               }

                    for(int r = 0;r != '\0';r++)
                        cout << postFix[r] << " ";

                        if(inFix[i] == ')')
                       {
                           while(stack.stackTop()!= '(')
                         {
                               postFix[j] = stack.pop();
                               i++;
                               j++;
                                }
                           stack.pop();

                            }
                       }
           }

                   }

注意:convertToPostfix函数是使用以下算法生成的:

>

>

  • 如果内缀中的当前字符是数字,则将其复制到后缀的下一个元素。
  • 如果中缀的当前字符是左括号,将其推到堆栈上。
  • 如果内缀中的当前字符是运算符,

    • (如果在堆栈顶部有Pop运算符,则它们的优先级等于或高于Pop运算符的优先级)
    • 从堆栈顶部弹出运算符并将其插入后缀,直到左括号位于堆栈顶部
    • 从堆栈中弹出(并放弃)左括号
  • 共有3个答案

    陶博耘
    2023-03-14

    这是我用C和多个数字的评估。

    #include <stdio.h>
    #include <math.h>
    #define MAX 50
    void push(char[],char);
    void in_push(double[], double);
    int pop();
    int prec(char);
    double eval(char[],int,double[]);
    int top = 0;
    void main() {
    double eval_stack[MAX];
    int op_count=0;
    char stack[MAX], exps[MAX], symbols[MAX];
    int i=0,j=0,len,check;
    while((symbols[i]=getchar())!='\n') {
    if(symbols[i]!=' ' || symbols[i]!='\t') {
    if(symbols[i]=='+' || symbols[i]=='-' || symbols[i]=='/' || symbols[i]=='*' || symbols[i]=='^')
    op_count++;
    i++;
    }
    }
    symbols[i]='#';
    symbols[++i]='\0';
    len = strlen(symbols);
    stack[top] = '#';
    for(i=0; i<=len; i++) {
    if(symbols[i]>='a'  && symbols[i]<='z') {
    exps[j]=symbols[i];
    j++;
    }
    switch(symbols[i]) {
    case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
    //if(symbols[i]>='a'  && symbols[i]<='z') {
    exps[j]=symbols[i];
    j++;
    break;
    case '+': case '-': case '*': case '/': case '^':
    exps[j++] = ' ';
    while(prec(symbols[i]) <= prec(stack[top])) {
    
                 exps[j] = stack[top];
                 pop();
                 //printf("\n\t\t%d\t\t%d\n", top,j);
                    j++;
    
    
    }
    if(prec(symbols[i]) > prec(stack[top])) {
    push(stack,symbols[i]);
    }
    break;
    case '(':
    push(stack,symbols[i]);
    break;
    case ')':
    while(stack[top]!='(') {
          exps[j] = stack[top];
           pop();
          j++;
    
    }
    pop();
    break;
    case '#':
    exps[j++] = ' ';
    while(stack[top]!='#') {
          exps[j] = stack[top];
           pop();
           j++;
    
    }
    pop();
    break;
    }
    }
    exps[j]='\0';
    printf("Postfix: %s", exps);
    for(i=0; i<j; i++)
    if(exps[i]=='a')
    check = 1;
    if(check!=1)
    printf("\nSolution: %.1f", eval(exps,j,eval_stack));
    }
    
    double eval(char exps[],int exps_len,double eval_stack[]) {
        int i; int len=exps_len,temp;
        double in_temp[MAX],t;
        int count,power,j,in_count;
        count=power=j=t=in_count=0;
        double result;
    for(i=0; i<len; i++) {
    switch(exps[i]) {
    case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
    in_temp[i] = exps[i]-'0';
    j=i+1;
    while(exps[j]>='0' && exps[j]<='9') {
    in_temp[j] = exps[j]-'0';
    j++; // 2
    }
    count = i; // 3
    while(in_temp[count]<='0' && in_temp[count]<='9') {
    power = (j-count)-1;
    t = t + in_temp[count]*(pow(10,power));
    power--;
    count++;
    }
    in_push(eval_stack,t);
    i=j-1;
    t=0;
    break;
    case '+':
    temp = pop();
    pop();
    result = eval_stack[temp] + eval_stack[temp+1];
    in_push(eval_stack,result);
    break;
    case '-':
    temp = pop();
    pop();
    result = eval_stack[temp] - eval_stack[temp+1];
    in_push(eval_stack,result);
    break;
    case '*':
    temp = pop();
    pop();
    result = eval_stack[temp] * eval_stack[temp+1];
    in_push(eval_stack,result);
    break;
    case '/':
    temp = pop();
    pop();
    result = eval_stack[temp] / eval_stack[temp+1];
    in_push(eval_stack,result);
    break;
    case '^':
    temp = pop();
    pop();
    result = pow(eval_stack[temp],eval_stack[temp+1]);
    in_push(eval_stack,result);
    break;
    }
    }
    return eval_stack[top];
    }
    int prec(char a) {
    if(a=='^')
    return 3;
    else if(a=='*' || a=='/' || a=='%')
    return 2;
    else if(a=='+' || a=='-')
    return 1;
    else if(a=='(')
    return 0;
    else
    return -1;
    }
    
    void push(char stack[], char ele) {
        if(top>=MAX) {
        printf("\nStack Overflow");
        exit(1);
        }
    stack[++top] = ele;
    }
    void in_push(double stack[], double ele) {
        if(top>=MAX) {
        printf("\nStack Overflow");
        exit(1);
        }
    stack[++top] = ele;
    }
    int pop() {
        if(top<0) {
        printf("\nStack Underflow");
        exit(1);
        }
    
    top = top - 1;
    return top;
    }
    
    徐焱
    2023-03-14

    因此,您的代码存在许多问题。我将发布(应该是)一个纠正的解决方案,其中有大量的评论来解释发生了什么以及你在哪里犯了错误。前面有几件事:

    >

    我正在使用标准库中的堆栈

    它是一个自由函数,不是类的一部分,但应该很容易修改——这样测试对我来说很简单。

    我不相信你的操作员优先级表是正确的,但是,我会让你仔细检查一下。

    #include <stack>
    #include <cctype>
    #include <iostream>
    
    std::string convertToPostfix(std::string& infix)
    {
        std::string postfix; //Our return string
        std::stack<char> stack;
        stack.push('('); //Push a left parenthesis ‘(‘ onto the stack.
        infix.push_back(')');
    
        //We know we need to process every element in the string,
        //so let's do that instead of having to worry about
        //hardcoded numbers and i, j indecies
        for(std::size_t i = 0; i < infix.size(); ++i) {
    
            //If it's a digit, add it to the output
            //Also, if it's a space, add it to the output 
            //this makes it look a bit nicer
            if(isdigit(infix[i]) || isspace(infix[i])) {
                postfix.push_back(infix[i]);
            }
    
            //Already iterating over i, so 
            //don't need to worry about i++
            //Also, these options are all mutually exclusive,
            //so they should be else if instead of if.
            //(Mutually exclusive in that if something is a digit,
            //it can't be a parens or an operator or anything else).
            else if(infix[i] == '(') {
                stack.push(infix[i]);
            }
    
            //This is farily similar to your code, but cleaned up. 
            //With strings we can simply push_back instead of having
            //to worry about incrementing some counter.
            else if(isOperator(infix[i]))
            {
                char operator1 = infix[i];
                if(isOperator(stack.top())) {
                    while(!stack.empty() && precedence(operator1,stack.top())) {
                        postfix.push_back(stack.top());
                        stack.pop();
                    }
                }
                //This shouldn't be in an else - we always want to push the
                //operator onto the stack
                stack.push(operator1);
            }    
    
            //We've hit a right parens - Why you had a for loop
            //here originally I don't know
            else if(infix[i] == ')') {
                //While top of stack is not a right parens
                while(stack.top() != '(') {
                //Insert into postfix and pop the stack
                    postfix.push_back(stack.top());
                    stack.pop();
                }
                // Discard the left parens - you'd forgotten to do this
                stack.pop(); 
            }
        }
    
        //Remove any remaining operators from the stack
        while(!stack.empty()) {
            postfix.push_back(stack.top());
            stack.pop();
        }
    }
    
    孟泽宇
    2023-03-14

    这基本上是对Yuushi回答的评论。

    • 外部while(!stack.empty())循环错误。把它拿走。(保持循环体为ofc)。在函数末尾,检查堆栈是否为空,否则表达式有语法错误
    • 正如Yuushi已经说过的,优先函数看起来是假的。首先,应该为参数指定更好的名称:一个是左边的运算符,另一个是右边的运算符。(现在称之为优先(rightOp,leftOp))。然后,您应该记录结果的含义-如果a rOp b lOp c==(a rOp b)lOp c(是的,运算符顺序与您所称的不匹配,例如-“”和“-”在两个顺序中都不相同,那么现在返回true)
    • 如果您找到一个新运算符,则需要在堆栈上的旧运算符上循环,例如,在读取a-b*c后,您的输出是a-b-c,堆栈是[-*]。现在您阅读了一个,需要同时弹出两个操作符,结果是abc*-。即,输入a-b*cd应导致a-b*cd

    更新:附加完整的解决方案(基于Yuushi的回答):

    bool isOperator(char currentChar)
    {
        switch (currentChar) {
        case '+':
        case '-':
        case '*':
        case '/':
        case '^':
        case '%':
            return true;
        default:
            return false;
        }
    }
    
    // returns whether a `lOp` b `rOp` c == (a `lOp` b) `rOp` c
    bool precedence(char leftOperator, char rightOperator)
    {
        if ( leftOperator == '^' ) {
            return true;
        } else if ( rightOperator == '^' ) {
            return false;
        } else if ( leftOperator == '*' || leftOperator == '/' || leftOperator == '%' ) {
            return true;
        } else if ( rightOperator == '*' || rightOperator == '/' || rightOperator == '%' ) {
            return false;
        }
    
        return true;
    }
    
    #include <stdexcept>
    #include <cctype>
    #include <sstream>
    #include <stack>
    std::string convertToPostfix(const std::string& infix)
    {
        std::stringstream postfix; // Our return string
        std::stack<char> stack;
        stack.push('('); // Push a left parenthesis ‘(‘ onto the stack.
    
        for(std::size_t i = 0, l = infix.size(); i < l; ++i) {
            const char current = infix[i];
    
            if (isspace(current)) {
                // ignore
            }
            // If it's a digit or '.' or a letter ("variables"), add it to the output
            else if(isalnum(current) || '.' == current) {
                postfix << current;
            }
    
            else if('(' == current) {
                stack.push(current);
            }
    
            else if(isOperator(current)) {
                char rightOperator = current;
                while(!stack.empty() && isOperator(stack.top()) && precedence(stack.top(), rightOperator)) {
                    postfix << ' ' << stack.top();
                    stack.pop();
                }
                postfix << ' ';
                stack.push(rightOperator);
            }
    
            // We've hit a right parens
            else if(')' == current) {
                // While top of stack is not a left parens
                while(!stack.empty() && '(' != stack.top()) {
                    postfix << ' ' << stack.top();
                    stack.pop();
                }
                if (stack.empty()) {
                    throw std::runtime_error("missing left paren");
                }
                // Discard the left paren
                stack.pop();
                postfix << ' ';
            } else {
                throw std::runtime_error("invalid input character");
            }
        }
    
    
        // Started with a left paren, now close it:
        // While top of stack is not a left paren
        while(!stack.empty() && '(' != stack.top()) {
            postfix << ' ' << stack.top();
            stack.pop();
        }
        if (stack.empty()) {
            throw std::runtime_error("missing left paren");
        }
        // Discard the left paren
        stack.pop();
    
        // all open parens should be closed now -> empty stack
        if (!stack.empty()) {
            throw std::runtime_error("missing right paren");
        }
    
        return postfix.str();
    }
    
    #include <iostream>
    #include <string>
    int main()
    {
        for (;;) {
            if (!std::cout.good()) break;
            std::cout << "Enter the Arithmetic Expression: ";
            std::string infix;
            std::getline(std::cin, infix);
            if (infix.empty()) break;
    
            std::cout << "Postfix: '" << convertToPostfix(infix) << "'\n";
        }
    
        return 0;
    }
    
     类似资料:
    • 本文向大家介绍将中缀转换为后缀表达式,包括了将中缀转换为后缀表达式的使用技巧和注意事项,需要的朋友参考一下 前缀表达式是人类可读和可解的。我们可以轻松地区分算子的顺序,也可以在计算数学表达式时先使用括号将其求解。计算机无法轻松地区分运算符和括号,这就是为什么需要后缀转换的原因。 要将中缀表达式转换为后缀表达式,我们将使用堆栈数据结构。通过从左到右扫描infix表达式,当我们得到任何操作数时,只需将

    • 我正在为我的一堂计算机科学课开发一个计算后缀表达式结果的程序。该程序使用堆栈ADT来实现这一点。 我已经编写了程序,但相信可能会有错误,因为一些表达式的结果不正确。我不确定我的错误在哪里。 此外,当输入文件为空时,程序将生成一个值32767。那是从哪里来的? 表达式:34+3*值=21。 主程序:

    • 本文向大家介绍将中缀转换为前缀表达式,包括了将中缀转换为前缀表达式的使用技巧和注意事项,需要的朋友参考一下 要通过计算机求解表达式,我们可以将其转换为后缀形式或前缀形式。在这里,我们将看到中缀表达式如何转换为前缀形式。 首先,中缀表达式反转。注意,对于反转,圆括号也将反转。 例如:表达式:A + B *(C-D) 反转后的表达式为:)D – C(* B + A 因此我们需要将左括号转换为右括号,反

    • 本文向大家介绍中缀表达式转后缀表达式相关面试题,主要包含被问及中缀表达式转后缀表达式时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 对于中缀表达式,遇到操作数直接将其输出,如果遇到操作符和左括号全部压入栈中,若遇到右括号则将栈中元素全部弹出,直到遇到左括号为止。压栈过程中,若遇到其它操作符,从栈中弹出元素直到遇到更低优先级的操作符为止。

    • 我的讲师给了我一个任务,创建一个程序,使用堆栈将中缀表达式转换为后缀。我制作了堆栈类和一些函数来读取中缀表达式。 但是这个名为inToPos(charstring[])的函数正在创建断点,该函数负责使用堆栈将字符串中缀中的中缀表达式转换为字符串后缀中的后缀表达式。你们能帮帮我,告诉我我做错了什么吗? 这些是我的代码,非常需要您的帮助:) 注:inToPos功能是使用以下算法实现的: 从左到右扫描中

    • 我试图在1次传递中评估一个内插表达式,而不将其转换为后缀,但它没有为某些表达式提供正确的输出。例如:3-5*10/5 10 , (45 5)-5*(100/10) 5 是否有人能在cpp中为这个问题提供适当的解决方案。 链接到上一个问题:如何使用堆栈在一次扫描中计算中缀表达式? 请不要将其标记为重复,因为我已经尝试了上述给定线程中回答的算法,但没有效果。