C语言课程设计-航空订票系统

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cheng_cuo_tuo/article/details/85058436
/*
码农:成蹉跎
内容:模拟航空订票系统,包含对文件的处理。
2018-12-12:
	一个bug,在没有航班信息表的情况下,添加航班信息之后,输出的航班信息为空。
		已改正,原因是,航班信息是存储在临时数组里面的,数组的信息在管理员登录的时候添加了依次,但是在管理员
	添加完信息后并没有更新。航班信息,只是在管理员登录成功,用户登录和管理员添加航班信息时候,才会到文件中去
	读数据。
		优化航班信息在文件中的修改,只有用户确定修改一个元组信息的时候,才会把一个完整的新的元组写入文件中。
2018-12-14:
	新发现一个bug,当没有人退票的时候,显示所有订票信息的时候会出现一个空值。应该是排序算法写错了。
		已改正,错误原因:进行排序的时候,总的订票人数(index)比实际大1,标记第一个有效订票位置(firstValid)位
	置正好,混乱了

	业务不合理部分:
		在修改航班信息的时候应该给顾客提示信息,需要在顾客结构体中添加一个提示信息属性
	属性已经添加。

	在修改航班信息的时候,对相关的顾客提供提示信息。
		当管理员修改的是飞机号和时间的话,只需要给出提示信息就好了,但是管理员直接修改了航班的出发地和目的地的话,那
	该航线的所有顾客的飞机票就要作废了。这样的话,在顾客查看自己的机票的时候第一次查看机票,机票是存在的,但是会
	告诉顾客此机票已经作废,已经退款,再次查询的话就应该是不存在了。
	以实现。

	仍需增加的功能:删除航班信息。
		已经实现,当航班被删除后修改顾客的信息的提示(tips),同时删除航班信息表中的信息
2018-12-16:
	设置清屏内容,使显示更加简洁,清晰
*/

#include<stdio.h>			//标准输入、输出头文件
#include<string.h>			//包含字符串函数处理头文件
#include<unistd.h>			//access 函数的头文件
#include <stdlib.h>			//清屏
#define MaxAirlines 1000	//允许输入的最多的航班数量
#define MaxClients	10000	//允许最多的用户
#define PRINT "%d\t\t%d\t\t%s\t\t%s\t\t星期%d\t\t%d\t\t%d\n", array_Airline[index_airline].airlineNum, array_Airline[index_airline].airplaneNum, array_Airline[index_airline].departure, array_Airline[index_airline].destionation, array_Airline[index_airline].time, array_Airline[index_airline].totalTickets, remain(array_Airline[index_airline].remainTickets)		//宏定义输出格式
#define PRINTCLIENT "%d\t\t%d\t\t%s\t\t%s\t\t星期%d\t\t%s\t\t%d\t\t%s\n", array_Airline[index_airline].airlineNum, array_Airline[index_airline].airplaneNum, array_Airline[index_airline].departure, array_Airline[index_airline].destionation, array_Airline[index_airline].time, client.name, client.seatNum, client.tips

struct Airline {			//航班结构体
	int airlineNum;			//航班号
	int airplaneNum;		//飞机号
	char departure[10];		//出发地点
	char destionation[10];	//目的地
	int time;				//飞行时间(星期几)
	int totalTickets;		//总票数
	int remainTickets[1024];//剩余票数
} array_Airline[MaxAirlines];	

struct Client{				//用户的结构体
	char name[10];			//用户名
	int airlineNum;			//航班号
	int seatNum;			//座位号
	char tips[50];			//提示信息
} client;

int totalAirlines;			//统计总航班数量
int index_airline;			//查询航班使用的下标
char manager[] = {"root"};
char password[] = {"root"};
Client clients[MaxClients];	

void userLoginForm();		//登录确定身份页面
void managerLogin();		//管理员身份确认
void managerForm();			//管理员页面
void userForm();			//用户页面
void showAirlineForm();		//显示航班信息页面
void addAirlineForm();		//增加航班信息页面
void updateAirlineForm();	//更新航班信息页面
void deleteAirlineForm();	//删除航班信息页面
void showUserInfoForm();	//显示所有用户信息页面
void clientShowAirlineForm();//显示航班信息
void selectClientInfo();	//显示用户信息页面
void bookingTicketsForm();	//订票页面
void deleteClientForm();	//退票页面

