数据结构课程设计——客运订票系统

本文档详细描述了一个客运订票系统的功能需求、总体设计和详细设计。系统包含车次搜索查询、订票、退票和管理员管理等功能模块,支持车次信息的增删查改,提供候补购票服务。用户可以查询车次信息,订票时根据余票情况决定是否排队候补,退票时将票额分配给候补乘客。管理员可验证账号并进行车次管理操作。
摘要由CSDN通过智能技术生成

2需求分析

2.1系统功能

1、 客运订票系统的功能描述
每条车次所涉及的信息有:起点站名、终点站名、车次ID、列车号、出发日期(星期几)、乘员定额、剩余票数、票价、已经订票的客户名单(包括姓名、订票量)以及等候替补的客户名单(包括姓名、所需票量)。
2、通过此订票系统可以实现如下功能:
①查询车次:根据客户提供的终点站名进行查询,可以输出以下信息:车次号、列车号、星期几出发和余票量等。也可以根据车次号,查询列车某个车次的情况;
②订票:根据客户提出的要求(姓名、终点站名、订票数量)查询该车次的余票量情况。如尚有足够的余票,则为客户办理订票手续;若已满员或余票量少于订票数量,则需要重新询问客户要求,如需要,可登记排队候补;
③退票:根据客户提供的情况(姓名、终点站名、出发日期、列车号),为客户办理退票手续,然后查询该车次是否有人排队候补,首先询问排在第一的客户,若所退的票额能满足他的要求,则为他办理订票手续,否则依次询问其他排队候补的客户;
④管理员对车次信息进行增、删、改、查操作:可以录入车次、删除车次、查询车次的功能,但是只限于管理员操作。

3总体设计

3.1功能模块图

本客运订票系统分为五个功能模块,分别是车次搜索查询模块、订票模块、退票模块、管理员模块。查询搜索模块可以进行显示当前车次功能、搜索车次信息:订票模块可以对用户的需求来进行订相当于的机票功能:退票模块可以对用户的需求来进行退票功能:管理员功能可以通过登陆管理员账号来进行增加、删除、查找和更改车次车次信息。功能模块图如图3-1所示。

在这里插入图片描述

4详细设计

4.1 详细的设计思路

车次设置:

每条车次所设计的信息有:车次ID、起点站名、终点站名、列车号、出发时间(星期几)、成员定额、总余票量、二等座余票量、一等座余票量、已订票的客户名单、二等座候补客户名单、一等座候补客户名单。其中,二等座候补客户名单和一等座候补客户名单中的包括以下几个域:姓名、身份证、所需票量、预定票的等级
车次搜索查询模块的功能
1.搜索所有车次的相关信息
2.根据起点和终点查询车次
3.返回上一级菜单

订票模块的功能:

1.输入车次ID进行订票,当车次ID不存在或者不合法时要求重新输入车次ID,然后输入订票数量和等级,数量和等级要合法,订票数目要大于0,等级输入1代表二等座,输入其他数据一等座。不合法则重新输入,再判断对应等级的票是否足够 ,足够则继续输入客户信息(姓名和身份证),然后订票成功。当对应等级的票数不足时,询问是否改变订票计划,同意改变计划则重新输入车次ID进行相应的订票操作。不同意改变计划则继续询问是否排队等候,不同意排队等候则询问是否需要推荐相同车次的其他车次,询问操作时,输入Y或者y表示同意,输入N,n或者其它数据表示不同意。
2.根据起点和终点查询车次
3.查询所有车次的相关信息
4.查询车次的订票情况,输入车次ID,当车次ID不存在或者不合法时要求重新输入车次ID,根据ID查询车次,显示出已订票的客户的姓名、订票数目和仓位等级,为了保密,不能显示客户的身份证。
5.返回上一级菜单

退票模块的功能:

