C/C++ 基于链队列的自行车租赁管理系统

 这是学校数据结构实验课所给的一个作业

一、题目 

“绿色出行”正逐步成为时尚,有些城市开始在固定的站点提供自行车租借服务。设计数据结构及算法完成自行车租借的日常工作的组织与管理。基本管理对象为自行车,每辆自行车用一个id进行唯一标识。每辆自行车存在三种可能状态:

可以租借(available for rent)

已借(rented)

修理中(in repair)

实验要求:

其中在available队列中自行车应该依据其租借的时间总数进行排序,租借时间最少的自行车排在最前面。在rented队列中的自行车应依据其预期返回时间进行排序,排在最前的应是预期最早返回的自行车。

1用三个链表组织三种状态的自行车,初始时有10辆自行车(a-j)可以租借。

2能够实现租借的日常事务:引入新车,租借,收费,修理等。

3租借收费应根据自行车借去的时间计算得出,路程收费标准如下:每小时收费1元

4根据被借的总时间长短(超过5小时)定期对自行车进行维护(维护时间为2小时)。

5还需实现辅助操作:自行车查询,打印全部信息,计算并打印收入(成本及收益)。

6应有完整的界面。

必做要求:

1用三个链表组织三种状态的自行车,初始时有10辆自行车(a-j)可以租借。

2能够实现租借的日常事务:引入新车,租借,修理等。

3在租借状态下的自行车超过5辆以后,排在第一位的自行车以随机20%的概率进行修理维护(租借队列中自行车80%的可能回到available队列,20%的可能进入repair队列)。

4 在修理状态下的自行车超过3辆以后,排在第一位的自行车回到可以租借队列中。

5实现在控制台输入“引入新车,租借,修理”时,能够要求有适当的输入提示如引入新车的编号,并能够分别显示租借或修理的自行车编号,以及三个队列中所有自行车编号序列。

实现提示

主要集中在链队列的基本操作上。

对于题目所给的要求我没有完全实现,如必做要求中的3就没写,必做要求中的5没有做分别显示租借或修理的自行车编号

二、实验步骤

1、设计链表队列并实现

设计链表队列的数据域含有的数据项,包括编号id、租借总时间sumrenttime、开始租借时间rent_time、归还时间return_time、开始修理时间repair_time、修理次数repair、目前状态now。

设计链表队列的操作函数,包括初始化链表队列InitQueue()、销毁链表队列DestroyQueue()、入队EnQueue()、出队DeQueue()、清空队列ClearQueue()、求队列长度QueueLength()、得到队列中第i个元素GetElem()。

代码如下,该代码存放在Queue.h头文件中:

#include <stdlib.h>
#include <time.h>
#include <iostream>
using namespace std;

typedef struct Bicycle{
	char id;                    //自行车编号 
	int sumrenttime=0;          //租借总时间 
    time_t rent_time=0;         //开始租借时间
    time_t return_time=0;       //归还时间 
    time_t repair_time=0;       //开始修理时间 
    int repair=0;               //修理次数 
    int now=0;                  //目前状态(可租借0、已租借1、修理中2)   
}Bicycle;

typedef struct QNode{           //队列的结点 
	Bicycle data;               //数据域 
	struct QNode *next;         //指针域 
}QNode,*QueuePtr;

typedef struct{                 //队列 
	QueuePtr front;             //队头指针,从这头出队 
	QueuePtr rear;              //队尾指针,从这头入队 
}LinkQueue;

void InitQueue(LinkQueue&Q){       //初始化链表队列,带头结点
	Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
	if(!Q.front) exit(0);
	Q.front->next=NULL;
}

void DestroyQueue(LinkQueue&Q){    //销毁链表队列 
	while(Q.front){
		Q.rear=Q.front->next;
		free(Q.front);
		Q.front=Q.rear;
	}
}

void EnQueue(LinkQueue&Q,Bicycle e){    //将Bicycle类型的元素e入队
	QueuePtr p=(QueuePtr)malloc(sizeof(QNode));
	if(!p) exit(0);
	p->data=e;
	p->next=NULL;
	Q.rear->next=p;
	Q.rear=p;
}

void DeQueue(LinkQueue&Q,Bicycle&e){    //将队头元素出队,并用e存储数据 
	if(Q.front==Q.rear) exit(0);
	QueuePtr p=Q.front->next;
	e=p->data;
	Q.front->next=p->next;
	if(Q.rear==p) Q.rear=Q.front;
	free(p);
}

void ClearQueue(LinkQueue&Q){      //清空队列 
	QNode *p = Q.front; 
	while(p)
	{
		Q.front = p->next;
		delete p;
		p = Q.front;
	}
}

int QueueLength(LinkQueue &Q){     //求队列的长度 
    QNode *p=Q.front;
    int i=0;
    while(p->next!=NULL){
    	p=p->next;
    	i++;
	}
	return i;
}

void GetElem(LinkQueue Q, int i, Bicycle &e){ //得到队列中第i个元素的数据
	if(i<1) return;    //若i<1错误 
	QNode *p = Q.front->next; //
	for(int k=0; k<i-1; k++)
	{
		p = p->next;
	}
	e = p->data;
}

2、在主函数外声明功能函数,包括函数名及变量类型

需要实现的功能函数包括:引入新车addBicycle()、租借rentBicycle()、还车收费fee()、修理repair()、自行车查询search()、打印全部信息PrintAll()、计算并打印收入income()、对队列进行按总租借时间从小到大排序CompareMin()、整理修理中队列Test()。

代码如下,该代码存放在main.cpp文件中 :

#include "Queue.h"
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <math.h> 

char fileName[] = "Bicycle.txt";         //存放所有自行车信息的文件 

//功能函数 
//对队列进行按总租借时间从小到大排序
void CompareMin(LinkQueue &Q){
}

//整理修理中队列,将需要放回到可租借队列的自行车放回 
void Test(LinkQueue &Available,LinkQueue &Repair){
}

//租借自行车,将自行车从可租借队列放入已租借队列 
void rentBicycle(LinkQueue &Available,LinkQueue &Rent,LinkQueue &Repair){ 
}

//归还自行车并收费
void fee(LinkQueue &Available,LinkQueue &Rent,LinkQueue &Repair){ 
}

//手动将某在可租借队列的自行车送去修理
void repair(LinkQueue &Available,LinkQueue &Rent,LinkQueue &Repair){
}

//查询并打印某一自行车的信息
void search(LinkQueue &Q1,LinkQueue &Q2,LinkQueue &Q3){ 
}

//添加一辆新自行车到可租借队列
void addBicycle(LinkQueue &Available,LinkQueue &Rent,LinkQueue &Repair){ 
}