void printAirlineInfo();	//显示航班信息,开始时候,包含读取文件
void readInfoToArray();		//将航班信息从文件中读取到数组中
void addAirline();			//添加航班信息
void outputAirlineInfo();	//仅仅将数组中的信息输出
void outputSingalAirlineInfo(int index); //输出单独一条航班信息
void updateAirlineInfo();	//修改航线信息
int searchAirline(int id);			//查询航班信息在数组中的位置,使用二分法查找
void printUpdateAirlineOptions();//显示可以修改的航班信息
void changeAirlineInfo(int index);//修改航班数组和文件信息,逐条信息修改
void changeAirlineTickets(int index);//修改航班信息中的剩余票数
void changeClientTickets(int index, int choose, int airline);//修改航班信息中的剩余票数
void deleteAirline();		//删除航班信息
void bookingTickets();		//用户订票
int remain (int *tickets);	//查询剩余票数
int selectSeat(int index);	//选择一张空作为给客户
void addUser();				//在用户信息表中添加用户信息
void outputClientInfo();	//输出所有用户的信息
int getAllClientInfo(bool show);	//显示所有的顾客信息
void cancelTickets();		//取消机票
bool searchClient(char name[10], bool displayInvalid); //在用户信息中查找用户信息到client结构体中,顺序查找
bool deleteClient(int airlineId, int seatId);		//删除客户机票
void setSeatNumZero(int airline, int seatId, int index); //设置对应的信息为0
void sortAirlineAsTimeUseBubble();	//按照时间顺序使用冒泡排序法对航班信息进行排序
void sortAirlineAsairlineNumUseInsert();	//按照航班号使用插入排序对航班信息进行排序

int main () {

	userLoginForm();
	
	//printAirlineInfo();
	//outputAirlineInfo();
	//sortAirlineAsTimeUseBubble();
	//addAirline();
	//outputAirlineInfo();
	//sortAirlineAsairlineNumUseInsert();
	//outputAirlineInfo();
	//updateAirlineInfo();
	//bookingTickets();
	//outputClientInfo();
	//getAllClientInfo(true);
	//getAllClientInfo(false);
	//cancelTickets();
	
	return 0;
}


void userLoginForm(){
	printf("\n\n					  欢迎使用航空订票系统\n\n");
	printf("================================================================================================================\n");
	printf("				1.管理员登录               2.用户登录\n");
	printf("				3.退出\n");
	printf("================================================================================================================\n");
	printf("请选择登录方式:");
	int choose;
	scanf("%d", &choose);
	switch (choose){
	case 1:
		managerLogin();
		break;
	case 2:
		printAirlineInfo();
		system("cls");
		userForm();
		break;
	default:
		printf("无效选择,正在跳转到初始页面...\n");
		sleep(1);
		system("cls");
		userLoginForm();
		break;
	}
}

void managerLogin() {
	char name[10];
	char pass[10];
	printf("输入管理员登录名:");
	scanf("%s", name);
	printf("输入管理员密码:");
	scanf("%s", pass);
	if (strcmp(name, manager) || (strcmp(pass, password))){
		printf("\n####用户名或密码错误####\n");
		sleep(1);
		system("cls");//清屏
		userLoginForm();
	} else {
		system("cls");//清屏
		printAirlineInfo();
		managerForm();
	}
}

void managerForm() {
	printf("						管理员页面\n\n");
	printf("================================================================================================================\n");
	printf("				1.查看航班信息               2.增加航班信息\n");
	printf("				3.修改航班信息               4.查看客户信息\n");
	printf("				5.删除航班信息               6.退出\n");
	printf("================================================================================================================\n");
	printf("请选择功能:");
	int choose;
	scanf("%d", &choose);
	switch (choose){
	case 1:
		showAirlineForm();
		break;
	case 2:
		addAirlineForm();
		break;
	case 3:
		updateAirlineForm();
		break;
	case 4:
		showUserInfoForm();
		break;
	case 5:
		deleteAirlineForm();
	case 6:
		getchar();
		system("cls");
		userLoginForm();
		break;
	default:
		printf("输入选项无效,即将跳转到管理员主页面...\n");
		sleep(1);
		system("cls");
		managerForm();
	}
}