1.先输入车次ID,然后输入姓名和身份证号码进行验证,验证成功则办理退票手续。然后查询该车次是否有人排队候补,如果有,而且票数够了,则首先询问排在第一的客户,是否需要订票,是则为他办理订票手续,否则出队,依次询问其他排队候补的客户。若刚刚退票的是二等座,则询问二等座排队的客户;若是一等座,则询问一等座排队的客户。
2.返回上一级菜单

管理员模块的功能:

1.管理员账号密码验证
2.查询所有车次信息
3.根据车次ID查询客户信息(包括身份证号码)
4.增加车次(车次的各个信息输入要合法,不合法的重新输入)
5.删除车次,根据ID进行删除,ID不存在则删除失败。
6.返回上一级菜单

4.2 算法流程图

在这里插入图片描述

5编码

5.1数据结构定义

1.乘客信息

使用结构体存储客户订票信息(客户姓名、订票量、身份证号码、座位等级)

typedef struct CustomerNode {
    	char name[10];//客户姓名
    	int clientTickets;//客户订票量
    	char identification[20];//客户身份证号码
    	int rank;//座位等级
    	CustomerNode *next;
} CustomerNode, *CusLinkList;

2. 候补队列乘客信息

typedef struct WaitPassenger {
    	char name[10];//姓名
    	char identification[20]; //身份证
    	int preTickets;//预定的票量
    	struct WaitPassenger *next;
} WaitQNode, *PWait;

3.候补票队列

typedef struct Queue {
 	   PWait front;//等候替补客户名单域的头指针
  	  PWait rear;//等候替补客户名单域的尾指针
} LinkQueue;

4.乘客信息

typedef struct NameAndNumAndID {
    char name[10];//姓名
    	char identification[20]; //身份证号码
    	int num;//订票量
} NameAndNumAndID;

5.车次信息:

使用结构体定义车次的起点站名,终点站名,车次ID,列车号,出发日期,乘员定额,总余票量,二等座剩余量,一等座剩余量等信息。

typedef struct TrainNumber{
    	char startPoint[20];//起点站名
    	char destination[20];//终点站名
    	char TrainNumberCodeID[20];//车次ID
    	char planeNum[20];//列车号
    	char day[20];//出发(星期几)
    	int totalTickets;//乘员定额(总票数)
    	int left;//总余票量
    	int leftEconomicTicket; //二等座剩余量
    	int leftBusinessTicket; //一等座剩余量
    	TrainNumber*next;
    	CusLinkList cusLinkList;//乘员名单域,指向乘员名单链表的头指针
LinkQueue waitQueue1;// 二等座候补,等候替补的客户名单域,指向一个队列
LinkQueue waitQueue2;// 一等座候补,等候替补的客户名单域,指向一个队列
} TrainNumber, TrainNumberNode, *PTrainNumber;

5.2功能函数设计

(1)功能函数 MenuSelect

函数的功能:主菜单界面函数,对车次搜索查询模块,订票模块,退票模块,管理员模块,退出模块进行选择调用。
函数的入口:AdministratorFace,Suggest,SearchFace,BookticketFace,ReturnTicketsFace,main函数。
函数调用关系:被AdministratorFace,MenuSelect,Suggest,SearchFace,BookticketFace,ReturnTicketsFace,main函数调用。调用了system,SearchFace, MenuSelect,BookticketFace,ReturnTicketsFace,AdministratorVerify,AdministratorFace,GoodbyeFace函数。
函数的出口:调用完相对应的功能函数后break结束。

(2)功能函数 BookticketFace;

函数的功能:订票模块菜单界面。对客户订票,根据起点和终点查询车次,查询所有车次,通过ID查询订票客户名单进行选择调用。
函数的入口:MenuSelect函数
函数调用关系:被MenuSelect,BookticketFace调用。调用了BookTickets,BookticketFace,SearchTrainNumber,PrintTrainNumberlist,PriCusInfo,system,MenuSelect函数。
函数的出口:调用完相对应的功能函数后break结束。