//将所有自行车数据打印到屏幕 
void PrintAll(LinkQueue &Available,LinkQueue &Rent,LinkQueue &Repair) {
}

//计算并打印收入
void income(LinkQueue &Available,LinkQueue &Rent,LinkQueue &Repair){
}

3、编写主函数

(1)建立三个队列:可租借队列Available、已租借队列Rent、修理中队列Repair,并将它们初始化。

(2)将初始的10辆自行车通过for循环语句存入可租借队列。

(3)打印可选择的功能并提示选择对应功能。

(4)根据选择的功能调用对应功能函数。

(5)选择退出系统后,清空三个队列。

int main()
{
	LinkQueue Available;     //建立一个可租借队列 
	LinkQueue Rent;          //建立一个已租借队列 
	LinkQueue Repair;        //建立一个修理中队列 
	InitQueue(Available);    //初始化队列
	InitQueue(Rent);         //初始化队列
	InitQueue(Repair);       //初始化队列
	//将初始的10个自行车放入可租借队列 
	Bicycle y[10];
	for(int x=0;x<10;x++){
		y[x].id=char('a'+x);
		EnQueue(Available,y[x]);
	}
	
	int x = 0;
	bool out = 0;    //判断是否停止使用系统,退出程序 
	Bicycle e;
	while(!out)      //提示选择功能 
	{
		Test(Available,Repair);
		printf("引入新车(0)\n");
		printf("租借(1)\n");
		printf("还车收费(2)\n");
		printf("修理(3)\n");
		printf("自行车查询(4)\n");
		printf("打印全部信息(5)\n");
		printf("计算并打印收入(6)\n");
		printf("退出系统(7)\n");
		printf("请输入要选择的功能:"); 
		scanf("%d",&x);
		switch(x)
		{
			case 0: addBicycle(Available,Rent,Repair); break;
			case 1: rentBicycle(Available,Rent,Repair); break;
			case 2: fee(Available,Rent,Repair); break; 
			case 3: repair(Available,Rent,Repair); break;
			case 4: search(Available,Rent,Repair); break;
			case 5: PrintAll(Available,Rent,Repair); break;
			case 6: income(Available,Rent,Repair); break;                     
			case 7: out = 1; break;     //退出系统 
			default: printf("选择错误\n\n\n");
		}
	}
	ClearQueue(Available);
	ClearQueue(Rent);
	ClearQueue(Repair); 
}

4、编写功能函数

编写过程中还另外定义了几个功能函数,包括判断两条自行车编号信息是否重复compare()、打印一条自行车信息visit()、保存信息到文件savetoFile()、打印输出文件printFile()、清空文件clearFile()

(1)引入新车addBicycle():

定义一个队列的数据项,将新车的编号写入,比较编号是否与已有自行车重复,若重复停止使用该功能,返回到选择功能界面。若不重复,再将该数据项存入可租借队列。新车的租借总时间为零,不需要对可租借队列进行排序。调用了新定义的函数compare()。

代码如下:

int compare(Bicycle e1, Bicycle e2){
	if(e1.id==e2.id) return 1;
	else return 0;
}

void addBicycle(LinkQueue &Available,LinkQueue &Rent,LinkQueue &Repair){ 
	Bicycle e;
	int x=0,l=0;
	QNode *p=Available.front->next;      //指针指向可租借队列第一辆自行车 
	printf("输入自行车的编号信息:");
	getchar();
	scanf("%c", &e.id);
	//比较编号是否重复
	l=QueueLength(Available);
	for(int i=0;i<l;i++){       //比较编号是否与可租借队列的自行车重复 
		x=compare(e,p->data);
		if(x==1){
			printf("编号与已有自行车重复,请重新选择功能\n\n\n");
			return ;
		}
		p=p->next;
	}
	p=Rent.front->next;
	l=QueueLength(Rent);
	for(int i=0;i<l;i++){       //比较编号是否与已租借队列的自行车重复
		x=compare(e,p->data);
		if(x==1){
			printf("编号与已有自行车重复,请重新选择功能\n\n\n");
			return ;
		}
		p=p->next;
	}
	p=Repair.front->next;
	l=QueueLength(Repair);
	for(int i=0;i<l;i++){       //比较编号是否与修理中队列的自行车重复
		x=compare(e,p->data);
		if(x==1){
			printf("编号与已有自行车重复,请重新选择功能\n\n\n");
			return ;
		}
		p=p->next;
	} 
	EnQueue(Available,e);
    printf("成功引入编号为%c的新车\n\n\n",e.id);
}

(2)租借rentBicycle():

将可租借队列的队头元素出队,把该元素存入已租借队列,并记录开始租借时间、改变自行车状态。已租借队列中按预期归还时间排序,假设借出最早的自行车预期最早归还,则不需要进行排序,只需要在入队出队时注意操作顺序。

代码如下:

void rentBicycle(LinkQueue &Available,LinkQueue &Rent,LinkQueue &Repair){ 
	Bicycle e,e1;
	EnQueue(Rent,Available.front->next->data);
	DeQueue(Available,e);                      //将可租借队列的队头元素挪至已租借队列的队尾
	Rent.rear->data.now = 1;                   //改变自行车状态 
	Rent.rear->data.rent_time = time(NULL);    //记录开始租借时间 
	printf("您已成功租借了编号为%c的自行车\n\n\n",Rent.rear->data.id);   //提示租借成功 
	//这里应当将可租借队列按预期归还时间排序,假设借出最早的自行车预期最早归还 
}

(3)还车收费fee():

提示输入要归还的自行车编号,比较编号是否与已租借队列中的自行车相同,若不同则提示输入错误,返回选择功能界面,若相同则计算租借时间,向上取整得到小时数,按1小时1元收费,打印并输出开始租借时间、归还时间、需支付费用。

判断此归还自行车是否需要修理,若距离上次修理又使用了5小时及以上则送去修理,若不需要修理则返回到可租借队列并改变相应数据项。

对该自行车进行操作时,先声明并初始化一个辅助队列,将已租借队列中排在此自行车前面的自行车存入辅助队列,再对该自行车进行操作,操作完后再将已租借队列中剩下的自行车存入辅助队列,再把该辅助队列复制到已租借队列。此操作目的在于保证已租借队列按开始租借时间排序,最早租借的排在队头。

注:

这部分代码有误:关键在于“若距离上次修理又使用了5小时及以上则送去修理”这一句,采用的是租借总时间减去5*修理次数,这是不对的。若用户租赁一辆租借总时间为0的自行车7个小时后还回来,此时租借总时间变为7,需要送去修理。修理完后,下一位用户租借该自行车3小时后还回来,距离上次修理又使用了3个小时,其实不需要送去修理,但按照我的写法其实又送去修理了,与需要完成的功能不符。

