【数据结构--栈】c语言实现计算器|后缀表达式|栈的操作

这个计算器不是包含了所有可能遇到的情况,因为学业紧张,所以bug没有改,但是可以实现加减乘除运算和括号的优先级判断。

以后有机会可能会把bug改过来。

小数的运算(有优先级判断):


对于计算器来说,复杂的符号优先级判断是通过栈来完成的。

我们把输入的计算式叫做中缀表达式,比如:

3+5*(4-6)

我们要把他换成后缀表达式

从左到右遍历中缀表达式的每一个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级不高于栈顶符号(乘除优先加减)则栈顶元素依次出栈并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。

--》》》 3546-*+

计算后缀表达式:

从左到右遍历后缀表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶的两个数字出栈,进行运算,运算结果进栈。

--》》》栈:3

--》》》栈:35

--》》》栈:354

--》》》栈:3546

--》》》栈:35-2

--》》》栈:3-10

--》》》栈:-7


在c语言里面,我们可以设置两个栈,一个数据栈,一个符号栈,数据栈用来表示数字的运算情况,符号栈用来表示符号的运算情况。

那么以上结果的生成可细分为以下步骤:

---》》》数据栈:3  符号栈:null

---》》》数据栈: 3   符号栈:+

---》》》数据栈:35   符号栈:+

---》》》数据栈: 35  符号栈:+*