(3)功能函数 BookTickets

函数的功能:实现订票功能。
函数的入口:Suggest,BookticketFace函数。
函数调用关系:被BookTickets,Suggest,BookticketFace函数调用,调用了system,FlightInfo,BookTickets函数。
函数的出口:输入Y/N和y/n。

(4)功能函数 ReturnTicketsFace

函数的功能: 退票模块菜单界面。
函数的入口:MenuSelect函数
函数调用关系:被MenuSelect函数调用,调用了ReturnTicketsFace, ReturnTicket,MenuSelect函数。
函数的出口:调用完相对应的功能函数后break结束。

(5)功能函数 ReturnTicket

函数的功能: 实现退票功能。
函数的入口:ReturnTicketsFace函数
函数调用关系:只被ReturnTicketsFace函数调用,调用了strcmp函数
函数的出口:调用完相对应的功能函数后break结束。

(6)功能函数 AdministratorFace

函数的功能:管理员界面函数
函数的入口:MenuSelect函数
函数调用关系:只被MenuSelect函数调用。调用了PrintTrainNumberlist,AdministratorFace,AdminPriCusInfo,InsertTrainNumber,DeleteTrainNumber,MenuSelect函数
函数的出口:调用完相对应的功能函数后break结束。

(7)功能函数 AdministratorVerify

函数的功能:验证管理员账号和密码。
函数的入口:MenuSelect函数。
函数调用关系:只被MenuSelect函数调用,只调用strcmp函数。
函数的出口:验证成功返回1。

5.3函数流程图

(1) 主菜单界面函数流程图如图5-1所示。

在这里插入图片描述

图5-1

(2) 订票模块菜单界面函数流程图如图5-2所示。

在这里插入图片描述
图5-2

(3) 订票模块函数流程图如图5-3所示。

在这里插入图片描述

图5-3

(4) 退票模块菜单界面函数流程图如图5-4所示。

在这里插入图片描述

图 5-4

(5) 退票功能函数流程图如图5-5所示。

在这里插入图片描述

图 5-5

(6) 管理员界面函数流程图如图5-6所示。

在这里插入图片描述

图 5-6

(7) 管理员账号验证函数流程图如图5-7所示。

在这里插入图片描述

图5-7

5.4 程序实现

主菜单界面函数


//主菜单界面函数
//@return 返回选择的操作
int MenuSelect() {
    int select;
    Status status;
    flag:
  {
        system("cls"); 
        printf("\n                19级软件工程xxxx  xxxxxxxxxxxx\n");
        printf("                         指导老师:xxx        \n\n\n"); 
        printf("                    欢迎来到客运订票系统\n");
        printf("               -----------------------------------------------------\n");
        printf("               |          1.  车次搜索查询模块     |\n");
        printf("               |          2.  订票模块             |\n");
        printf("               |          3.  退票模块             |\n");
        printf("               |          4.  管理员模块           |\n");
        printf("               |          5.  离开系统             |\n");
        printf("               -----------------------------------------------------\n");
        printf("                        请输入您的选择:");
        scanf("%d", &select);
} 
    switch (select) {
        case 1:
            //查询所有车次信息
				 //进入搜索模块
            //传入车次链表头指针,打印出所有车次信息
            SearchFace();
            MenuSelect();
            break;
        case 2:
            //进入订票模块
            BookticketFace();
            system("PAUSE");
            MenuSelect();
            break;
        case 3:
            //进入退票模块
            ReturnTicketsFace();
            system("PAUSE");
            MenuSelect();
            break;
        case 4:
            //进入管理员模块
            while (1) {
                status = AdministratorVerify();
                if (1 == status)
                    break;
            }
            AdministratorFace();
            system("PAUSE");
            MenuSelect();
            break;
        case 5:
            //退出模块
            GoodbyeFace();
            break;
        default:
            goto flag;
    }
}

(2)订票模块菜单界面函数。