void showAirlineForm(){
	printf("================================================================================================================\n");
	printf("				1.航班号顺序				 2.时间顺序\n");
	printf("				3.返回\n");
	printf("================================================================================================================\n");
	printf("请选择功能:");
	int order;
	scanf("%d", &order);
	switch (order){
	case 1:
		sortAirlineAsairlineNumUseInsert();
		break;
	case 2:
		sortAirlineAsTimeUseBubble();		
		break;
	case 3:
		managerForm();
		break;
	default:
		printf("输入选项无效,即将跳转到管理员主页面...\n");
		sleep(1);
		system("cls");
		managerForm();
	}
	printf("\n\n");
	outputAirlineInfo();
	printf("\n\n");

	getchar();
	printf("按任意键继续...");
	getchar();
	system("cls");
	managerForm();
}

void addAirlineForm() {
	printf("\n\n");	
	addAirline();
	printAirlineInfo();//添加航班信息之后,需要更新航班信息的数组
	getchar();
	printf("按任意键继续...");
	getchar();
	system("cls");
	managerForm();
	printf("\n\n");
}

void updateAirlineForm() {
	sortAirlineAsairlineNumUseInsert();
	printf("\n\n");
	outputAirlineInfo();
	updateAirlineInfo();
	printAirlineInfo();
	getchar();
	printf("按任意键继续...");
	getchar();
	system("cls");
	managerForm();
	printf("\n\n");
}

void deleteAirlineForm(){
	sortAirlineAsairlineNumUseInsert();
	printf("\n\n");
	outputAirlineInfo();
	deleteAirline();
	printAirlineInfo();
	getchar();
	printf("按任意键继续...");
	getchar();
	system("cls");
	managerForm();
	printf("\n\n");
}

void showUserInfoForm() {
	printf("\n\n");
	printf("================================================================================================================\n");
	//outputClientInfo();
	getAllClientInfo(true);
	printf("================================================================================================================\n");
	printf("\n\n");

	getchar();
	printf("按任意键继续...");
	getchar();
	system("cls");
	managerForm();
	
}

void userForm() {
	int choose;
	printf("						顾客页面\n\n");
	printf("================================================================================================================\n");
	printf("				1.查看航班信息               2.查看已定机票\n");
	printf("				3.订票                       4.退票\n");
	printf("				5.退出\n");
	printf("================================================================================================================\n");
	printf("请选择功能:");
	scanf("%d", &choose);
	switch (choose){
	case 1:
		clientShowAirlineForm();
		break;
	case 2:
		selectClientInfo();
		break;
	case 3:
		bookingTicketsForm();
		break;
	case 4:
		deleteClientForm();
		break;
	case 5:
		getchar();
		system("cls");
		userLoginForm();
		break;
	default:
		printf("输入选项无效,即将跳转顾客登录界面...\n");
		sleep(1);
		system("cls");
		userForm();
	}

}

void clientShowAirlineForm() {
	printf("================================================================================================================\n");
	printf("				1.航班号顺序				 2.时间顺序\n");
	printf("				3.返回\n");
	printf("================================================================================================================\n");
	printf("请选择功能:");
	int order;
	scanf("%d", &order);
	switch (order){
	case 1:
		sortAirlineAsairlineNumUseInsert();
		break;
	case 2:
		sortAirlineAsTimeUseBubble();		
		break;
	default:
		printf("输入选项无效,即将跳转顾客登录界面...\n");
		sleep(1);
		system("cls");
		userForm();
	}
	printf("\n\n");
	
	outputAirlineInfo();
	printf("\n\n");

	getchar();
	printf("按任意键继续...");
	getchar();
	system("cls");
	userForm();
}

void selectClientInfo() {
	printf("\n\n");
	char name[10];
	printf("输入用户名:");
	scanf("%s", &name);
	printf("订票信息如下:\n");
	searchClient(name, false);
	printf("\n\n");

	getchar();
	printf("按任意键继续...");
	getchar();
	system("cls");
	userForm();
}

void bookingTicketsForm() {
	printf("\n\n");
	outputAirlineInfo();
	bookingTickets();
	printf("\n\n");

	getchar();
	printf("按任意键继续...");
	getchar();
	system("cls");
	userForm();
	
}

