Zijeak
2018-11-28 13:43
采纳率: 66.7%
浏览 558
已采纳

【数据结构】求大佬帮忙看一下这个错误是怎么回事?(用栈实现带括号的多位数四则运算器)

题目原型: 四则运算器:实现多位整数的带括号的四则运算

现存问题:

程序中出现如图所示错误,麻烦大佬指点一下原因

图片说明

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

#define TRUE 1
#define FALSE 0
#define Stack_Size 50

typedef char StackElementType; //运算符 
typedef double StackElementType_num; //运算数 
typedef struct
{
    StackElementType elem[Stack_Size];
    int top;
}SeqStack; //运算符栈 
typedef struct
{
    StackElementType_num elem[Stack_Size];
    int top;
}SeqStack_num; //运算数栈 

StackElementType_num ExpEvaluation();

void InitStack(SeqStack *S);
int Push(SeqStack *S,StackElementType x);
int Push_num(SeqStack *S,StackElementType_num x);

int Pop(SeqStack *S,StackElementType *x);
int Pop_num(SeqStack *S,StackElementType_num *x);
int GetTop(SeqStack *S,StackElementType *x);
int GetTop_num(SeqStack *S,StackElementType_num *x);
StackElementType Compare(StackElementType ch1,StackElementType ch2);
StackElementType Execute(StackElementType_num a,StackElementType op,StackElementType_num b);

int main()
{
    printf("%lf",ExpEvaluation()); 
    return(0);
}
StackElementType_num ExpEvaluation()
{
    char exp[100];//用字符数组将运算表达式存起来 
    int i=0,count=0;
    printf("Please input an expression (Ending with #:)");
    exp[i]=getchar();
    while(exp[i]!='#')
    {
        i++;count++; 
        exp[i]=getchar();
    }
    SeqStack OPTR;
    SeqStack_num OVS;
    StackElementType ch,op,x;
    StackElementType_num a,b,v;
    InitStack(&OPTR);
    InitStack_num(&OVS);
    Push(&OPTR,'#');
    for(i=0;i<count;i++)
    {
        ch=exp[i];
        while(ch!='#'||GetTop(&OPTR,&x)!='#')
        {
          if(ch>='0'&&ch<='9')//不是操作符,是操作数,进OVS栈 
          {
            int temp;
            temp=ch-'0';//先把当前操作数从字符变为数字 
            i++;
            ch=exp[i];
            while(ch>='0'&&ch<='9')//继续判断下一位是否为操作数
            {
                temp=temp*10+ch-'0';
                i++;
                ch=exp[i];
            } 
            Push_num(&OVS,temp);//压栈 

          }
          else
          switch(Compare(ch,GetTop(&OPTR,&x)))
          {
            case '>':Push(&OPTR,ch);
              i++;ch=exp[i];
            case '=':Pop(&OPTR,&op);i++;ch=exp[i];break;//脱括号 
            case '<':Pop(&OPTR,&op);//形成运算 
            Pop_num(&OVS,&b);
            Pop_num(&OVS,&a);
            v=Execute(a,op,b);
            Push_num(&OVS,v);
            break; 
          }
        }
    }

    v=GetTop_num(&OVS,&x);
    return(v);
} 

//初始化
void InitStack(SeqStack *S)
{
    /*构造一个空栈S*/
    S->top=-1; 
} 
void InitStack_num(SeqStack_num *S)
{
    /*构造一个空栈S*/
    S->top=-1; 
} 
//进栈
int Push(SeqStack *S,StackElementType x)
{
    if(S->top==Stack_Size-1)
     return(FALSE);
    S->top++;
    S->elem[S->top]=x;
    return(TRUE);
} 
int Push_num(SeqStack *S,StackElementType_num x)
{
    if(S->top==Stack_Size-1)
     return(FALSE);
    S->top++;
    S->elem[S->top]=x;
    return(TRUE);
} 

//出栈
int Pop(SeqStack *S,StackElementType *x)
{
    if(S->top==-1)
     return(FALSE);
    *x=S->elem[S->top];
    S->top--;
    return(TRUE);
} 
int Pop_num(SeqStack *S,StackElementType_num *x)
{
    if(S->top==-1)
     return(FALSE);
    *x=S->elem[S->top];
    S->top--;
    return(TRUE);
} 

//读栈顶
int GetTop(SeqStack *S,StackElementType *x)
{
    if(S->top==-1)
     return(FALSE);
    else
    {
        *x=S->elem[S->top];
        return(TRUE);
    }
} 