//订票界面
//属于订票模块
void BookticketFace() {
    int a3;
    int loop3;
    loop3:
    {
        system("cls");
        printf("\n\n ");
        printf("                      订票模块\n");
        printf("       ------------------------------------------------------------------\n");
        printf("       |        1.客户订票                          |\n");
        printf("       |        2.根据起点和终点搜索车次            |\n");
        printf("       |        3.查询所有车次                      |\n");
        printf("       |       4.通过车次ID查询订票客户名单        |\n");
        printf("       |        5.返回上一级菜单                    |\n");
        printf("       -----------------------------------------------------------------\n");
        printf("                 请输入您的选择:");
        scanf("%d", &a3);
    }
    switch (a3) {
        case 1:
            //订票
            BookTickets();
            system("PAUSE");
            BookticketFace();
            break;
        case 2:
            //输入起点和终点查询
            SearchTrainNumber();
            system("PAUSE");
            BookticketFace();
            break;
        case 3:
            PrintTrainNumberlist(pTrainNumber);
            system("PAUSE");
            BookticketFace();
            break;
        case 4:
            //为了保密,只能查到客户的姓名和订票量,查不到身份证
            PriCusInfo();
            system("PAUSE");
            BookticketFace();
            break;
        case 5:
            MenuSelect();
            break;
        default:
            goto loop3;
    }
}

(3)订票功能函数

//订票模块
void BookTickets() {
    struct TrainNumber *info;
    int amount, rank;
    int tickets;//剩余的一等座数目或者二等座数目
    char name[10];
    char identification[20];
    system("cls");
    //调用查找车次函数,返回给
    int loop1;
    loop1:
    {
        info = find();
    };
    if (info == NULL){
        printf("没有这个车次, 请重新输入\n");
        goto loop1;
    }
    int loop2;
    loop2:
    {  printf("请正确输入你订票所需要的数量:");
        scanf("%d", &amount);
    };
    //非法字符,重新输入
    if (amount <= 0 ) {
        goto loop2;
    }
    printf("请正确输入您的票的座位等级(1代表二等座,2或其他代表一等座):");
    scanf("%d", &rank);
    if (rank == 1)
        tickets = info->leftEconomicTicket;
    else
        tickets = info->leftBusinessTicket;
    if (amount <= tickets) {
        int i;
        printf("请输入您的姓名:");
        scanf("%s", name);
        printf("请输入您的身份证号码:");
        scanf("%s", identification);
        CusLinkList head = info->cusLinkList;
        //订票成功,插入成员名单链表
        insertlink(head, amount, name, identification, rank);
        for (i = 0; i < amount; i++)
      printf("%s 的座位号是: %d\n", name, info->totalTickets - info->left + i + 1);
        info->left -= amount;
        if (rank == 1)
            info->leftEconomicTicket -= amount;
        else
            info->leftBusinessTicket -= amount;
        printf("\n祝您旅途愉快!欢迎再次光临\n");
    } else
        loop0:
        {
            char r;
            printf("该等级的票不足,订票失败,以下为该车次乘客信息,希望对您的订票有所帮助\n");
            FlightInfo(info);
            printf("是否改变订票计划?Y/N\n");
            r = getch();
            printf("%c", r);
            if (r == 'Y' || r == 'y') {//改变计划,重新选择车次
                BookTickets();
            } else {
                printf("\n已经没有更多的票,您需要排队等候吗?(Y/N)");
                r = getch();
                printf("%c", r);
                if (r == 'Y' || r == 'y') {//不改变计划,排队候票
                    printf("\n请输入您的姓名(排队订票客户):");
                    scanf("%s", name);
                    printf("\n请输入您的身份证号码(排队订票客户):");
                    scanf("%s", identification);
                    if (rank == 1) {//进入二等座排队队列
  info->waitQueue1=Appendqueue(info->waitQueue1,name, amount, identification);
                    } else {//进入一等座排队队列
  info->waitQueue2=Appendqueue(info->waitQueue2,name, amount, identification);
                    }
                    printf("\n排队成功!\n");
                } else {//不排队,选择系统提供的其他建议方案
                    printf("\n是否根据建议订票?若是,则推荐相同的起点和终点的车次Y/N");
                    r = getch();
                    printf("%c", r);
                    printf("%c", r);
                    if (r == 'Y' || r == 'y') {
                        //调用推荐函数
                        Suggest(info->startPoint, info->destination, info);
                    } else
                        printf("\n欢迎您下次再次订购!\n");
                }
            } 
        }
}