void deleteClientForm() {
	printf("\n\n");
	cancelTickets();
	printf("\n\n");

	getchar();
	printf("按任意键继续...");
	getchar();
	system("cls");
	userForm();
}

/////////////////////////////////////////////////////////////////////////////////////////////////
void printAirlineInfo(){
	FILE *read = fopen("airline.dat", "r");
	if (read == NULL){
		printf("航班信息为空\n");
	} else {
		readInfoToArray();			//读取文件内容到数组中
		/*
		printf("航班号\t\t飞机号\t\t出发地\t\t目的地\t\t起飞时间\t机票总数\t剩余票数\n");		//信息标题
		for (index_airline = 0; index_airline < totalAirlines; index_airline++){
			printf(PRINT);
		}
		*/
	}
	fclose(read);
}

void outputAirlineInfo(){
	printf("航班号\t\t飞机号\t\t出发地\t\t目的地\t\t起飞时间\t机票总数\t剩余票数\n");		//信息标题
	for (index_airline = 0; index_airline < totalAirlines; index_airline++){
		printf(PRINT);
	}
}
void outputSingalAirlineInfo(int index){
	printf("航班号\t\t飞机号\t\t出发地\t\t目的地\t\t起飞时间\t机票总数\t剩余票数\n");
	index_airline = index;
	printf(PRINT);
}

void readInfoToArray() {
	FILE *readToArray = fopen("airline.dat", "r");

	totalAirlines = 0;
	while (!feof(readToArray)){
		fread(&array_Airline[totalAirlines],sizeof(struct Airline),1,readToArray);		//逐块读取数据
		totalAirlines++;
	}
	fclose(readToArray);
//printf("%d", totalAirlines);
	totalAirlines--;//为什么会多一
}

void addAirline(){
	int week;		//航班出行时间,周一到周天,用1到7表示
	FILE *writeInfo = fopen("airline.dat", "ab+");
	char end[10];
	do{
		printf("请依次输入您要增加的航班信息(以回车键结束):  \n");
		printf("================================================================================================================\n");
		printf("航班号: ");  
		array_Airline[totalAirlines].airlineNum = totalAirlines;
		printf("%d\n",array_Airline[totalAirlines].airlineNum);
		printf("请输入飞机号: ");
		scanf("%d",&array_Airline[totalAirlines].airplaneNum);		
		printf("请输入出发地点: ");
		scanf("%s",&array_Airline[totalAirlines].departure);		
		printf("请输入目的地: ");
		scanf("%s",&array_Airline[totalAirlines].destionation);		
		printf("请输入出发时间(1-7): ");
		scanf("%d",&week);
		while (week < 1 || week > 7){
			printf("输入正确时间,周一到周天用 1 到 7 表示:");
			scanf("%d",&week);
		}
		array_Airline[totalAirlines].time= week;
		printf("机票总数: ");
		scanf("%d",&array_Airline[totalAirlines].totalTickets);
		//剩余票数为机票总数
		for (int i = 0; i < array_Airline[totalAirlines].totalTickets; i++){
//printf("%d", i);
			array_Airline[totalAirlines].remainTickets[i] = 0;
		}
		//写入文件
		fwrite(&array_Airline[totalAirlines], sizeof(struct Airline), 1, writeInfo);
		totalAirlines++;
		printf("添加完毕,是否继续添加?请键入y或n以回车键结束:");
		scanf("%s",end);
	}
	while (!strcmp(end,"y"));
	fclose(writeInfo);
}

