天星灵师 2021-06-17 18:10 采纳率: 50%
浏览 546
已结题

用C语言编写一个计算器,要求能进行加减乘除,乘方和带括号的运算

 

  • 写回答

4条回答 默认 最新

  • CSDN专家-link 2021-06-17 18:16
    关注
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #define INIT_STRING_SIZE 100
    #define True 1
    #define False 0
    int saved_class[4] = { 0, 0, 0, 0 };
    typedef struct aNum {
    	double data;
    	char oper;
    	int dataClass;
    	int power;
    	struct aNum *next;
    }num;
    typedef struct {
    	char *formula;
    	int length;
    }string;
    
    void setNULL(char *num)//清空一个字符串
    {
    	int i = 0;
    	while (i<5)
    	{
    		num[i] = NULL;
    		++i;
    	}
    }
    int countOperators(string *input, int &counter)//processing step 1
    {//计算运算符个数
    	int i = 0;
    	while (input->formula[i] != '\0')
    	{
    		switch (input->formula[i++])
    		{
    		case '+':
    		case '-':
    		case '*':
    		case '/':++counter; break;
    		default:break;
    		}
    		++input->length;
    	}
    	return 1;
    }
    int getData(string *input, num *nums)//processing step 2
    {//把数字,符号和class存入nums的结构体
    	int i = 0;    //counter of input->formula
    	int k = 0;  //counter of temp;
    	int power = 0;
    	char temp[5];
    	int inBracket = False;
    	num *p = nums;
    	num *body;
    
    	while (i <= input->length)
    	{
    		if ((input->formula[i]<'0' || input->formula[i]>'9')&&input->formula[i]!='.'&&input->formula[i]!='^')
    		{//进入此处时数据已经收集完毕
    			if (input->formula[i] == '(')
    			{
    				inBracket = True;
    				++i;
    				continue;
    			}
    			if (input->formula[i] == ')')
    			{
    				inBracket = False;
    				++i;
    				continue;
    			}
    			body = (num *)calloc(1, sizeof(num));
    
    			body->data = atof(temp);    //得到数字
    			setNULL(temp);              //归零temp
    			k = 0;
    
    			switch (input->formula[i])
    			{
    			case '+':body->dataClass = inBracket == False ? 1 : 3;  //计算当前运算符的等级
    				++saved_class[body->dataClass - 1];                 //在等级数组里记录一次
    				body->oper = input->formula[i];                     //得到运算符
    				break;
    
    			case '-':body->dataClass = inBracket == False ? 1 : 3;
    				++saved_class[body->dataClass - 1];
    				body->oper = input->formula[i];
    				break;
    
    			case 'x':
    			case '*':body->dataClass = inBracket == False ? 2 : 4;
    				++saved_class[body->dataClass - 1];
    				body->oper = input->formula[i];
    				break;
    
    			case '/':body->dataClass = inBracket == False ? 2 : 4;
    				++saved_class[body->dataClass - 1];
    				body->oper = input->formula[i];
    				break;
    
    			default:break;
    			}
    			if (power != 0)
    			{
    				body->power = power;
    				power = 0;
    			}
    			p->next = body;
    			p = p->next;
    		}
    		else if (input->formula[i] == '^')
    		{
    			power = input->formula[++i] - 48;
    		}
    		else
    		{
    			temp[k++] = input->formula[i];
    		}
    		++i;
    	}
    	return 1;
    }
    double compute(double num1, double num2, char opt)
    {//每次运算单独提取
    	double result;
    	switch (opt)
    	{
    	case '-':result = num1 - num2; break;
    	case '+':result = num1 + num2; break;
    	case 'x':
    	case '*':result = num1 * num2; break;
    	case '/':result = num1 / num2; break;
    	}
    	return result;
    }
    int processingData(num *nums)//processing step 3
    {//nums作为头结点是没有数据的
    	int s = 3;//saved_class
    	int i = 0;
    	num *p = nums;
    	num *p_front;
    	while (saved_class[s] == 0&&s>0)
    		--s;
    	while (p->next->next != NULL)//class oper next 都可以
    	{
    		if (p->next->dataClass != s + 1)
    		{
    			p = p->next;
    			continue;
    		}
    		p_front = p;
    		p = p->next;//p此时指向待计算的第一个struct aNUm
    		if(p->power != 0)
    		{
    			p->data = pow(p->data, p->power);
    			p->power = 0;
    		}
    		if (p->next->power != 0)
    		{
    			p->next->data = pow(p->next->data, p->next->power);
    			p->next->power = 0;
    		}
    		p->next->data = compute(p->data, p->next->data, p->oper);
    
    		p_front->next = p->next;
    		free(p);
    		--saved_class[s];
    		while (saved_class[s] == 0&&s!=0)
    			--s;
    		p = nums;
    
    
    	}
    	if (nums->next->power != 0)//处理单个数字输入的情况,比如2^2
    	{
    		nums->next->data = pow(nums->next->data, nums->next->power);
    	}
    
    
    	printf("result=%lf\n", nums->next->data);
    	return 1;
    }
    int main()
    {
    	int counter = 0;
    	num *nums = NULL;
    	string *input;
    	input = (string *)calloc(1, sizeof(string));
    	input->formula = (char *)calloc(INIT_STRING_SIZE, sizeof(string));
    
    
    	puts("Input formula:");
    	scanf("%s", input->formula);
    
    	//得到运算符和运算符个数
    	countOperators(input, counter);
    	//根据运算符个数申请存储数字的空间
    	nums = (num *)calloc(1, sizeof(num));
    	//存储数字和运算符
    	getData(input, nums);
    	processingData(nums);
    
    	free(input->formula);
    	free(input);
    	free(nums->next);
    	free(nums);
    	system("pause");//如果你是linux或者macos,可能需要去掉这句
    	return 0;
    }
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
  • CSDN专家-微编程 2021-06-17 18:25
    关注

    代码如下:

    #include<stdio.h>
    #include<stdlib.h>
    
    
    /*数据栈*/
    struct shuju   //struct结构体构建栈 
    {
    	int data[100];
    	int top;
    };
    
    
    /*符号栈*/ 
    struct fuhao
     {
    	char symbol[100];
    	int top;
    };
    
    
    void InitOperateNum(struct shuju *StackNum)    //数据栈非空 
    {
        StackNum->top = -1;
    }
    
    
    void InitOperateSymbol(struct fuhao *StackSymbol)    //符号栈非空 
    {  
        StackSymbol->top = -1; 
    }
    
    
    /*存入数据栈*/
    void Inshuju(struct shuju *StackNum, int num)
    {
    	StackNum->top ++;
    	StackNum->data[StackNum->top] = num;
    }
    
    
    /*存入符号栈*/ 
    void Infuhao(struct fuhao *StackSymbol, char ch)
    {
    	StackSymbol->top ++;
    	StackSymbol->symbol[StackSymbol->top] = ch;
    }
    
    
    /*读取数据栈*/
    int Randshuju(struct shuju *StackNum)
    {
    	return StackNum->data[StackNum->top];
    }
    
    
    /*读取符号栈*/
    char Randfuhao(struct fuhao *StackSymbol)
    {
    	return StackSymbol->symbol[StackSymbol->top];
    }
    
    
    /*从数据栈取出数据*/
    int Putshuju(struct shuju *StackNum)
    {
    	int x;
    	x = StackNum->data[StackNum->top];
    	StackNum->top --;
    	return x;
    }
    
    
    /*从符号栈取出符号*/
    char Putfuhao(struct fuhao *StackSymbol)
    {
    	char c;
    	c = StackSymbol->symbol[StackSymbol->top];
    	StackSymbol->top --;
    	return c;
    }
    
    
    /*符号优先级判断*/
    int judge(char ch) {
    	if(ch == '(')
    	 {
    		return 1; 
      	}
    	if(ch == '+' || ch == '-') {
    		return 2;
    	}
    	else if(ch == '*' || ch == '/') {
    		return 3;
    	}
    	else if(ch == ')') {
    		return 4;
    	}
    }
    
    
    /*四则运算*/
    int Math(int v1, int v2, char c)
    {
    	int sum;
    	switch(c) {
    		case '+' : {
    			sum = v1 + v2;
    			break;
    		}
    		case '-' : {
    			sum = v1 - v2;
    			break;
    		}
    		case '*' : {
    			sum = v1 * v2;
    			break;
    		} 
    		case '/' : {
    			sum = v1 / v2;
    			break;
    		}
    	}
    	return sum;
    }
    
    
    int main()
    {
    	struct shuju data;
    	struct fuhao symbol;
    	InitOperateNum(&data);   //调用数据 
    	InitOperateSymbol(&symbol);  //调用符号 
    	int i, t, sum, v1, v2;
    	char c;
    	i = t = sum = 0;
    	char v[100] = {0};
    	char *str = (char *)malloc(sizeof(char)*200);
    	while((c = getchar()) != '\n')  //非空字符 
    	 {
    		str[i] = c;
    		i ++;
    	}
    	str[i] = '\0';
    	for(i = 0; str[i] != '\0'; i ++) {
    		if(i == 0 && str[i] == '-') {
    			v[t++] = str[i];
    		}
    		else if(str[i] == '(' && str[i+1] == '-') {
    			i ++;
    			v[t++] = str[i++];
    			while(str[i] >= '0' && str[i] <= '9') {
    				v[t] = str[i];
    				t ++;
    				i ++;
    			}
    			Inshuju(&data, atoi(v));
    			while(t > 0) {
    				v[t] = 0;
    				t --;
    			}
    			if(str[i] != ')') {
    				i --;
    				Infuhao(&symbol, '(');
    			}
    		}
    		else if(str[i] >= '0' && str[i] <= '9') {
    			while(str[i] >= '0' && str[i] <= '9') {
    				v[t] = str[i];
    				t ++;
    				i ++;
    			}
    			Inshuju(&data, atoi(v));
    			while(t > 0) {
    				v[t] = 0;
    				t --;
    			}
    			i --;
    		}
    		else {
    			if(symbol.top == -1) 
    			{        //如果符号栈没有元素,直接把符号放入符号栈 
    				Infuhao(&symbol, str[i]);
    			}
    			else if(judge(str[i]) == 1) { //如果此符号是'(',直接放入符号栈 
    				Infuhao(&symbol, str[i]);
    			}
    			else if(judge(str[i]) == 2) { //如果此符号是'+'或'-',判断与栈顶符号是优先级 
    				if(judge(Randfuhao(&symbol)) == 1) { //如果栈顶符号是'(',放入符号栈 
    					Infuhao(&symbol, str[i]);
    				}
    				else if(judge(Randfuhao(&symbol)) == 2) { //如果栈顶符号是'+'或'-',则出栈运算 
    					while(symbol.top >= 0 && data.top >= 1) { //循环出栈
    						v2 = Putshuju(&data);
    						v1 = Putshuju(&data);
    						sum = Math(v1, v2, Putfuhao(&symbol));
    						Inshuju(&data, sum); //将运算结果压入数据栈 
    					}
    					Infuhao(&symbol, str[i]); //新符号进栈 
    				}
    				else if(judge(Randfuhao(&symbol)) == 3) { //如果栈顶符号是'*'或'/',则进符号栈 
    					while(symbol.top >= 0 && data.top >= 1) { //循环出栈
    						v2 = Putshuju(&data);
    						v1 = Putshuju(&data);
    						sum = Math(v1, v2, Putfuhao(&symbol));
    						Inshuju(&data, sum); //将运算结果压入数据栈 
    					}
    					Infuhao(&symbol, str[i]); //新符号进栈 
    				}
    				/*栈顶符号不可能是')',故不做判断*/ 
    			}
    			else if(judge(str[i]) == 3) { //如果此符号是'*'或'/',则判断与栈顶符号是优先级
    				if(judge(Randfuhao(&symbol)) == 1) { //如果栈顶符号是'(',放入符号栈 
    					Infuhao(&symbol, str[i]);
    				}
    				else if(judge(Randfuhao(&symbol)) == 2) { //如果栈顶符号是'+'或'-',则进符号栈
    					Infuhao(&symbol, str[i]); //新符号进栈
    				}
    				else if(judge(Randfuhao(&symbol)) == 3) { //如果栈顶符号是'*'或'/',则出栈运算 
    					while(symbol.top >= 0 && data.top >= 1) { //循环出栈
    						v2 = Putshuju(&data);
    						v1 = Putshuju(&data);
    						sum = Math(v1, v2, Putfuhao(&symbol));
    						Inshuju(&data, sum); //将运算结果压入数据栈 
    					}
    					Infuhao(&symbol, str[i]); //新符号进栈
    				}
    			}
    			else if(judge(str[i]) == 4) { // 如果此符号是')',则出栈运算直到遇到'('
    				do { //循环出栈直到遇到'('
    					v2 = Putshuju(&data);
    					v1 = Putshuju(&data);
    					sum = Math(v1, v2, Putfuhao(&symbol));
    					Inshuju(&data, sum); //将运算结果压入数据栈 
    				}while(judge(Randfuhao(&symbol)) != 1);
    				Putfuhao(&symbol); //括号内运算结束后使'('出栈 
    			} 		
    		}
    	}
    	free(str); //释放内存空间
    	while(symbol.top != -1) {
    		v2 = Putshuju(&data);
    		v1 = Putshuju(&data);
    		sum = Math(v1, v2, Putfuhao(&symbol));
    		Inshuju(&data, sum);	
    	}
    	printf("%d", data.data[0]);
    	
    	return 0;
    }
    

    运行截图:

     

     

    评论
  • CSDN专家-sinJack 2021-06-17 18:16
    关注

    如有帮助,请采纳。

    #include "stdio.h"
    
    int n,i;         /* 请注意这里的n与i设置为全局变量的用意 */  
    
    float val[100];  /* 这个数组用来收集字符流中的数 */
    
    char c[1000],fu[100];  /* c数组是字符流,而fu数组用来收集计算符号+-* /和{、}*/
    
    
    
    float digui()
    
    {
    
    	float he=0,ji=0;  /* he代表加减运算结果,ji代表乘除运算结果 */
    
    	char hefu='+';    /* 每次进入递归是,都要把标示符he设置为0,hefu设置为+。但那个标示符ji可以不用设置 */
    
    	
    
    	for( ;fu[i]!='}'&&fu[i]!='=';i++)
    
    	{
    
    		switch(fu[i])
    
    		{
    
    
    
    			case '{':
    
    			i++;
    
    			digui();  // 如果遇到圆括号,则优先计算圆括号里面的内容
    
    			break;
    
    			
    
    			
    
    			
    
    			case '+':
    
    			if(hefu=='+') {val[n] = he + val[n];he = val[n];}  
    
    			else          {val[n] = he - val[n],he = val[n];}  // 如果+、-后面的符号依然是加减,则可以进行计算
    
    			hefu = '+';                                        
    
    			n++;
    
    			break;
    
    			
    
    			case '-':
    
    			if(hefu=='+')  {val[n] = he + val[n];he = val[n];}  
    
    			else           {val[n] = he - val[n];he = val[n];}  // 同上
    
    			hefu = '-';
    
    			n++;
    
    			break;
    
    			
    
    			case '*':  //  如果遇到优先级高一级的乘符号【或除符号】,则进入循环,直至遇到非乘除符号时推出
    
    			{
    
    			ji=val[n];  // ji在这里被设置
    
    			while(1)
    
    			{
    
    			   if(fu[i] == '*')
    
    			   {
    
    				  if(fu[i+1] == '{')  //  如果在乘除循环里遇到圆括号,则递归调用自身,就是优先计算圆括号里面的内容
    
    					{
    
    							i+=2;n++;
    
    							ji = ji * digui();
    
    					}
    
    				  else
    
    					{
    
    							ji = ji*val[n+1];
    
    							i++;n++;
    
    					}
    
    				}
    
    				else if(fu[i] == '/')
    
    				{
    
    					if(fu[i+1] == '{')
    
    					{
    
    							i+=2;n++;
    
    							ji = ji / digui();
    
    					}
    
    					else
    
    					{
    
    							ji = ji/val[n+1];
    
    							i++;n++;
    
    					}
    
    				}
    
    				else break;  // 遇到非乘除符号,退出
    
    			}
    
    		    val[n] = ji;  // 乘除循环结束,把n现在指向的数设置成循环计算的结果数,以便它以后可以与he计算,最后得出前面所有数的运算结果
    
    		    if(fu[i]=='+'||fu[i]=='-')
    
    		    i--;
    
    			break;
    
    			}
    
    			
    
    			case '/':   //这个与上面那个case里面的作用一样
    
    			{
    
    				ji = val[n];
    
    				while(1)
    
    				{
    
    					if(fu[i] == '*')
    
    					{
    
    						if(fu[i+1] == '{')
    
    						{
    
    							i+=2;n++;
    
    							ji = ji * digui();
    
    						}
    
    						else
    
    						{
    
    							ji = ji*val[n+1];
    
    							i++;n++;
    
    						}
    
    					}
    
    					if(fu[i] == '/')
    
    					{
    
    						if(fu[i+1] == '{')
    
    						{
    
    							i+=2;n++;
    
    							ji = ji / digui();
    
    							
    
    						}
    
    						else
    
    						{
    
    							ji = ji/val[n+1];
    
    							i++;n++;
    
    						}
    
    					}
    
    					else break;  
    
    				}
    
    			} 
    
    			val[n] = ji;
    
    		    if(fu[i]=='+'||fu[i]=='-')
    
    		    i--;
    
    			break;
    
    		    }
    
    	}
    
    	
    
    	if(hefu == '+') val[n] = he + val[n];  // 到这里就是到了一个递归的结束,然后根据hefu的状态决定进行+运算或-运算
    
    	else val[n] = he - val[n];
    
    	
    
    	return val[n];  // 最后我们需要返回这个值
    
    }
    
    
    
    void main()
    
    {
    
        int a=0,j=0;float b=0,d=0,g=10;;
    
        gets(c);
    
        
    
        for(i=0;c[i]!=0&&i<1000;i++)
    
        {
    
        	if(c[i]>='0'&&c[i]<='9')
    
        	{
    
        		
    
        		while(c[i]>='0'&&c[i]<='9')
    
        		{
    
        			b=(c[i]-'0')+b*10;
    
        			i++;
    
        		}
    
        		if(c[i]=='.')
    
        		{
    
        			i++;
    
        			while(c[i]>='0'&&c[i]<='9')
    
        			{
    
        				d=d+(c[i]-'0')/g;
    
        				g*=10;
    
        				i++;
    
        			}
    
        		}  // 以上是手机输入流中的数
    
        	val[n]=b+d;
    
        	n++;
    
        	}
    
          b=0;d=0;g=10;
    
        }
    
        
    
        for(i=0;c[i]!=0;i++)
    
        	{
    
        		if(c[i] < '0' || c[i] > '9')
    
        		fu[j++]=c[i];
    
        	}  // 这个则是收集输入流中的运算符
    
    
        j=n;
    
        
    
        i=0;
    
        n=0;  // 这里的清零是必须的
       
        printf(":::::%f\n", digui());
    
    }
    评论
  • 有问必答小助手 2021-06-18 23:53
    关注

    您好,我是有问必答小助手,您的问题已经有小伙伴解答了,您看下是否解决,可以追评进行沟通哦~

    如果有您比较满意的答案 / 帮您提供解决思路的答案,可以点击【采纳】按钮,给回答的小伙伴一些鼓励哦~~

    ps: 问答会员年卡【8折】购 ,限时加赠IT实体书,即可 享受50次 有问必答服务,了解详情>>>https://t.csdnimg.cn/RW5m

    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 6月12日

悬赏问题

  • ¥20 C语言字符串不区分大小写字典排序相关问题
  • ¥15 关于#python#的问题:我希望通过逆向技术爬取1688搜索页下滑加载的数据
  • ¥15 学习C++过程中遇到的问题
  • ¥15 关于Linux的终端里,模拟实现一个带口令保护的屏保程序遇到的输入输出的问题!(语言-c语言)
  • ¥15 学习C++过程中遇到的问题
  • ¥15 请问,这个嵌入式Linux系统怎么分析,crc检验区域在哪
  • ¥15 二分类改为多分类问题
  • ¥15 Unity微信小游戏上调用ReadPixels()方法报错
  • ¥15 如何通过求后验分布求得样本中属于两种物种其中一种的概率?
  • ¥15 q从常量变成sin函数,怎么改写python代码?