解决办法:

在Bicycle中添加一个int类型数据项after_repair,意为距上次修理后自行车又使用的小时数,每次还车时将本次租借的小时数加到该项上,每次修理完后把该项改为零,使用if(after_repair>=5)语句进行判断是否要送去修理。

代码如下:

void fee(LinkQueue &Available,LinkQueue &Rent,LinkQueue &Repair){ 
	Bicycle e1,e2;
	char id1;
	int x=0,n=0;
	int j=QueueLength(Rent);
	printf("请输入要归还的自行车编号:");
	getchar();
	scanf("%c",&id1); 
	for(int k=0; k<j; k++)       //查询已租借队列中是否有要归还的自行车
	{
		GetElem(Rent,k+1,e1);    //得到Rent队列中第k+1个元素的数据
		if(e1.id==id1){
			x=1;
			e1.return_time = time(NULL);      //得到当前时间 
			double rent_time_seconds = difftime(e1.return_time,e1.rent_time);    //求被租借的时间有多少秒 
			double rent_time_minutes = rent_time_seconds/60;     //求被租借的时间有多少分钟 
			int  rent_time_hours = ceil(rent_time_minutes/60);   //向上取整求被租借的时间有多少小时
			 
			printf("开始租借时间为:%s",ctime(&e1.rent_time));
			printf("归还时间为:%s",ctime(&e1.return_time));
			printf("需支付%d元\n\n\n",rent_time_hours);        //向客户收费,1小时1元,不满一小时按一小时计 

			LinkQueue T;
			InitQueue(T);
			for (int i=0;i<k;i++)        //将队列中排在要归还的自行车前面的自行车出队存入队列T 
			{
				EnQueue(T,Rent.front->next->data);
				DeQueue(Rent,e2);
			}
			//判断该刚归还的自行车是否要修理
			if(Rent.front->next->data.sumrenttime-(Rent.front->next->data.repair*5)>=5) 
			{
				EnQueue(Repair,Rent.front->next->data);
				Repair.rear->data.now = 2;
				Repair.rear->data.repair_time = e1.return_time;    //记录开始修理时间
				Repair.rear->data.sumrenttime = Repair.rear->data.sumrenttime+rent_time_hours;  //将被租借的时间按小时加入总租借时间中
				DeQueue(Rent,e2);
			}
			else{            //不修理,返回到可租借队列 
				EnQueue(Available,Rent.front->next->data);
				Available.rear->data.now = 0;
				Available.rear->data.repair_time = e1.return_time;
				Available.rear->data.sumrenttime = Available.rear->data.sumrenttime + rent_time_hours;
				DeQueue(Rent,e2);
				CompareMin(Available);
			}
			n=QueueLength(Rent);
            //将已租借队列剩下的自行车存入队列T,再将队列T复制到已租借队列
			for (int i=0;i<n;i++) {
				EnQueue(T,Rent.front->next->data);
				DeQueue(Rent,e2);
			}
			n=QueueLength(T);
			for (int i=0;i<n;i++) {   //将T的元素逐个复制给已租借队列 
 		        EnQueue(Rent,T.front->next->data);
    	        DeQueue(T,e2);
 	        }
 	        DestroyQueue(T);
			break;
	    }
	}
	if(x==0){
		printf("此自行车编号不属于已租借自行车,请重新选择功能\n\n\n"); 
	}
}

(4)修理repair():

将可租借队列中的自行车送去修理。提示输入要修理的自行车编号,比较编号是否与可租借队列中的自行车相同,若不同则提示输入错误,返回选择功能界面,若相同则把该自行车放入修理中队列并改变数据项中的状态、开始租借时间。

对该自行车进行操作时,先声明并初始化一个辅助队列,将可租借队列中排在此自行车前面的自行车存入辅助队列,再对该自行车进行操作,操作完后再将可租借队列中剩下的自行车存入辅助队列,再把该辅助队列复制到已租借队列。此操作目的在于保证已租借队列按开始租借时间排序,最早租借的排在队头。

代码如下:

void repair(LinkQueue &Available,LinkQueue &Rent,LinkQueue &Repair){
	Bicycle e1,e2;
	int x=0;
	int j=QueueLength(Available),n;
	char id1;
	printf("请输入要修理的自行车编号:");
	getchar();
	scanf("%c",&id1);
	for (int k=0; k<j; k++) {    //查询可租借队列中是否有要修理的自行车
		GetElem(Available,k+1,e1);    //得到Available队列中第k+1个元素的数据
		if(e1.id==id1){
			x=1;		 
			e1.repair_time = time(NULL);
			printf("开始修理时间为:%s\n\n\n",ctime(&e1.repair_time));
			LinkQueue T;
			InitQueue(T);
			for(int i=0;i<k;i++){        //将队列中排在要修理的自行车前面的自行车出队存入队列T 
				EnQueue(T,Available.front->next->data);
				DeQueue(Available,e2);
			}
			EnQueue(Repair,Available.front->next->data);
			Repair.rear->data.repair_time = time(NULL);   //得到当前时间为开始修理时间 	
			Repair.rear->data.repair++;
			Repair.rear->data.now=2;
			DeQueue(Available,e2);
			n=QueueLength(Available);
			for(int i=0;i<n;i++){ //可租借队列剩下的自行车存入队列T,再将队列T复制到可租借队列
				EnQueue(T,Available.front->next->data);
				DeQueue(Available,e2);
			}
			n=QueueLength(T);
			for(int i=0;i<n;i++) {      //将T的元素逐个复制给可租借队列 
 		        EnQueue(Available,T.front->next->data);
    	        DeQueue(T,e2);
 	        }
 	        DestroyQueue(T);
			break;
		}
		j=QueueLength(Available);
	}
	if(x==0) printf("此自行车编号不属于可租借自行车,请重新选择功能\n\n\n");
}

(5)自行车查询search():

提示输入要查询的自行车编号,在三个队列中查询,若查询到则输出信息,若没有查询到则提示输入错误,返回到功能选择界面。输出信息时调用新定义的功能函数visit()。

代码如下:

void visit(Bicycle e){
	printf("编号%c,", e.id);
	if(e.now==0){
		printf("可租借,");
		printf("租借总时间为:%d,",e.sumrenttime);
		printf("修理次数为:%d\n\n\n",e.repair);
	}
	else if(e.now==1){
		printf("已租借,");
		printf("开始租借时间为:%s,",ctime(&e.rent_time));
		printf("修理次数为:%d\n\n\n",e.repair); 
	} 
	else if(e.now==2){
		printf("修理中,");
		printf("开始修理时间为:%s,",ctime(&e.repair_time));
		printf("修理次数为:%d\n\n\n",e.repair);
	} 
}

