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

前两天忙着改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;         // 第几排
};
View Code

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;   // 指向下一班飞机;
};
View Code

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

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

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

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

  1 #ifndef MY_AIR_TICKET_H
  2 #define MY_AIR_TICKET_H
  3 #include <stdlib.h>
  4 #include <stdio.h>
  5 #include <string.h>
  6 #define LINE 7       // 行数
  7 #define COLUMN 6     // 列数  ABCDEF
  8 #define CHARLEN 16   //  字符数组长度
  9 #define TOTALTICKET (LINE*COLUMN)   // 单一航班机票总数。 其实line和column应该要放在fly结构体中,这样能够自定义飞机的容量
 10 enum Pos{A,B,C,D,E,F};   //  A==0, 可以当做下标使用,这样代码更好读
 11 enum REQUIRE{WINDOW, ASIDE, BINARY, TRIPLE};
 12 enum ISREMINDER{NO,YES};   // NO查询已售票  or  YES余票
 13 
 14 #define trace printf("line: %d\n",__LINE__)   // 调试宏,适当的摆放,能够快速2分定位到错误的位置
 15 
 16 // 机票信息
 17 struct Ticket{
 18     int id;       // 机票号
 19     char buyerName[CHARLEN];
 20     unsigned long buyerID;// 持票人
 21     int price;           // 价格
 22     char postion;     // AF  靠窗  CD 走道  A
 23     int line;         // 第几排
 24 };
 25 
 26 //struct Ticket* initTicket(void)
 27 //{
 28 //    struct Ticket* ticket = (struct Ticket*) malloc (sizeof(struct Ticket));
 29 //    ticket->buyerID = 0;
 30 //    ticket->buyerName[0] = '\0';
 31 //    ticket->id = 0;
 32 //    ticket->line = 0;
 33 //    ticket->postion = 0;
 34 //    ticket->price = 0;
 35 //    return ticket;
 36 //}
 37 
 38 struct Ticket* createTicket(int tid, char pos, int line,
 39                             char* bn, unsigned long bid,int prs)
 40 {
 41     struct Ticket* ticket = (struct Ticket*)malloc(sizeof(struct Ticket));
 42     ticket->id = tid;
 43     ticket->postion = pos;
 44     ticket->line = line;
 45     strncpy(ticket->buyerName, bn, strlen(bn)+1);              //  注意cpy要包含最后一个'\0'
 46     ticket->buyerID = bid;
 47     ticket->price = prs;
 48     return ticket;    // 这里的ticket是局部指针,为啥能返回呢?大家思考下哦。对于可以返回指针,这算是一种,因为它指向malloc出来的东西,这个东西在函数析构时不会消失。
 49 }
 50 
 51 void freeTicket(struct Ticket* t)
 52 {
 53     if (t != NULL) {    //  最好进行free操作时,要先判断下非空
 54         free(t);
 55     }
 56 }
 57 struct LiftTime{   // 起飞时间结构体
 58     unsigned char hour;
 59     unsigned char minite;
 60 };
 61 
 62 struct Fly{
 63     int id;      // 航班号
 64     char company[CHARLEN];   // 航空公司
 65     char source[CHARLEN];     //  出发地
 66     char destination[CHARLEN];  // 目的地
 67     int sold;           // 已售票
 68     struct LiftTime lift;
 69     struct Ticket*** ticket;   // 本班飞机票池   
 70     struct Fly* next;   // 指向下一班飞机;
 71 };
 72 
 73 struct Fly* initFly()    // 为了给机场类的head指针使用。
 74 {
 75     struct Fly* plane = (struct Fly*)malloc(sizeof(struct Fly));
 76     plane->id = 0;
 77     plane->lift.hour = 0;
 78     plane->lift.minite = 0;
 79     plane->source[0] = '\n';
 80     plane->destination[0] = '\n';
 81     plane->company[0] = '\n';
 82     plane->next = NULL;
 83     plane->sold = 0;
 84     plane->next = NULL;
 85     plane->ticket = NULL;
 86     return plane;
 87 }
 88 
 89 struct Fly* createFly(int fid, char* from, char* to, struct LiftTime* lt, char* cmpy)    // 真正的航班类创建
 90 {
 91     int i,j;
 92     struct Fly* plane = (struct Fly*)malloc(sizeof(struct Fly));
 93     plane->id = fid;
 94     plane->lift.hour = lt->hour;
 95     plane->lift.minite = lt->minite;
 96     strncpy(plane->source, from, strlen(from)+1);
 97     strncpy(plane->destination, to, strlen(to)+1);
 98     strncpy(plane->company, cmpy, strlen(cmpy)+1);
 99     plane->next = NULL;
100     plane->sold = 0;
101     plane->next = NULL;
102     plane->ticket = (struct Ticket***)malloc(sizeof(struct Ticket**)*COLUMN);    从102--104其实就是C++中怎么new个二维数组的写法
103     for(i=0; i<COLUMN;++i)
104         plane->ticket[i] = (struct Ticket**) malloc(sizeof(struct Ticket*)*LINE);
105     for (i=0; i<COLUMN; ++i) {
106         for(j=0; j<LINE; ++j){
107             plane->ticket[i][j] = NULL;
108         }
109     }
110     return plane;
111 }
112 void freeFly(struct Fly* f)
113 {
114     int i, j;
115     if (f != NULL) {
116         for (i=0; i<COLUMN; i++) {
117             for(j=0; j<LINE; j++){
118                 if(f->ticket == NULL)          // 这里是一大疏忽点! 要是没这个判断,那么程序将会出错。那是因为head指针的ticket域为空!
119                     break;
120                 freeTicket(f->ticket[i][j]);
121             }
122         }
123         free(f->ticket);
124         free(f);
125     }
126 }
127 
128 struct Pool{                   // 航班池
129     struct Fly* head;
130 //    struct Fly* tail;   // 让学弟自己实现,因此我没做
131     int total;
132 };
133 
134 
135 struct Pool* initPool()
136 {
137     struct Pool* p = (struct Pool*)malloc(sizeof(struct Pool));
138     p->head = initFly();   // 唯一一次的initFly。
139     p->total = 0;
140     return p;
141 }
142 
143 
144 struct Pool* addFly(struct Pool* p, struct Fly* f)
145 {
146     if (p->head->next == NULL) {   // 若无航班,则添加到头结点后
147         p->head->next = f;
148         p->total++;
149     }else{                           //  添加到原有航班池最后。  有tail指针,一切将变得更加简单。。因此我们更要注意用空间换时间
150         struct Fly* tmp = p->head;
151         int t = p->total;
152         while(t--){ tmp = tmp->next;}
153         tmp->next = f;
154         p->total++;
155     }
156     return p;
157 }
158 
159 int delFly(struct Pool* a, int id)    // 根据航班Id删除航班
160 {
161     struct Fly* tmp;
162     struct Fly* p = a->head;
163 
164     while( p && (p->next->id != id)){
165             p = p->next;
166     }
167     if ( p == NULL || p->next == NULL) {
168         printf("No fly %d\n",id);
169         return 0;
170     }
171     tmp = p->next;
172     p->next = p->next->next;
173     freeFly(tmp);
174     a->total--;
175     printf("Delete fly %d\n",id);
176     return 1;    
177 }
178 
179 int delPool(struct Pool* p){     // 销毁机场
180     if( p != NULL){
181         struct Fly* f = p->head->next;
182         struct Fly* tmp;
183         while(f != NULL){
184             tmp = f->next;
185             freeFly(f);
186             f = tmp;
187         }
188     freeFly(p->head);
189     }
190     return 1;
191 }
192 
193 
194 int buyTicket(struct Fly* f, struct Ticket* t)    //订票
195 {
196     int pos = t->postion - 'A';
197     if ((f->ticket)[pos][t->line] != NULL) {
198         printf("Sorry, seat exist! please change another seat!\n");
199         return 0;
200     }
201     (f->ticket)[pos][t->line] = t;
202     f->sold++;
203     printf("Book successfully!\n");
204     return 1;
205 }
206 
207 int delTicket(struct Fly* f, int tid)    // 退票
208 {
209     int i,j;
210     for(i=0; i<COLUMN; i++){
211         for(j=0; j<LINE; j++){
212             if (((f->ticket)[i][j])->id == tid) {
213                 freeTicket(((f->ticket)[i][j]));
214                 ((f->ticket)[i][j]) = NULL;
215                 f->sold--;
216                 printf("ticket id %d successfully deleted!\n", tid);
217                 return 1;
218             }
219         }
220     }
221     printf("No %d ticket exist!\n",tid);
222     return 0;
223 }
224 
225 void showFlyInfo(struct Fly* f)
226 {
227     printf("Plane %d:  %s--->%s, lift: %2d:%2d | Remind Ticket %d/%d , Company of %s\n", 
228                f->id, f->source, f->destination, f->lift.hour, f->lift.minite, TOTALTICKET-f->sold,TOTALTICKET, f->company);
229 }
230 
231 int showTicketInfo(struct Fly* f, int tid)
232 {
233     int i,j;
234     showFlyInfo(f);
235     for (i=0; i<COLUMN; i++) {
236         for (j=0; j<LINE; j++) {
237             if ( (f->ticket[i][j] != NULL) && (f->ticket[i][j]->id == tid)) {
238                 printf("Ticket id: %d , price: %d\tName: %s ID: %ld\n",
239                         f->ticket[i][j]->id,
240                         f->ticket[i][j]->price,
241                         f->ticket[i][j]->buyerName,
242                         f->ticket[i][j]->buyerID);
243                 return 1;
244             }
245         }
246     }
247     return 0;    
248 }
249 // 根据出发目的地查询航班
250 void searchByDST(struct Pool* p, char* from, char* to)
251 {
252     struct Fly* plane = p->head->next;
253     int i;
254     for(i=1; plane && (i<p->total); ++i){
255         if( !strcmp(from, plane->source) && !strcmp(to,plane->destination)){
256             showFlyInfo (plane);
257         }
258         plane = plane->next;
259     }
260 }
261 // 时间段查询航班
262 void searchByTime(struct Pool* p, unsigned char start, unsigned char last)
263 {
264     struct Fly* plane = p->head->next;
265     int i;
266     for(i=0; plane && (i<p->total); ++i){
267         if( (plane->lift.hour>=start) && (plane->lift.hour <= last) ){
268             showFlyInfo (plane);
269         }
270         plane = plane->next;
271     }
272 }
273 
274 // 按要求查询,这段代码其实可以重构下,太多相似的东西了。
275 void searchByRequire(struct Fly* f, enum REQUIRE r, enum ISREMINDER c)
276 {
277     int i,j;
278     int count = 1;
279     switch(r)
280     {
281         case WINDOW:
282             if (c == YES) {
283                 printf("Search by Window remind:\n");
284             }else{
285                 printf("Search by Window Sold:\n");
286             }    
287             for(i=0; i<COLUMN; i+=(COLUMN-1)){
288                 for (j=0; j<LINE; j++) {
289                     if (   ((f->ticket[i][j] == NULL) && (c==YES)) 
290                        ||  ((f->ticket[i][j] != NULL) && (c==NO)))
291                     {                        
292                         count++;
293                         printf("%c%2d  ", i+'A',j);
294                     }
295                     if (count % 8 == 0) { printf("\n");}
296                 }
297             }
298             putchar('\n');
299             break;
300         case ASIDE:
301             if (c == YES) {
302                 printf("Search by Aside remind:\n");
303             }else{
304                 printf("Search by Aside Sold:\n");
305             }    
306             for(i=C; i<=D; i++){
307                 for (j=0; j<LINE; j++) {
308                     if (   ((f->ticket[i][j] == NULL) && (c==YES)) 
309                         ||  ((f->ticket[i][j] != NULL) && (c==NO)))
310                     {
311                         count++;
312                         printf("%c%2d  ", i+'A',j);
313                     }
314                     if (count % 8 == 0) { printf("\n");}
315                 }
316             }
317             putchar('\n');
318             break;
319         case BINARY:
320             if (c == NO) {
321                 printf("Twins seats sold:\n");
322                 for(j=0; j<LINE; ++j){
323                     if (f->ticket[B][j] != NULL) {
324                         if(f->ticket[A][j] != NULL){
325                             printf("(%c%d, %c%d) ",'A',j,'B',j);
326                             count++;
327                             if (count % 8 == 0) { printf("\n");}
328                         }
329                         if(f->ticket[C][j] != NULL){
330                             printf("(%c%d, %c%d) ",'B',j,'C',j);
331                             count++;
332                             if (count % 8 == 0) { printf("\n");}
333                         }
334                     }
335                     if (f->ticket[E][j] != NULL) {
336                         if(f->ticket[D][j] != NULL){
337                             printf("(%c%d, %c%d) ",'D',j,'E',j);
338                             count++;
339                             if (count % 8 == 0) { printf("\n");}
340                         }
341                         if(f->ticket[F][j] != NULL){
342                             printf("(%c%d, %c%d) ",'E',j,'F',j);
343                             count++;
344                             if (count % 8 == 0) { printf("\n");}
345                         }
346                     }
347                 }
348                     
349             }
350             if (c == YES){
351                 printf("Twins seats remaid:\n");
352                 for(j=0; j<LINE; ++j){
353                     if(f->ticket[B][j] == NULL){
354                         if(f->ticket[A][j] == NULL){
355                             printf("(%c%d, %c%d) ",'A',j,'B',j);
356                             count++;
357                             if (count % 8 == 0) { printf("\n");}
358                         }
359                         if(f->ticket[C][j] == NULL){
360                             printf("(%c%d, %c%d) ",'B',j,'C',j);
361                             count++;
362                             if (count % 8 == 0) { printf("\n");}
363                         }
364                     }
365                     if(f->ticket[E][j] == NULL){
366                         if(f->ticket[D][j] == NULL){
367                             printf("(%c%d, %c%d) ",'D',j,'E',j);
368                             count++;
369                             if (count % 8 == 0) { printf("\n");}
370                         }
371                         if(f->ticket[F][j] == NULL){
372                             printf("(%c%d, %c%d) ",'E',j,'F',j);
373                             count++;
374                             if (count % 8 == 0) { printf("\n");}
375                         }
376                     }
377                 }
378             }
379             putchar('\n');
380             break;
381         case TRIPLE:
382             if(c == NO){
383                 printf("Triple seats:\n");
384                 for(j=0; j<LINE; ++j){
385                     if(f->ticket[B][j] != NULL)
386                         if(f->ticket[A][j] != NULL)
387                             if(f->ticket[C][j] != NULL){
388                                 printf("(%c%d--%c%d) ",'A',j,'C',j);
389                                 count++;
390                                 if (count % 4 == 0) { printf("\n");}
391                             }
392 
393                             if(f->ticket[E][j] != NULL)
394                                 if(f->ticket[D][j] != NULL)
395                                     if(f->ticket[F][j] != NULL){
396                                         printf("(%c%d--%c%d) ",'D',j,'F',j);
397                                         count++;
398                                         if (count % 4 == 0) { printf("\n");}
399                                     }                
400                 }
401             }
402             if(c == YES){
403                 printf("Triple seats:\n");
404                 for(j=0; j<LINE; ++j){
405                     if(f->ticket[B][j] == NULL)
406                         if(f->ticket[A][j] == NULL)
407                             if(f->ticket[C][j] == NULL){
408                                 printf("(%c%d--%c%d) ",'A',j,'C',j);
409                                 count++;
410                                 if (count % 4 == 0) { printf("\n");}
411                             }
412                             
413                     if(f->ticket[E][j] == NULL)
414                         if(f->ticket[D][j] == NULL)
415                             if(f->ticket[F][j] == NULL){
416                                 printf("(%c%d--%c%d) ",'D',j,'F',j);
417                                 count++;
418                                 if (count % 4 == 0) { printf("\n");}
419                             }                
420                 }
421             }
422             putchar('\n');
423             break;
424     }
425     printf("\n");
426 }
427 #endif
428 
429 void main()
430 {
431     struct Pool* airport = initPool();
432     struct LiftTime flt1 = {10,10};
433     struct LiftTime flt2 = {6,40};
434     struct Fly* f1 = createFly(1,"Xiamen","Beijing", &flt1, "xmu");
435     struct Fly* f2 = createFly(2,"Fuzhou","Beijing", &flt2, "xmu");
436     addFly(airport, f1);
437     addFly(airport, f2);
438     buyTicket (f1, createTicket(1,'A',3, "zy",1234567,400));
439     buyTicket (f1, createTicket(2,'B',3,"xld",2345678,400));
440     showTicketInfo (f1,1);
441     showTicketInfo (f1,2);
442     searchByTime (airport,8,12);
443     searchByDST (airport,"Fuzhou","Beijing");
444     searchByRequire (f1,BINARY,YES);
445     delPool (airport);
446 }

测试代码结果:

posted @ 2013-05-25 23:22  xield  阅读(1263)  评论(0编辑  收藏  举报