前两天忙着改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掉,这样才不会造成内存泄露。
好的,其实代码不算很复杂,我就把代码全贴上来,主要从代码的注释中来看。
enum Pos{A,B,C,D,E,F}; // A==0, 可以当做下标使用,这样代码更好读
enum REQUIRE{WINDOW, ASIDE, BINARY, TRIPLE};
enum ISREMINDER{NO,YES}; // NO查询已售票 or YES余票
// 机票信息
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 && (i
total); ++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 && (i
total); ++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");
}
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程序课程设计之航班订票系统
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论