void search(LinkQueue &Q1,LinkQueue &Q2,LinkQueue &Q3){ 
	char id1;
	Bicycle e1,e2; 
	int n=0;
	printf("输入要查询的自行车编号:");
	getchar();
	scanf("%c",&id1);
	for(int k=0; k<QueueLength(Q1) && n==0; k++){     //查询可租借队列中是否有要找的自行车
		GetElem(Q1,k+1,e1);
		if(e1.id==id1){
			visit(e1);
			n=1;
			break;
		}
	} 
	for(int k=0; k<QueueLength(Q2) && n==0; k++){     //查询已租借队列中是否有要找的自行车
		GetElem(Q2,k+1,e1);
		if(e1.id==id1){
			visit(e1);
			n=1;
			break;
		}
	}
	for(int k=0; k<QueueLength(Q3) && n==0; k++){     //查询修理中队列中是否有要找的自行车
		GetElem(Q3,k+1,e1);
		if(e1.id==id1){
			visit(e1);
			n=1;
			break;
		}
	}
	if(n==0) printf("此自行车编号不属于已有的自行车,请重新选择功能\n\n\n");
}

(6)打印全部信息PrintAll():

先调用clearFile()函数清空文件,再调用三次savetoFile()函数分别将可租借队列、已租借队列、修理中队列的信息存入文件,最后调用printFile()函数将文件中的信息打印到屏幕上。

代码如下:

void savetoFile(LinkQueue &Q){
	Bicycle e;
	int j=QueueLength(Q);
	FILE *f = fopen(fileName, "a");    //打开文件,a是只写并向文件尾部追加数据 
	for(int k=0; k<j; k++){     //将队列中的信息打印到文件中 
		GetElem(Q,k+1,e);
		fprintf(f,"编号:%c\t", e.id);
		fprintf(f,"状态:");
		if(e.now==0){
			fprintf(f,"可租借\t");
			fprintf(f,"租借总时间:%d\t",e.sumrenttime);
			fprintf(f,"修理次数:%d\n",e.repair);
		}
	    else if(e.now==1){
	    	fprintf(f,"已租借\t");
	    	fprintf(f,"开始租借时间:%s\t",ctime(&e.rent_time));
	    	fprintf(f,"修理次数:%d\n",e.repair);
		}
	    else if(e.now==2){
	    	fprintf(f,"修理中\t");
	    	fprintf(f,"开始修理时间:%s\t",ctime(&e.repair_time));
	    	fprintf(f,"修理次数:%d\n",e.repair);
		}
	}
	fclose(f);
}

void printFile(){
	FILE *f = fopen(fileName, "r");   //打开文件,r是只读
	char str[200];          //存放每一行的信息 
	while(!feof(f)){
	    char *p = fgets(str,200,f);
	    if(p!=NULL) printf("%s\n",str);
    }
	fclose(f); 
}

void clearFile(){
	printf("\n\n"); 
	FILE *f = fopen(fileName, "w");    //打开文件,w是只写并向覆盖原文件
	fclose(f);
}

void PrintAll(LinkQueue &Available,LinkQueue &Rent,LinkQueue &Repair) {
	clearFile();
	savetoFile(Available);
	savetoFile(Rent);
	savetoFile(Repair);
	printFile();
	printf("\n\n\n"); 
}

(7)计算并打印收入income():

采用for循环计算三个队列中所有自行车的租借总时间和修理次数的和,按每小时收费1元,每辆自行车成本200元、修理一次花费10元计算利润及总收入并输出。

代码如下:

void income(LinkQueue &Available,LinkQueue &Rent,LinkQueue &Repair){
    int sum=0,repair1=0,in=0;
    int j;
    //计算可租借队列中所有自行车的租借总时间和修理次数 
    QNode *p=Available.front->next;
    j=QueueLength(Available);
	for(int i=0;i<j;i++){
		sum=sum+p->data.sumrenttime;
		repair1=repair1+p->data.repair;
		p=p->next;
	} 
	//计算已租借队列中所有自行车的租借总时间和修理次数
	p=Rent.front->next;
	j=QueueLength(Rent);
	for(int i=0;i<j;i++){
		sum=sum+p->data.sumrenttime;
		repair1=repair1+p->data.repair;
		p=p->next;
	}
	//计算修理中队列中所有自行车的租借总时间和修理次数
	p=Repair.front->next;
	j=QueueLength(Repair);
	for(int i=0;i<j;i++){
		sum=sum+p->data.sumrenttime;
		repair1=repair1+p->data.repair;
		p=p->next;
	}
	//求总收入和总利润并打印输出 
	int number=QueueLength(Available)+QueueLength(Rent)+QueueLength(Repair);
	in=sum-200*number-10*repair1;
	printf("总收入为:%d元\n",sum);
	printf("每辆自行车的成本为200元,假设修理一次花费10元,总利润为:%d元\n\n\n",in); 
}

(8)对队列进行按总租借时间从小到大排序CompareMin():

采用for循环,遍历寻找当前队列中总租借时间最小的元素。找到后,把在该元素之前的元素从队头出队,存入队尾。然后把该元素存入辅助队列T。

采用for循环将上述操作重复需排序队列的长度次后,辅助队列T即为排序好的队列,将T的元素逐个复制给原队列,排序完成。

代码如下:

void CompareMin(LinkQueue &Q) {
    if(Q.front==Q.rear)  exit(0);
    int j;
    LinkQueue T;       //新建一个用于排序的队列 
    InitQueue(T);      //初始化用于排序的队列  
    Bicycle e;
    int min=0; 
    
    while(Q.front->next!=NULL){
    	j=QueueLength(Q);           //j等于需排序队列的长度
    	QNode *p=Q.front->next;     //新建一个指针
		min=p->data.sumrenttime; 
		for(int i=0;i<j-1;i++)      //找到最小 
        {
    	    p=p->next;
    	    if(p->data.sumrenttime<min){
    		    min=p->data.sumrenttime;
		    }
	    }
	    for(int i=0;i<j;i++){
            //若不是最小值,将该元素从队头出队,从队尾入队,
	    	if(Q.front->next->data.sumrenttime>min){
	    		EnQueue(Q,Q.front->next->data);
	    		DeQueue(Q,e);
			}
            //若是最小值,将该元素出队,放到备用队列
			else{
				EnQueue(T,Q.front->next->data);
				DeQueue(Q,e);
			}
		}
	} 
	InitQueue(Q);
	j=QueueLength(T);
 	for(int i=0;i<j;i++)    //将T的元素逐个复制给Q 
 	{
 		EnQueue(Q,T.front->next->data);
    	DeQueue(T,e);
 	}
}