void updateAirlineInfo(){
	char chooseChangeAirline[2];
	bool changeClient = false;
	int id;
	do{
		printf("\n输入需要修改的航班的航班号:");
		scanf("%d", &id);
		sortAirlineAsairlineNumUseInsert();
		int index = searchAirline(id);
		if (index == -1){
			printf("输入的航班不存在");
		} else{
			//航班信息只要修改,顾客信息表中的提示信息就要修改,所以有必要将用户的信息添加到临时数组中
			int week;	//表示修改的新的时间,周一到周天用1到7表示
			char choose[2];	//选择是否继续修改该条航班信息
			do{
				changeClient = false;
				outputSingalAirlineInfo(index);
				//不仅仅要修改数组的内容还要修改文件中内容
				printf("\n");
				printUpdateAirlineOptions();
				printf("选择需要修改的选项:");
				int option;
				scanf("%d", &option);
				if (option > 5){
					printf("选项无效");
					break;
				}
				switch (option){
				case 1:
					printf("输入新的飞机号:");
					scanf("%d", &array_Airline[index].airplaneNum);
					break;
				case 2:
					changeClient = true;
					printf("输入新的出发地:");
					scanf("%s", &array_Airline[index].departure);
					break;
				case 3:
					changeClient = true;
					printf("输入新的目的地:");
					scanf("%s", &array_Airline[index].destionation);
					break;
				case 4:
					printf("输入新的时间:");
					scanf("%d",&week);
					while (week < 1 || week > 7){
						printf("输入正确时间,周一到周天用 1 到 7 表示:");
						scanf("%d",&week);
					}
					array_Airline[index].time = week;
					break;
				case 5:
					break;
				default:
					printf("输入选项无效\n");
					sleep(1);
					break;
				}	
				outputSingalAirlineInfo(index);
				printf("是否继续修改该条航线信息(y/n):");
				scanf("%s", choose);
			}
			while (!strcmp(choose,"y"));
			changeAirlineInfo(index);
		}
		if (changeClient){
			changeClientTickets(0, 3, id);
			printf("相关用户提示信息已经修改\n");
		} 
		else {
			changeClientTickets(0, 2, id);
			printf("相关用户提示信息已经修改\n");
		}
		printf("是否需要修改其他航线(y/n):");
		scanf("%s", chooseChangeAirline);
		//调用修改用户信息的方法
	}
	while (!strcmp(chooseChangeAirline,"y"));
}

int searchAirline(int id){
	//先将航班信息按照航班号进行排序再查找
	//二分法查找
	int low = 0, high = totalAirlines, mid;
	while (low <= high){
		mid = (low + high) / 2;
		if (id == array_Airline[mid].airlineNum){
			return mid;
		} else if (id < array_Airline[mid].airlineNum){
			high = mid - 1;
		} else {
			low = mid + 1;
		}
	}

	return -1; //没有查到
}

void changeAirlineInfo(int index){
	FILE *change = fopen("airline.dat", "rb+");
	fseek(change, sizeof(struct Airline) * index, 0);
	fwrite(&array_Airline[index], sizeof(struct Airline), 1, change); //修改文件内容
	fclose(change);
}
void printUpdateAirlineOptions(){
	printf("				修改航班信息页面\n\n");
	printf("================================================================================================================\n");
	printf("             1.飞机号				2.出发地\n");
	printf("             3.目的地				4.时间\n");
	printf("             5.退出\n");
	printf("================================================================================================================\n");
}

