数据结构-C描述-堆栈-简单计算器

1.实验需求

请按照四则运算加、减、乘、除、幂(^)和括号的优先关系和惯例,编写计算器程序。要求:

  • 从键盘输入一个完整的表达式,以回车作为表达式输入结束的标志。
  • 输入表达式中的数值均为大于等于零的整数。中间的计算过程如果出现小数也只取整。

例如,输入:4+2*5=                      输出:14

      输入:(4+2)*(2-10)=            输出:-48


2.概要设计

(1)抽象数据类型的定义:

采用两种栈(符号栈和数字栈)分别存储运算符和数字

两种栈都有各自的初始化、push、pop等函数

typedef struct{//符号栈 
	char *base;
	char *top;
	int stacksize;	
}Opstack;

typedef struct{//数字栈 
	int *base;
	int *top;
	int stacksize;	
}Numstack;

(2)主程序流程

主函数main

先定义栈符号栈和数字栈,定义一个数组ch临时存储输入的计算式初始化符号栈schar,调用PushOp函数在栈底放一个’=’,初始化数字栈snum,调用gets函数,将表达式临时存储在数组ch里,求数组长度。

在while循环(ch数组不到最后一个=或者schar不到栈底=)中,先判断现在所指数组元素是数字还是符号,如果是数字,调用Num函数将char型数字转换成int型,并将数字存储进数字栈,数组指针移动。如果是符号,调用Precede函数比较它和符号栈栈顶元素的优先级,如果栈顶元素优先级小于现在数组里的运算符,将该运算符进栈,移动数组指针;如果等于,栈顶元素出栈;如果大于,取数字栈栈顶两个元素,和符号栈栈顶元素,进行计算,再将结果压入数字栈。

循环结束,输出数字栈栈顶元素,即为结果。

(3)各模块介绍

由主程序main依次调用:

  1. int InitOpStack(Opstack &s)符号栈初始化函数
  2. int PushOp(Opstack &s, char e)符号栈进栈函数
  3. int InitNumStack(Numstack &s)数字栈初始化函数
  4. char GetTopOp(Opstack &s)符号栈取栈顶函数
  5. int In(char c)判断是运算符还是数字函数
  6. int Getnum(char ch[], int j)数组中char型数字转int型函数
  7. int PushNum(Numstack &s, int e)数字栈进栈函数
  8. char Precede(char c1, char c2)运算符优先级判断函数
  9. int PopOp(Opstack &s, char &e)符号栈pop函数
  10. int PopNum(Numstack &s, int &e)数字栈pop函数
  11. int Operate(int a, char theta, int b)运算函数

3.详细设计

(1)主函数main:

int main(){//主函数 
	Opstack schar;
	Numstack snum;
	char ch[100],x,theta;
	int a,b;
	int Num;
	int l;
	InitOpStack(schar);
	PushOp(schar,'=');//栈底压一个= 
	InitNumStack(snum);
	gets(ch);//把式子先存进去了 
	l=strlen(ch);
	while(ch[i]!='=' || GetTopOp(schar)!='=')
	{

		if(!In(ch[i])){//判断输入的是数字 
			Num=Getnum(ch,i);
			PushNum(snum, Num); 
		}
		else{
			switch(Precede(GetTopOp(schar),ch[i])){
				case '<':
					PushOp(schar,ch[i]);
					i++; 
					break;
				case '=':
					PopOp(schar, x); 
					i++;
					break;
				case '>':
					PopOp(schar, theta);
					PopNum(snum, b);
					PopNum(snum, a);
					PushNum(snum,Operate(a, theta, b));
					break;
					
			}
		}
	}
	printf("%d", GetTopNum(snum));
	return 0;
}	

(2)数字栈的基本操作函数

int InitNumStack(Numstack &s){//创建数字栈 
	s.base = (int *)malloc(STACK_INIT_SIZE * sizeof(int));
	if(!s.base) exit(OVERFLOW);
	s.top = s.base;
	s.stacksize = STACK_INIT_SIZE;
	return OK;
}

