精华内容
下载资源
问答
  • 用两种方式实现表达式自动计算 - PAGE 2 - 设计思想 计算算术表达式可以用两种方法实现 1.中缀转后缀算法 此算法分两步实现先将算术表达式转换为后缀表达式然后对后缀表达式进行计算具体实现方法如下 中缀转后缀 ...
  • 计算下面数学表达式的值:cos3.56+log1035+ln8.56+e2.63+tan0.78 输入:无。 输出:表达式的值。
  • 中缀转后缀算法 此算法分两步实现先将算术表达式转换为后缀表达式然后对后缀表达式进行计算具体实现方法如下 1中缀转后缀 需要建一个操作符栈op和一个字符数组expop栈存放操作符字符数组用来存放转换以后的后缀...
  • 运算符是一种符号,它告诉计算机执行某些数学或逻辑操作。 在程序中,运算符用于数据和变量的操作。
  • 中缀转后缀算法 此算法分两步实现先将算术表达式转换为后缀表达式然后对后缀表达式进行计算具体实现方法如下 中缀转后缀 需要建一个操作符栈op和一个字符数组expop栈存放操作符字符数组用来存放转换以后的后缀表达式...
  • 用两种方式实现表达式自动计算 一设计思想 计算算术表达式可以用两种方法实现 1.中缀转后缀算法 此算法分两步实现 先将算术表达式转换为后缀表达式 然后对后缀表达式进行计算具体实现方法如下 1中缀转后缀 需要建一...
  • 问题:用户输入一个包含“+”、“-”、“*”、“/”、正整数和圆括号的合法数学表达式计算该表达式的运算结果 C语言 我这里是使用两个栈实现的,直接对中缀表达式进行运算的 输入的算式以#结尾 除此之外该问题...

    问题:用户输入一个包含“+”、“-”、“*”、“/”、正整数和圆括号的合法数学表达式,计算该表达式的运算结果
    C语言
    我这里是使用两个栈实现的,直接对中缀表达式进行运算的
    输入的算式以#结尾

    除此之外该问题还可以使用一个栈,如:先转化成后缀表达式;或者使用char型共享栈,操作数进出栈时进行类型转换即可。
    Evaluation.h

    #ifndef EVALUATION_H_INCLUDED
    #define EVALUATION_H_INCLUDED
    
    #include <stdio.h>
    #include <stdlib.h>
    #define MAXSIZE 20
    //操作数
    typedef struct Operand
    {
        int Data[MAXSIZE];
        int top;
    }Rand;
    //运算符
    typedef struct Operator
    {
        char Data[MAXSIZE];
        int top;
    }Rator;
    //定义栈存放操作数和运算符
    Rand operands;
    Rator operators;
    //初始化栈
    void InitOperand(Rand *ra);
    void InitOperator(Rator *op);
    //判栈空
    int EmptyRand(Rand *ra);
    int EmptyRator(Rator *op);
    //进栈
    int PushRand(Rand *ra,int e);
    int PushRator(Rator *op,char e);
    //出栈
    int PopRand(Rand *ra,int *e);
    int PopRator(Rator *op,char *e);
    //取栈顶元素
    int GetTopRand(Rand *ra);
    char GetTopRator(Rator *op);
    //判断字符是否为运算符
    int InOp(char ch);
    //判断运算符优先级
    int Priority(char s);
    //比较运算符优先级
    int Precede(char op1,char op2);
    //判断符号并运算
    int Calculation(int a,int b,char c);
    //计算表达式
    int ExpCalculation(Rand *ra,Rator *op);
    #endif // EVALUATION_H_INCLUDED
    

    Evaluation.c

    #include "Evaluation.h"
    //初始化栈
    void InitOperand(Rand *ra)
    {
        ra->top = -1;
    }
    void InitOperator(Rator *op)
    {
        op->top = -1;
    }
    //栈栈空
    int EmptyRand(Rand *ra)
    {
        ra->top = -1;
        return 0;
    
    }
    int EmptyRator(Rator *op)
    {
        op->top = -1;
        return 0;
    }
    //进栈
    int PushRand(Rand *ra,int e)
    {
        if(ra->top == MAXSIZE-1)
            return 0;
        ra->top++;
        ra->Data[ra->top] = e;
        return 1;
    }
    int PushRator(Rator *op,char e)
    {
        if(op->top == MAXSIZE-1)
            return 0;
        op->top++;
        op->Data[op->top] = e;
        return 1;
    }
    //出栈
    int PopRand(Rand *ra,int *e)
    {
        if(ra->top == -1)
            return 0;
        *e = ra->Data[ra->top];
        ra->top--;
        return 1;
    }
    int PopRator(Rator *op,char *e)
    {
        if(op->top == -1)
            return 0;
        *e = op->Data[op->top];
        op->top--;
        return 1;
    }
    //取栈顶元素
    int GetTopRand(Rand *ra)
    {
        if(ra->top == -1)
            return 0;
        return ra->Data[ra->top];
    }
    char GetTopRator(Rator *op)
    {
        if(op->top == -1)
            return 'N';
        return op->Data[op->top];//
    }
    //判断字符是否为运算符
    int InOp(char ch)
    {
        if(ch == '(' || ch == ')' || ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '#')
            return 1;
        return 0;
    }
    //判断运算符优先级
    int Priority(char s)
    {
        switch(s)
        {
        case '(':
            return 4;
        case '*':
        case '/':
            return 3;
        case '+':
        case '-':
            return 2;
        case ')':
            return 1;
        default:
            return 0;
        }
    }
    //比较运算符优先级
    int Precede(char op1,char op2)
    {
        if(Priority(op1) < Priority(op2))
            return 0;
        return 1;
    }
    //判断符号并运算
    int Calculation(int a,int b,char c)
    {
        switch(c)
        {
        case '+':
            return a+b;
        case '-':
            return a-b;
        case '*':
            return a*b;
        case '/':
            if(b == 0)
                exit(1);
            return a/b;
    
        }
    }
    //计算表达式
    int ExpCalculation(Rand *ra,Rator *op)
    {
        int a,b;
        char ch,s;
        PushRator(op,'#');
        printf("请输入要计算的算式(以#结尾):");
        ch = getchar();
        while(ch != '#' || GetTopRator(op) != '#')
        {
            if(!InOp(ch))
            {
                int temp;
                temp = ch - '0';
                ch = getchar();
                while(!InOp(ch))
                {
                    temp = temp * 10 + ch - '0';
                    ch = getchar();
                }
                PushRand(ra,temp);
            }
            else
            {
                if(GetTopRator(op) == '(')
                {
                    if(ch == ')')
                        PopRator(op,&s);
                    else
                        PushRator(op,ch);
                    ch = getchar();
                }
                else
                {
                    if(!Precede(GetTopRator(op),ch))
                    {
                        PushRator(op,ch);
                        ch = getchar();
                    }
                    else
                    {
                        PopRand(ra,&b);
                        PopRand(ra,&a);
                        PopRator(op,&s);
                        PushRand(ra,Calculation(a,b,s));
                    }
                }
            }
        }
        printf("运算结果为%d\n",GetTopRand(ra));
        return 0;
    }
    
    

    在main.c文件中使用了一个死循环while(1),执行一次程序可以计算多个算式,在要最后一次输入算式时以#~结尾即可结束程序
    main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include "Evaluation.h"
    #include "Evaluation.c"
    int main()
    {
        InitOperand(&operands);
        InitOperator(&operators);
        while(1)
        {
            char ch;
            ExpCalculation(&operands,&operators);
            EmptyRand(&operands);
            EmptyRator(&operators);
            ch = getchar();
            if(ch == '~')   //在输入要运算的算式时,在#后面输入~来退出循环结束程序
                exit(0);
        }
        return 0;
    }
    
    

    括号可以嵌套使用,在运行程序输入算式时要注意不要输入中文括号,否则计算结果可能会出现错误。
    运行截图

    展开全文
  • 数学计算表达式解析

    千次阅读 2018-10-15 16:02:46
    最近在写一个计算器的项目,其中最麻烦的就是数学表达试的解析,用C语言解决问题,每一步进本都要自己实现,非常锻炼逻辑能力。用了将近两个晚上的时间,终于完成了大部分表达式的解析,写这篇文章来记录下遇到的...

    写在前面

    最近在写一个计算器的项目,其中最麻烦的就是数学表达试的解析,用C语言解决问题,每一步基本都要自己实现,非常锻炼逻辑能力。用了将近两个晚上的时间,终于完成了大部分表达式的解析,写这篇文章来记录下遇到的问题。

    问题

    动态字符串实现

    最棘手的就是动态内存的分配,在这块遇到了很大的困难,经过百度,也是解决了问题。
    参考链接:https://blog.csdn.net/ljwy1234/article/details/79036371
    涉及到二维指针。

    解析

    这个程序主要解决的是括号,乘除,加减的运算优先级的处理。
    参考链接:https://blog.csdn.net/yorhomwang/article/details/76691459
    主要思想和这篇博客中的一样:

    1. 首先进行括号代换,就是将括号中的表达式单独计算出来,计算出来的字符串代替原来括号的位置。
    2. 然后进行乘除晕眩,将解析式中的乘除单独计算出来,计算出来的字符串代替原来乘除的位置。
    3. 最后进行加减法的运算,从左到右进行计算,得到结果。

    代码中运用到了指针数组,数组中存放的都是指针,每个指针指向表达式中的子串。
    这种方法可以运用于命令行参数的解析。

    代码示例

    代码可以直接运行

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    /****************************str*****************************/
    
    char *str_init()
    {
        char *p = (char *)malloc(1);
        p[0] = '\0';
    
        return p;
    }
    
    void str_free(char *p)
    {
        free(p);
    }
    
    void str_append(char **src, const char *str)
    {
        int len = strlen(*src) + strlen(str);
    
        char *str1_tmp = *src;  //保存原来指针位置
        *src = (char *)malloc(len + 1); //重新申请内存
    
        //操作
        strcpy(*src, str1_tmp);
        strcat(*src, str);
        (*src)[len] = '\0';
    
        free(str1_tmp);
    }
    /****************************str*****************************/
    
    
    /****************************calculate*****************************/
    void deal_split(char *a, int len, char *list[])
    {
        int i = 0, j = 0;
    
        list[j++] = &a[0];
        for (i = 0; i < len; i++)
        {
            if (a[i] == ' ')
            {
                a[i] = '\0';
                list[j++] = &a[i + 1];
            }
        }
    }
    
    //加减
    int deal_add_sub(char *str)
    {
        //分割
        char *list[30] = { NULL };
        deal_split(str, strlen(str), list);
    
        int result = atoi(list[0]);
        int i = 0;
        for (i = 1; i < 10 && list[i] != NULL; i += 2)
        {
            if (*list[i] == '+')
            {
                result += atoi(list[i + 1]);
            }
            if (*list[i] == '-')
            {
                result -= atoi(list[i + 1]);
            }
        }
        return result;
    }
    
    //乘除
    char *deal_mul_div(char *str)
    {
        //分割
        char *list[30] = { NULL };
        deal_split(str, strlen(str), list);
    
        char *dst = str_init(); //输出字符串
        char *temp = list[0];
    
        char itoa_temp[10] = {0};
    
        int i = 0;
        for (i = 1; i < 30 && list[i] != NULL; i += 2)
        {
            if (*list[i] == '+')
            {
                str_append(&dst, temp);
                str_append(&dst, " + ");
                temp = list[i + 1];
            }
            else if (*list[i] == '-')
            {
                str_append(&dst, temp);
                str_append(&dst, " - ");
                temp = list[i + 1];
            }
            else if (*list[i] == '*')
            {
                int value = atoi(temp);
                value *= atoi(list[i + 1]);
                itoa(value, itoa_temp, 10);
                temp = itoa_temp;
            }
            else if (*list[i] == '/')
            {
                int value = atoi(temp);
                value /= atoi(list[i + 1]);
                itoa(value, itoa_temp, 10);
                temp = itoa_temp;
            }
        }
        str_append(&dst, temp);
        return dst;
    }
    
    void printf_list(char *list[])
    {
        int iii = 0;
        for (iii = 0; iii < 30 && list[iii] != NULL; iii++)
        {
            printf("%s\n", list[iii]);
        }
    }
    
    //括号
    char *deal_bracket(char *str)
    {
        //分割
        char *list[30] = { NULL };
        deal_split(str, strlen(str), list);
    
        char *dst = str_init(); //输出字符串
        char *dst_temp = str_init();
        char *temp = list[0];
    
        char itoa_temp[10] = {0};
    
        int i = 0;
        for (i = 1; i < 30 && list[i] != NULL; i++)
        {
            if (*list[i] == '+')
            {
                str_append(&dst, temp);
                str_append(&dst, " + ");
                temp = list[i + 1];
            }
            else if (*list[i] == '-')
            {
                str_append(&dst, temp);
                str_append(&dst, " - ");
                temp = list[i + 1];
            }
            else if (*list[i] == '*')
            {
                str_append(&dst, temp);
                str_append(&dst, " * ");
                temp = list[i + 1];
            }
                    else if (*list[i] == '/')
            {
                str_append(&dst, temp);
                str_append(&dst, " / ");
                temp = list[i + 1];
            }
            else if (*list[i] == '(')
            {
                i++;
                str_append(&dst_temp, list[i]);
    
                i++;
                while (*list[i] != ')')
                {
                    str_append(&dst_temp, " ");
                    str_append(&dst_temp, list[i]);
                    i++;
                }
    
                char *p1 = deal_mul_div(dst_temp);
                int value = deal_add_sub(p1);
    
                itoa(value, itoa_temp, 10);
                temp = itoa_temp;
            }
        }
        str_append(&dst, temp);
    
        str_free(dst_temp);
        return dst;
    }
    
    /****************************calculate*****************************/
    
    int main()
    {
        char a[100] = "6 / 2 + ( 2 * 5 + 2 * 2 ) - 9 / 3";
        printf("original = %s\n", a);
        char *p = deal_bracket(a);
        printf("bracket  = %s\n", p);
        char *pp = deal_mul_div(p);
        str_free(p);
        printf("mul_div  = %s\n", pp);
        int ppp = deal_add_sub(pp);
        str_free(pp);
        printf("result   = %d\n", ppp);
    
        return 0;
    }
    
    

    反思

    展开全文
  • C语言利用栈计算算式(表达式

    千次阅读 2019-08-11 18:33:38
    一般普通计算器都是计算两个数相乘,除,加,减,即时计算出答案,而并不能实现输入一个简单数学算式并进行计算得出结果。对于很多人来说,没有合适的方法计算一个算式,那么我们其实也可以通过栈来实现计算算式。 ...

    本文介绍如何通过来实现计算算式。


    首先

    我们要通过多个栈对算式进行操作和计算得出答案,在计算前,我们需要先明确整个计算的流程:

    • 获取用户输入并保存
    • 判断算式是否合理
    • 一些预处理…(例如:删除空格,大括号中括号全部转为小括号等)并把处理后的式子存入另一个地方
    • 根据优先级进行计算,先乘除括号,再加减
    • 输出答案

    而这其中,至关重要的便是计算这部分了,继续看计算的原理:

    通过栈计算算式的原理

    1.优先级高的先算

    以算式9+8*2-(3+1)为例
    正常计算时,应该先乘除后加减,括号内的要先算。那么就是:

    9+8*2-(3+1)
    =9+16-4
    

    计算完优先级高的之后,再计算优先级低的。就是:

    9+16-4
    =21
    

    为了让电脑能够计算出9+8*2-(3+1)=21,我们现在可以开始使用
    根据栈的特性(后入先出),我们可以把算式中的字符逐个导入栈,然后根据算数的优先级,先算掉乘除和括号,然后留下加减运算,再把加减算掉,就可以了。
    那么,应该怎么做呢?
    首先,要创建一个数组来模拟栈,像:

    char Stack[512];
    

    但是,算式中有运算符和数字,怎么区分他们呢?
    我们可以定义一个结构体,像:

    struct Stack
    {
    	int who; //存储存储在单个结构体内的数据类型是数字(int)还是运算符(char),
    				//0为数字(Int),1为运算符(char)
    				
    	int num; //存储数字
    	char word; //存储运算符
    }
    

    假如有一个数字3,那么它放在结构体内,就是:

    struct Stack A;	//创建一个结构体A
    A.who = 0;	//类型为0,即数字
    A.num = 3;	//数字的值是3
    A.word = NULL;	//因为不是字符,存储字符的变量可以是空
    

    再假如是运算符+,那么它在结构体里就是:

    struct Stack B;	//创建一个结构体B
    B.who = 1;	//类型为1,即符号
    B.num = 0;	//因为不是数字,存储数字的变量可以是空
    B.word = '+';	//字符是+
    

    那又因为我们需要一个栈,栈要有长度,我们可以创建一个结构体数组来模拟栈:

    struct Stack compute[512];
    

    我们同样需要一个int变量来存储现在栈顶的位置:

    int top  = 0;
    

    在使用栈之前,应该要对栈进行初始化,即清空:

    for(int i=0;i<512;i++)
    {
    	compute[i].who = 0;
    	compute[i].num = 0;
    	compute[i].word = NULL;
    }
    

    有了栈,就可以继续下一步,将算式导入栈了。循环判断算式9+8*2-(3+1)的第n个字符是数字还是符号,再存储到栈中。

    //存储用户输入的算式的数组是chInPut,原先是char型的
    //存储算式长度的变量是nLong
    //循环判断chInPut[n]是数字还是符号然后分类存入栈中
    for(int n=0;n<nLong;n++)
    {
        //如果chInPut的第n个是数字的话
        if('0'<=chInPut[n]&&chInPut[n]<='9')
        {
    	    //定义的临时变量ch,用于转换类型
    	    char ch[2];
    	    //数组chInPut原先是char型的,所以要把其中的值存储到栈中的int变量的话,要使用atoi函数进行类型转换后再存储进栈内
    	    ch[0] = chInPut[n];
    	    //定义的临时变量temp用于存储atoi的结果
    	    int temp = atoi(ch);
    	    
    	    //将这个数字的信息存储到栈顶,就是入栈。
    	    //字符类型:数字
    	    compute[top].who = 0;
    	    //将temp中的值入栈
    	    compute[top].num = temp;
    	    //运算符,设不设置都可以,为空。
    	    compute[top].word = NULL;
    	    //既然新入栈了信息,那么栈顶的位置也要相应的增加
    	    top++;
        }
         //如果chInPut的第n个是字符的话
        else
        {	    
        	//要是是乘除号,要先算
        	if(chInPut[n] == '*')
    		{
    			//计算...
    		}
    		else if(chInPut[n] == '/')
    		{
    			//计算...
    		}
    		//不是乘除号,还有可能是加减号和括号
    		else if(chInPut[n] == '+' || chInPut[n] == '-' || chInPut[n] == '(')
    		{
    			//入栈...先不计算,因为要先算乘除和括号
    			//为什么碰到左括号也先入栈呢?因为碰到左括号的时候,这个括号里的信息都还没有入栈,要等碰到右括号的时候,把已入栈的括号里的算式取出来算
    		}
    		//是右括号
    		else if(chInPut[n] == ')')
    		{
    			//计算括号内的算式...然后再从栈顶弹出,就是出栈,把整个括号都出栈,再将括号内的算式算出来的答案入栈,这样就以一个数代替了括号
    		}
        }
    }
    

    这样,循环完毕的时候,就会只剩下像9+16-4一样的算式,或者只剩下一个数了。因为在循环中,已经把乘除和括号先算完了。还有,代码中的入栈代码很长,可以将出入栈的代码封装成函数,这样出入栈就方便了,这个函数像是:

    //入栈函数
    void push(int in_who,int in_num,char in_word)
    {
    		compute[top].who = in_who;
    		compute[top].num = in_num;
    		compute[top].word = in_word;
    		top++;
    }
    //出栈函数
    void pop()
    {
    		compute[top-1].who = 0;
    		compute[top-1].num = 0;
    		compute[top-1].word = NULL;
    		top--;
    }
    

    2.剩下的一点…加减混合运算怎么办

    因为在刚刚的循环中,把乘除和括号算完了,那么就可能只剩下一个只有加或是减或是加减混合运算的式子,如果说用户给出的算式只有乘除和括号运算的话,那么到这一步的时候,就只剩下一个数了。那么我们应该先判断是不是只剩下一个数了,如果是的话,输出这个数,因为它就是答案了。如果还有算式需要计算的话,那么,计算他们。

    判断是不是只剩下一个数:

    if(top == 1)
    {
    	printf("答案是:%d",compute[0].num);
    }
    

    计算算式(见源代码):

    while (top >= 1)
    {
    	pNode[3-nPopNum] = pop(MAIN_STACK);
    	nPopNum++;
    	if(nPopNum == 4)
    	{
    		if( 1 == pNode[0].who )
    		{
    			if('-' == pNode[0].word)
    			{
    				if((1 == pNode[2].who) &&(0 == pNode[1].who) && (0 == pNode[3].who))
    				{
    					if('+' == pNode[2].word)
    					{
    						result.who = 0;
    						result.num = pNode[1].num - pNode[3].num;
    					}
    					else if('-' == pNode[2].word)
    					{
    						result.who = 0;
    						result.num = pNode[1].num + pNode[3].num;
    					}
    					else
    					{
    						//表达式错误
    						printf("MISS BUG!\n");
    						break;
    					}
    				}
    				else
    				{
    					//表达式错误
    					printf("MISS BUG!\n");
    					break;
    				}
    			}
    			else if('+' == pNode[0].word)
    			{
    				if((1 == pNode[2].who) &&(0 == pNode[1].who) && (0 == pNode[3].who))
    				{
    					if('+' == pNode[2].word)
    					{
    						result.who = 0;
    						result.num = pNode[1].num + pNode[3].num;
    					}
    					else if('-' == pNode[2].word)
    					{
    						result.who = 0;
    						result.num = pNode[1].num - pNode[3].num;
    					}
    					else
    					{
    						//表达式错误
    						printf("MISS BUG!\n");
    						break;
    					}
    				}
    				else
    				{
    					//表达式错误
    					printf("MISS BUG!\n");
    					break;
    				}
    			}
    			else
    			{
    				//表达式错误
    				printf("MISS BUG!\n");
    				break;
    			}
    		}
    		push(MAIN_STACK,1,0,pNode[0].word);
    		push(MAIN_STACK,0,result.num,NULL);
    		nPopNum = 0;
    	}
    }
    if(nPopNum == 3)
    {
    	if(pNode[2].word == '+')
    	{
    		result.num = pNode[1].num + pNode[3].num;
    	}
    	if(pNode[2].word == '-')
    	{
    		result.num = pNode[1].num - pNode[3].num;
    	}
    	//pop(MAIN_STACK);
    	push(MAIN_STACK,0,result.num,NULL);
    }
    else
    {
    	//有问题
    	printf("MISS BUG!\n");
    }
    

    3.整体的步骤

    在开始写代码之前,整理一下整个程序的思路(变量名称是源码的):

    1. 获取用户输入到chInPut
    2. 进行预处理:判断算式开头是不是负号,是的话在temp_Stack开头添0
    3. 将数字,符号放入temp_Stack,’{‘和’[‘作为’(‘放入temp_Stack,’}‘和’]‘作为’)'放入temp_Stack
    4. 由于chInPut是char型数组,所以每个数或符号都在一个区域内,所以如果有多位数,要进行合并
    5. 预处理结束,开始计算。循环判断temp_Stack的第n个值是什么:
    6. 若是数字,加减号和左括号,放入Stack
    7. 若是乘除号,先判断下一个是不是数,是数的话算掉,不是数就先放入Stack
    8. 若是右括号,循环将括号内的值放入pNode中计算,计算完后得出的结果代替整个括号,判断Stack[top-2]是不是乘除号,若是,进行计算
    9. 判断完整个temp_Stack后,乘除号和括号都已算完。判断现在的Stack中是否只剩下一个数,是的话直接显示答案,就是这个数,如果不止一个数,继续计算
    10. 循环将栈顶和栈顶前三个字符提取到pNode进行计算,直至只能提取到3个字符,将这三个字符进行计算,得到最终答案,显示答案。

    整体的大概步骤就像这10步。


    源代码

    (在www.huidong.xyz有相应程序下载)

    // HuiDongExpression.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "targetver.h"
    #include <stdio.h>
    #include <tchar.h>
    #include <stdlib.h>
    #include <conio.h>
    #include <memory.h>
    #include <string.h>
    
    #define TEMP_STACK 0
    #define MAIN_STACK 1
    
    typedef struct bowl
    {
    	int who; //存储存储在单个结构体内的数据类型是int还是char,
    				//0为Int,1为char
    
    	int num; //存储数字
    	char word; //存储字符
    } BOWL;
    
    //全局变量
    BOWL temp_Stack[512];		//用于临时存放,预处理的时候用的
    int temp_top;				//存储上述栈顶
    BOWL Stack[512];			//真正计算用的栈
    int top;					//存储上述栈顶
    char chInPut[512] = {0};	//获取用户输入
    int Result;					//最终结果
    int CS;						//记录打印次数
    
    void push(int NAME,int in_who,int in_num,char in_word)
    {
    	if(NAME == TEMP_STACK)
    	{
    		temp_Stack[temp_top].who = in_who;
    		temp_Stack[temp_top].num = in_num;
    		temp_Stack[temp_top].word = in_word;
    		temp_top++;
    	}
    	else if(NAME == MAIN_STACK)
    	{
    		Stack[top].who = in_who;
    		Stack[top].num = in_num;
    		Stack[top].word = in_word;
    		top++;
    	}
    }
    
    BOWL pop(int NAME)
    {
    	BOWL node;
    	if(NAME == TEMP_STACK)
    	{
    		node = temp_Stack[temp_top-1];
    
    		temp_Stack[temp_top-1].who = 0;
    		temp_Stack[temp_top-1].num = 0;
    		temp_Stack[temp_top-1].word = NULL;
    		temp_top--;
    	}
    	else if(NAME == MAIN_STACK)
    	{
    		node = Stack[top-1];
    
    		Stack[top-1].who = 0;
    		Stack[top-1].num = 0;
    		Stack[top-1].word = NULL;
    		top--;
    	}
    	return node;
    }
    
    void init_Stack()//初始化栈及对用户输入的预处理
    {
    	//清空Stack
    	int i;
    	temp_top = 0;
    	top = 0;
    	for(i=0;i<512;i++)
    	{
    		Stack[i].num = 0;
    		Stack[i].who = 0;
    		Stack[i].word = NULL;
    		temp_Stack[i].num = 0;
    		temp_Stack[i].who = 0;
    		temp_Stack[i].word = NULL;
    	}
    
    	//开始读用户输入,进行预处理
    	int j;
    	if(chInPut[0] == '-')//开头是负号
    	{
    		push(TEMP_STACK,0,0,NULL);
    	}
    
    	int Converge = 0;		//用于累计以存放多位数
    	for(j=0;j<512;j++)
    	{
    		if('0'<=chInPut[j]&&chInPut[j]<='9')//如果是数字
    		{
    			if('0'<=chInPut[j+1]&&chInPut[j+1]<='9')//这个数是两位以上,因为下一个也是数
    			{
    				if(!('0'<=chInPut[j-1]&&chInPut[j-1]<='9'))//这只是这个两位以上的数的开头
    				{
    					char ch[2];
    					ch[0] = chInPut[j];
    					Converge = atoi(ch);//先就直接放进去
    					continue;
    				}
    				int n;
    				char ch[2];
    				ch[0] = chInPut[j];
    				n = atoi(ch);
    				Converge*=10;
    				Converge+=n;
    			}
    			else if(('0'<=chInPut[j-1]&&chInPut[j-1]<='9')&&!('0'<=chInPut[j+1]&&chInPut[j+1]<='9'))//这个数是两位以上的一个数的结尾
    			{
    				int n;
    				char ch[2];
    				ch[0] = chInPut[j];
    				n = atoi(ch);
    				Converge*=10;
    				Converge+=n;
    				push(TEMP_STACK,0,Converge,NULL);
    				Converge = 0;//清零
    			}
    			else//这只是个位数
    			{
    				char ch[2];
    				ch[0] = chInPut[j];
    				int temp_into = atoi(ch);
    				push(TEMP_STACK,0,temp_into,NULL);
    			}
    		}
    		else if((chInPut[j] == '+')||(chInPut[j] == '-')||(chInPut[j] == '*')
    			||(chInPut[j] == '/')||(chInPut[j] == ')'))//是符号
    		{
    			push(TEMP_STACK,1,0,chInPut[j]);
    		}
    		//一切的括号都必须是小括号,如遇中大括号,转换为小括号
    		else if(chInPut[j] == '('||chInPut[j] == '['||chInPut[j] == '{')//是左括号,要确认一下是不是以负号开头
    		{
    			push(TEMP_STACK,1,0,'(');
    			if(chInPut[j+1] == '-')
    			{
    				push(TEMP_STACK,0,0,NULL);
    			}
    		}
    		else if(chInPut[j] == ']'||chInPut[j] == '}')
    		{
    			push(TEMP_STACK,1,0,')');
    		}
    	}
    	
    }
    
    void count()	//开始计算
    {
    	int progress;//指向现在计算到的地方
    	for(progress=0;progress<temp_top;progress++)
    	{
    		if((temp_Stack[progress].who == 1)&&(temp_Stack[progress].word == '*'))//碰上乘号
    		{
    			if(temp_Stack[progress+1].who == 0)//乘号后面是数字
    			{
    				int C1 = Stack[top-1].num;
    				int C2 = temp_Stack[progress+1].num;
    				int J = C1*C2;
    				pop(MAIN_STACK);
    				push(MAIN_STACK,0,J,NULL);
    				progress++;
    				continue;
    			}
    			else
    			{
    				push(MAIN_STACK,1,0,'*');
    			}
    		}
    		else if((temp_Stack[progress].who == 1)&&(temp_Stack[progress].word == '/'))//碰上除号
    		{
    			if(temp_Stack[progress+1].who == 0)//除号后面是数字
    			{
    				int C1 = Stack[top-1].num;
    				int C2 = temp_Stack[progress+1].num;
    				int J = C1/C2;
    
    				//由于可能会出现余数,有余数的情况要提示
    				int ys = C1%C2;
    				if(ys != 0)
    				{
    					printf("余数已忽略");
    				}
    
    				pop(MAIN_STACK);
    				push(MAIN_STACK,0,J,NULL);
    				progress++;
    				continue;
    			}
    			else
    			{
    				push(MAIN_STACK,1,0,'/');
    			}
    		}
    		else if((temp_Stack[progress].who == 1)&&(temp_Stack[progress].word == ')'))//碰上右括号
    		{
    			int J;
    			if((Stack[top-1].who == 0)&&(Stack[top-2].who == 1 && Stack[top-2].word == '('))//有一个特殊情况,就是括号内已经只剩下数字
    			{
    				//如果括号内只剩下数字,那么就把数字提出,去掉括号,再将数字放回
    				int shift;
    				shift = Stack[top-1].num;
    				pop(MAIN_STACK);
    				pop(MAIN_STACK);
    				push(MAIN_STACK,0,shift,NULL);
    				goto Checkpoints;//直接跳转到乘除号检查点
    			}
    
    			int k;
    			BOWL result;//计算的结果
    			int nPopNum = 0;//出栈计数
    			BOWL pNode[4];//保存出栈的数据
    			//初始化
    			for(k=0;k<4;k++)
    			{
    				pNode[k].who = 0;
    				pNode[k].num = 0;
    				pNode[k].word = NULL;
    			}
    			result.who = 0;
    			result.num = 0;
    			result.word = NULL;
    
    			while(!((Stack[top - 1].who == 1)&&(Stack[top - 1].word == '(')))//碰到左括号之前,while循环成立
    			{
    				pNode[3-nPopNum] = pop(MAIN_STACK);
    				nPopNum++;
    				if(nPopNum == 4)
    				{
    					if( 1 == pNode[0].who )
    					{
    						if('-' == pNode[0].word)
    						{
    							if((1 == pNode[2].who) &&(0 == pNode[1].who) && (0 == pNode[3].who))
    							{
    								if('+' == pNode[2].word)
    								{
    									result.who = 0;
    									result.num = pNode[1].num - pNode[3].num;
    								}
    								else if('-' == pNode[2].word)
    								{
    									result.who = 0;
    									result.num = pNode[1].num + pNode[3].num;
    								}
    								else
    								{
    									printf("MISS BUG!\n");
    									//表达式错误
    									break;
    								}
    							}
    							else
    							{
    								printf("MISS BUG!\n");
    								//表达式错误
    								break;
    							}
    						}
    						else if('+' == pNode[0].word)
    						{
    							if((1 == pNode[2].who) &&(0 == pNode[1].who) && (0 == pNode[3].who))
    							{
    								if('+' == pNode[2].word)
    								{
    									result.who = 0;
    									result.num = pNode[1].num + pNode[3].num;
    								}
    								else if('-' == pNode[2].word)
    								{
    									result.who = 0;
    									result.num = pNode[1].num - pNode[3].num;
    								}
    								else
    								{
    									printf("MISS BUG!\n");
    									//表达式错误
    									break;
    								}
    							}
    							else
    							{
    								printf("MISS BUG!\n");
    								//表达式错误
    								break;
    							}
    						}
    						else
    						{
    							printf("MISS BUG!\n");
    							//表达式错误
    							break;
    						}
    					}
    					push(MAIN_STACK,1,0,pNode[0].word);
    					push(MAIN_STACK,0,result.num,NULL);
    					nPopNum = 0;
    				}
    			}
    			if(nPopNum == 3)
    			{
    				if(pNode[2].word == '+')
    				{
    					result.num = pNode[1].num + pNode[3].num;
    				}
    				if(pNode[2].word == '-')
    				{
    					result.num = pNode[1].num - pNode[3].num;
    				}
    				pop(MAIN_STACK);
    				push(MAIN_STACK,0,result.num,NULL);
    			}
    			else
    			{
    				//有问题
    				printf("MISS BUG!\n");
    			}
    Checkpoints:
    			if(Stack[top-2].word == '*' || Stack[top-2].word == '/')//再次确认一下前面是不是乘除号
    			{
    				if(Stack[top-2].word == '*')
    				{
    					J = Stack[top-3].num * Stack[top-1].num;
    				}
    				else if(Stack[top-2].word == '/')
    				{
    					J = Stack[top-3].num / Stack[top-1].num;
    				}
    				pop(MAIN_STACK);
    				pop(MAIN_STACK);
    				pop(MAIN_STACK);
    				push(MAIN_STACK,0,J,NULL);
    			}
    		}
    		else//如果是数字和加减号,直接放进栈里就好,最后一起计算。
    		{
    			if (temp_Stack[progress].who == 0)
    			{
    				push(MAIN_STACK,0,temp_Stack[progress].num,NULL);
    			}
    			else if (temp_Stack[progress].who == 1)
    			{
    				push(MAIN_STACK,1,0,temp_Stack[progress].word);
    			}
    		}
    	}
    
    	//最后的一点计算
    	int k;
    	BOWL result;//计算的结果
    	int nPopNum = 0;//出栈计数
    	BOWL pNode[4];//保存出栈的数据
    	//初始化
    	for(k=0;k<4;k++)
    	{
    		pNode[k].who = 0;
    		pNode[k].num = 0;
    		pNode[k].word = NULL;
    	}
    	result.who = 0;
    	result.num = 0;
    	result.word = NULL;
    
    	//如果只剩下一个数
    	if(top == 1 && Stack[top].who == 0)
    	{
    		goto last;
    	}
    
    	while (top >= 1)
    	{
    		//此处要参照中间处理括号的方法重写
    		pNode[3-nPopNum] = pop(MAIN_STACK);
    		nPopNum++;
    		if(nPopNum == 4)
    		{
    			if( 1 == pNode[0].who )
    			{
    				if('-' == pNode[0].word)
    				{
    					if((1 == pNode[2].who) &&(0 == pNode[1].who) && (0 == pNode[3].who))
    					{
    						if('+' == pNode[2].word)
    						{
    							result.who = 0;
    							result.num = pNode[1].num - pNode[3].num;
    						}
    						else if('-' == pNode[2].word)
    						{
    							result.who = 0;
    							result.num = pNode[1].num + pNode[3].num;
    						}
    						else
    						{
    							//表达式错误
    							printf("MISS BUG!\n");
    							break;
    						}
    					}
    					else
    					{
    						//表达式错误
    						printf("MISS BUG!\n");
    						break;
    					}
    				}
    				else if('+' == pNode[0].word)
    				{
    					if((1 == pNode[2].who) &&(0 == pNode[1].who) && (0 == pNode[3].who))
    					{
    						if('+' == pNode[2].word)
    						{
    							result.who = 0;
    							result.num = pNode[1].num + pNode[3].num;
    						}
    						else if('-' == pNode[2].word)
    						{
    							result.who = 0;
    							result.num = pNode[1].num - pNode[3].num;
    						}
    						else
    						{
    							//表达式错误
    							printf("MISS BUG!\n");
    							break;
    						}
    					}
    					else
    					{
    						//表达式错误
    						printf("MISS BUG!\n");
    						break;
    					}
    				}
    				else
    				{
    					//表达式错误
    					printf("MISS BUG!\n");
    					break;
    				}
    			}
    			push(MAIN_STACK,1,0,pNode[0].word);
    			push(MAIN_STACK,0,result.num,NULL);
    			nPopNum = 0;
    		}
    	}
    	if(nPopNum == 3)
    	{
    		if(pNode[2].word == '+')
    		{
    			result.num = pNode[1].num + pNode[3].num;
    		}
    		if(pNode[2].word == '-')
    		{
    			result.num = pNode[1].num - pNode[3].num;
    		}
    		//pop(MAIN_STACK);
    		push(MAIN_STACK,0,result.num,NULL);
    	}
    	else
    	{
    		//有问题
    		printf("MISS BUG!\n");
    	}
    
    last:
    	Result = Stack[0].num;
    }
    
    int _tmain()
    {
    	printf("汇东表达式计算器  Ver1.0\n官网:www.huidong.xyz\n请输入你的表达式(要求表达式要正确):\n");
    	gets_s(chInPut);
    	system("cls");
    	system("title 汇东表达式计算器");
    	CS = 0;
    	init_Stack();
    	count();
    	printf("\n原算式:");
    	puts(chInPut);
    	printf("\n处理后算式:");
    	for(int i=0;i<temp_top;i++)
    	{
    		if(temp_Stack[i].who == 0)
    		{
    			printf("%d",temp_Stack[i].num);
    		}
    		else if(temp_Stack[i].who == 1)
    		{
    			printf("%c",temp_Stack[i].word);
    		}
    	}
    	printf("\n计算结果:%d\n按R结束...\n",Result);
    	while(true)
    	{
    		char ch = _getch();
    		if(ch == 'R' || ch == 'r')
    			return 0;
    	}
    }
    
    
    

    效果预览

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • C语言基础算法总结 表达式计算、分支函数、判特殊数、数位分解合成、求最值、累加算法、典型数学问题、穷举、查找、排序、易位
  • 这里限定的表达式求值问题是:用户输入一个包含“+”、“-”、“*”、“/”、正整数和圆括号的合法数学表达式,计算该表达式的运算结果 2.输入 表达式字符串 3.输出 表达式值 4.样例输入 15 5.提示 1)运算符...

    一、实验要求

    1.描述

    这里限定的表达式求值问题是:用户输入一个包含“+”、“-”、“*”、“/”、正整数和圆括号的合法数学表达式,计算该表达式的运算结果

    2.输入

    表达式字符串

    3.输出

    表达式值

    4.样例输入

    15

    5.提示

    1)运算符优先级关系

     

    ×

    (

    )

    #

    >

    >

    <

    <

    <

    >

    >

    >

    >

    <

    <

    <

    >

    >

    ×

    >

    >

    >

    >

    <

    >

    >

    >

    >

    >

    >

    <

    >

    >

    (

    <

    <

    <

    <

    <

    =

     

    )

    >

    >

    >

    >

     

    >

    >

    #

    <

    <

    <

    <

    <

     

    =

    2)涉及的基本操作(函数)

    函数名

    功能

    函数名

    功能

    InitStack()

    初始化栈

    Push()

    入栈

    GetTop()

    获栈顶元素

    Precede()

    优先级比较

    Pop()

    出栈

    Operate()

    运算

    3)解题思想实现算法描述

    OperandType EvaluateExpression()
    { //算术表达式求值的算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈,OP为运算符的集合。
        InitStack(OPTR);Push(OPTR,'#');
        InitStack(OPND);c=getchar();
        while(c!='#'||GetTop(OPTR)!='#')
        {
            if(!In(c,OP))
            {
                Push((OPND,c);
                c=getchar();
            }
            //不是运算符则进栈
            else
                switch(Precede(GetTop(OPTR), c)
                {
                    case '<'://栈顶元素优先权低
                        Push(OPTR,c); c=getchar(); break;
                    case '=':// 脱括号并接收下一个字符
                        Pop(OPTR, x); c=getchar(); break;
                    case ‘>’://出栈,并将运算结果入栈
                        Pop(OPTR,theta);
                        Pop(OPND,b); Pop(OPND,a);
                        Push(OPND,Operate(a,theta,b));
                }//swith
        }//while
        return GetTop(OPND);
    }//EvaluateExpression

    二、需求分析

    本实验通过C语言来实现数据结构中的栈,以及通过使用栈这个数据结构完成1~9整数之间的加、减、乘、除四则混合运算的实验,并完成指定的测试操作。

    1. 从键盘输入:数字1-9、“(”左括号、“)”右括号、“+”加号、“-”减号、“*”乘号、“/”除号构成的表达式并以“#”号结尾,结果输出:形如:“结果=”+表达式的值。
    2. 本程序没有边界约束,违反输入规则的均会导致程序运行失败。

    三、概要设计

    1.抽象数据类型的定义

    typedef struct{
        SElemType *base; //在栈构造之前和销毁之后,base的初值为NULL
        SElemType *top; //栈顶指针,设栈顶、栈底指针的目的是便于判断栈是否为空
        int stacksize; //当前已分配的存储空间,以元素为单位.
    }SqStack;//栈
    

    2.主程序的流程图

    3.本程序各功能模块之间均不互相调用,单独成块,由主函数一一调用。

    四、详细设计

    1.程序开始预编译部分如下:

    //头文件
    #include <stdio.h>
    #include <stdlib.h>
    
    // 函数结果状态代码
    #define OVERFLOW -2
    #define TRUE 1
    #define FALSE 0
    #define OK 1
    #define ERROR 0
    
    typedef int Status;
    
    typedef char RElemtype;
    typedef int DElemtype;
    
    //内存空间数量级
    #define STACK_INIT_SIZE 100
    #define STACKINCREMENT 10
    
    typedef struct {
        RElemtype *base;
        RElemtype *top;
        int stacksize;
    } SqStack1;//运算符栈类型定义
    
    typedef struct {
        DElemtype *base;
        DElemtype *top;
        int stacksize;
    } SqStack2;//操作数栈类型定义
    

    2.程序主要功能函数如下:

    DElemtype EvaluateExpression();//计算表达式值
    Status OPTR_InitStack(SqStack1 *S);//运算符栈的初始化
    Status OPND_InitStack(SqStack2 *S);//操作数栈的初始化
    RElemtype OPTR_GetTop(SqStack1 S);//取运算符栈的栈顶元素
    DElemtype OPND_GetTop(SqStack2 S);//取操作数栈的栈顶元素
    Status OPTR_Push(SqStack1 *S, RElemtype e);//压栈
    Status OPND_Push(SqStack2 *S, DElemtype e);//压栈
    RElemtype OPTR_Pop(SqStack1 *S, RElemtype *e);//出栈
    DElemtype OPND_Pop(SqStack2 *S, DElemtype *e);//出栈
    char Precede(char a, char b);//运算符优先级比较
    DElemtype Operate(DElemtype d, char e, DElemtype f);//操作数d、f参加e运算的结果
    extern int In(char c);//判断c是否是运算符

    3.函数调用关系图

    五、调试分析

    1. 在EvaluateExpression()表达式计算中,默认开始初始化OPTR运算符栈和OPND运算数栈,在运算符栈的栈底要默认有一个“#”号用于结束表达式的计算和字符输入。刚开始我没加,导致程序一直需要输入字符,无法结束,之后加上,解决。
    2. In(char c)运算符判断函数,刚开始写时忘记加入左右括号和“#”号的判断,没有对“#”号导致EvaluateExpression()函数中的while循环成死循环状态,最终使程序陷入死循环;没有判断括号,导致括号入错栈,造成表达式的计算的顺序和计算的数的位置出现问题,括号被做为数值参与到运算,同时导致运算数栈存在计算完成,元素仍有存留的现象,最终导致计算结果不正确。
    3. 如何将输出的char字符转成正确的int数值存入操作数栈中?解决办法:每次存入OPND的char字符减去字符‘0’的ASCII值从而得到正确的int数值,在存入其中。
    4. 比较两个运算符的优先级函数char Precede(char a, char b)思路解析:

    运算符优先级比较表:

    将运算符之间的优先级制作成一张表格,使用二维数组存放;

        char pre[][7] = {
                //将运算符之间的优先级制作成一张表格
                {'>', '>', '<', '<', '<', '>', '>'},
                {'>', '>', '<', '<', '<', '>', '>'},
                {'>', '>', '>', '>', '<', '>', '>'},
                {'>', '>', '>', '>', '<', '>', '>'},
                {'<', '<', '<', '<', '<', '=', '0'},
                {'>', '>', '>', '>', '0', '>', '>'},
                {'<', '<', '<', '<', '<', '0', '='}
        };
    

    通过两个switch语句来定位需要判断符号的优先级所对应的数组的一维下标和二维下标,取出指定的元素,'>'表示a>b;'<'表示a<b;'0'表示不可能出现的比较;“(“=”)”表示左右括号相遇,括号内的运算已经完成, “#“=”#” 表达式求值完成。

    switch (a) {
            case '+':i = 0;break;
            case '-':i = 1;break;
            case '*':i = 2;break;
            case '/':i = 3;break;
            case '(':i = 4;break;
            case ')':i = 5;break;
            case '#':i = 6;break;
            default:return OVERFLOW;
        }
        switch (b) {
            case '+':j = 0;break;
            case '-':j = 1;break;
            case '*':j = 2;break;
            case '/':j = 3;break;
            case '(':j = 4;break;
            case ')':j = 5;break;
            case '#':j = 6;break;
            default:return OVERFLOW;
        }
    

    六、测试数据与结果

    1.开始界面

    2.输入 指定格式的运算符表达式(因为格式有所要求,故不做边界测试)

    如:2+3x(5+6-3x2)+4/(6-4)-3x3+1=11

    结果如下:

    3.输出结果格式:“结果=” +表达式的值

    实验成功!

    附录——源代码清单

    fun.h

    //头文件
    #include <stdio.h>
    #include <stdlib.h>
    
    // 函数结果状态代码
    #define OVERFLOW -2
    #define TRUE 1
    #define FALSE 0
    #define OK 1
    #define ERROR 0
    
    typedef int Status;
    
    typedef char RElemtype;
    typedef int DElemtype;
    
    //内存空间数量级
    #define STACK_INIT_SIZE 100
    #define STACKINCREMENT 10
    
    typedef struct {
        RElemtype *base;
        RElemtype *top;
        int stacksize;
    } SqStack1;//运算符栈类型定义
    
    typedef struct {
        DElemtype *base;
        DElemtype *top;
        int stacksize;
    } SqStack2;//操作数栈类型定义
    
    extern DElemtype EvaluateExpression();//计算表达式值
    extern Status OPTR_InitStack(SqStack1 *S);//运算符栈的初始化
    extern Status OPND_InitStack(SqStack2 *S);//操作数栈的初始化
    extern RElemtype OPTR_GetTop(SqStack1 S);//取运算符栈的栈顶元素
    extern DElemtype OPND_GetTop(SqStack2 S);//取操作数栈的栈顶元素
    extern Status OPTR_Push(SqStack1 *S, RElemtype e);//压栈
    extern Status OPND_Push(SqStack2 *S, DElemtype e);//压栈
    extern RElemtype OPTR_Pop(SqStack1 *S, RElemtype *e);//出栈
    extern DElemtype OPND_Pop(SqStack2 *S, DElemtype *e);//出栈
    extern char Precede(char a, char b);//运算符优先级比较
    extern DElemtype Operate(DElemtype d, char e, DElemtype f);//操作数d、f参加e运算的结果
    extern int In(char c);//判断c是否是运算符
    

    main.c

    #include "fun.h"
    /**
     * 默认栈底有一个结束符‘#’
     * 操作符忘记判断#号 (号 )号  死了多次
     * 操作数ascii值转int再运算 死了两次
     */
    Status OPTR_InitStack(SqStack1 *S) {//运算符栈的初始化
        //构造一个空栈S
        S->base = (RElemtype *) malloc(STACK_INIT_SIZE * sizeof(RElemtype));
        if (!S->base) return (OVERFLOW); //存储分配失败
        S->top = S->base;
        S->stacksize = STACK_INIT_SIZE;
        return OK;
    }
    
    Status OPND_InitStack(SqStack2 *S) {//操作数栈的初始化
        //构造一个空栈S
        S->base = (DElemtype *) malloc(STACK_INIT_SIZE * sizeof(DElemtype));
        if (!S->base) return (OVERFLOW); //存储分配失败
        S->top = S->base;
        S->stacksize = STACK_INIT_SIZE;
        return OK;
    }
    
    RElemtype OPTR_GetTop(SqStack1 S) {//取运算符栈的栈顶元素
        if (S.top == S.base) return ERROR;//若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
        return *(S.top - 1); //栈顶指针不变
    }
    
    DElemtype OPND_GetTop(SqStack2 S) {//取操作数栈的栈顶元素
        if (S.top == S.base) return ERROR;//若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
        return *(S.top - 1); //栈顶指针不变
    }
    
    Status OPTR_Push(SqStack1 *S, RElemtype e) {//压栈
        //插入元素e为新的栈顶元素
        if (S->top - S->base >= S->stacksize) {//栈满,追加存储空间
            S->base = (RElemtype *) realloc(S->base, (S->stacksize + STACKINCREMENT) * sizeof(RElemtype));
            if (!S->base) return (OVERFLOW);
            S->top = S->base + S->stacksize;
            S->stacksize += STACKINCREMENT;
        }
        *S->top++ = e;
        return OK;
    }
    
    
    Status OPND_Push(SqStack2 *S, DElemtype e) {//压栈
        //插入元素e为新的栈顶元素
        if (S->top - S->base >= S->stacksize) {//栈满,追加存储空间
            S->base = (DElemtype *) realloc(S->base, (S->stacksize + STACKINCREMENT) * sizeof(DElemtype));
            if (!S->base) return (OVERFLOW);
            S->top = S->base + S->stacksize;
            S->stacksize += STACKINCREMENT;
        }
        *S->top++ = e;
        return OK;
    
    }
    
    RElemtype OPTR_Pop(SqStack1 *S, RElemtype *e) {//出栈
        //若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
        if (S->top == S->base) return ERROR; //栈空
        *e = *--S->top;
        return *e;
    }
    
    DElemtype OPND_Pop(SqStack2 *S, DElemtype *e) {//出栈
        //若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
        if (S->top == S->base) return ERROR; //栈空
        *e = *--S->top;
        return *e;
    }
    
    char Precede(char a, char b) {
        /**
         * 比较两个运算符的优先级;
         * a,b中存放待比较的运算符;
         * '>'表示a>b;
         * '0'表示不可能出现的比较.
         */
        int i, j;
        char pre[][7] = {
                //将运算符之间的优先级制作成一张表格
                {'>', '>', '<', '<', '<', '>', '>'},
                {'>', '>', '<', '<', '<', '>', '>'},
                {'>', '>', '>', '>', '<', '>', '>'},
                {'>', '>', '>', '>', '<', '>', '>'},
                {'<', '<', '<', '<', '<', '=', '0'},
                {'>', '>', '>', '>', '0', '>', '>'},
                {'<', '<', '<', '<', '<', '0', '='}
        };
        switch (a) {
            case '+':
                i = 0;
                break;
            case '-':
                i = 1;
                break;
            case '*':
                i = 2;
                break;
            case '/':
                i = 3;
                break;
            case '(':
                i = 4;
                break;
            case ')':
                i = 5;
                break;
            case '#':
                i = 6;
                break;
            default:
                return OVERFLOW;
        }
        switch (b) {
            case '+':
                j = 0;
                break;
            case '-':
                j = 1;
                break;
            case '*':
                j = 2;
                break;
            case '/':
                j = 3;
                break;
            case '(':
                j = 4;
                break;
            case ')':
                j = 5;
                break;
            case '#':
                j = 6;
                break;
            default:
                return OVERFLOW;
        }
        return pre[i][j];
    }
    
    DElemtype Operate(DElemtype d, char e, DElemtype f) {//操作数d、f参加e运算的结果
        DElemtype i = d, j = f, result;
        switch (e) {
            case '+':
                result = i + j;
                break;
            case '-':
                result = i - j;
                break;
            case '*':
                result = i * j;
                break;
            case '/':
                result = i / j;
                break;
            default://可能不会被使用
                printf("出现非法运算符,程序终止!");
                exit(0);
        }
        return result;
    }
    
    int In(char c) {//判断c是否是运算符
        return c == '+' ||
               c == '-' ||
               c == '*' ||
               c == '/' ||
               c == '(' ||
               c == ')' ||
               c == '#' ?
               TRUE : FALSE;
    }
    
    DElemtype EvaluateExpression() {//计算表达式值
        /**
         * 算术表达式求值的算符优先算法;
         *设OPTR和OPND分别为运算符栈和运算数栈;
         */
        SqStack1 OPTR;
        SqStack2 OPND;
        DElemtype a, b;
        char flag;
        char c, x, theta;
        OPTR_InitStack(&OPTR);
        OPTR_Push(&OPTR, '#');//默认栈底有一个结束符‘#’
        OPND_InitStack(&OPND);
        c = getchar();
        while (c != '#' || OPTR_GetTop(OPTR) != '#') {
            if (In(c) != TRUE) {//不是运算符则进操作数栈
                OPND_Push(&OPND, c - '0');
    
                c = getchar();
            } else {
                flag = Precede(OPTR_GetTop(OPTR), c);
                switch (flag) {
                    case '<'://栈顶元素优先权低
                        OPTR_Push(&OPTR, c);
                        c = getchar();
                        break;
                    case '='://脱括号并接收下一字符
                        OPTR_Pop(&OPTR, &x);
                        c = getchar();
                        break;
                    case '>'://退栈并将运算结果入栈
                        OPTR_Pop(&OPTR, &theta);
                        OPND_Pop(&OPND, &b);
                        OPND_Pop(&OPND, &a);
                        OPND_Push(&OPND, Operate(a, theta, b));
                        break;
                }//swith
            }
        }//while
        return OPND_GetTop(OPND);
    }//EvaluateExpression
    
    int main() {
        DElemtype c;
        printf("请输入一个算数表达式(操作数为1~9的整数)并以“#”号结束:");
        c = EvaluateExpression();
        printf("结果=%d\n", c);
    }
    

     

    展开全文
  • 本章的主要内容包括: C语言中的数据表示 C语言数据类型 C语言表达式计算C语言数学函数。
  • 数学中,数值是不分类型的,数值的运算是绝对准确的,例如:1/3的值是0.333333(循环小数)。而在计算机中,数据是存放在存储单元中的,它是具体存在的。而且,存储单元是由有限的字节构成的,每一个存储单元中存放...
  • 本文演示如何利用自定义堆栈(可实现通用性)和逆波兰表达式(后缀表达式)来进行数学四则运算。 阅读须知:了解堆栈定义过程、了解中缀表达式、了解后缀表达式(逆波兰表达式)。不清楚的同学百度一下,用10分钟了解一下...
  • 要先明白怎么让计算机认得你输入的数学表达式2.1解决方案——将表达式转为后缀表达式二、有了理论知识后我们开搞1.准备工作2.大致的实现过程3.个函数实现的详细步骤3.1: int LeftPri(char op); //左运算符op的...
  • 规定 标识符只能由字母、数字、下划线组成 只能以字母或下划线开头 不能使用系统关键词 int main ...①数学表达式C语言表达式 ②一目运算符优先于二目运算符 ③相同类型的算数运算结果一定是原类型,不行类型...
  • 前言 先来啰嗦几句,身边的朋友,同事都喜欢在博客上记录自己在学习计算机编程技术...对于计算技术,越是深入越越数学挂钩,想达到大神级别,嗯,我是有自知之明的。计算机技术虽然之多,并不需要我们每一个领域每...
  • 又回归到简单的数学问题,让我们一起学习c语言在计算机里面运算的表达。运算符:1算术运算符算术运算符解释例子+加c = a+b;-减c = a-b;*乘c = a*b;/除法(取整数)c = a/b;%取余数(除法)c = a%b;++自增1c++;先赋值...
  • 数学中,数值是不分类型的,数值的运算是绝对准确的,例如:1/3的值是0.333333(循环小数)。而在计算机中,数据是存放在存储单元中的,它是具体存在的。而且,存储单元是由有限的字节构成的,每一个存储单元中存放...
  • 一、选择题(10分) 21、以下关于C语言源程序的叙述中,错误的是_____。 A.一个C语言源程序由若干个函数定义组成,其中必须有且仅有一个名为main的...24、以下表示数学式“a”的逻辑表达式中,错误的是____。
  • C语言习题综合.pdf

    2020-08-21 10:31:47
    第二章练习题 .选择题 1. 以下选项中正确的实型常量 2 A 0 B 3....对数学表达式 ,写出三个等价的c语言表达式_ } 第三章 练习题 一选择题 1.若a ,b,c都是int型变量且初值为0以下选项中不正确的赋值 语句 A
  • C语言概念

    2018-03-05 00:09:49
    C语言概念 ...高级语言:最接近 于数学语言或人的自然语言 C语言发展史 C语言的工作方式 C程序的结构 2. 常量、变量、表达式 声明和定义 C语言中的声明有变量声明、函数声明、类型声...
  • C语言即是一种用英语和数学表达式这样的一种接近自然语言的语句来描述程序过程中的计算机程序设计语言。C语言结构简洁,只有32个关键字,9种控制语句,因此书写方便。 由C语言规定的文字和规则书写的程序叫做C的源...
  • 前面我们已经知道位置型PID和增量型PID的数学表达式,我们根据这些表达式就可以实现基本的PID的C语言编程了!下面我们开始C语言的编写。 第一步:创建一个PID各项参数的变量结构体。 第二步:PID参数...
  • C语言算式判断

    2019-11-22 22:05:48
    一个100以内加减法的数学表达式 输出 如果小明算的正确,输出YES,如果小明算错了,那么第一行输出NO,第二行输出正确结果的表达式 样例输入 Copy 1+2=4 样例输出 Copy NO 1+2=3 #include<stdio.h> ...
  • 输入数学表达式 输入为数字 和“+ - * / ^(平方) r(根号)s(sin) c(cos) t(tan) l(ln)以及括号" 2、思路 (1)识别小数和大于10的数,和运算符同时存入double类型的数组 (2)改写为后缀表达式 (3)用后缀表达式...
  • 一、知识点总结 ... //就是一般的单条表达式语句,笔者前面发的程序大部分都是都是由语句序列组成 (2) 如果满足某种条件就重复执行语句序列(循环);//靠while,do while,for循环实现此功能。为了满足...
  • C语言表达式由运算符和运算对象组成,任何一个表达式都有一个确定的值,称为该表达式的值 运算符的优先级与结合性 戳这里,超详解 常用运算符 数学函数的使用(需要#include<math.h>) 函数名 ...
  • 们打算为用户提供一个简单计算功能,用户输入数学算式,就可以得到计算结果。其中涉及的计算包括:”+”、”-”、 ”*”、”/”、”^”、”(”、”)”,分别表示加减乘除和指数,其中括号用于调整计算的顺序。合法...
  • 计算数学公式/数学表达式** 重点:数学公式,Format表达式(小数点) %6.2f 表示一共6位数,其中两位是小数,不足六位前面补空格,小数点不算一位 1)关于圆 2)从键盘输入小于1000的正数,要求输出平方根,如果...

空空如也

空空如也

1 2 3 4 5 ... 13
收藏数 244
精华内容 97
关键字:

c语言计算数学表达式

c语言 订阅