用c++实现浮点数的加减乘除(顺序栈)数据结构 项目 大作业

首先申明头文件

#include "stdafx.h"
#include "iostream"
#include <stdio.h>
#include <string.h>	  // 用于获取字符串长度
#include <stdlib.h>
using namespace std; 

定义栈相关的变量及函数操作

// 定义栈结构
typedef struct 
{
	double *data;	 // 数据域数组名
	int top;		 // 栈顶
	int stackSize;   // 栈最大可用容量
} Stack;

// 初始化栈,输入栈名和容量
void initStack(Stack *stack, int stackSize) 
{
	stack->data = new double[stackSize];	// 申请一段连续的double类型空间,首地址赋值给data
	stack->top = -1;	// 栈顶初始化为-1,代表栈空
	stack->stackSize = stackSize;	// 赋值栈的容量
}

// 判断栈是否为空,为空返回1,非空返回0
int isEmpty(Stack *stack) 
{
	return stack->top == -1;   // 判断栈顶是否为-1,是则代表栈空,输出1
}

// 将值入栈
void push(Stack *stack, double value) 
{
	if (stack->top < stack->stackSize - 1)   // 栈顶未到最大容量
	{
		stack->data[++stack->top] = value;	 // 栈顶先自增,再存放元素
	}
	
	else 
	{
		cout << "栈满!" << endl;
	}
}

// 出栈,返回出栈的元素值,栈空返回0
double pop(Stack *stack) 
{
	if (!isEmpty(stack))	// 栈非空
	{
		return stack->data[stack->top--];	// 先取栈顶元素,栈顶再自减
	}
	
	else 
	{
		cout << "栈空!" << endl;
		
		return 0; // 栈为空时返回一个默认值
	}
}

// 获取栈顶元素
double getTop(Stack *stack) 
{
	if (!isEmpty(stack)) 	// 栈非空
	{
		return stack->data[stack->top];	 // 返回栈顶元素值
	}
	
	else   // 栈空
	{
		return 0; // 栈为空时返回一个默认值
	}
}

// 释放栈空间
void destroy(Stack *stack)
{
	delete[] stack->data;
	stack->top = -1;
	stack->stackSize = 0;
}

定义数与表达式相关的函数操作

// 判断是否为操作符(+ - * /和左右小括号),是则返回1,不是返回0
int isOperator(char ch) 
{
	return (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' || ch == ')');
}

// 判断是否为数字,是则返回1,不是返回0
int isNumber(char ch)
{
	return (ch >= '0' && ch <= '9');
}

// 判断是否为合法表达式
int isCorrectExpression(char *expression)
{
	int i = 0;    // 用于遍历表达式数组
	
	for (i = 0; expression[i] != '\0'; i++)
	{
		if ((isOperator(expression[i]) == 0) && (isNumber(expression[i]) == 0) && (expression[i] != '.'))
		{
			cout << "请输入正确的表达式!" << endl;

			exit(1);	// 表达式中有非操作符或非数字,程序异常结束
		}
	}
	return 1;
}

// 判断是否存在括号不匹配
int checkParen(char *expression)
{
	Stack checkStack;	// 创建用于括号检查的栈
	initStack(&checkStack, strlen(expression)); 	 // 初始化检查栈

	int i = 0;    // 用于遍历表达式数组

	for (i = 0; expression[i] != '\0'; i++)		// 遍历表达式数组
	{
		if (expression[i] == '(')	// 遇到左括号就入栈
			push(&checkStack, 1);	// 用1代表括号入栈
		
		if (expression[i] == ')')	//遇到右括号就出栈
		{
			int tmp = (int) pop(&checkStack);		// 定义临时变量存放出栈的数
			if (tmp == 0)	// pop函数在栈空时不会输出1,而是输出默认值0
			{
				cout << "括号不匹配!(右括号多)" << endl;		// 栈空代表出栈函数比入栈函数调用多,即右括号多
				exit(1);	// 程序异常结束
			}
		}
	}	// 遍历完成

	if (isEmpty(&checkStack) == 0)		// 括号栈非空
	{
		cout << "括号不匹配!(左括号多)" << endl;		// 栈非空,代表入栈函数比出栈函数调用多,即左括号多
		exit(1);	// 程序异常结束
	}

	destroy(&checkStack);	// 申请完的内存在用完释放
	return 0;
}