(9)整理修理中队列:

修理状态下的自行车超过3辆,排在第一位的自行车回到可租借队列中。

修理队列中若有修理完成(修理时间超过2小时)的自行车,将该自行车放回可租借队列。

代码如下:

void Test(LinkQueue &Available,LinkQueue &Repair){
    //修理状态下的自行车超过3辆,排在第一位的自行车回到可租借队列中 
	int j=QueueLength(Repair);
	Bicycle e,e1;
	if(j>3) 
	{
		EnQueue(Available,Repair.front->next->data);
		Available.rear->data.now = 0;
		DeQueue(Repair,e);
		CompareMin(Available);
	}
	
	//修理队列中若有修理完成(修理时间超过2小时)的自行车,将该自行车放回可租借队列 
	time_t now_time = time(NULL);         //当前时间
	for (int k=0; k<j; k++)    //判断修理中队列中是否有修理完成的自行车 
	{
		GetElem(Repair,k+1,e1);    //得到Repair队列中第k+1个元素的数据
		double repair_time_seconds = difftime(now_time, e1.repair_time); //求被修理的时间有多少秒 
	    int repair_time_hours = ceil(repair_time_seconds/3600);  //求被修理的时间有多少小时
	    if(repair_time_hours>=2){   //修理时间大于等于2小时,自行车回到可租借队列中 
	    	EnQueue(Available,Repair.front->next->data);
			Available.rear->data.now = 0;
			DeQueue(Repair,e); 
			CompareMin(Available);
		}
	}
}

 

5、对代码进行调试

修改语法错误及语义错误,使其成为能正常运行的控制台程序。

以下为我在调试过程中遇到的问题,由于根据记忆写的,可能有错误:

  1. Q.front. data,Q.front.next报错,无法编译。解决:不明原因,但都改成Q.front ->data,Q.front->next就可以编译了。
  2. 在对队列进行操作时发现Q.front->data出错,没有显示相应的数据。解决:发现所用队列是带头结点的队列,需要都改成Q.front->next->data。
  3. 程序先选择一次功能,第二次选择功能完成后自动结束程序。解决:单步跟踪发现运行到CompareMin()或者EnQueue()函数时报错program received signal sigsegvCSDN上搜索得可能是对空指针进行操作。在Debug窗口中添加队列的front->next->data等发现是在front->next->data没有分配地址,为空指针的时候对其进行了操作,导致程序直接结束。需要修改函数中使用的for循环语句,避免出现此情况。
  4. 使用GetElem()函数时自动结束程序。解决:GetElem()函数中if(i<1) exit(0);exit(0)表示结束程序,把它改为return;意为结束当前void类型函数。
  5. 使用rentBicycle()函数后,Rent队列、Available队列并非预期的队列。解决:修改rentBicycle()函数的变量,从rentBicycle(LinkQueue Available,LinkQueue Rent,LinkQueue Repair)改为rentBicycle(LinkQueue &Available,LinkQueue &Rent,LinkQueue &Repair),其他函数也类似。
  6. 归还自行车并收费时,归还后打印的队列出错,归还后的队列也出错。解决:在代码中大量使用类似于for(int i=0;i<QueueLength(Q);i++)的语句,因为每次循环开始前都重新计算Q队列的长度,导致循环运行次数是原来的一半,出错。将代码中所有类似语句修改,在for循环前添加int j=QueueLength(Q)for循环为:for(int i=0;i<j;i++)。
  7. 调用fee()函数时,发现自行车的数据项如状态、租借总时间没有对应修改。解决:发现是先用了Bicycle e1;GetElem(Rent,k+1,e1)语句,然后对e1的数据项进行操作,但对e1的地址不是队列的元素,没有在队列的相应元素上进行对应操作。将代码中所有该错误改为对队列的元素的数据项进行操作。
  8. 调用income()函数时,发现总收入计算错误导致总利润计算错误。解决:单步跟踪运行,发现是for循环中没有令指针p指向下一个元素,导致遍历错误,没有把租借总时间正确地求和,for循环中添加p=p->next语句。

三、待改进的地方

  1. 改进交互界面,从控制台程序改为windows窗体应用程序。
  2. 每辆车的成本和每次修理花费可自行设置。
  3. 自行车的idchar型,若按英文字母编号最多只能有26个,可以改成string型或char型数组
  4. 实现题目要求的:在租借状态下的自行车超过5辆以后,排在第一位的自行车以随机20%的概率进行修理维护(租借队列中自行车80%的可能回到available队列,20%的可能进入repair队列)。
  5. 将fee()函数中的错误改正。

四、完整代码

1、main.cpp

#include "Queue.h"
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <math.h> 

char fileName[] = "Bicycle.txt";         //存放所有自行车信息的文件 

//功能函数 
//对队列进行按总租借时间从小到大排序
void CompareMin(LinkQueue &Q) {
    if(Q.front==Q.rear)  exit(0);
    int j;
    LinkQueue T;       //新建一个用于排序的队列 
    InitQueue(T);      //初始化用于排序的队列  
    Bicycle e;
    int min=0; 
    
    while(Q.front->next!=NULL){
    	j=QueueLength(Q);         //j等于需排序队列的长度
    	QNode *p=Q.front->next;   //新建一个指针
		min=p->data.sumrenttime; 
		for(int i=0;i<j-1;i++){   //找到最小
    	    p=p->next;
    	    if(p->data.sumrenttime<min){
    		    min=p->data.sumrenttime;
		    }
	    }
	    for(int i=0;i<j;i++){
            //若不是最小值,将该元素从队头出队,从队尾入队 
	    	if(Q.front->next->data.sumrenttime>min){
	    		EnQueue(Q,Q.front->next->data);
	    		DeQueue(Q,e);
			}
            //若是最小值,将该元素出队,放到备用队列 
			else{
				EnQueue(T,Q.front->next->data);
				DeQueue(Q,e);
			}
		}
	} 
	InitQueue(Q);
	j=QueueLength(T);
 	for(int i=0;i<j;i++){//将T的元素逐个复制给Q 
 		EnQueue(Q,T.front->next->data);
    	DeQueue(T,e);
 	}
}