(4)退票模块菜单界面函数

//退票模块界面
void ReturnTicketsFace() {
    int a3;
    int loop4;
    loop4:
    {
        system("cls");
        printf("\n\n ");
        printf("                     退票模块\n");
        printf("    --------------------------------------------------------\n");
        printf("    |           1.办理退票手续            |\n");
        printf("    |           2.返回上一级菜单          |\n");
        printf("    --------------------------------------------------------\n");
        printf("                            请输入您的选择:");
        scanf("%d", &a3);
    }
    switch (a3) {
        case 1:
            ReturnTicket();
            system("PAUSE");
            ReturnTicketsFace();
            break;
        case 2:
            MenuSelect();
            break;
        default:
            goto loop4;
    }
}

(5)退票功能函数

//退票功能函数
void ReturnTicket() {
    struct TrainNumber  *info;
    int rank;
    //p1为遍历指针,p2为辅助指针,指向p1的前驱
    CustomerNode *p1, *p2, *head;
    //客户姓名
    char cusname[10];
    //客户身份证
    char identification[20];
    system("cls");
    //info指针,find函数根据车次ID返回该车次节点的指针
    int loop;
    loop:
    {
        info = find();
    };
    if (info == NULL){
        printf("没有这个车次, 请重新输入\n");
        goto loop;
    }
    //head为该车次的的乘员名单域的头指针
    head = info->cusLinkList;
    //带头结点的指针,head->next 开始遍历
    p1 = head->next;
    printf("请输入你的姓名: ");
    scanf("%s", cusname);
    printf("请输入你的身份证号码: ");
    scanf("%s", identification);
    //根据客户姓名搜索客户是否订票
    p2 = head;
    while (p1 != NULL) {
        if ((strcmp(cusname, p1->name) == 0) && (strcmp(identification, p1->identification) == 0)) break;
        p2 = p1;
        p1 = p1->next;
    }
    if (p1 == NULL) {
        printf("对不起,你没有订过票或姓名和身份证不对应\n");
        return;
    } else {//退票成功
        //从乘客名单域中移除该节点
        rank = p1->rank;
        p2->next = p1->next;
        //加回该车次的剩余票
        info->left += p1->clientTickets;
        if (rank == 1) {
            info->leftEconomicTicket += p1->clientTickets;
        } else {
            info->leftBusinessTicket += p1->clientTickets;
        }
        printf("%s  成功退票!\n", p1->name);
        free(p1);
    }
    LinkQueue queue1 = info->waitQueue1;
    LinkQueue queue2 = info->waitQueue2;
    NameAndNumAndID nameAndNumAndID = {0, 0};
    if (rank == 1) { //有二等座退票,询问二等座排队的客户
        for (; queue1.front->next != NULL && queue1.front->next->preTickets <= info->leftEconomicTicket;) {
  //从候补客户队列中,出队客户的姓名和订票量用NameAndNumAndID返回
            QueueDelete(info->waitQueue1, nameAndNumAndID);
            int y;
            printf("有 二等座票 剩余 , 尊敬的%s :\n", nameAndNumAndID.name);
            printf("是否确认订票(1确认订票, 其他数字拒绝订票\n");
            scanf("%d", &y);
            if (y == 1) {
                //排队订票成功
                for (int i = 0; i < nameAndNumAndID.num; i++)
                    printf("排队订票成功  %s 的座位号是:%d\n", nameAndNumAndID.name, (info->left) - i);
                //剩余票减少
                info->left -= nameAndNumAndID.num;
                info->leftEconomicTicket -= nameAndNumAndID.num;
                //乘员名单链表插入排队订票成功的客户
                info->cusLinkList = insertlink(info->cusLinkList, nameAndNumAndID.num, nameAndNumAndID.name,
                                               nameAndNumAndID.identification, rank);
            }
        }
    } else { //有一等座客户退票,询问一等座排队的客户
        for (; queue2.front->next != NULL && queue2.front->next->preTickets <= info->leftBusinessTicket;) {
   //从候补客户队列中,出队客户的姓名和订票量用NameAndNumAndID返回
            QueueDelete(info->waitQueue2, nameAndNumAndID);
            int y;
printf("有 一等座票 剩余 , 尊敬的%s :\n", nameAndNumAndID.name);
            printf("是否确认订票(1确认订票, 其他数字拒绝订票\n");
            scanf("%d", &y);
            if (y == 1) {
                //排队订票成功
                for (int i = 0; i < nameAndNumAndID.num; i++)
printf("排队订票成功%s 的座位号是:%d\n", nameAndNumAndID.name, (info->left) - i);
                //剩余票减少
                info->left -= nameAndNumAndID.num;
                info->leftBusinessTicket -= nameAndNumAndID.num;
                //乘员名单链表插入排队订票成功的客户
info->cusLinkList=insertlink(info->cusLinkList,nameAndNumAndID.num, nameAndNumAndID.name, nameAndNumAndID.identification, rank);
            }
        }
    }
}