---》》》数据栈:35    符号栈: +*(

---》》》数据栈:354    符号栈: +*(

---》》》数据栈:354  符号栈: +*(-

---》》》数据栈:3546  符号栈: +*(-)

---》》》数据栈:35-2   符号栈: +*

---》》》数据栈:3-10    符号栈: +

---》》》数据栈:-7    符号栈:null


代码实现的时候注意一下可能会出现的所有情况即可。

以下是我的代码(有点bug,仅供参考和交流):

头文件:head.h

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

#define MAXSIZE 50

//数据栈
struct Data
{
	double num[MAXSIZE];
	int top;
};

//符号栈
struct Sign
{
	char s[MAXSIZE];
	int top;
};

//数据栈置空
void init_data(struct Data* data)
{
	data->top = -1;
}

//符号栈置空
void init_sign(struct Sign* sign)
{
	sign->top = -1;
}

//数据栈满
int judge_data_max(struct Data* data)
{
	if (data->top == MAXSIZE - 1)
	{
		printf("数据栈已经满了哦");
		return 0;
	}

	return 1;
}

//符号栈满
int judge_sign_max(struct Sign* sign)
{
	if (sign->top == MAXSIZE - 1)
	{
		printf("符号栈已经满了哦");
		return 0;
	}

	return 1;
}

//数据栈判空
int judge_data_zero(struct Data* data)
{
	if (data->top == -1)
	{
		//printf("数据栈已经空了哦");
		return 0;
	}

	return 1;
}

//符号栈判空
int judge_sign_zero(struct Sign* sign)
{
	if (sign->top == -1)
	{
		//printf("符号栈已经空了哦");
		return 0;
	}

	return 1;
}

//数据栈入栈
void create_data(struct Data* data, double num)
{ 
	int judge = judge_data_max(data);

	if (judge == 1)
	{
		data->top++;
		data->num[data->top] = num;
	}
}

//符号栈入栈
void create_sign(struct Sign* sign, char s)
{
	int judge = judge_sign_max(sign);

	if (judge == 1)
	{
		sign->top++;
		sign->s[sign->top] = s;
	}
}

//数据栈出栈
double data_out(struct Data* data)
{
	int judge = judge_data_zero(data);
	double num;

	if (judge == 1)
	{
		num = data->num[data->top];
		data->top--;
	}

	return num;
}
//符号栈出栈
char sign_out(struct Sign* sign)
{
	int judge = judge_sign_zero(sign);
	char s = (char)malloc(sizeof(char));

	if (judge == 1)
	{
		s = sign->s[sign->top];
		sign->top--;
	}

	return s;
}

//读取数据栈
double read_data(struct Data* data)
{
	return data->num[data->top];
}

//读取符号栈
char read_sign(struct Sign* sign)
{
	return sign->s[sign->top];
}

//四则运算
double math(double x, double y, char s)
{
	switch (s)
	{
	case '+':
		return x + y;

	case '-':
		return x - y;

	case '/':
		return x / y;

	case '*':
	default:
		return x * y;
	}
}

//优先级判断
int judge(char s)
{
	switch (s)
	{
	case '(':
		return 1;

	case '+':
	case '-':
		return 2;

	case '*':
	case '/':
		return 3;

	case ')':
		return 4;
	}
}

源文件:demo.c

#include "head.h"

//输入中缀表达式
void input(char* before_list)
{
	char ch;
	int index = 0;

	printf("输入'='(等于)计算结果!不要输入回车。。\n");
	while ((ch = getch()))
	{
		if (ch == '=')
		{
			break;
		}

		before_list[index++] = ch;
		printf("%c", ch);
	}

	before_list[index] = '\0';
}

//对每一次的符号栈改变进行计算,直到循环结束
void in_out(struct Data* data, struct Sign* sign)
{
	if (sign->top == 0)
	{
		return;
	}

	char ch = sign_out(sign);
	char ch2;

	if (ch == ')')
	{
		while ((ch2 = sign_out(sign)) != '(')
		{
			double num1 = data_out(data), num2 = data_out(data);

			double num = math(num2, num1, ch2);

			create_data(data, num);
		}
	}
	else
	{
		while (judge(read_sign(sign)) >= judge(ch))
		{
			ch2 = sign_out(sign);

			double num1 = data_out(data), num2 = data_out(data);

			double num = math(num2, num1, ch2);

			create_data(data, num);
		}

		create_sign(sign, ch);
	}
}

//清空符号栈
void clean_sign(struct Data* data, struct Sign* sign)
{
	char ch;

	while (judge_sign_zero(sign))
	{
		ch = sign_out(sign);

		double num1 = data_out(data), num2 = data_out(data);
		double num = math(num2, num1, ch);

		create_data(data, num);
	}
}

//输出结果
void show_answer(struct Data* data)
{
	double answer = data_out(data);

	printf("\n%.2lf", answer);
}

void run()
{
	//数据栈
	struct Data* data = (struct Data*)malloc(sizeof(struct Data));
	init_data(data);
	//符号栈
	struct Sign* sign = (struct Sign*)malloc(sizeof(struct Sign));
	init_sign(sign);
	//前缀表达式
	char* before_list = (char*)malloc(sizeof(char) * MAXSIZE);
	//保存每一个数字
	char* nums_list = (char*)malloc(sizeof(char) * MAXSIZE);
	//生成前缀表达式
	input(before_list);

	//计算
	int before_index, num_index, target;

	before_index = num_index = target = 0;

	for (; before_list[before_index] != '\0'; before_index++)
	{
		if (before_list[before_index] >= '0' && before_list[before_index] <= '9' || before_list[before_index] == '.')
		{
			nums_list[num_index++] = before_list[before_index];
			target = 1;


			if (before_list[before_index + 1] == '\0')
			{
				nums_list[num_index] = '\0';
				create_data(data, atof(nums_list));
				num_index = 0;
			}
		}
		else
		{
			if (target == 1 || before_list[before_index] == ')')
			{
				nums_list[num_index] = '\0';
				create_data(data, atof(nums_list));

				num_index = 0;
				create_sign(sign, before_list[before_index]);
	
				in_out(data, sign);

				target = 0;
			}
			else
			{
				create_sign(sign, before_list[before_index]);
			}
		}
	}
	clean_sign(data, sign);

	//输出结果
	show_answer(data);
}
int main()
{
	while (1)
	{
		run();
		fflush(stdin);
		system("pause");
		system("clear");
	}
}

欢迎大家交流讨论!!!

  • 9
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C 语言实现计算器可以使用以下步骤: 1. 读取用户输入的算术表达式,并进行表达式的语法分析。 2. 将表达式转换为后缀表达式,以便于计算器进行计算。可以使用实现转换。 3. 对后缀表达式进行计算,可以使用实现计算。具体实现方式是:遍历后缀表达式,如果是数字则入,如果是运算符则取出顶的两个数字进行相应的运算,并将结果入,最终中只剩下一个数字,即为表达式的计算结果。 4. 输出计算结果。 下面是一个简单的 C 语言实现计算器的代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <ctype.h> #define MAX_EXPR_LEN 100 // 最长的表达式长度 // 定义结构 typedef struct { int top; double data[MAX_EXPR_LEN]; } Stack; // 初始化 void init(Stack *s) { s->top = -1; } // 判断是否为空 int is_empty(Stack *s) { return s->top == -1; } // 判断是否已满 int is_full(Stack *s) { return s->top == MAX_EXPR_LEN - 1; } // 入 void push(Stack *s, double value) { if (is_full(s)) { printf("Error: Stack is full.\n"); exit(EXIT_FAILURE); } s->data[++(s->top)] = value; } // 出 double pop(Stack *s) { if (is_empty(s)) { printf("Error: Stack is empty.\n"); exit(EXIT_FAILURE); } return s->data[(s->top)--]; } // 获取顶元素 double top(Stack *s) { if (is_empty(s)) { printf("Error: Stack is empty.\n"); exit(EXIT_FAILURE); } return s->data[s->top]; } // 判断是否是操作符 int is_operator(char c) { return c == '+' || c == '-' || c == '*' || c == '/'; } // 判断操作符的优先级 int operator_priority(char c) { if (c == '+' || c == '-') { return 1; } else if (c == '*' || c == '/') { return 2; } else { return 0; } } // 将中缀表达式转换为后缀表达式 void infix_to_postfix(char *expr, char *postfix) { Stack op_stack; // 运算符 init(&op_stack); int i, j; for (i = j = 0; expr[i] != '\0'; i++) { if (isdigit(expr[i])) { // 如果是数字,直接输出到后缀表达式中 postfix[j++] = expr[i]; } else if (is_operator(expr[i])) { // 如果是运算符,将其入或者输出中的运算符 while (!is_empty(&op_stack) && operator_priority(top(&op_stack)) >= operator_priority(expr[i])) { postfix[j++] = pop(&op_stack); } push(&op_stack, expr[i]); } else if (expr[i] == '(') { // 如果是左括号,将其入 push(&op_stack, expr[i]); } else if (expr[i] == ')') { // 如果是右括号,将中的运算符输出直到遇到左括号 while (!is_empty(&op_stack) && top(&op_stack) != '(') { postfix[j++] = pop(&op_stack); } if (is_empty(&op_stack)) { printf("Error: Mismatched parentheses.\n"); exit(EXIT_FAILURE); } pop(&op_stack); // 弹出左括号 } else { // 如果是非法字符,报错退出 printf("Error: Invalid character: %c\n", expr[i]); exit(EXIT_FAILURE); } } while (!is_empty(&op_stack)) { // 将中剩余的运算符输出 if (top(&op_stack) == '(') { printf("Error: Mismatched parentheses.\n"); exit(EXIT_FAILURE); } postfix[j++] = pop(&op_stack); } postfix[j] = '\0'; // 将后缀表达式末尾置为'\0' } // 计算后缀表达式的值 double eval_postfix(char *postfix) { Stack num_stack; // 数字 init(&num_stack); int i; for (i = 0; postfix[i] != '\0'; i++) { if (isdigit(postfix[i])) { // 如果是数字,将其入 push(&num_stack, postfix[i] - '0'); } else if (is_operator(postfix[i])) { // 如果是运算符,取出顶的两个数字进行相应的运算,并将结果入 double num2 = pop(&num_stack); double num1 = pop(&num_stack); double result; switch (postfix[i]) { case '+': result = num1 + num2; break; case '-': result = num1 - num2; break; case '*': result = num1 * num2; break; case '/': if (num2 == 0) { printf("Error: Divide by zero.\n"); exit(EXIT_FAILURE); } result = num1 / num2; break; } push(&num_stack, result); } else { // 如果是非法字符,报错退出 printf("Error: Invalid character: %c\n", postfix[i]); exit(EXIT_FAILURE); } } if (is_empty(&num_stack)) { // 如果数字为空,报错退出 printf("Error: Invalid expression.\n"); exit(EXIT_FAILURE); } double result = pop(&num_stack); // 将数字中剩余的数字作为表达式的值 if (!is_empty(&num_stack)) { // 如果数字中还有数字,说明表达式不合法,报错退出 printf("Error: Invalid expression.\n"); exit(EXIT_FAILURE); } return result; } int main() { char expr[MAX_EXPR_LEN]; char postfix[MAX_EXPR_LEN]; printf("Enter an expression: "); gets(expr); infix_to_postfix(expr, postfix); printf("Postfix expression: %s\n", postfix); double result = eval_postfix(postfix); printf("Result: %g\n", result); return 0; } ``` 这个程序可以处理基本的四则运算,可以通过 infix_to_postfix 函数将中缀表达式转换为后缀表达式,然后通过 eval_postfix 函数计算后缀表达式的值。输入的算术表达式可以是以空格分隔的数字和运算符,例如:1 + 2 * 3 / 4。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

活成自己的样子啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值