//整理修理中队列,将需要放回到可租借队列的自行车放回 
void Test(LinkQueue &Available,LinkQueue &Repair){
    //修理状态下的自行车超过3辆,排在第一位的自行车回到可租借队列中 
	int j=QueueLength(Repair);
	Bicycle e,e1;
	if(j>3){
		EnQueue(Available,Repair.front->next->data);
		Available.rear->data.now = 0;
		DeQueue(Repair,e);
		CompareMin(Available);
	}
	
	//修理队列中若有修理完成(修理时间超过2小时)的自行车,将该自行车放回可租借队列 
	time_t now_time = time(NULL);         //当前时间
	for(int k=0; k<j; k++){    //判断修理中队列中是否有修理完成的自行车 
		GetElem(Repair,k+1,e1);    //得到Repair队列中第k+1个元素的数据
		double repair_time_seconds = difftime(now_time,e1.repair_time);    //求被修理的时间有多少秒 
	    int repair_time_hours = ceil(repair_time_seconds/3600);  //求被修理的时间有多少小时
	    if(repair_time_hours>=2){   //修理时间大于等于2小时,自行车回到可租借队列中 
	    	EnQueue(Available,Repair.front->next->data);
			Available.rear->data.now = 0;
			DeQueue(Repair,e); 
			CompareMin(Available);
		}
	}
}

//租借自行车,将自行车从可租借队列放入已租借队列 
void rentBicycle(LinkQueue &Available,LinkQueue &Rent,LinkQueue &Repair){ 
	Bicycle e,e1;
	EnQueue(Rent,Available.front->next->data);
	DeQueue(Available,e);                      //将可租借队列的队头元素挪至已租借队列的队尾
	Rent.rear->data.now = 1;                   //改变自行车状态 
	Rent.rear->data.rent_time = time(NULL);    //记录开始租借时间 
	printf("您已成功租借了编号为%c的自行车\n\n\n",Rent.rear->data.id);   //提示租借成功 
	//这里应当将可租借队列按预期归还时间排序,假设借出最早的自行车预期最早归还 
}

//归还自行车并收费
void fee(LinkQueue &Available,LinkQueue &Rent,LinkQueue &Repair){ 
	Bicycle e1,e2;
	char id1;
	int x=0,n=0;
	int j=QueueLength(Rent);
	printf("请输入要归还的自行车编号:");
	getchar();
	scanf("%c",&id1); 
	for(int k=0; k<j; k++){       //查询已租借队列中是否有要归还的自行车
		GetElem(Rent,k+1,e1);    //得到Rent队列中第k+1个元素的数据
		if(e1.id==id1){
			x=1;
			e1.return_time = time(NULL);      //得到当前时间 
			double rent_time_seconds = difftime(e1.return_time,e1.rent_time);    //求被租借的时间有多少秒 
			double rent_time_minutes = rent_time_seconds/60;      //求被租借的时间有多少分钟 
			int  rent_time_hours = ceil(rent_time_minutes/60);    //向上取整求被租借的时间有多少小时
			printf("开始租借时间为:%s",ctime(&e1.rent_time));
			printf("归还时间为:%s",ctime(&e1.return_time));
			printf("需支付%d元\n\n\n",rent_time_hours);        //向客户收费,1小时1元,不满一小时按一小时计 

			LinkQueue T;
			InitQueue(T);
            //将队列中排在要归还的自行车前面的自行车出队存入队列T
			for(int i=0;i<k;i++){ 
				EnQueue(T,Rent.front->next->data);
				DeQueue(Rent,e2);
			}
			//判断该刚归还的自行车是否要修理
			if(Rent.front->next->data.sumrenttime-(Rent.front->next->data.repair*5)>=5){
				EnQueue(Repair,Rent.front->next->data);
				Repair.rear->data.now = 2;
				Repair.rear->data.repair_time = e1.return_time;    //记录开始修理时间
				Repair.rear->data.sumrenttime = Repair.rear->data.sumrenttime+rent_time_hours;  //将被租借的时间按小时加入总租借时间中
				DeQueue(Rent,e2);
			}
            //不修理,返回到可租借队列
			else{ 
				EnQueue(Available,Rent.front->next->data);
				Available.rear->data.now = 0;
				Available.rear->data.repair_time = e1.return_time;
				Available.rear->data.sumrenttime = Available.rear->data.sumrenttime + rent_time_hours;
				DeQueue(Rent,e2);
				CompareMin(Available);
			}
			n=QueueLength(Rent);
            //将已租借队列剩下的自行车存入队列T,再将队列T复制到已租借队列
			for(int i=0;i<n;i++){
				EnQueue(T,Rent.front->next->data);
				DeQueue(Rent,e2);
			}
			n=QueueLength(T);
            //将T的元素逐个复制给已租借队列
			for(int i=0;i<n;i++){
 		        EnQueue(Rent,T.front->next->data);
    	        DeQueue(T,e2);
 	        }
 	        DestroyQueue(T);
			break;
	    }
	}
	if(x==0){
		printf("此自行车编号不属于已租借自行车,请重新选择功能\n\n\n"); 
	}
}

//手动将某在可租借队列的自行车送去修理
void repair(LinkQueue &Available,LinkQueue &Rent,LinkQueue &Repair){
	Bicycle e1,e2;
	int x=0;
	int j=QueueLength(Available),n;
	char id1;
	printf("请输入要修理的自行车编号:");
	getchar();
	scanf("%c",&id1);
    //查询可租借队列中是否有要修理的自行车
	for(int k=0; k<j; k++){
		GetElem(Available,k+1,e1);    //得到Available队列中第k+1个元素的数据
		if(e1.id==id1){
			x=1;		 
			e1.repair_time = time(NULL);
			printf("开始修理时间为:%s\n\n\n",ctime(&e1.repair_time));
			LinkQueue T;
			InitQueue(T);
			for(int i=0;i<k;i++){       //将队列中排在要修理的自行车前面的自行车出队存入队列T 
				EnQueue(T,Available.front->next->data);
				DeQueue(Available,e2);
			}
			EnQueue(Repair,Available.front->next->data);
			Repair.rear->data.repair_time = time(NULL);   //得到当前时间为开始修理时间 	
			Repair.rear->data.repair++;
			Repair.rear->data.now=2;
			DeQueue(Available,e2);
			n=QueueLength(Available);
            //可租借队列剩下的自行车存入队列T,再将队列T复制到可租借队列
			for(int i=0;i<n;i++){
				EnQueue(T,Available.front->next->data);
				DeQueue(Available,e2);
			}
			n=QueueLength(T);
            //将T的元素逐个复制给可租借队列
			for(int i=0;i<n;i++){
 		        EnQueue(Available,T.front->next->data);
    	        DeQueue(T,e2);
 	        }
 	        DestroyQueue(T);
			break;
		}
		j=QueueLength(Available);
	}
	if(x==0) printf("此自行车编号不属于可租借自行车,请重新选择功能\n\n\n");
}