int PushNum(Numstack &s, int e){//数字栈push函数 
	if(s.top - s.base >= s.stacksize){
		s.base = (int *)realloc(s.base, (s.stacksize + STACKINCREMENT) * sizeof(int));
		if (!s.base) exit(OVERFLOW);
		s.top = s.base + s.stacksize;
		s.stacksize += STACKINCREMENT; 
	}	
	*s.top++=e;
	return OK;
}

int PopNum(Numstack &s, int &e){//数字栈pop函数 
	if(s.top == s.base) return ERROR;
	e = *--s.top;
	return OK;
}

int GetTopNum(Numstack &s){//数字栈取栈顶 
	int e;
	if(s.top == s.base) return ERROR;
	e = *(s.top-1);
	return e;
}

(3)符号栈的基本操作函数

int InitOpStack(Opstack &s){//创建符号栈 
	s.base = (char *)malloc(STACK_INIT_SIZE * sizeof(char));
	if(!s.base) exit(OVERFLOW);
	s.top = s.base;
	s.stacksize = STACK_INIT_SIZE;
	return OK;
}

int PushOp(Opstack &s, char e){//符号栈push函数 
	if(s.top - s.base >= s.stacksize){
		s.base = (char *)realloc(s.base, (s.stacksize + STACKINCREMENT) * sizeof(char));
		if (!s.base) exit(OVERFLOW);
		s.top = s.base + s.stacksize;
		s.stacksize += STACKINCREMENT; 
	}	
	*s.top++=e;
	return OK;
}

int PopOp(Opstack &s, char &e){//符号栈pop函数 
	if(s.top == s.base) return ERROR;
	e = *--s.top;
	return OK;
}

char GetTopOp(Opstack &s){//符号栈取栈顶 
	char e;
	if(s.top == s.base) return ERROR;
	e = *(s.top-1);
	return e;
}