// 判断是否为正确的计算式(最后一个除括号外的字符不能是加减乘除;两个运算符间除了括号外必须是一个数字;两个小数点不能出现在同一个数里,如1.1.1)
int checkCalculation(char *expression)
{
	int i = 0;    // 用于遍历表达式数组

	// 先判断符号的正确性(最后一个除括号外的字符不能是加减乘除,且两个运算符间除了括号外必须是一个数字)
	for (i = 0; expression[i] != '\0'; i++)		// 遍历表达式数组
	{
		if ((expression[i] == '+' || expression[i] == '-' || expression[i] == '*' || expression[i] == '/'))		// 遇到加减乘除
		{
			i++;	// 开始判断表达式下一个字符

			while (isNumber(expression[i]) == 0)	// 表达式当前字符不是数字
			{
				if (expression[i] == '+' || expression[i] == '-' || expression[i] == '*' || expression[i] == '/')	// 遇到加减乘除
				{
					cout << "错误的计算式!(两个加减乘除间无数字)" << endl;
					exit(1);
				}

				if (expression[i] == '\0')	// 遍历到表达式尾,但仍然不是数字
				{
					cout << "错误的计算式!(除括号外最后一个字符为加减乘除)" << endl;
					exit(1);
				}

				i++;	// 继续往下遍历
			}
		}
	}

	// 再判断数字的正确性,一个数内不能有两个小数点
	for (i = 0; expression[i] != '\0'; i++)		// 遍历表达式数组
	{
		if ((expression[i] == '.'))		// 遇到小数点
		{
			i++;	// 开始往后遍历
			while (isNumber(expression[i]))		// 移动到非数字的位置
			{
				i++;
			}
			
			if (expression[i] == '.')	// 如果是小数点则代表一个数中有至少两个小数点
			{
				cout << "错误的数据形式!(一个数内有至少两个小数点)" << endl;
				exit(1);	// 程序异常停止
			}
		}
	}
	return 1;
}

// 获取操作符的优先度,返回值越大越优先,0为非法操作符
int getPriority(char Operator) 
{
	if (Operator == '(')	// 括号最先计算
		return 3;

	else if (Operator == '*' || Operator == '/')  // 先乘除
		return 2;
	
	else if (Operator == '+' || Operator == '-')  // 后加减
		return 1;
	
	else
		return 0; // 非法操作符
}

// 执行操作符计算,numberStack为数栈引用,operand1和operand2分别为第1、2个数,Operator为操作符
double performOperation(Stack &numberStack, double operand1, double operand2, char Operator)
{
	switch (Operator)
	{
		case '+':    // 操作符为'+'
		{
			cout << operand1 << "+" << operand2 << "=" << operand1 + operand2 << endl;	// 运算过程可视化
			
			push(&numberStack, operand1 + operand2);	// 将运算结果入栈

			return operand1 + operand2;
		}

		case '-':    // 操作符为'-'
		{
			cout << operand1 << "-" << operand2 << "=" << operand1 - operand2 << endl;	// 运算过程可视化

			push(&numberStack, operand1 - operand2);	// 将运算结果入栈
			
			return operand1 - operand2;
		}

		case '*':    // 操作符为'*'
		{
			cout << operand1 << "*" << operand2 << "=" << operand1 * operand2 << endl;	// 运算过程可视化
			
			push(&numberStack, operand1 * operand2);	// 将运算结果入栈
			
			return operand1 * operand2;
		}

		case '/':    // 操作符为'/'
		{
			if (operand2 != 0)     // 判断除数是否为0,不为0就正常运算
			{
				cout << operand1 << "/" << operand2 << "=" << operand1 / operand2 << endl;	// 运算过程可视化

				push(&numberStack, operand1 / operand2);	// 将运算结果入栈
				
				return operand1 / operand2;
			}
			
			else	// 除数为0
			{
				cout << "除数不能为0!" << endl;
				
				exit(1);	// 程序异常结束
			}
		}

		default:	// 操作符不为'+''-''*''/'
		{
			cout << "非法操作符!" << endl;
			
			exit(1);	// 程序异常结束
		}
	}
}