int GetTop_num(SeqStack *S,StackElementType_num *x)
{
    if(S->top==-1)
     return(FALSE);
    else
    {
        *x=S->elem[S->top];
        return(TRUE);
    }
} 


//比较优先级,返回'>','<','=' 
StackElementType Compare(StackElementType ch1,StackElementType ch2)
//ch1为还未进栈的运算符,ch2为当前运算符栈顶元素 
{
    //'('未入栈时,优先级最高,入栈后,优先级最低
    int m,n; 
    switch(ch1)
    {
        case '(':m=6;break;
        case '*':
        case '/':m=5;break;
        case '+':
        case '-':m=4;break;
        case ')':m=3;break;

    }
    switch(ch2)
    {
        case '*':
        case '/':n=6;break;
        case '+':
        case '-':n=5;break;
        case ')':n=4;break;
        case '(':n=3;break;

    }
    if(ch1>ch2)
     return('>');
     else if(ch1=ch2)
      return('=');
      else
       return('<');
}
StackElementType_num Execute(StackElementType_num a,StackElementType op,StackElementType_num b)
{
    StackElementType_num v;
    switch(op)
    {
        case '+':v=a+b;break;
        case '-':v=a-b;break;
        case '*':v=a*b;break;
        case '/':v=a/b;break;
    }
    return(v);
}

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • threenewbee 2018-11-28 14:27
    已采纳

    不考虑运行,仅仅修改编译错误,如下:

    // Q715047.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #define TRUE 1
    #define FALSE 0
    #define Stack_Size 50
    
    typedef char StackElementType; //运算符 
    typedef double StackElementType_num; //运算数 
    typedef struct
    {
        StackElementType elem[Stack_Size];
        int top;
    }SeqStack; //运算符栈 
    typedef struct
    {
        StackElementType_num elem[Stack_Size];
        int top;
    }SeqStack_num; //运算数栈 
    
    StackElementType_num ExpEvaluation();
    
    void InitStack(SeqStack *S);
    void InitStack_num(SeqStack_num *S);
    int Push(SeqStack *S,StackElementType x);
    int Push_num(SeqStack_num *S,StackElementType_num x);
    
    int Pop(SeqStack *S,StackElementType *x);
    int Pop_num(SeqStack_num *S,StackElementType_num *x);
    int GetTop(SeqStack *S,StackElementType *x);
    int GetTop_num(SeqStack_num *S,StackElementType_num *x);
    StackElementType Compare(StackElementType ch1,StackElementType ch2);
    StackElementType_num Execute(StackElementType_num a,StackElementType op,StackElementType_num b);
    
    int main()
    {
        printf("%lf",ExpEvaluation()); 
        return(0);
    }
    StackElementType_num ExpEvaluation()
    {
        char exp[100];//用字符数组将运算表达式存起来 
        int i=0,count=0;
        printf("Please input an expression (Ending with #:)");
        exp[i]=getchar();
        while(exp[i]!='#')
        {
            i++;count++; 
            exp[i]=getchar();
        }
        SeqStack OPTR;
        SeqStack_num OVS;
        StackElementType ch,op,x;
        StackElementType_num a,b,v;
        InitStack(&OPTR);
        InitStack_num(&OVS);
        Push(&OPTR,'#');
        for(i=0;i<count;i++)
        {
            ch=exp[i];
            while(ch!='#'||GetTop(&OPTR,&x)!='#')
            {
              if(ch>='0'&&ch<='9')//不是操作符,是操作数,进OVS栈 
              {
                int temp;
                temp=ch-'0';//先把当前操作数从字符变为数字 
                i++;
                ch=exp[i];
                while(ch>='0'&&ch<='9')//继续判断下一位是否为操作数
                {
                    temp=temp*10+ch-'0';
                    i++;
                    ch=exp[i];
                } 
                Push_num(&OVS,temp);//压栈 
    
              }
              else
              switch(Compare(ch,GetTop(&OPTR,&x)))
              {
                case '>':Push(&OPTR,ch);
                  i++;ch=exp[i];
                case '=':Pop(&OPTR,&op);i++;ch=exp[i];break;//脱括号 
                case '<':Pop(&OPTR,&op);//形成运算 
                Pop_num(&OVS,&b);
                Pop_num(&OVS,&a);
                v=Execute(a,op,b);
                Push_num(&OVS,v);
                break; 
              }
            }
        }
    
        GetTop_num(&OVS,&v);
        return(v);
    } 
    
    //初始化
    void InitStack(SeqStack *S)
    {
        /*构造一个空栈S*/
        S->top=-1; 
    } 
    void InitStack_num(SeqStack_num *S)
    {
        /*构造一个空栈S*/
        S->top=-1; 
    } 
    //进栈
    int Push(SeqStack *S,StackElementType x)
    {
        if(S->top==Stack_Size-1)
         return(FALSE);
        S->top++;
        S->elem[S->top]=x;
        return(TRUE);
    } 
    int Push_num(SeqStack_num *S,StackElementType_num x)
    {
        if(S->top==Stack_Size-1)
         return(FALSE);
        S->top++;
        S->elem[S->top]=x;
        return(TRUE);
    } 
    
    //出栈
    int Pop(SeqStack *S,StackElementType *x)
    {
        if(S->top==-1)
         return(FALSE);
        *x=S->elem[S->top];
        S->top--;
        return(TRUE);
    } 
    int Pop_num(SeqStack_num *S,StackElementType_num *x)
    {
        if(S->top==-1)
         return(FALSE);
        *x=S->elem[S->top];
        S->top--;
        return(TRUE);
    } 
    
    //读栈顶
    int GetTop(SeqStack *S,StackElementType *x)
    {
        if(S->top==-1)
         return(FALSE);
        else
        {
            *x=S->elem[S->top];
            return(TRUE);
        }
    } 
    
    int GetTop_num(SeqStack_num *S,StackElementType_num *x)
    {
        if(S->top==-1)
         return(FALSE);
        else
        {
            *x=S->elem[S->top];
            return(TRUE);
        }
    } 
    
    
    //比较优先级,返回'>','<','=' 
    StackElementType Compare(StackElementType ch1,StackElementType ch2)
    //ch1为还未进栈的运算符,ch2为当前运算符栈顶元素 
    {
        //'('未入栈时,优先级最高,入栈后,优先级最低
        int m,n; 
        switch(ch1)
        {
            case '(':m=6;break;
            case '*':
            case '/':m=5;break;
            case '+':
            case '-':m=4;break;
            case ')':m=3;break;
    
        }
        switch(ch2)
        {
            case '*':
            case '/':n=6;break;
            case '+':
            case '-':n=5;break;
            case ')':n=4;break;
            case '(':n=3;break;
    
        }
        if(ch1>ch2)
         return('>');
         else if(ch1=ch2)
          return('=');
          else
           return('<');
    }
    
    StackElementType_num Execute(StackElementType_num a,StackElementType op,StackElementType_num b)
    {
        StackElementType_num v = 0.0;
        switch(op)
        {
            case '+':v=a+b;break;
            case '-':v=a-b;break;
            case '*':v=a*b;break;
            case '/':v=a/b;break;
        }
        return(v);
    }
    

    但是你StackElementType_num ExpEvaluation()会死循环,原因是你在while循环里面i++,这会导致i超过输入长度范围,而没有办法退出循环

    整个这段代码都要重写。

    我这里有个写好的,你自己看下吧

    // Q703345.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    
    
    
    #include <iostream>
    #include <stack>        //use STL
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    using namespace std;
    
    const int MAXSIZE=256;
    
    
    int InfixToPostfix(char *infix,char *postfix);
    double Calculate(char *arr);
    int main() {
        cout << "请输入表达式:"; // prints 四则运算
        char in[MAXSIZE]={0};
        char postfix[MAXSIZE]={'\0'};
        fgets(in,MAXSIZE,stdin);
        if(InfixToPostfix(in,postfix)!=1)
        {   cout<<"错误";
            return -1;
        }
        //puts(in);
        puts(postfix);
        cout<<"由后缀表达式计算出的结果是" << Calculate(postfix) << endl;
        return 0;
    }
    /*
    将中缀表达式转换为后缀表达式
    参数:infix 指向中缀表达式,以回车键即\n结尾。
    postfix 指向后缀表达式临时缓冲区,用来存放转换后的结果。
    附转换规则:从左到右遍历中缀表达式的每个数字和符号,若是数字则直接保存在postfix数组中;若是符号,则判断其与栈顶符号的优先级,是右括号或者优先级不大于栈顶符号,则栈顶元素依次出栈并输出,直到遇到左括号或者栈空时,才将刚才的那个符号入栈。
    */
    int InfixToPostfix(char *infix,char *postfix)
    {
      stack<char> s;
      char c,e;
      int j=0,i=0;
      c=*(infix+i); //取出中缀表达式中的第一个字符
      i++;
      while('\n'!=c) //遇到换行符,表示转换结束
      {
           while(c>='0'&&c<='9') //先判断一下取出的字符是否是数字,如果是数字的话,则直接存入postfix数组
           {
              postfix[j++]=c;
              c=*(infix+i);
              i++;
              if(c<'0'||c>'9') //如果不是数字,则在后面添加空格,以便区分各个符号
                {
                postfix[j++]=' ';
                }
           }
          if(')'==c) //不是数字,则判断是否为右括号。[括号的优先级最高,所以,如果是右括号的话,就得先进行括号里的各种运算]
          {
              e=s.top();s.pop();
              while('('!=e) //直到遇到左括号为止
              {
                 postfix[j++]=e;
                 postfix[j++]=' ';
                 e=s.top();s.pop();
              }
          }
          else if('+'==c||'-'==c) //如果是加减号,因为他俩的优先级最低了,所以此时先将栈里的所有符号出栈后(除非遇到左括号),再把此符号入栈
            {
              if(!(s.size())) //如果是空栈,则直接将加减号入栈
              {
                  s.push(c);
              }
              else//如果不是空栈,首先将所有优先级大于加减的出栈,然后再把加减号入栈
              {
                  do{
                      e=s.top();s.pop();
                      if('('==e)
                      {
                        s.push(e);
                      }
                      else
                      {
                        postfix[j++]=e;
                        postfix[j++]=' ';
                      }
                    }while(s.size()&&'('!=e);  //将栈里的所有符号出栈(除非遇到左括号)
                  s.push(c); //最后将新来的加减号再入栈
                }
            }
          else if('*'==c||'/'==c||'('==c) //如果是乘除号或左括号,因为他们的优先级高,所以直接入栈。
            {
              s.push(c);
            }
          else if('\n'==c) //判断一下,所有符号是否都已转换完成
            {
              break;
            }
          else //能走到这个else的,都是我不认识的符号了
            {
              // printf("\nError:input error,the character %d cann't recognize!\n",c);
              return -1;
            }
          c=*(infix+i); //取出下一个字符进行转换
          i++;
        }
      while(s.size()) //转换完成后,栈里可能还有没出栈的运算符号
        {
          e=s.top();s.pop();
          postfix[j++]=e;
          postfix[j++]=' ';
        }
      return true;
    }
    
    /*
    计算后缀表达式的结果
    参数:arr使用空格分隔的后缀表达式字符串。例:arr="31 5 + "
    result 保存计算完毕后的结果
    注:如何利用栈来计算后缀表达式的结果:依次取出后缀表达式中的符号进行比较,如果是数字,则直接入栈;如果是符号,则出栈两次,弹出两个要计算的因数,进行计算,之后再将计算结果入栈。知道后缀表达式中所有符号都已比较完毕。
    */
    double Calculate(char *arr)
    {
      // printf("%s\n",arr);
      double d,e,f; //d,e 存放两个因数。f存放d,e计算后的结果.
      stack<double> s;
      char *op; //存放后缀表达式中的每个因数或运算符
      char *buf=arr; //声明bufhe saveptr两个变量,是strtok_r函数的需要。
      char *saveptr=NULL;
      while((op=strtok(buf," "))!=NULL) //利用strtok_r函数分隔字符串
        {
          buf=NULL;
          switch(op[0])
          {
            case '+':
                d=s.top();s.pop();
                e=s.top();s.pop();
              f=d+e;
              s.push(f);
              break;
            case '-':
                d=s.top();s.pop();
                e=s.top();s.pop();
              f=e-d;
              s.push(f);
              break;
            case '*':
              d=s.top();s.pop();
              e=s.top();s.pop();
              f=d*e;
              s.push(f);
              break;
            case '/':
              d=s.top();s.pop();
              e=s.top();s.pop();
              f=e/d;
              s.push(f);
              break;
            default:
              d=atof(op); //不是运算符,就肯定是因数了。所以,用atof函数,将字符串转换为double类型
              s.push(d);
              break;
            }
        }
      double result=s.top();s.pop();
      return result;
    }
    
    
    
    打赏 评论

相关推荐 更多相似问题