1. 程式人生 > >資料結構課程設計---計算器模擬器

資料結構課程設計---計算器模擬器

#include <iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#define MaxSize 1000
#define MaxOp 1000
using namespace std;

struct  charac   //設定運算子優先順序
{
    char ch;   //運算子
    int pri;   //優先順序
};

struct charac lpri[]=//左運算子及優先順序
{
    {'=',0},
    {'(',1},
    {'*',5},
    {'/',5},
    {'+',3},
    {'-',3},
    {')',8},
    {'a',7},//a代表abs
    {'q',7},//q代表sqrt
    {'c',7},//c代表cos
    {'%',5},//模運算
    {'s',7},//s代表sin
    {'t',7},//t代表tan
    {'^',7},
    {'!',7}//階乘
},
rpri[]=//右運算子及優先順序
{
    {'=',0},
    {'(',8},
    {'*',4},
    {'/',4},
    {'+',2},
    {'-',2},
    {')',1},
    {'a',6},
    {'q',6},
    {'c',6},
    {'%',4},
    {'s',6},
    {'t',6},
    {'^',6},
    {'!',6}
};
int leftpri(char op)    //求左運算子op的優先順序
{
    int i;
    for (i=0; i<MaxOp; i++)
        if (lpri[i].ch==op) return lpri[i].pri;

}
int rightpri(char op)  //求右運算子op的優先順序
{
    int i;
    for (i=0; i<MaxOp; i++)
        if (rpri[i].ch==op) return rpri[i].pri;
}
bool InOp(char ch)       //判斷ch是否為運算子
{
    if (ch=='(' || ch==')' || ch=='+' || ch=='-'|| ch=='*' || ch=='/'||ch=='a'
            ||ch=='q'||ch=='c'||ch=='%'||ch=='s'||ch=='t'||ch=='^'||ch=='!')
        return true;
    else
        return false;
}
int Precede(char op1,char op2)  //op1和op2運算子優先順序的比較結果
{
    if (leftpri(op1)==rightpri(op2))
        return 0;
    else if (leftpri(op1)<rightpri(op2))
        return -1;
    else
        return 1;
}
void trans(char *exp,char postexp[])//將算術表示式exp轉換成字尾表示式postexp
{
    struct
    {
        char data[MaxSize]; //存放運算子
        int top;   //棧指標
    } op;    //定義運算子棧
    int i=0;    //i作為postexp的下標
    op.top=-1;
    op.top++;                  //將'='進棧
    op.data[op.top]='=';
    while (*exp!='\0')  //exp表示式未掃描完時迴圈
    {
        if (!InOp(*exp))  //為數字字元的情況或小數
        {
            while (*exp>='0' && *exp<='9'||*exp=='.') //判定為數字
            {
                postexp[i++]=*exp;
                exp++;
            }
            postexp[i++]='#'; //用#標識一個數值串結束
        }
        else //為運算子的情況
            switch(Precede(op.data[op.top],*exp))
            {
            case -1:     //棧頂運算子的優先順序低:進棧
                op.top++;
                op.data[op.top]=*exp;
                exp++;    //繼續掃描其他字元
                break;
            case 0:     //只有括號滿足這種情況
                op.top--;    //將(退棧
                exp++;
                break;
            case 1:             //退棧並輸出到postexp中
                postexp[i++]=op.data[op.top];
                op.top--;
                break;
            }
    }
    while (op.data[op.top]!='=') //將棧中運算子退到postexp中
    {
        postexp[i++]=op.data[op.top];
        op.top--;
    }
    postexp[i]='\0'; //給postexp表示式新增結束標識
}
int fact(int n)//階乘
{
    if(n==1)return 1;
    return n*fact(n-1);
}
float compvalue(char exp[]) //計算字尾表示式的值
{
    struct
    {
        float data[MaxSize]; //存放數值
        int top;   //棧指標
    } st;    //定義數值棧
    float d;
    char ch;
    int t=0; //t作為exp的下標
    st.top=-1;
    ch=exp[t];
    t++;
    while (ch!='\0') //exp字串未掃描完時迴圈
    {
        switch (ch)
        {
        case '!':
            st.data[st.top]=fact(st.data[st.top]);
            break;
        case '^':
            st.data[st.top-1]=pow(st.data[st.top-1],st.data[st.top]);
            st.top--;
            break;
        case 's':
            st.data[st.top]=sin(st.data[st.top]);
            break;
        case 't':
            st.data[st.top]=tan(st.data[st.top]);
            break;
        case '%':
            st.data[st.top-1]=
                (float)(((int)st.data[st.top-1])%((int)st.data[st.top]));
            st.top--;
            break;
        case 'c':
            st.data[st.top]=cos(st.data[st.top]);
            break;
        case 'a':
            st.data[st.top]=abs(st.data[st.top]);
            break;
        case 'q':
            st.data[st.top]=sqrt(st.data[st.top]);
        case'+':
            st.data[st.top-1]=
                st.data[st.top-1]+st.data[st.top];
            st.top--;
            break;
        case '-':
            st.data[st.top-1]=
                st.data[st.top-1]-st.data[st.top];
            st.top--;
            break;
        case '*':
            st.data[st.top-1]=
                st.data[st.top-1]*st.data[st.top];
            st.top--;
            break;
        case '/':
            if (st.data[st.top]!=0)
                st.data[st.top-1]=
                    st.data[st.top-1]/st.data[st.top];
            else
            {
                printf("\n\t除零錯誤!\n");
                exit(0);  //異常退出
            }
            st.top--;
            break;
        default:
            d=0;
            int flag=0,count=0; //將數字字元轉換成數值存放到d中
            while (ch>='0' && ch<='9'||ch=='.')   //為數字字元
            {
                if(ch=='.')flag=1;
                if(flag==0)
                {
                    d=10*d+ch-'0';
                }
                else
                {
                    if(ch<='9'&&ch>='0')
                        d=d+(ch-'0')/pow(10,count);
                    count++;
                }
                ch=exp[t];
                t++;
            }
            st.top++;
            st.data[st.top]=d;
        }
        ch=exp[t];
        t++;
    }
    return st.data[st.top];
}
bool checkbracket(char *exp,int n)
{
    int i=0;
    bool match=true;
    struct
    {
        char data[MaxSize]; //存放數值
        int top;   //棧指標
    } st;
    st.top=-1;
    while(i<n&&match)
    {
        if(exp[i]=='(')
        {
            st.top++;
            st.data[st.top]=exp[i];
        }
        else if(exp[i]==')')
        {
            if(st.top!=-1)
                if(st.data[st.top]!='(')
                    match=false;
                else st.top--;
            else match=false;

        }
        i++;
    }
    if(st.top!=-1)
        match=false;
    return match;
}
bool check(char *exp,int n)
{
    int i=0,match=true;
    while(*exp!='\0'&&i<n&&match)
    {
        if(*exp<='9'&&*exp>='0'||*exp=='.'||InOp(*exp)==true)
            ;
        else
            match=false;
        i++;
    }
    return match;
}
int main()
{
    system("簡易計算器");
    system("mode con cols=90 ");
    printf("=================簡易計算器==================\n");
    printf(" * 本計算器支援整型、浮點型數運算\n");
    printf(" * 本計算器支援四則運算、sqrt、abs\n   cos、sin、tan、mod、^運算及階乘運算\n");
    printf(" * sin用s表示,cos用c表示,tan用t表示\n");
    printf(" * abs用a表示,sqrt用q表示\n");
    printf(" * ^表示平方,!表示階乘\n");
    printf("==============================================\n");
    printf("請輸入表示式\n");
    char exp[100];
    char postexp[MaxSize],c='y';
    while(c=='y')
    {
        gets(exp);
        int n=strlen(exp);
        if(n==0)printf("沒有任何輸入,請重新輸入\n");
        else
        {
            if(!checkbracket(exp,n))printf("表示式括號不匹配,請重新輸入!\n");
            else if(!check(exp,n))printf("表示式中出現無法識別符號,請重新輸入!\n");
            else
            {
                trans(exp,postexp);
                printf("字尾表示式:%s\n",postexp);
                printf("表示式的值:%g\n",compvalue(postexp));
            }
        }
        printf("繼續請輸入y,任意鍵退出");
        scanf("%c",&c);
        getchar();
    }
    return 0;
}