//判断两条自行车编号信息是否重复
int compare(Bicycle e1, Bicycle e2){
	if(e1.id==e2.id) return 1;
	else return 0;
}

//打印自行车e的信息
void visit(Bicycle e){
	printf("编号%c,", e.id);
	if(e.now==0) {
		printf("可租借,");
		printf("租借总时间为:%d,",e.sumrenttime);
		printf("修理次数为:%d\n\n\n",e.repair);
	}
	else if(e.now==1){
		printf("已租借,");
		printf("开始租借时间为:%s,",ctime(&e.rent_time));
		printf("修理次数为:%d\n\n\n",e.repair); 
	} 
	else if(e.now==2){
		printf("修理中,");
		printf("开始修理时间为:%s,",ctime(&e.repair_time));
		printf("修理次数为:%d\n\n\n",e.repair);
	} 
}

//查询并打印某一自行车的信息
void search(LinkQueue &Q1,LinkQueue &Q2,LinkQueue &Q3){ 
	char id1;
	Bicycle e1,e2; 
	int n=0;
	printf("输入要查询的自行车编号:");
	getchar();
	scanf("%c",&id1);
	for(int k=0; k<QueueLength(Q1) && n==0; k++){    //查询可租借队列中是否有要找的自行车
		GetElem(Q1,k+1,e1);
		if(e1.id==id1){
			visit(e1);
			n=1;
			break;
		}
	} 
	for(int k=0; k<QueueLength(Q2) && n==0; k++){    //查询已租借队列中是否有要找的自行车
		GetElem(Q2,k+1,e1);
		if(e1.id==id1){
			visit(e1);
			n=1;
			break;
		}
	}
	for(int k=0; k<QueueLength(Q3) && n==0; k++){    //查询修理中队列中是否有要找的自行车
		GetElem(Q3,k+1,e1);
		if(e1.id==id1){
			visit(e1);
			n=1;
			break;
		}
	}
	if(n==0) printf("此自行车编号不属于已有的自行车,请重新选择功能\n\n\n");
}

//添加一辆自行车到可租借队列
void addBicycle(LinkQueue &Available,LinkQueue &Rent,LinkQueue &Repair){ 
	Bicycle e;
	int x=0,l=0;
	QNode *p=Available.front->next;      //指针指向可租借队列第一辆自行车 
	printf("输入自行车的编号信息:");
	getchar();
	scanf("%c", &e.id);
	//比较编号是否重复
	l=QueueLength(Available);
	for(int i=0;i<l;i++){       //比较编号是否与可租借队列的自行车重复 
		x=compare(e,p->data);
		if(x==1){
			printf("编号与已有自行车重复,请重新选择功能\n\n\n");
			return ;
		}
		p=p->next;
	}
	p=Rent.front->next;
	l=QueueLength(Rent);
	for(int i=0;i<l;i++){       //比较编号是否与已租借队列的自行车重复
		x=compare(e,p->data);
		if(x==1){
			printf("编号与已有自行车重复,请重新选择功能\n\n\n");
			return ;
		}
		p=p->next;
	}
	p=Repair.front->next;
	l=QueueLength(Repair);
	for(int i=0;i<l;i++){       //比较编号是否与修理中队列的自行车重复
		x=compare(e,p->data);
		if(x==1){
			printf("编号与已有自行车重复,请重新选择功能\n\n\n");
			return ;
		}
		p=p->next;
	} 
	EnQueue(Available,e);
    printf("成功引入编号为%c的新车\n\n\n",e.id);
}

//保存信息到文件 
void savetoFile(LinkQueue &Q){
	Bicycle e;
	int j=QueueLength(Q);
	FILE *f = fopen(fileName, "a");    //打开文件,a是只写并向文件尾部追加数据 
	for(int k=0; k<j; k++){     //将队列中的信息打印到文件中 
		GetElem(Q,k+1,e);
		fprintf(f,"编号:%c\t", e.id);
		fprintf(f,"状态:");
		if(e.now==0){
			fprintf(f,"可租借\t");
			fprintf(f,"租借总时间:%d\t",e.sumrenttime);
			fprintf(f,"修理次数:%d\n",e.repair);
		}
	    else if(e.now==1){
	    	fprintf(f,"已租借\t");
	    	fprintf(f,"开始租借时间:%s\t",ctime(&e.rent_time));
	    	fprintf(f,"修理次数:%d\n",e.repair);
		}
	    else if(e.now==2){
	    	fprintf(f,"修理中\t");
	    	fprintf(f,"开始修理时间:%s\t",ctime(&e.repair_time));
	    	fprintf(f,"修理次数:%d\n",e.repair);
		}
	}
	fclose(f);
}

//打印输出存放自行车数据的文本文件
void printFile(){
	FILE *f = fopen(fileName, "r");   //打开文件,r是只读
	char str[200];          //存放每一行的信息 
	while(!feof(f)){
	    char *p = fgets(str,200,f);
	    if(p!=NULL) printf("%s\n",str);
    }
	fclose(f); 
}

//将存放自行车数据的文本文件清空 
void clearFile(){
	printf("\n\n"); 
	FILE *f = fopen(fileName, "w");    //打开文件,w是只写并向覆盖原文件
	fclose(f);
}

//将所有自行车数据打印到屏幕 
void PrintAll(LinkQueue &Available,LinkQueue &Rent,LinkQueue &Repair) {
	clearFile();
	savetoFile(Available);
	savetoFile(Rent);
	savetoFile(Repair);
	printFile();
	printf("\n\n\n"); 
}

//计算并打印收入
void income(LinkQueue &Available,LinkQueue &Rent,LinkQueue &Repair){
    int sum=0,repair1=0,in=0;
    int j;
    //计算可租借队列中所有自行车的租借总时间和修理次数 
    QNode *p=Available.front->next;
    j=QueueLength(Available);
	for(int i=0;i<j;i++){
		sum=sum+p->data.sumrenttime;
		repair1=repair1+p->data.repair;
		p=p->next;
	} 
	//计算已租借队列中所有自行车的租借总时间和修理次数
	p=Rent.front->next;
	j=QueueLength(Rent);
	for(int i=0;i<j;i++){
		sum=sum+p->data.sumrenttime;
		repair1=repair1+p->data.repair;
		p=p->next;
	}
	//计算修理中队列中所有自行车的租借总时间和修理次数
	p=Repair.front->next;
	j=QueueLength(Repair);
	for(int i=0;i<j;i++){
		sum=sum+p->data.sumrenttime;
		repair1=repair1+p->data.repair;
		p=p->next;
	}
	//求总收入和总利润并打印输出 
	int number=QueueLength(Available)+QueueLength(Rent)+QueueLength(Repair);
	in=sum-200*number-10*repair1;
	printf("总收入为:%d元\n",sum);
	printf("每辆自行车的成本为200元,假设修理一次花费10元,总利润为:%d元\n\n\n",in); 
}