(4)判断数组中char型是运算符还是数字函数

 int In(char c)//判断是数字还是符号 
{
	if(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'||c=='^'||c=='\n'||c=='=')
	return 1;
	else return 0;
}

(5)运算函数

int Operate(int a, char theta, int b){//运算函数 
	int num=0;
	switch(theta){
		case '+': num=a+b; break;
		case '-': num=a-b; break;
		case '*': num=a*b; break;
		case '/': num=a/b; break;
		case '^': 
			num = 1;
			while(b!=0) 
			{
				num *= a;
				b--;
			}
			break;
	} 
	return num;
}

(6)运算符优先级比较函数

输入两个运算符,运用二维数组构造一个类似表格一样结构查询两个运算符之间的关系,返回<,>,=

char Precede(char c1, char c2){//查表比较优先级 
	char levelTable[] = { '+', '-', '*', '/','^', '(',')','='};
	int m,n;
	char ch[8][8]={//查表!!!
	   {'>','>','<','<','<','<','>','>'},
	   {'>','>','<','<','<','<','>','>'},
	   {'>','>','>','>','<','<','>','>'},
	   {'>','>','>','>','<','<','>','>'},
	   {'>','>','>','>','>','<','>','>'},
	   {'<','<','<','<','<','<','=',' '},
	   {'>','>','>','>','>',' ','>','>'},
	   {'<','<','<','<','<','<',' ','='}
	};
	for(m=0;m<8;m++)
	{
		if(c1==levelTable[m]) break;
	 } 
	for(n=0;n<8;n++)
	{
		if(c2==levelTable[n]) break;
	} 
	return ch[m][n];
}

(7)char型转Int型函数

只要下一位还是数字,这个函数就会把数组里的数字组合成Int型的数字


4.总代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#define OK 1
#define ERROR 0 
#define TRUE 1
#define FALSE 0 

int i=0;//全局变量,用于判断字符是否全部进栈 

typedef struct{//符号栈 
	char *base;
	char *top;
	int stacksize;	
}Opstack;

typedef struct{//数字栈 
	int *base;
	int *top;
	int stacksize;	
}Numstack;


int InitOpStack(Opstack &s){//创建符号栈 
	s.base = (char *)malloc(STACK_INIT_SIZE * sizeof(char));
	if(!s.base) exit(OVERFLOW);
	s.top = s.base;
	s.stacksize = STACK_INIT_SIZE;
	return OK;
}

int InitNumStack(Numstack &s){//创建数字栈 
	s.base = (int *)malloc(STACK_INIT_SIZE * sizeof(int));
	if(!s.base) exit(OVERFLOW);
	s.top = s.base;
	s.stacksize = STACK_INIT_SIZE;
	return OK;
}


int PushOp(Opstack &s, char e){//符号栈push函数 
	if(s.top - s.base >= s.stacksize){
		s.base = (char *)realloc(s.base, (s.stacksize + STACKINCREMENT) * sizeof(char));
		if (!s.base) exit(OVERFLOW);
		s.top = s.base + s.stacksize;
		s.stacksize += STACKINCREMENT; 
	}	
	*s.top++=e;
	return OK;
}

int PushNum(Numstack &s, int e){//数字栈push函数 
	if(s.top - s.base >= s.stacksize){
		s.base = (int *)realloc(s.base, (s.stacksize + STACKINCREMENT) * sizeof(int));
		if (!s.base) exit(OVERFLOW);
		s.top = s.base + s.stacksize;
		s.stacksize += STACKINCREMENT; 
	}	
	*s.top++=e;
	return OK;
}

int PopOp(Opstack &s, char &e){//符号栈pop函数 
	if(s.top == s.base) return ERROR;
	e = *--s.top;
	return OK;
}

int PopNum(Numstack &s, int &e){//数字栈pop函数 
	if(s.top == s.base) return ERROR;
	e = *--s.top;
	return OK;
}


int In(char c)//判断是数字还是符号 
{
	if(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'||c=='^'||c=='\n'||c=='=')
	return 1;
	else return 0;
}

char GetTopOp(Opstack &s){//符号栈取栈顶 
	char e;
	if(s.top == s.base) return ERROR;
	e = *(s.top-1);
	return e;
}

int GetTopNum(Numstack &s){//数字栈取栈顶 
	int e;
	if(s.top == s.base) return ERROR;
	e = *(s.top-1);
	return e;
}

int Operate(int a, char theta, int b){//运算函数 
	int num=0;
	switch(theta){
		case '+': num=a+b; break;
		case '-': num=a-b; break;
		case '*': num=a*b; break;
		case '/': num=a/b; break;
		case '^': 
			num = 1;
			while(b!=0) 
			{
				num *= a;
				b--;
			}
			break;
	} 
	return num;
}

char Precede(char c1, char c2){//查表比较优先级 
	char levelTable[] = { '+', '-', '*', '/','^', '(',')','='};
	int m,n;
	char ch[8][8]={//查表!!!
	   {'>','>','<','<','<','<','>','>'},
	   {'>','>','<','<','<','<','>','>'},
	   {'>','>','>','>','<','<','>','>'},
	   {'>','>','>','>','<','<','>','>'},
	   {'>','>','>','>','>','<','>','>'},
	   {'<','<','<','<','<','<','=',' '},
	   {'>','>','>','>','>',' ','>','>'},
	   {'<','<','<','<','<','<',' ','='}
	};
	for(m=0;m<8;m++)
	{
		if(c1==levelTable[m]) break;
	 } 
	for(n=0;n<8;n++)
	{
		if(c2==levelTable[n]) break;
	} 
	return ch[m][n];
}

int Getnum(char ch[], int j){//字符串转数字 
	int num=ch[j]-48;
	j++;
	while(ch[j]>='0'&&ch[j]<='9')//处理多位数字 
		num=num*10+ch[j++]-48;
	i=j;//处理到第几位了 
	return num;
}

int main(){//主函数 
	Opstack schar;
	Numstack snum;
	char ch[100],x,theta;
	int a,b;
	int Num;
	int l;
	InitOpStack(schar);
	PushOp(schar,'=');//栈底压一个= 
	InitNumStack(snum);
	gets(ch);//把式子先存进去了 
	l=strlen(ch);
	while(ch[i]!='=' || GetTopOp(schar)!='=')
	{

		if(!In(ch[i])){//判断输入的是数字 
			Num=Getnum(ch,i);
			PushNum(snum, Num); 
		}
		else{
			switch(Precede(GetTopOp(schar),ch[i])){
				case '<':
					PushOp(schar,ch[i]);
					i++; 
					break;
				case '=':
					PopOp(schar, x); 
					i++;
					break;
				case '>':
					PopOp(schar, theta);
					PopNum(snum, b);
					PopNum(snum, a);
					PushNum(snum,Operate(a, theta, b));
					break;
					
			}
		}
	}
	printf("%d", GetTopNum(snum));
	return 0;
}

5.运行结果

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个简单的计算器程序,支持基本的加、减、乘、除、幂和括号运算: ``` #include <stdio.h> #include <stdlib.h> #include <math.h> #define MAX_EXPR_LEN 100 int is_operator(char c) { return c == '+' || c == '-' || c == '*' || c == '/' || c == '^'; } int is_digit(char c) { return c >= '0' && c <= '9'; } int priority(char c) { if (c == '+' || c == '-') return 1; else if (c == '*' || c == '/') return 2; else if (c == '^') return 3; else return 0; } double eval(char *expr) { char stack_op[MAX_EXPR_LEN]; double stack_val[MAX_EXPR_LEN]; int top_op = -1, top_val = -1; int i = 0; while (expr[i]) { if (expr[i] == '(') { stack_op[++top_op] = expr[i]; } else if (is_digit(expr[i])) { double val = expr[i] - '0'; while (is_digit(expr[i+1])) { val = val * 10 + (expr[++i] - '0'); } stack_val[++top_val] = val; } else if (is_operator(expr[i])) { while (top_op >= 0 && priority(stack_op[top_op]) >= priority(expr[i])) { char op = stack_op[top_op--]; double b = stack_val[top_val--]; double a = stack_val[top_val--]; double res = 0; switch (op) { case '+': res = a + b; break; case '-': res = a - b; break; case '*': res = a * b; break; case '/': res = a / b; break; case '^': res = pow(a, b); break; } stack_val[++top_val] = res; } stack_op[++top_op] = expr[i]; } else if (expr[i] == ')') { while (stack_op[top_op] != '(') { char op = stack_op[top_op--]; double b = stack_val[top_val--]; double a = stack_val[top_val--]; double res = 0; switch (op) { case '+': res = a + b; break; case '-': res = a - b; break; case '*': res = a * b; break; case '/': res = a / b; break; case '^': res = pow(a, b); break; } stack_val[++top_val] = res; } top_op--; } i++; } while (top_op >= 0) { char op = stack_op[top_op--]; double b = stack_val[top_val--]; double a = stack_val[top_val--]; double res = 0; switch (op) { case '+': res = a + b; break; case '-': res = a - b; break; case '*': res = a * b; break; case '/': res = a / b; break; case '^': res = pow(a, b); break; } stack_val[++top_val] = res; } return stack_val[top_val]; } int main() { char expr[MAX_EXPR_LEN]; printf("请输入表达式:"); fgets(expr, MAX_EXPR_LEN, stdin); double result = eval(expr); printf("结果为:%g\n", result); return 0; } ``` 程序中使用了两个栈,一个用来存储运算符,一个用来存储数字。遍历表达式时,如果遇到数字,则将其转换为 double 类型并压入数字栈中;如果遇到运算符,则将其与运算符栈顶元素比较优先级,如果当前运算符优先级较低,则将栈顶运算符弹出,并从数字栈中弹出两个数进行计算,将计算结果压入数字栈中,直到栈顶运算符优先级低于当前运算符或栈空为止,然后将当前运算符压入运算符栈中。如果遇到左括号,则将其压入运算符栈中;如果遇到右括号,则弹出运算符栈中的元素,直到遇到左括号为止,并从数字栈中弹出两个数进行计算,将计算结果压入数字栈中。最后,再依次弹出运算符栈中的元素,进行计算,直到运算符栈为空,此时数字栈中的唯一元素即为表达式的值。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值