之所以把这个代码称为一个程序而不叫一个项目,是因为鄙人还是个还没入行的新人,不敢妄自菲薄,只因一时兴起上来感慨吐槽一番,如果有什么不对的地方,请各位大牛高台贵手,如果能提点一番,小弟感激不尽
废话不多,拿到题目就开干。
刚学完内核链表,就拿它来开刀。内核给你写好封装一些链表操作的接口函数,拿来用多爽,不用自己写。这个写好的东西在哪呢,在内核目录的include/linux/下。
#include #include #include #include "kernel_list.h" struct flight { char flight_id[15]; //航班号 //航班号 char flight_place[15]; //航班起飞站->终点站 //买票者的名字 char flight_time[15]; //起飞时间 //买到的票的座位号 int flight_seat; //航班总座位数 //票的张数 float price; //机票价格 //花费的金额 int remain; //剩余座位数 char st[15]; //座位标志 struct list_head mylist; }; // 内核链表的初始化 struct flight * list_init() { struct flight *head=malloc(sizeof(struct flight)); INIT_LIST_HEAD(&(head->mylist)); return head; } //判断链表是否为空 int kernellist_empty(struct flight *head) { return list_empty(&(head->mylist)); } // 创建新的节点 struct flight * new_node(char *flight_id,char *flight_place,char *flight_time,int flight_seat,float price) { struct flight *new=malloc(sizeof(struct flight)); strcpy(new->flight_id,flight_id); strcpy(new->flight_place,flight_place); strcpy(new->flight_time,flight_time); new->flight_seat=flight_seat; new->remain=flight_seat; new->price=price; bzero(new->st,15); INIT_LIST_HEAD(&(new->mylist)); return new; } // 添加新的节点到内核链表中 添加到head的前面 int kernellist_add(struct flight *new,struct flight *head) { list_add_tail(&(new->mylist), &(head->mylist)); return 0; } //添加到head的后面 int kernellist_add_tail(struct flight *new,struct flight *head) { list_add(&(new->mylist), &(head->mylist)); return 0; } //删除一个节点 int kernellist_del(struct flight *del) { list_del(&(del->mylist)); return 0; } // 打印航班信息 int show(struct flight *head) { if(kernellist_empty(head)) { printf("no any flight exist!\n"); return 1; } printf("----------------------------------------------------------\n"); printf("flight_id flight_place flight_time flight_seat price\n"); struct flight *pos; list_for_each_entry(pos,&(head->mylist),mylist) //该宏函数实际是个for循环 //for (pos = list_entry((head)->next, typeof(*pos), member); &pos->member != (head); pos = list_entry(pos->member.next, typeof(*pos), member)) { printf("%-16s%-16s%-16s%-13d%.2f\n",pos->flight_id,pos->flight_place,pos->flight_time,pos->flight_seat,pos->price); } printf("----------------------------------------------------------\n"); return 0; } //打印卖票信息 int show_ticket(struct flight *head) { int i; if(kernellist_empty(head)) { printf("no bodey buy ticket!\n"); return 0; } printf("----------------------------------------------------------\n"); printf("flight_id name num price ticketnum\n"); struct flight *pos; list_for_each_entry(pos,&(head->mylist),mylist) //该宏函数实际是个for循环 //for (pos = list_entry((head)->next, typeof(*pos), member); &pos->member != (head); pos = list_entry(pos->member.next, typeof(*pos), member)) { printf("%-16s%-16s%-16d%-8.2f",pos->flight_id,pos->flight_place, pos->flight_seat,pos->price); for(i=0;i<15;i++) { if(pos->flight_time[i] == 1) printf("%d ",i+1); } printf("\n"); } printf("----------------------------------------------------------\n"); return 0; } //翻转航班信息 int reversal(struct flight *head) { struct list_head *pos; pos = head->mylist.next; while(pos->next != &(head->mylist)) list_move_tail(head->mylist.prev,pos); return 0; } //航班信息排序 int flight_sort(struct flight *head) { int choose; struct list_head *posi; struct list_head *posj; struct list_head *temp; while(1) { printf( "====================================================================\n" "[1]flight_id [2]flight_time [3]price [4]reversal [5]show [0]quit\n" "====================================================================\n"); if(scanf("%d",&choose) != 1 || getchar()!='\n') //判断是否正确输入 { choose=6; while(getchar() != '\n'); } switch(choose) { case 0: return 0; break; case 1: list_for_each(posi,&(head->mylist)) //for (posi = head->mylist.next; posi != &(head->mylist);posi = posi->next) { for (posj = posi->next; posj != &(head->mylist);posj = posj->next) { if(strcmp(list_entry(posi,struct flight,mylist)->flight_id,list_entry(posj,struct flight,mylist)->flight_id)==1) { temp = posi->prev; list_move(posi,posj); list_move(posj,temp); temp=posi; posi = posj; posj = temp; } } } break; case 2: list_for_each(posi,&(head->mylist)) //for (posi = head->mylist.next; posi != &(head->mylist);posi = posi->next) { for (posj = posi->next; posj != &(head->mylist);posj = posj->next) { if(strcmp(list_entry(posi,struct flight,mylist)->flight_time,list_entry(posj,struct flight,mylist)->flight_time)==1) { temp = posi->prev; list_move(posi,posj); list_move(posj,temp); temp=posi; posi = posj; posj = temp; } } } break; case 3: list_for_each(posi,&(head->mylist)) //for (posi = head->mylist.next; posi != &(head->mylist);posi = posi->next) { for (posj = posi->next; posj != &(head->mylist);posj = posj->next) { if(list_entry(posi,struct flight,mylist)->price>list_entry(posj,struct flight,mylist)->price) { temp = posi->prev; list_move(posi,posj); list_move(posj,temp); temp=posi; posi = posj; posj = temp; } } } break; case 4: reversal(head); show(head); break; case 5: show(head); break; default: printf("invalid input !!\n"); //输入错误 break; } } } //买票 int flight_buy(struct flight *head,struct flight *masg) { int i; int count = 0; char str[15]; //存放买票的航班号 char name[15]; //存放买票的名字 char seat[15]; memset(seat,2,15); //临时存放座位号 由于后面使用strcpy 所以不能用0 struct flight *pos; int ticket; //买票的张数 struct flight *mynewnode; struct flight *n; show(head); while(1) { printf("enter flight id you want buy or quit to back primary menu\n"); gets(str); if(strcmp(str, "quit") == 0) break; list_for_each_entry(pos,&(head->mylist),mylist) { if(strcmp(str,pos->flight_id) == 0) //查找航班号 { printf("enter how many you want buy\n"); // scanf("%d",&ticket); // getchar(); lable1: if(scanf("%d",&ticket) != 1 || getchar()!='\n') //判断是否正确输入 { while(getchar() != '\n'); printf("invalid intput! try again\n"); goto lable1; } if(ticket<=0) //输入的票数小于等于0 { printf("invalid intput! try again\n"); goto lable1; } printf("%s flight have %d tickets!\n",pos->flight_id,pos->remain); if(ticket > pos->remain) //余票不足 { printf("no have more tickets!\n"); } else { printf("please enter you name!\n"); gets(name); printf("you tiickets numbel is:\n"); for(i=0;i<15;i++) //分配座位号 { if(pos->st[i] != 1) { pos->st[i]=1; count++; seat[i]=1; printf("%d\t",i+1); } if(count>=ticket) { count=0; break; } } printf("\n"); if(kernellist_empty(masg)) //买票链表为空 { mynewnode = new_node(str,name,seat,ticket,ticket*pos->price); kernellist_add(mynewnode,masg); } else { list_for_each_entry(n,&(masg->mylist),mylist) //查找是否有相同的票 { if(strcmp(name,n->flight_place) == 0 && strcmp(str,n->flight_id) == 0) //有相同的票则票数量添加 { n->flight_seat+=ticket; n->price+=ticket*pos->price; for(i=0;i<15;i++) { if(seat[i] == 1) n->flight_time[i]=1; } break; } if(n->mylist.next==&(masg->mylist)) //没有则建立一个新的结构体存放 { mynewnode = new_node(str,name,seat,ticket,ticket*pos->price); kernellist_add(mynewnode,masg); break; } } } printf("succeed buy tickets!\n"); pos->remain -= ticket; //余票减少 } break; } if(pos->mylist.next==&(head->mylist)) //没有查找到航班号 printf("no such flight exist!\n"); } memset(seat,2,15); //清空座位号 } } //退票 int unticket(struct flight *p,struct flight *masg) { int i; int ticketnum; //退票数量 int count=0; char str[15]; //名字 char strid[15]; //航班号 struct flight *pos; struct flight *pos1; while(1) { printf("please enter you name or quit to back!\n"); gets(str); if(strcmp(str, "quit") == 0) break; printf("flight_id name num price\n"); list_for_each_entry(pos,&(masg->mylist),mylist)// 双向链表没有遍历完 { if(strcmp(str,pos->flight_place) == 0) { printf("%-16s%-16s%-16d%.2f\n",pos->flight_id,pos->flight_place,pos->flight_seat,pos->price); // if(pos->flight_seat > 1) // { // pos->flight_seat -= 1; // } // else // kernellist_del(pos); // break; count++; } // if(pos->mylist.next==&(masg->mylist)) // printf("no such ticket exist!\n"); } if(count==0) //你没有买票 printf("no such ticket exist!\n"); else if(count > 1) //你买了两种以上 { printf("please enter you want flight id unticket!\n"); gets(strid); list_for_each_entry(pos,&(masg->mylist),mylist) { if(strcmp(str,pos->flight_place) == 0 && strcmp(strid,pos->flight_id) == 0) { printf("you have ticket numbel is \n"); // printf("flight_id name num price\n"); // printf("%-16s%-16s%-16d%.2f\n",pos->flight_id,pos->flight_place,pos->flight_seat,pos->price); for(i=0;i<15;i++) { if(pos->flight_time[i] == 1) printf("%d\t",i+1); } printf("\n"); printf("how many you want unticket!\n"); lable: if(scanf("%d",&ticketnum) != 1 || getchar()!='\n') //判断是否正确输入 { while(getchar() != '\n'); printf("invalid intput! try again\n"); goto lable; } if(pos->flight_seat < ticketnum || ticketnum <= 0) { printf("invalid intput! try again\n"); goto lable; } else if(pos->flight_seat == ticketnum) //全退 { kernellist_del(pos); list_for_each_entry(pos1,&(p->mylist),mylist) { if(strcmp(strid, pos1->flight_id)==0) { pos1->remain += ticketnum; break; } } printf("unticket successful!\n"); } else // 退ticketnum张 { pos->flight_seat -= ticketnum; //你拥有的票减少ticketnum张 list_for_each_entry(pos1,&(p->mylist),mylist) { if(strcmp(strid, pos1->flight_id)==0) { pos1->remain += ticketnum; //剩余的票数增加 break; } } pos->price -= pos1->price*ticketnum; //你付的总价减少 for(i=0;i<15;i++) { if(pos->flight_time[i] == 1) //座位号回收 默认从小开始回收 { pos->flight_time[i]=2; ticketnum--; } if(ticketnum == 0) break; } printf("unticket successful!\n"); } break; } } } else if(count==1) //你只买了一种票 { list_for_each_entry(pos,&(masg->mylist),mylist) { if(strcmp(str,pos->flight_place) == 0 ) { printf("you have ticket numbel is \n"); for(i=0;i<15;i++) { if(pos->flight_time[i]==1) printf("%d\t",i+1); } printf("\n"); printf("how many you want unticket!\n"); lable2: if(scanf("%d",&ticketnum) != 1 || getchar()!='\n') //判断是否正确输入 { while(getchar() != '\n'); printf("invalid intput! try again\n"); goto lable2; } if(pos->flight_seat < ticketnum || ticketnum <= 0) { printf("invalid intput! try again\n"); goto lable2; } else if(pos->flight_seat == ticketnum) //全退 { kernellist_del(pos); list_for_each_entry(pos1,&(p->mylist),mylist) { if(strcmp(strid, pos1->flight_id)==0) { pos1->remain += ticketnum; break; } } printf("unticket successful!\n"); } else { pos->flight_seat -= ticketnum; list_for_each_entry(pos1,&(p->mylist),mylist) { if(strcmp(strid, pos1->flight_id)==0) { pos1->remain += ticketnum; break; } } pos->price -= pos1->price*ticketnum; for(i=0;i<15;i++) { if(pos->flight_time[i] == 1) { pos->flight_time[i]=2; ticketnum--; } if(ticketnum == 0) break; } printf("unticket successful!\n"); } break; } } } count = 0; } return 0; } //管理员执行函数 int admi(struct flight *p, char *password,struct flight *masg) { int choose=0; char str1[15]; char str2[15]; char str3[15]; int seat; float price; struct flight *mynewnode; struct flight *pos; struct flight *n; while(1) { printf("please enter password!\n"); gets(str1); if(strcmp(str1,password) != 0) { printf("error password!\n"); choose++; } else break; if(choose == 3) { return 1; } } while(1) { printf( "************************enter you choice**********************************\n" "[1]insert [2]remove [3]show [4]clear [5]sort [6]changepassword [0]quit\n" "**************************************************************************\n"); if(scanf("%d",&choose) != 1 || getchar()!='\n') //判断是否正确输入 { choose=7; while(getchar() != '\n'); } switch(choose) { case 0: return 0; break; case 1: while(1) { printf("enter flight id you want add or quit to back primary menu\n"); gets(str1); if(strcmp(str1, "quit") == 0) break; printf("enter the flight place\n"); gets(str2); printf("enter the flight time\n"); gets(str3); if(str3[1]==':') //判断时间输入格式,为后面的排序做准备 { for(seat=4;seat>=0;seat--) str3[seat+1]=str3[seat]; str3[0]=' '; } printf("enter the flight seat\n"); scanf("%d",&seat); getchar(); printf("enter the flight price\n"); scanf("%f",&price); getchar(); mynewnode = new_node(str1,str2,str3,seat,price); printf("you want add the flight who's id next\n"); //插入到哪个航班号的后面 gets(str1); list_for_each_entry(pos,&(p->mylist),mylist) { if(strcmp(str1,pos->flight_id) == 0) { kernellist_add_tail(mynewnode,pos); break; } if(pos->mylist.next==&(p->mylist)) //如果没找到默认插到最后一个 { printf("no such flight exist!\n"); kernellist_add(mynewnode,p); break; } } } show(p); break; case 2: while(1) { if(kernellist_empty(p)) //如果航班信息为空 { printf("no any flight exist!\n"); break; } printf("enter flight id you want remove or quit to back primary menu\n"); gets(str1); if(strcmp(str1, "quit") == 0) break; list_for_each_entry(pos,&(p->mylist),mylist)// 双向链表没有遍历完 { if(strcmp(str1,pos->flight_id) == 0) { kernellist_del(pos); break; } if(pos->mylist.next==&(p->mylist)) printf("no such flight exist!\n"); } if(show(p)) //如果航班信息为空打印信息并退出 break; } break; case 3: while(1) { printf( "---------------------------\n" "please enter you want print\n" "[1] print flight message\n" "[2] print ticket message\n" "[0] quit\n" "---------------------------\n"); if(scanf("%d",&seat) != 1 || getchar()!='\n') //判断是否正确输入 { seat=3; while(getchar() != '\n'); } if(seat == 1) { show(p); } else if(seat == 2) { show_ticket(masg); } else if(seat == 0) break; else printf("invalid input !!\n"); } break; case 4: list_for_each_entry_safe(pos,n,&(p->mylist),mylist) //安全删除条目 { kernellist_del(pos); free(pos); } break; case 5: flight_sort(p); break; case 6: printf("please enter new password!\n"); gets(str1); printf("please enter new password again!\n"); gets(str2); if(strcmp(str1,str2) != 0) printf( "twice enter different!\n" "change fail!\n"); else { strcpy(password,str1); printf("change succeed!\n"); } break; default: printf("invalid input !!\n"); //输入错误 break; } } return 0; } //用户执行函数 int user(struct flight *p,struct flight *masg) { int choose; while(1) { printf( "************************enter you choice************************\n" "[1]buyticket [2]unticket [3]show [4]sort [0]quit\n" "****************************************************************\n"); if(scanf("%d",&choose) != 1 || getchar()!='\n') //判断是否正确输入 { choose=5; while(getchar() != '\n'); } switch(choose) { case 0: return 0; break; case 1: flight_buy(p,masg); break; case 2: unticket(p,masg); break; case 3: show(p); break; case 4: flight_sort(p); break; default: printf("invalid input !!\n"); //输入错误 break; } } return 0; } int main(int argc,char *argv[]) { int choose; struct flight *p=list_init(); struct flight *masg=list_init(); char password[15] = "123"; struct flight *mynewnode; // char st[15]={0}; mynewnode = new_node("A001","gz->jy"," 8:30",6,260); kernellist_add(mynewnode,p); mynewnode = new_node("A002","gz->cs","10:30",8,160); kernellist_add(mynewnode,p); mynewnode = new_node("A003","gz->hz","12:30",6,185); kernellist_add(mynewnode,p); mynewnode = new_node("A004","gz->sz"," 9:50",4,230); kernellist_add(mynewnode,p); mynewnode = new_node("A005","gz->hn","22:30",12,175); kernellist_add(mynewnode,p); while(1) { printf(" Welcome to Flights System\n"); printf( "************************enter you choice************************\n" "[1]administrator [2]user [0]end\n" "****************************************************************\n"); //scanf("%d",&choose); if(scanf("%d",&choose) != 1 || getchar()!='\n') //判断是否正确输入 { choose=3; while(getchar() != '\n'); } switch(choose) { case 0: return 0; //程序结束 break; case 1: admi(p, password,masg); break; case 2: user(p,masg); break; default: printf("invalid input !!\n"); //输入错误 break; } } return 0; } #ifndef __DLIST_H #define __DLIST_H /* This file is from Linux Kernel (include/linux/list.h) * and modified by simply removing hardware prefetching of list items. * Here by copyright, credits attributed to wherever they belong. * Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu) */ /* * Simple doubly linked list implementation. * * Some of the internal functions (“__xxx”) are useful when * manipulating whole lists rather than single entries, as * sometimes we already know the next/prev entries and we can * generate better code by using them directly rather than * using the generic single-entry routines. */ /** * container_of - cast a member of a structure out to the containing structure * * @ptr: the pointer to the member. * @type: the type of the container struct this is embedded in. * @member: the name of the member within the struct. * */ #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) /* * These are non-NULL pointers that will result in page faults * under normal circumstances, used to verify that nobody uses * non-initialized list entries. */ #define LIST_POISON1 ((void *) 0x00100100) #define LIST_POISON2 ((void *) 0x00200) struct list_head { struct list_head *next, *prev; }; #define LIST_HEAD_INIT(name) { &(name), &(name) } #define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name) #define INIT_LIST_HEAD(ptr) do { \ (ptr)->next = (ptr); (ptr)->prev = (ptr); \ } while (0) /* * Insert a new entry between two known consecutive entries. * * This is only for internal list manipulation where we know * the prev/next entries already! */ static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) { next->prev = new; new->next = next; new->prev = prev; prev->next = new; } /** * list_add – add a new entry * @new: new entry to be added * @head: list head to add it after * * Insert a new entry after the specified head. * This is good for implementing stacks. */ static inline void list_add(struct list_head *new, struct list_head *head) { __list_add(new, head, head->next); } /** * list_add_tail – add a new entry * @new: new entry to be added * @head: list head to add it before * * Insert a new entry before the specified head. * This is useful for implementing queues. */ static inline void list_add_tail(struct list_head *new, struct list_head *head) { __list_add(new, head->prev, head); } /* * Delete a list entry by making the prev/next entries * point to each other. * * This is only for internal list manipulation where we know * the prev/next entries already! */ static inline void __list_del(struct list_head *prev, struct list_head *next) { next->prev = prev; prev->next = next; } /** * list_del – deletes entry from list. * @entry: the element to delete from the list. * Note: list_empty on entry does not return true after this, the entry is in an undefined state. */ static inline void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); entry->next = (void *) 0; entry->prev = (void *) 0; } /** * list_del_init – deletes entry from list and reinitialize it. * @entry: the element to delete from the list. */ static inline void list_del_init(struct list_head *entry) { __list_del(entry->prev, entry->next); INIT_LIST_HEAD(entry); } /** * list_move – delete from one list and add as another’s head * @list: the entry to move * @head: the head that will precede our entry */ static inline void list_move(struct list_head *list, struct list_head *head) { __list_del(list->prev, list->next); list_add(list, head); } /** * list_move_tail – delete from one list and add as another’s tail * @list: the entry to move * @head: the head that will follow our entry */ static inline void list_move_tail(struct list_head *list, struct list_head *head) { __list_del(list->prev, list->next); list_add_tail(list, head); } /** * list_empty – tests whether a list is empty * @head: the list to test. */ static inline int list_empty(struct list_head *head) { return head->next == head; } static inline void __list_splice(struct list_head *list, struct list_head *head) { struct list_head *first = list->next; struct list_head *last = list->prev; struct list_head *at = head->next; first->prev = head; head->next = first; last->next = at; at->prev = last; } /** * list_splice – join two lists * @list: the new list to add. * @head: the place to add it in the first list. */ static inline void list_splice(struct list_head *list, struct list_head *head) { if (!list_empty(list)) __list_splice(list, head); } /** * list_splice_init – join two lists and reinitialise the emptied list. * @list: the new list to add. * @head: the place to add it in the first list. * * The list at @list is reinitialised */ static inline void list_splice_init(struct list_head *list, struct list_head *head) { if (!list_empty(list)) { __list_splice(list, head); INIT_LIST_HEAD(list); } } /** * list_entry – get the struct for this entry * @ptr: the &struct list_head pointer. * @type: the type of the struct this is embedded in. * @member: the name of the list_struct within the struct. */ #define list_entry(ptr, type, member) \ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) /** * list_for_each - iterate over a list * @pos: the &struct list_head to use as a loop counter. * @head: the head for your list. */ #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); \ pos = pos->next) /** * list_for_each_prev - iterate over a list backwards * @pos: the &struct list_head to use as a loop counter. * @head: the head for your list. */ #define list_for_each_prev(pos, head) \ for (pos = (head)->prev; pos != (head); \ pos = pos->prev) /** * list_for_each_safe - iterate over a list safe against removal of list entry * @pos: the &struct list_head to use as a loop counter. * @n: another &struct list_head to use as temporary storage * @head: the head for your list. */ #define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) /** * list_for_each_entry - iterate over list of given type * @pos: the type * to use as a loop counter. * @head: the head for your list. * @member: the name of the list_struct within the struct. */ #define list_for_each_entry(pos, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member); \ &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member)) /** * list_for_each_entry_safe – iterate over list of given type safe against removal of list entry * @pos: the type * to use as a loop counter. * @n: another type * to use as temporary storage * @head: the head for your list. * @member: the name of the list_struct within the struct. */ #define list_for_each_entry_safe(pos, n, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member), \ n = list_entry(pos->member.next, typeof(*pos), member); \ &pos->member != (head); \ pos = n, n = list_entry(n->member.next, typeof(*n), member)) #endif 在来个Makefile TARGET=flight_system SRCS=$(wildcard *.c) OBJ=$(patsubst %.c, %.o, $(SRCS)) CC=gcc $(TARGET):$(OBJ) $(CC) $^ -o $@ %.o:%.c $(CC) -o $@ -c $< clean: rm *.o $(TARGET)