(6)管理员模块界面函数

// 管理员模块
//管理员界面函数
void AdministratorFace() {
    int a2;
    int loop2;//goto语句
    loop2:
    {
        system("cls");
        printf("\n\n \n \n ");
        printf("                          欢迎进入管理系统  \n");
        printf("                -----------------------------------------------------\n");
        printf("                |           1.车次信息              |\n");
        printf("                |           2.客户信息              |\n");
        printf("                |           3.增加车次              |\n");
        printf("                |           4.删除车次              |\n");
        printf("                |           5.返回上一级            |\n");
        printf("                -----------------------------------------------------\n");
        printf("                 请输入您的选择:");
        scanf("%d", &a2);
    }
    switch (a2) {
        case 1:
            PrintTrainNumberlist(pTrainNumber);
            system("PAUSE");
            AdministratorFace();
            break;
        case 2:
            AdminPriCusInfo();
            AdministratorFace();
        case 3:
            InsertTrainNumber();
            AdministratorFace();
            break;
        case 4:
            if (1 == DeleteTrainNumber()) {
                printf("删除成功\n");
            } else {printf("没有这个车次,删除失败!\n");
            };
            AdministratorFace();
        case 5:
            MenuSelect();
            break;
        default:
            goto loop2;
    }
}

(7)管理员账号验证函数

//验证管理员账号密码
//@return 返回操作结果
Status AdministratorVerify() {
    char pwd[20] = "123456";//管理员密码
    char ID[20]="admin" ;//管理员ID 
    char  id[20];
    char password[20];//待输入密码,用来验证
    printf("请输入管理员账号:\n");
	scanf("%s",id);
    if (strcmp(ID, id)) {
        printf("账号错误,请重新输入:\n");
        return -1;
        
    }
    printf("请输入管理员密码:\n");
    scanf("%s", password);
    if (strcmp(pwd, password)) {
        printf("密码错误,请重新输入:\n");
        return -1;
    }
    printf("验证成功\n");
    return 1;
}

源码:

https://download.csdn.net/download/weixin_46703995/67723503

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

沐雨风栉

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

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

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

打赏作者

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

抵扣说明:

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

余额充值