栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

用C语言实现四则预算

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

用C语言实现四则预算

前段时间学习了栈的基础操作后,想着用栈实现四则运算来巩固以下所学知识。

什么是栈

栈(Stack)是规定只能在表尾进行插入和删除操作的线性表。这一规定决定了栈中数据具有后入先出的特点。

由图可知,可以通过栈顶元素、存储元素、栈的最大空间来一起描述一个栈。对于顺序栈,存在一个定义栈的最大空间的参数使顺序栈具有固定的大小。如果想要一个没有存储元素个数限制的栈,则可以模仿动态链表的思路,让栈中元素包含有一个指向下一个元素地址的指针,从而形成一个链栈,这也正是实现四则运算所需要的。

实现思路 首先是实现要用到的栈的操作,分别是元素入栈、元素出栈、获取栈顶元素

栈的基本定义:

typedef enum Status 
{
    ERROR = 0, 
	SUCCESS = 1
} Status;

typedef struct StackNode
{
	int data;
	struct StackNode *next;
}Node;

typedef struct StackInfo
{
	struct StackNode *top;
	int count;
}Stack;
入栈

1、形成新结点

2、新节结点的直接后继指向当前的栈顶元素

3、栈顶指针指向新结点

Status Push(Stack *s, int e)
{
	if (s == NULL)
	{
		return ERROR;
	}

	Node *p = (Node *)malloc(sizeof(Node));
	if (p == NULL)
	{
		return ERROR;
	}

	p->data = e;
	p->next = s->top;
	s->top = p;
	s->count = s->count + 1;

	return SUCCESS;
}
出栈

1、判断栈顶是否为空

2、p指向栈顶元素,栈顶指针下移一位

3、释放p所指向的空间

Status Pop(Stack *s)
{
	if (s == NULL)
	{
		return ERROR;
	}
	if (s->top == NULL)
	{
		return ERROR;
	}

	int save;
	Node *p = s->top;
	save = s->top->data;
	s->top = p->next;
	free(p);
	p = NULL;
	s->count = s->count - 1;

	return save;

}
得到栈顶元素
Status GetTop(Stack *s)
{
	if (s == NULL)
	{
		return ERROR;
	}
	if (s->top == NULL)
	{
		return ERROR;
	}
	return s->top->data;
}
栈的判空
Status EmptyStack(Stack *s)
{
	if (s == NULL)
	{
		return ERROR;
	}
	if(s->top == NULL)
	{
		return SUCCESS;
	}
	else{
		return ERROR;
	}
}
接下来,先理解以下四则运算的实现原理

观察式子:1+2       = 3

平时我们所用的四则运算表达式都是运算符在两个数字中间的,所以称这种表达式为中缀表达式。

而后缀表达式定义为运算符在两个数字之后的表达式。例如:

式子「1」:6 + ( 4 - 2 ) × 3 + 9 ÷ 3             = 15

式子「2」:6  4  2  -  3  × + 9  3  ÷ +           = ?

式子「1」是中缀表达式,式子「2」是后缀表达式

与中缀表达式相比,后缀表达式的优点是不需要考虑括号匹配、运算符优先级和简化运算。

我们利用链栈来表示后缀表达式,从而可以计算出结果。所以首先要将中缀表达式转换为后缀表达式,方法如下:

从头到尾读取中缀表达式的每个对象,对不同对象按不同情况处理。

1 运算数:直接输出

2 左括号:压入堆栈

3 右括号:将栈顶元素弹出直到遇到左括号(出栈,不输出)

4 运算符:

        若优先级大于栈顶元素,将它压栈

        若优先级小于栈顶元素,栈顶元素弹出并输出;再比较新的栈顶元素,直到该运算符大于栈顶运算符优先级为止,然后将该运算符号压栈

5 各对象处理完毕后,把堆栈中存留的运算符一并输出

优先级如代码所示:

int Priority(char ch) 
{
	switch(ch)
	{
		case '(':
			return 3;
		case '*':
		case '/':
			return 2;
		case '+':
		case '-':
			return 1;
		default:
			return 0;
	} 
}

接下来是后缀表达式的运算

规则:(用栈来进出运算的数字)

1.从左到右遍历后缀表达式的每一个数字和符号

2.若是数字,则进栈

3.若是符号,则把处于栈顶的两个数字出栈,进行运算

4.运算结果进栈

5.直到获得最终结果

最后附上主函数的完整代码
int main()
{
	int i = 0;
	int num1,num2;
	int tem = 0;         
	char str[111] = {0}; 
	Stack *res,*ope;    
	if(!(InitStack(&res)) || !(InitStack(&ope))){
		printf("初始化失败n"); 
	}
	printf("请输入您的式子:");
	scanf("%s",str);
	
	while(str[i] != '' || ope->count != 0){ 
		if('0'<=str[i] && str[i]<='9'){
			tem = tem*10+str[i]-'0'; 
			i++;
			if('0'>=str[i] || str[i]>='9'){
				Push(res,tem); 
				tem = 0; 
			}
		} 
		else{ 
		      
		if (GetTop(ope) == '(' && str[i] ==')')	//直接出栈,不计算,栈顶为'(' ,表达式为')'
			{
				Pop(ope);	//括号直接出栈
				i++;
				continue;	//继续下一次循环
			}
			if((EmptyStack(ope) == SUCCESS) || (Priority(str[i]) > Priority(GetTop(ope))) || (GetTop(ope) == '(' && str[i] != ')')) 
			{
				Push(ope,str[i]);
				i++;
				continue;
			}
		
			if((Priority(str[i]) <= Priority(GetTop(ope)))|| str[i] == ')'|| (str[i] == '' && EmptyStack(ope) != SUCCESS))
			{
				int num; 
				num1 = Pop(res);	//数字栈顶出栈
				num2 = Pop(res);	//数字栈第二个数字出栈
				switch (Pop(ope))	//后出的数字在前
				{
					case '+':
						num = num1 + num2;
						Push(res,num); 
						break;
					case '-':
						num = num2 - num1;
						Push(res,num);
						break;
					case '*':
						num = num1 * num2;
						Push(res,num);
						break;
					case '/':
						num = num2 / num1;
						Push(res,num);
						break;
			}
			
			}
		}	
}
printf("result = %d",GetTop(res));
	return 0;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/883108.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号