void deleteAirline() {
	printf("选择需要删除的航班的航班号:");
	int airline;
	scanf("%d", &airline);
	if (searchAirline(airline) == -1){
		printf("输入的航班号无效");
	}
	else {
		char choose[2];
		printf("确认要删除此航班信息吗?(y/n):");
		scanf("%s", &choose);
		if (!strcmp(choose, "y")){
			index_airline = airline;
			int total = array_Airline[airline].totalTickets - remain(array_Airline[airline].remainTickets);
			printf("将会有 %d 名顾客收到影响,请再次确认(y/n): ", total);
			scanf("%s", &choose);
			if (!strcmp(choose, "y")){
				//将相关的顾客的信息全改成无效
				changeClientTickets(0, 3, airline);
				//重新写航班信息文件
				FILE * reWrite = fopen("airline.dat", "w");
				for (int i = 0; i < totalAirlines; i++){
					if (array_Airline[i].airlineNum != airline){
						fwrite(&array_Airline[i], sizeof(struct Airline), 1, reWrite);
					}
				}
				fclose(reWrite);
				totalAirlines--;
				
				printAirlineInfo();
			} 
			else {
				printf("删除航班命令已经取消\n");
			}
		}
		else {
			printf("删除航班命令已经取消\n");
		}
	}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void bookingTickets() {
	readInfoToArray();
	char choose[2];
	printf("输入用户名:");
	scanf("%s", &client.name);
	printf("输入航班号:");
	scanf("%d", &index_airline);
	if (searchAirline(index_airline) != -1){
		client.airlineNum = index_airline;
		strcpy( client.tips, "有效");//给字符数组赋值。。。。。尴尬
		//查询该航班剩余票数
		outputSingalAirlineInfo(index_airline);
		if (remain(array_Airline[index_airline].remainTickets) > 0){
			printf("请仔细查看航班信息再确认(y/n):");
			scanf("%s", choose);

			if (!strcmp(choose, "y")){
				//保证座位号不为0
				client.seatNum = selectSeat(index_airline);
				printf("谢谢您选择本次航班:\n");
				printf("航班号\t\t飞机号\t\t出发地\t\t目的地\t\t起飞时间\t用户名\t\t用户座位号\t提示\n");
				//修改航班信息表和客户信息表
				changeAirlineTickets(index_airline);
				printf(PRINTCLIENT);
				//添加用户信息表
				addUser();
			}  else {
				printf("本次订票已取消");
			}
		} else {
			printf("该航班已经没有剩余的票,此次购票自动取消");
		}
		
	} else {
		printf("该航班不存在,此次购票自动取消");
	}
}

int remain (int *tickets){
	int num = 0;
	for (int i = 0; i < array_Airline[index_airline].totalTickets; i++){
		if (tickets[i] == 0){
			num++;
		}
	}

	return num;
}

void changeAirlineTickets(int index){
	FILE *change = fopen("airline.dat", "rb+");
	fseek(change, sizeof(struct Airline) * index, 0);
	fwrite(&array_Airline[index], sizeof(struct Airline), 1, change); 
	fclose(change);
}

int selectSeat(int index){
	for (int i = 0; i < array_Airline[index].totalTickets; i++){
		if (array_Airline[index].remainTickets[i] == 0){
			array_Airline[index].remainTickets[i] = 1;
			return i + 1;
		}
	}

	return -1;
}

void addUser(){
	FILE * userFile = fopen("customer.dat", "ab+");
	fwrite(&client, sizeof(client), 1, userFile);
	fclose(userFile);
}

void outputClientInfo() {
	FILE *readCustomer = fopen("customer.dat", "r");
	if (readCustomer == NULL){
		printf("用户信息为空\n");
	} else {
		printf("航班号\t\t飞机号\t\t出发地\t\t目的地\t\t起飞时间\t用户名\t用户座位号\n");		//信息标题
		fread(&client,sizeof(struct Client),1,readCustomer);		//逐块读取数据
//printf("%s\n", client.name);
		index_airline = client.airlineNum;
		while (!feof(readCustomer)){
			printf(PRINTCLIENT);
			fread(&client,sizeof(struct Client),1,readCustomer);		//逐块读取数据
			index_airline = client.airlineNum;
		}
	}
	fclose(readCustomer);
}
int getAllClientInfo(bool show) {
	//把所有的用户信息读到数组中,根据机票是否有效和航班号进行排序
	//依次读取用户信息,当读到无效的机票,就让他和第一个有效的机票位置交换
	int firstValid = 1;	//记录第一个有效机票的位置,也是无效机票的张数
	int index = 1;	//下表从1开始存储,0位作为交换的中转站
	FILE *readCustomer = fopen("customer.dat", "r");
	if (readCustomer == NULL){
		printf("用户信息为空\n");
	} else {
		if (show){
			fread(&clients[index],sizeof(struct Client),1,readCustomer);		//逐块读取数据
			//读到的第一个如果无效不用交换,但是要把标记第一个有效位的数值
			if (clients[index].seatNum == -1 || clients[index].seatNum == 0){
				firstValid++;
			}
			index++;
	//printf("%d, %d", firstValid, index);	
			while (!feof(readCustomer)){
				fread(&clients[index],sizeof(struct Client),1,readCustomer);		//逐块读取数据
			
				if (clients[index].seatNum == -1 || (
					clients[index].seatNum == 0 && strlen(clients[index].name) > 1)){
	//printf("%d\t\t%s\t%d\n", clients[index].airlineNum, clients[index].name, clients[index].seatNum);
	//printf("%d\t\t%s\t%d\n", clients[firstValid].airlineNum, clients[firstValid].name, clients[firstValid].seatNum);
					if (index > firstValid){
						clients[0] = clients[firstValid];
						clients[firstValid] = clients[index];
						clients[index] = clients[0];
					}
					firstValid++;
				}
				
				index++;
			}
			index -= 1;
	//printf("%d, %d", firstValid, index);
			//将读到的信息进行排序,无效的订票信息和有效的订票信息分开来排序,都使用冒泡
			bool change;
			if (firstValid != 1){
				for (int i = 1; i < firstValid; i++){
					change = false;
					for (int j = 1; j < firstValid - i; j++){
						if (clients[j].airlineNum > clients[j + 1].airlineNum){
							clients[0] = clients[j];
							clients[j] = clients[j + 1];
							clients[j + 1] = clients[0];
							change = true;
						}
					}
					if (!change){
						break;
					}
				}
			}
			
			for (int i = firstValid; i < index; i++){
				change = false;
				for (int j = firstValid; j < index - i; j++){
					if (clients[j].airlineNum > clients[j + 1].airlineNum){
						clients[0] = clients[j];
						clients[j] = clients[j + 1];
						clients[j + 1] = clients[0];
						change = true;
					}
				}
				if (!change){
					break;
				}
			}

			printf("航班号\t\t用户名\t\t座位号\t\t提示\n");
			for (int i = 1; i < index ; i++){
				printf("%d\t\t%s\t\t%d\t\t%s\n", clients[i].airlineNum, clients[i].name, clients[i].seatNum, clients[i].tips);
			}
			fclose(readCustomer);
			return 0;
		}
		else {
			int clientIndex = 0;
			while (!feof(readCustomer)){
				fread(&clients[clientIndex],sizeof(struct Client),1,readCustomer);		//逐块读取数据
				clientIndex++;
			}
			fclose(readCustomer);
			clientIndex--;

			//printf("航班号\t\t用户名\t\t座位号\t\t提示\n");
			//for (int i = 0; i < clientIndex ; i++){
			//	printf("%d\t\t%s\t\t%d\t\t%s\n", clients[i].airlineNum, clients[i].name, clients[i].seatNum, clients[i].tips);
			//}
			
			return clientIndex;
		}
	}
}

void cancelTickets() {
	char name[10];
	int airlineId;
	int seatId;

	readInfoToArray();

	printf("输入用户名:");
	scanf("%s", &name);
	if (!searchClient(name, false)){
		printf(" %s %s\n", name, "没有订票信息");
	} else { //根据航班号和座位号确定座位号
		printf("输入航班号,座位号,以确定需要取消的机票:\n");
		printf("航班号:");
		scanf("%d", &airlineId);
		printf("座位号:");
		scanf("%d", &seatId);
		if (deleteClient(airlineId, seatId)){
			printf("已经成功删除\n");
		} else {
			printf("输入信息不匹配,取消机票失败\n");
		}
	}
}

bool searchClient(char name[10], bool displayInvalid){
	bool had = false;
	int index = 0;
	FILE *readCustomer = fopen("customer.dat", "r");
	if (readCustomer == NULL){
		printf("查询信息为空\n");
		return false;
	}
	//注意这里的读法,详情参照https://blog.csdn.net/bingqing07/article/details/5785080/
	printf("航班号\t\t飞机号\t\t出发地\t\t目的地\t\t起飞时间\t用户名\t\t座位号\t\t提示\n");		//信息标题
	fread(&client,sizeof(struct Client),1,readCustomer);		//逐块读取数据
	index_airline = client.airlineNum;
	while (!feof(readCustomer)){
		if (!strcmp(name, client.name)){
			if (displayInvalid){
				printf(PRINTCLIENT);
				had = true;
			} else{
				if (client.seatNum != -1){
					printf(PRINTCLIENT);
					had = true;
				} 
				if (client.seatNum == 0){//修改顾客的座位号为-1,并更新用户表中信息
					client.seatNum = -1;
					changeClientTickets(index, 1, 0);
				}
			}
		}
		fread(&client,sizeof(struct Client),1,readCustomer);		//逐块读取数据
		index_airline = client.airlineNum;
		index++;
	}
	fclose(readCustomer);
	if (!had){
		printf("查询信息为空\n");
	}
	return had;
}

bool deleteClient(int airlineId, int seatId) {
	bool change = false;
	int index = 0;	//记录修改用户信息表的时候需要跳转几个用户结构体
	FILE *readCustomer = fopen("customer.dat", "r");
	fread(&client,sizeof(struct Client),1,readCustomer);		//逐块读取数据
	index_airline = client.airlineNum;
	while (!feof(readCustomer)){
		if ((client.airlineNum == airlineId) && (client.seatNum == seatId)){
			//修改用户信息表中座位号为-1
			client.seatNum = -1;
			strcpy(client.tips, "退票");
			//修改航班表中的remainTickets对应的位置为0
			//此时需要修改的用户已经读取到client中了
			setSeatNumZero(airlineId, seatId, index);

			change = true;
		}

		fread(&client,sizeof(struct Client),1,readCustomer);		//逐块读取数据
		index_airline = client.airlineNum;
		index++;
	}
	fclose(readCustomer);
	
	return change;
}

void setSeatNumZero(int airline, int seatId, int index){
	array_Airline[airline].remainTickets[seatId - 1] = 0;
	changeAirlineTickets(airline);
	changeClientTickets(index, 1, 0);
}

void changeClientTickets(int index, int choose, int airline) {
	FILE *change = fopen("customer.dat", "rb+");
	if (choose == 1){
		fseek(change, sizeof(struct Client) * index, 0);
//printf("%s, %d", client.name, client.seatNum);
		fwrite(&client, sizeof(struct Client), 1, change); 
		fclose(change);
	}
	else {
		char tips[50];
		if (choose == 2){//需要修改用户的提示信息为,航班信息已修改,请注意飞机号和起飞时间
			strcpy(tips, "航班信息已修改,请注意出行安排");
			int total = getAllClientInfo(false);
			for (int i = 0; i < total; i++){
				//有-1的判断:当管理员将航班取消的时候,为-1的信息改成0也没意义了,反倒给顾客混乱信息
				if (clients[i].airlineNum == airline && clients[i].seatNum != -1) {
					strcpy(clients[i].tips, tips);
					fseek(change, sizeof(struct Client) * i, 0);
					fwrite(&clients[i], sizeof(struct Client), 1, change); 
				}
			}
			fclose(change);
		}
		else if (choose == 3){//需要修改用户的航班信息为:抱歉,航线已修改,此机票作废,已经退款
			strcpy(tips, "抱歉,航线已修改,此机票作废,已经退款");
			int total = getAllClientInfo(false);
			for (int i = 0; i < total; i++){
				if (clients[i].airlineNum == airline && clients[i].seatNum != -1) {
					strcpy(clients[i].tips, tips);
					clients[i].seatNum = 0;
					fseek(change, sizeof(struct Client) * i, 0);
					fwrite(&clients[i], sizeof(struct Client), 1, change); 
				}
			}
			fclose(change);
		}
		
	}
}

void sortAirlineAsTimeUseBubble() {
	for (int i = totalAirlines; i >= 0; i--){
		array_Airline[i] = array_Airline[i - 1];
	}

	bool change = true;
	for (int i = 1; i <= totalAirlines; i++){
		change = false;
		for (int j = 1; j <= totalAirlines - i; j++){
			if (array_Airline[j].time > array_Airline[j + 1].time){
				array_Airline[0] = array_Airline[j];
				array_Airline[j] = array_Airline[j + 1];
				array_Airline[j + 1]= array_Airline[0];
				change = true;
			}
		}
		if (!change){
			break;
		}
	}
	//将数组中存储的数据复原为从0开始
	for (int i = 0; i < totalAirlines; i++){
		array_Airline[i] = array_Airline[i + 1];
	}
}

void sortAirlineAsairlineNumUseInsert() {
	//使用array_Airline[0]作为监视哨,需要将数组整体后移一位
	for (int i = totalAirlines; i >= 0; i--){
		array_Airline[i] = array_Airline[i - 1];
	}
	int j;
	for (int i = 2; i <= totalAirlines; i++){
		array_Airline[0] = array_Airline[i];
		j = i - 1;
		while (array_Airline[0].airlineNum < array_Airline[j].airlineNum){
			array_Airline[j + 1] = array_Airline[j];
			j = j - 1;
		}
		array_Airline[j + 1] = array_Airline[0];
	}
	//将数组中存储的数据复原为从0开始
	for (int i = 0; i < totalAirlines; i++){
		array_Airline[i] = array_Airline[i + 1];
	}
}

猜你喜欢

转载自blog.csdn.net/cheng_cuo_tuo/article/details/85058436