// 输入表达式的字符串数组名,计算表达式的结果
double calculateExpression(char *expression)
{
	isCorrectExpression(expression);	// 检查输入表达式是否合法
	checkParen(expression);				// 检查输入表达式是否存在括号不匹配
	checkCalculation(expression);		// 检查输入表达式是否正确

	Stack numberStack;		// 定义操作数栈
	Stack operatorStack;	// 定义操作符栈
	
	initStack(&numberStack, strlen(expression)); 	 // 初始化操作数栈
	initStack(&operatorStack, strlen(expression));	 // 初始化操作符栈


	int i = 0;	// 用i访问表达式中每个字符
	double operand = 0;		// 用于临时存放 要放入数栈的浮点数
	double num1, num2;	// 分别存两个要进行运算的数,num1在运算时靠前
	
	while (expression[i] != '\0' || !isEmpty(&operatorStack))	//遍历表达式数组,并处理完所有操作符栈内的元素
	{
		if (expression[i] >= '0' && expression[i] <= '9')		// 表达式当前字符为数字
		{
			// 处理数字
			operand = strtod(&expression[i], NULL);		// 将字符串中 从字符expression[i]开始的浮点数赋值给operand
			push(&numberStack, operand);		// 将operand入到操作数栈
			
			while ((expression[i] >= '0' && expression[i] <= '9') || expression[i] == '.')	// 将i移动到非浮点数所对应的字符位置处
			{
				i++;
			}
		}

		else  // 表达式当前字符为操作符
		{
			//	左括号出栈,不进行计算
			if (getTop(&operatorStack) == '(' && expression[i] == ')')	// 栈顶为'(' ,表达式当前字符为')',直接将'('出栈,不计算
			{
				pop(&operatorStack);	//左括号直接出栈
				
				i++;	// 移到表达式下一字符位置
				continue;	// 继续下一次循环
			}

			//	操作符进栈
			if ((isEmpty(&operatorStack) == 1) 	//操作符栈为空
				|| (getPriority(expression[i]) > getPriority( (char) getTop(&operatorStack))) 	//表达式操作符优先级 大于 栈顶操作符优先级
				|| (getTop(&operatorStack) == '(' && expression[i] != ')')) 	//栈顶为'('  且 表达式当前字符不为 ')'
			{
				push(&operatorStack, expression[i]);	//操作符进栈

				i++;	// 移到表达式下一字符位置
				continue;	// 继续下一次循环
			}

			//	操作符出栈,进行计算	
			if (getPriority(expression[i]) <= getPriority( (char) getTop(&operatorStack)) 	// 表达式当前字符优先级 小于等于 栈顶操作符优先级
				|| (expression[i] == '\0' && isEmpty(&operatorStack) == 0) 	// 表达式为空 且 操作符栈非空
				|| expression[i] == ')')	// 表达式当前字符为')'
			{
				num2 = pop(&numberStack);	// 数字栈顶出栈,后入先出
				num1 = pop(&numberStack);	// 数字栈新栈顶(原第二个数字)出栈,先入后出
				
				char op = (char) pop(&operatorStack);	// 定义字符op用来临时存放从操作符栈出栈的字符

				performOperation(numberStack, num1, num2, op);	// 对num1和num2进行op这种类型的运算,num1在前,num2在后,运算完的结果入栈到数栈numberStack中

				continue;	// 继续下一次循环
			}
		}
	}	// 此时已完成表达式的遍历,并处理完所有操作符栈内的元素,运算完成
	double result = getTop(&numberStack);	// 运算完的结果会存放在数栈的栈顶位置,通过定义result变量,取数栈栈顶,存放在result中,来获得运算结果

	destroy(&numberStack);		// 申请完的内存在用完释放
	destroy(&operatorStack);	// 申请完的内存在用完释放

	return result;	// 运算完的结果会存放在数栈的栈顶位置,通过取数栈栈顶,来获得运算结果,并返回值。
}

main函数

int main()
{
	char expression_example[] = "(2*(2*2.5+3/2)-1.2)*2";		// 定义字符数组并初始化
	char expression[100] = {0};		// 定义字符数组并初始化

	cout << "样例输入:" << "(2*(2*2.5+3/2)-1.2)*2" << endl << "计算过程:" << endl << endl;	// 提供样例
	cout << endl << "计算结果为:" << calculateExpression(expression_example) << endl << endl;	// 输出结果

	cout << "请输入您的表达式:";
	cin >> expression;	// 输入字符串

	cout << endl << "计算过程:" << endl;
	cout << endl << "计算结果为:" << calculateExpression(expression) << endl;	// 输出结果

	return 0;
}

航班订票系统:航空客运订票的业务活动包括查询航线、客票预定和办理退票等,设计航班信息、订票系统的存储结构,完成下面基本要求 基本要求 (1) 每条航线所涉及的信息有:终点站名、航班号、飞机号、飞行日期(具体时间)、成员定额、余票量、已订票的客户名单(包括姓名、订票量、舱位等级1,2或3)以及等候替补的客户名单(包括姓名、所需票量) (2) 要求数据等存放在文件中 (3) 录入:可以录入航班情况(数据可以存储在一个数据文件中,数据结构、具体数据自定) (4) 查询:可以查询某个航线的情况(如,输入航班号,查询起降时间,起飞抵达城市,航班票价,票价折扣,确定航班是否满仓); (5) 可以输入起飞抵达城市,查询飞机航班情况; (6) 订票:(订票情况可以存在一个数据文件中,结构自己设定),可以订票,如果该航班已经无票,可以提供相关可选择航班;若已满员或余票额少于订票额,则需重新询问客户要求。若需要,可登记排队候补; (7) 退票:可退票,退票后修改相关数据文件;然后查询该航班是否有人排队候补,首先询问排在第一的客户,若所退票额能满足他的要求,则为它办理订票手续,否则依次询问其他排队候补的客户 (8) 修改航班信息:当航班信息改变可以修改航班数据文件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值