C程序课程设计之航班订票系统

admin 2022年6月1日23:01:53评论2 views字数 9342阅读31分8秒阅读模式

前两天忙着改Paper的参考文献,今天终于搞定了,稍微舒了一口气,预祝我的Paper能够顺利发出。


今天早上要给大一的学弟讲C课程设计---航班订票系统。无奈时间不够,昨晚八九点才空下来有时间写代码,匆忙花点时间写好了,早上调试下Bug,就给学弟们讲去了。

航班订票系统的要求:
1)飞机信息及本飞机机票销售情况的存储结构。
飞机信息:飞机ID,航空公司,出发地、目的地、机票销售情况。
2)所有机票销售信息:飞机ID,机票号、购买者姓名、购买者身份证。
3)飞机管理(新增航班、停开航班)
4)飞机票查询(按目的地、按时间、按要求:靠窗、靠过道、n人连坐等)。
5)已售票信息查询
6)销售飞机票及办理退票
7)信息的存储和读取(读写文件)

这边,由于时间的关系,我对 7)没实现,另外,Dos下经典的界面也没去实现,就简单写了下前六个功能的实现。

另外,由于是C语言,结构体中无成员函数,因此需要定义函数来操作,这些函数需要传入结构体的指针。其实,某种意义上,可以认为C的文件,就是C++中的一个类(定义加实现)。

C系列语言的精髓就是指针,熟练操作指针,必须能够手动操纵指针,即malloc之类的函数使用。想下自己当初大一时写学生信息管理的课程设计,由于没学过链表之类的(高级)东西,恨死指针了!现在回想起来,感觉指针是个好东西,虽然我现在还经常要调试指针引发的BUG..

题外话,用c来写这样的系统,个人感觉比C++麻烦。看来,我开始接收面向对象思想了。。哈哈,好事。


按照题意的分析,我们可以知道,主要设计三个结构体:

Ticket: 机票信息

// 机票信息struct Ticket{    int id;       // 机票号    char buyerName[CHARLEN];    unsigned long buyerID;// 持票人    int price;           // 价格    char postion;     // AF  靠窗  CD 走道  A    int line;         // 第几排};

Fly: 航班信息,其中要包含Ticket。内部有一个指向next Fly的指针