int main()
{
	LinkQueue Available;     //建立一个可租借队列 
	LinkQueue Rent;          //建立一个已租借队列 
	LinkQueue Repair;        //建立一个修理中队列 
	InitQueue(Available);    //初始化队列
	InitQueue(Rent);         //初始化队列
	InitQueue(Repair);       //初始化队列
	//将初始的10个自行车放入可租借队列 
	Bicycle y[10];
	for(int x=0;x<10;x++){
		y[x].id=char('a'+x);
		EnQueue(Available,y[x]);
	}
	
	int x = 0;
	bool out = 0;    //判断是否停止使用系统,退出程序 
	Bicycle e;
	while(!out)      //提示选择功能 
	{
		Test(Available,Repair);
		printf("引入新车(0)\n");
		printf("租借(1)\n");
		printf("还车收费(2)\n");
		printf("修理(3)\n");
		printf("自行车查询(4)\n");
		printf("打印全部信息(5)\n");
		printf("计算并打印收入(6)\n");
		printf("退出系统(7)\n");
		printf("请输入要选择的功能:"); 
		scanf("%d",&x);
		switch(x)
		{
			case 0: addBicycle(Available,Rent,Repair); break;
			case 1: rentBicycle(Available,Rent,Repair); break;
			case 2: fee(Available,Rent,Repair); break; 
			case 3: repair(Available,Rent,Repair); break;
			case 4: search(Available,Rent,Repair); break;
			case 5: PrintAll(Available,Rent,Repair); break;
			case 6: income(Available,Rent,Repair); break;                     
			case 7: out = 1; break;     //退出系统 
			default: printf("选择错误\n\n\n");
		}
	}
	ClearQueue(Available);
	ClearQueue(Rent);
	ClearQueue(Repair); 
}

2、Queue.h 

#include <stdlib.h>
#include <time.h>
#include <iostream>
using namespace std;

typedef struct Bicycle{
	char id;                  //自行车编号 
	int sumrenttime=0;          //租借总时间 
    time_t rent_time=0;          //开始租借时间
    time_t return_time=0;        //归还时间 
    time_t repair_time=0;       //开始修理时间 
    int repair=0;               //修理次数 
    int now=0;                  //目前状态(可租借0、已租借1、修理中2)   
}Bicycle;

typedef struct QNode{             //队列的结点 
	Bicycle data;                 //数据域 
	struct QNode *next;           //指针域 
}QNode,*QueuePtr;

typedef struct{                   //队列 
	QueuePtr front;               //队头指针,从这头出队 
	QueuePtr rear;                //队尾指针,从这头入队 
}LinkQueue;

void InitQueue(LinkQueue&Q){      //初始化链表队列 
	Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
	if(!Q.front) exit(0);
	Q.front->next=NULL;
}
void DestroyQueue(LinkQueue&Q){    //销毁链表队列 
	while(Q.front){
		Q.rear=Q.front->next;
		free(Q.front);
		Q.front=Q.rear;
	}
}
void EnQueue(LinkQueue&Q,Bicycle e){    //将Bicycle类型的元素e入队
	QueuePtr p=(QueuePtr)malloc(sizeof(QNode));
	if(!p) exit(0);
	p->data=e;
	p->next=NULL;
	Q.rear->next=p;
	Q.rear=p;
}
void DeQueue(LinkQueue&Q,Bicycle&e){   //将队头元素出队,并用e存储数据 
	if(Q.front==Q.rear) exit(0);
	QueuePtr p=Q.front->next;
	e=p->data;
	Q.front->next=p->next;
	if(Q.rear==p) Q.rear=Q.front;
	free(p);
}
void ClearQueue(LinkQueue&Q){      //清空队列 
	QNode *p = Q.front; 
	while(p)
	{
		Q.front = p->next;
		delete p;
		p = Q.front;
	}
}

int QueueLength(LinkQueue &Q){     //求队列的长度 
    QNode *p=Q.front;
    int i=0;
    while(p->next!=NULL){
    	p=p->next;
    	i++;
	}
	return i;
}

void GetElem(LinkQueue Q, int i, Bicycle &e){ //得到队列中第i个元素的数据 
	if(i<1) return;    //若i<1错误 
	QNode *p = Q.front->next; //
	for(int k=0; k<i-1; k++)
	{
		p = p->next;
	}
	e = p->data;
}

结果截图我就不放了,图片太多了。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
一个简单的汽车租赁管理系统C++控制台程序): 利用C++实现对汽车和客户信息的增、删、改等操作,并保存。 部分代码: // CarRent.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "CarData.h" #include "Menu.h" #include"CustomerData.h" int main() { Menu::welcome(); Menu::login(); //登录界面 char choice; int carid, customerid; //汽车编号,客户编号 CustomerData CustomerDB; //客户库 Customer *r; //客户 CarData CarDB; //汽车库 Car *b; //汽车 Menu::showMenu(); //显示菜单 cout <> choice; while (choice != '0') { switch (choice) { case '1': //输入客户编号和要出租的汽车 cout <> customerid; try { if (customerid <= 0) throw 1; } catch (...) { cout << "输入有误,请重新输入"; break; } cout <> carid; try { if (carid <= 0) throw 1; } catch (...) { cout << "输入有误,请重新输入"; break; } r = CustomerDB.search(customerid); if (NULL == r) { cout << "不存在该客户!"; cout << endl; break; } b = CarDB.search(carid); if (b == NULL) { cout << "不存在该汽车!"; cout <borrowCar() == 0) { cout << "该汽车已租出!"; cout <borrowCar(b->getNo()); cout << "你在" <getBorTime()) << "成功出租一辆" <getName() << endl << "每日租金为(不足一天按一天计算):" <getPay(); break; case '2': //归还操作 cout <> customerid; try { if (customerid <= 0) throw 1; } catch (...) { cout << "输入有误,请重新输入"; break; } cout <> carid; try { if (carid <= 0) throw 1; } catch (...) { cout << "输入有误,请重新输入"; break; } r = CustomerDB.search(customerid); //按编号查找 if (r == NULL) { cout << "不存在该客户!" << endl; break; } b = CarDB.search(carid); if (b == NULL) { cout << "不存在该汽车!" <getOnshelf() == 1) { cout << "该汽车已经归还!" << endl; break; } cout << "您成功归还一辆"

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值