struct Fly{    int id;      // 航班号    char company[CHARLEN];   // 航空公司    char source[CHARLEN];     //  出发地    char destination[CHARLEN];  // 目的地    int sold;           // 已售票    struct LiftTime lift;    struct Ticket*** ticket;   // 本班飞机池       struct Fly* next;   // 指向下一班飞机;};

Pool: 机场,即航班池,包含Fly链表的头指针。

struct Pool{                   // 航班池    struct Fly* head;//    struct Fly* tail;        // 要让学弟自己实现tail的操作,所以就没用上这个tail    int total;                 // 航班总数};

由于结构体中定义了一堆的指针,因此我们在初始化的时候,就要注意下对指针符零值。我在Fly结构体中的Ticket全用指针,前两个**表示第几列第几排,最后一个*表示实际要指向的Ticket位置。这样就节省了初始化的开支;若仅有两个**, 那势必要进行Ticket实体的初始化,这样就浪费了太多空间和时间了。因此,结构体中指向复杂的的成员数据,最好使用指针形式表示。同时,使用指针表示意味着以后操作就要使用malloc操作,在程序适当时候需要free掉,这样才不会造成内存泄露。

好的,其实代码不算很复杂,我就把代码全贴上来,主要从代码的注释中来看。

#ifndef MY_AIR_TICKET_H#define MY_AIR_TICKET_H#include #include #include #define LINE 7       // 行数#define COLUMN 6     // 列数  ABCDEF#define CHARLEN 16   //  字符数组长度#define TOTALTICKET (LINE*COLUMN)   // 单一航班机票总数。 其实line和column应该要放在fly结构体中,这样能够自定义飞机的容量enum Pos{A,B,C,D,E,F};   //  A==0, 可以当做下标使用,这样代码更好读enum REQUIRE{WINDOW, ASIDE, BINARY, TRIPLE};enum ISREMINDER{NO,YES};   // NO查询已售票  or  YES余票
#define trace printf("line: %dn",__LINE__) // 调试宏,适当的摆放,能够快速2分定位到错误的位置
// 机票信息struct Ticket{ int id; // 机票号 char buyerName[CHARLEN]; unsigned long buyerID;// 持票人 int price; // 价格 char postion; // AF 靠窗 CD 走道 A int line; // 第几排};
//struct Ticket* initTicket(void)//{// struct Ticket* ticket = (struct Ticket*) malloc (sizeof(struct Ticket));// ticket->buyerID = 0;// ticket->buyerName[0] = '';// ticket->id = 0;// ticket->line = 0;// ticket->postion = 0;// ticket->price = 0;// return ticket;//}
struct Ticket* createTicket(int tid, char pos, int line, char* bn, unsigned long bid,int prs){ struct Ticket* ticket = (struct Ticket*)malloc(sizeof(struct Ticket)); ticket->id = tid; ticket->postion = pos; ticket->line = line; strncpy(ticket->buyerName, bn, strlen(bn)+1); // 注意cpy要包含最后一个'' ticket->buyerID = bid; ticket->price = prs; return ticket; // 这里的ticket是局部指针,为啥能返回呢?大家思考下哦。对于可以返回指针,这算是一种,因为它指向malloc出来的东西,这个东西在函数析构时不会消失。}
void freeTicket(struct Ticket* t){ if (t != NULL) { // 最好进行free操作时,要先判断下非空 free(t); }}struct LiftTime{ // 起飞时间结构体 unsigned char hour; unsigned char minite;};
struct Fly{ int id; // 航班号 char company[CHARLEN]; // 航空公司 char source[CHARLEN]; // 出发地 char destination[CHARLEN]; // 目的地 int sold; // 已售票 struct LiftTime lift; struct Ticket*** ticket; // 本班飞机票池 struct Fly* next; // 指向下一班飞机;};
struct Fly* initFly() // 为了给机场类的head指针使用。{ struct Fly* plane = (struct Fly*)malloc(sizeof(struct Fly)); plane->id = 0; plane->lift.hour = 0; plane->lift.minite = 0; plane->source[0] = 'n'; plane->destination[0] = 'n'; plane->company[0] = 'n'; plane->next = NULL; plane->sold = 0; plane->next = NULL; plane->ticket = NULL; return plane;}
struct Fly* createFly(int fid, char* from, char* to, struct LiftTime* lt, char* cmpy) // 真正的航班类创建{ int i,j; struct Fly* plane = (struct Fly*)malloc(sizeof(struct Fly)); plane->id = fid; plane->lift.hour = lt->hour; plane->lift.minite = lt->minite; strncpy(plane->source, from, strlen(from)+1); strncpy(plane->destination, to, strlen(to)+1); strncpy(plane->company, cmpy, strlen(cmpy)+1); plane->next = NULL; plane->sold = 0; plane->next = NULL; plane->ticket = (struct Ticket***)malloc(sizeof(struct Ticket**)*COLUMN); 从102--104其实就是C++中怎么new个二维数组的写法 for(i=0; i<column;++i)< span=""></column;++i)<> plane->ticket[i] = (struct Ticket**) malloc(sizeof(struct Ticket*)*LINE); for (i=0; i for(j=0; j plane->ticket[i][j] = NULL; } } return plane;}void freeFly(struct Fly* f){ int i, j; if (f != NULL) { for (i=0; i for(j=0; j if(f->ticket == NULL) // 这里是一大疏忽点! 要是没这个判断,那么程序将会出错。那是因为head指针的ticket域为空! break; freeTicket(f->ticket[i][j]); } } free(f->ticket); free(f); }}
struct Pool{ // 航班池 struct Fly* head;// struct Fly* tail; // 让学弟自己实现,因此我没做 int total;};

struct Pool* initPool(){ struct Pool* p = (struct Pool*)malloc(sizeof(struct Pool)); p->head = initFly(); // 唯一一次的initFly。 p->total = 0; return p;}

struct Pool* addFly(struct Pool* p, struct Fly* f){ if (p->head->next == NULL) { // 若无航班,则添加到头结点后 p->head->next = f; p->total++; }else{ // 添加到原有航班池最后。 有tail指针,一切将变得更加简单。。因此我们更要注意用空间换时间 struct Fly* tmp = p->head; int t = p->total; while(t--){ tmp = tmp->next;} tmp->next = f; p->total++; } return p;}
int delFly(struct Pool* a, int id) // 根据航班Id删除航班{ struct Fly* tmp; struct Fly* p = a->head;
while( p && (p->next->id != id)){ p = p->next; } if ( p == NULL || p->next == NULL) { printf("No fly %dn",id); return 0; } tmp = p->next; p->next = p->next->next; freeFly(tmp); a->total--; printf("Delete fly %dn",id); return 1;}
int delPool(struct Pool* p){ // 销毁机场 if( p != NULL){ struct Fly* f = p->head->next; struct Fly* tmp; while(f != NULL){ tmp = f->next; freeFly(f); f = tmp; } freeFly(p->head); } return 1;}

int buyTicket(struct Fly* f, struct Ticket* t) //订票{ int pos = t->postion - 'A'; if ((f->ticket)[pos][t->line] != NULL) { printf("Sorry, seat exist! please change another seat!n"); return 0; } (f->ticket)[pos][t->line] = t; f->sold++; printf("Book successfully!n"); return 1;}
int delTicket(struct Fly* f, int tid) // 退票{ int i,j; for(i=0; i for(j=0; j if (((f->ticket)[i][j])->id == tid) { freeTicket(((f->ticket)[i][j])); ((f->ticket)[i][j]) = NULL; f->sold--; printf("ticket id %d successfully deleted!n", tid); return 1; } } } printf("No %d ticket exist!n",tid); return 0;}
void showFlyInfo(struct Fly* f){ printf("Plane %d: %s--->%s, lift: %2d:%2d | Remind Ticket %d/%d , Company of %sn", f->id, f->source, f->destination, f->lift.hour, f->lift.minite, TOTALTICKET-f->sold,TOTALTICKET, f->company);}
int showTicketInfo(struct Fly* f, int tid){ int i,j; showFlyInfo(f); for (i=0; i for (j=0; j if ( (f->ticket[i][j] != NULL) && (f->ticket[i][j]->id == tid)) { printf("Ticket id: %d , price: %dtName: %s ID: %ldn", f->ticket[i][j]->id, f->ticket[i][j]->price, f->ticket[i][j]->buyerName, f->ticket[i][j]->buyerID); return 1; } } } return 0;}// 根据出发目的地查询航班void searchByDST(struct Pool* p, char* from, char* to){ struct Fly* plane = p->head->next; int i; for(i=1; plane && (itotal); ++i){ if( !strcmp(from, plane->source) && !strcmp(to,plane->destination)){ showFlyInfo (plane); } plane = plane->next; }}// 时间段查询航班void searchByTime(struct Pool* p, unsigned char start, unsigned char last){ struct Fly* plane = p->head->next; int i; for(i=0; plane && (itotal); ++i){ if( (plane->lift.hour>=start) && (plane->lift.hour <= last) ){ showFlyInfo (plane); } plane = plane->next; }}
// 按要求查询,这段代码其实可以重构下,太多相似的东西了。void searchByRequire(struct Fly* f, enum REQUIRE r, enum ISREMINDER c){ int i,j; int count = 1; switch(r) { case WINDOW: if (c == YES) { printf("Search by Window remind:n"); }else{ printf("Search by Window Sold:n"); } for(i=0; i-1)){ for (j=0; j if ( ((f->ticket[i][j] == NULL) && (c==YES)) || ((f->ticket[i][j] != NULL) && (c==NO))) { count++; printf("%c%2d ", i+'A',j); } if (count % 8 == 0) { printf("n");} } } putchar('n'); break; case ASIDE: if (c == YES) { printf("Search by Aside remind:n"); }else{ printf("Search by Aside Sold:n"); } for(i=C; i<=D; i++){ for (j=0; j if ( ((f->ticket[i][j] == NULL) && (c==YES)) || ((f->ticket[i][j] != NULL) && (c==NO))) { count++; printf("%c%2d ", i+'A',j); } if (count % 8 == 0) { printf("n");} } } putchar('n'); break; case BINARY: if (c == NO) { printf("Twins seats sold:n"); for(j=0; j if (f->ticket[B][j] != NULL) { if(f->ticket[A][j] != NULL){ printf("(%c%d, %c%d) ",'A',j,'B',j); count++; if (count % 8 == 0) { printf("n");} } if(f->ticket[C][j] != NULL){ printf("(%c%d, %c%d) ",'B',j,'C',j); count++; if (count % 8 == 0) { printf("n");} } } if (f->ticket[E][j] != NULL) { if(f->ticket[D][j] != NULL){ printf("(%c%d, %c%d) ",'D',j,'E',j); count++; if (count % 8 == 0) { printf("n");} } if(f->ticket[F][j] != NULL){ printf("(%c%d, %c%d) ",'E',j,'F',j); count++; if (count % 8 == 0) { printf("n");} } } }
} if (c == YES){ printf("Twins seats remaid:n"); for(j=0; j if(f->ticket[B][j] == NULL){ if(f->ticket[A][j] == NULL){ printf("(%c%d, %c%d) ",'A',j,'B',j); count++; if (count % 8 == 0) { printf("n");} } if(f->ticket[C][j] == NULL){ printf("(%c%d, %c%d) ",'B',j,'C',j); count++; if (count % 8 == 0) { printf("n");} } } if(f->ticket[E][j] == NULL){ if(f->ticket[D][j] == NULL){ printf("(%c%d, %c%d) ",'D',j,'E',j); count++; if (count % 8 == 0) { printf("n");} } if(f->ticket[F][j] == NULL){ printf("(%c%d, %c%d) ",'E',j,'F',j); count++; if (count % 8 == 0) { printf("n");} } } } } putchar('n'); break; case TRIPLE: if(c == NO){ printf("Triple seats:n"); for(j=0; j if(f->ticket[B][j] != NULL) if(f->ticket[A][j] != NULL) if(f->ticket[C][j] != NULL){ printf("(%c%d--%c%d) ",'A',j,'C',j); count++; if (count % 4 == 0) { printf("n");} }
if(f->ticket[E][j] != NULL) if(f->ticket[D][j] != NULL) if(f->ticket[F][j] != NULL){ printf("(%c%d--%c%d) ",'D',j,'F',j); count++; if (count % 4 == 0) { printf("n");} } } } if(c == YES){ printf("Triple seats:n"); for(j=0; j if(f->ticket[B][j] == NULL) if(f->ticket[A][j] == NULL) if(f->ticket[C][j] == NULL){ printf("(%c%d--%c%d) ",'A',j,'C',j); count++; if (count % 4 == 0) { printf("n");} }
if(f->ticket[E][j] == NULL) if(f->ticket[D][j] == NULL) if(f->ticket[F][j] == NULL){ printf("(%c%d--%c%d) ",'D',j,'F',j); count++; if (count % 4 == 0) { printf("n");} } } } putchar('n'); break; } printf("n");}#endif
void main(){ struct Pool* airport = initPool(); struct LiftTime flt1 = {10,10}; struct LiftTime flt2 = {6,40}; struct Fly* f1 = createFly(1,"Xiamen","Beijing", &flt1, "xmu"); struct Fly* f2 = createFly(2,"Fuzhou","Beijing", &flt2, "xmu"); addFly(airport, f1); addFly(airport, f2); buyTicket (f1, createTicket(1,'A',3, "zy",1234567,400)); buyTicket (f1, createTicket(2,'B',3,"xld",2345678,400)); showTicketInfo (f1,1); showTicketInfo (f1,2); searchByTime (airport,8,12); searchByDST (airport,"Fuzhou","Beijing"); searchByRequire (f1,BINARY,YES); delPool (airport);}

测试代码结果:

C程序课程设计之航班订票系统


原文始发于微信公众号(汇编语言):C程序课程设计之航班订票系统

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年6月1日23:01:53
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   C程序课程设计之航班订票系统https://cn-sec.com/archives/1078472.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息