Linux-C 航班信息管理程序练习
一、简述
记-使用内核链表简单的实现一个航班信息管理程序,数据保存在文件中。使用Makefile来管理工程(简单粗鲁,用来偷懒)。
工程文件打包:链接: https://pan.baidu.com/s/14-C3WDJXKDoHr26dwd7K9Q 密码: k1sx
二、效果
三、工程结构
所有文件版:
打包为动态库版
四、源文件
myhead.h文件
/*******************************
**
** Author: Genven_Liang
**
** Date: 2018-08-03
**
** Description:函数头文件
**
**
*******************************/
#ifndef __MYHEAD_H_
#define __MYHEAD_H_
#include <mylist.h>
#define PATHNAME "flights.data"
#define Print_Format(ptr)\
printf("%-10s- %-10s -> %-10s-%10s-%-10s-%c - $%-10s \n",(ptr)->info.number,\
(ptr)->info.staddr,\
(ptr)->info.destaddr,\
(ptr)->info.date,\
(ptr)->info.time,\
(ptr)->info.type,\
(ptr)->info.price);
#define Print_Format_Flight(ptr)\
printf("%-10s- %-10s -> %-10s-%10s-%-10s-%c - $%-10s \n",(ptr)->number,\
(ptr)->staddr,\
(ptr)->destaddr,\
(ptr)->date,\
(ptr)->time,\
(ptr)->type,\
(ptr)->price);
#define TITLE "--number------from---------to----------date-----time-----type----price----\n"
#define WEISHU 1 ^ 2
typedef struct flight //flight node
{
char number[10]; //flight bunber
char staddr[10]; //start address
char destaddr[10]; //destinaiotn address
char date[10]; //flight date
char time[10]; //fliht time
char type; //flight type
char price[10]; //ticket price
}Flight;
typedef struct node //list node
{
Flight info;
struct list flist;
}Node;
enum e_filght_op
{
EXIT_PROGRAM,
INPUT_FLIGHT_INFO,
BROWSER_ALL_FLIGHT_INFO,
SEARCH_FLIGHT_INFO,
CANCEL_FLIGHT_INFO,
MODIFY_FLIGHT_INFO,
SORT_FLIGHT_INFO,
CLEAR_ALL_FLIGHT_INFO,
ABOUT_AUTHOR,
REFRESH_FLIGHT_INFO
};
//extern Node* head;
/*functiom declear*/
void main_menu();
Node* init_list();
void free_list(Node* head);
void add_node(Node* head,Node* new_node);
Node* create_node(Flight *flight);
Flight* create_flight();
void input_flight_info(Node* head);
Node* load_data(Node* head,const char* pathname);
void clear_data(const char* pathname);
int save_list(Node* head,const char* pathname);
void browser(Node* head);
void display_list(Node* head);
void Pause();
void about();
void login();
int is_exist(Node* head,char number[10]);
int is_equal(Flight *flt,char target[],int type,int len);
int my_strcmp(const char *s1,const char*s2,int len);
void cancel_flight(Node* head);
int cancel_flight_by_number(Node* head,char number[]);
void modify_flight(Node* head);
int modify_flight_by_number(Node* head,char number[]);
void sort_menu();
Node* sort_flight(Node* head);
void sort_list(Node* head,int type);
void search_menu();
void search_flight(Node* head);
void call_search_list(Node* head,int type);
Flight search_list(Node* head,char target[],int type);
Node* search_list_more(Node* head,char target[],int type);
#endif
mylist.h文件
/*******************************
**
** Author: Genven_Liang
**
** Date: 2018-08-03
**
** Description:链表操作头文件
**
**
*******************************/
#ifndef __MYLIST_H_
#define __MYLIST_H_
struct list
{
struct list *next,*prev;
};
#define INIT_LIST_HEAD(ptr) \
({\
(ptr)->next = (ptr); (ptr)->prev = (ptr);\
})
static inline void list_add(struct list *new,struct list *head)
{
struct list *prev = head,*next = head->next;
new->next = next;
next->prev = new;
new->prev = prev;
prev->next = new;
}
static inline void list_add_tail(struct list *new,struct list *head)
{
list_add(new,head->prev);
}
static inline void list_del(struct list *entry)
{
entry->next->prev = entry->prev;
entry->prev->next = entry->next;
entry->next = (void*) 0;
entry->prev = (void*) 0;
}
static inline void list_move(struct list *target,struct list *head)
{
list_del(target);
list_add(target,head);
}
static inline void list_join(struct list *head,struct list *src)
{
if(src->next!=src)
{
struct list *first = src->next;
struct list *last = src->prev;
first->prev = head->prev;
head->prev->next = first;
last->next = head;
head->prev = last;
}
}
#define list_entry(ptr,type,member)\
((type*)((char*)(ptr)-(unsigned long)(&((type*)0)->member)))
#define list_for_each(pos,head)\
for(pos = (head)->next;pos != (head);pos = pos->next)
#define list_foe_each_prev(pos,head)\
for(pos = (head)->prev;pos != (head);pos = pos->prev)
#define list_for_each_safe(pos,n,head)\
for(pos = (head)->next,n = pos->next;pos != (head);pos = n,n = pos->next)
#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))\
#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(*pos),member))
#endif
main.c文件
/*******************************
**
** Author: Genven_Liang
**
** Date: 2018-08-03
**
** Description: 主函数
**
**
*******************************/
#include <stdio.h>
#include <stdlib.h>
#include <myhead.h>
Node* head = NULL;
int main(int argc,char* argv[])
{
login();
int main_choice = 10;
head = init_list();
if(head == NULL)
{
return -1;
}
load_data(head,PATHNAME);
if(head == NULL)
{
return -1;
}
while(1)
{
main_menu();
scanf("%d",&main_choice);
while(getchar()!='\n');
switch(main_choice)
{
case INPUT_FLIGHT_INFO: input_flight_info(head);
break;
case BROWSER_ALL_FLIGHT_INFO: browser(head);
break;
case SEARCH_FLIGHT_INFO: search_flight(head);
break;
case CANCEL_FLIGHT_INFO: cancel_flight(head);
break;
case MODIFY_FLIGHT_INFO: modify_flight(head);
break;
case SORT_FLIGHT_INFO: sort_flight(head);
break;
case CLEAR_ALL_FLIGHT_INFO: clear_data(PATHNAME);
break;
case ABOUT_AUTHOR: about();
break;
case REFRESH_FLIGHT_INFO: load_data(head,PATHNAME);
break;
case EXIT_PROGRAM: exit(0);
break;
default:
break;
}
}
return 0;
}
menu.c文件
/*******************************
**
** Author: Genven_Liang
**
** Date: 2018-08-03
**
** Description: 菜单
**
**
*******************************/
#include <stdio.h>
void main_menu()
{
printf("\033c");//clear screen
printf(" \t┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n");
printf(" \t┃********************************************************┃\n");
printf(" \t┃***┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓***┃\n");
printf(" \t┃***┃************************************************┃***┃\n");
printf(" \t┃***┃*** ****┃***┃\n");
printf(" \t┃***┃*** Welcome use The Flight System ****┃***┃\n");
printf(" \t┃***┃*** ****┃***┃\n");
printf(" \t┃***┃*** [1] Add ****┃***┃\n");
printf(" \t┃***┃*** [2] Browse ****┃***┃\n");
printf(" \t┃***┃*** [3] Search ****┃***┃\n");
printf(" \t┃***┃*** [4] Cancel ****┃***┃\n");
printf(" \t┃***┃*** [5] Modify ****┃***┃\n");
printf(" \t┃***┃*** [6] Sort ****┃***┃\n");
printf(" \t┃***┃*** [7] Clear ****┃***┃\n");
printf(" \t┃***┃*** [8] About ****┃***┃\n");
printf(" \t┃***┃*** [9] Refresh ****┃***┃\n");
printf(" \t┃***┃*** [0] Exit ****┃***┃\n");
printf(" \t┃***┃*** ****┃***┃\n");
printf(" \t┃***┃************************************************┃***┃\n");
printf(" \t┃***┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛***┃\n");
printf(" \t┃********************************************************┃\n");
printf(" \t┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n");
printf(" \t **************Please enter you choice[0~8]:");
}
void sort_menu()
{
printf("\033c");
printf(" \t***************Sort menu****************\n");
printf(" \t****** [1] Sort by number *****\n");
printf(" \t****** [2] Sort by destination *****\n");
printf(" \t****** [3] Sort by date *****\n");
printf(" \t****** [4] Sort by price *****\n");
printf(" \t****** [0] Back *****\n");
printf(" \t******************************************\n");
printf(" \t****** Please enter your choice[0~4]:");
}
void search_menu()
{
printf("\033c");
printf(" \t***************Search menu****************\n");
printf(" \t****** [1] Search by number *****\n");
printf(" \t****** [2] Search by destination *****\n");
printf(" \t****** [3] Search by date *****\n");
printf(" \t****** [0] Back *****\n");
printf(" \t******************************************\n");
printf(" \t****** Please enter your choice[0~3]:");
}
browser.c文件
/*******************************
**
** Author: Genven_Liang
**
** Date: 2018-08-03
**
** Description:打印链表数据
**
**
*******************************/
#include <stdio.h>
#include <myhead.h>
/*
* browser:打印链表数据
* @head: 链表头结点指针
*
*/
void browser(Node* head)
{
head = load_data(head,PATHNAME);
if(head == NULL)
{
return;
}
display_list(head);
}
/*
* display_list:打印链表数据
* @head: 链表头结点指针
*
*/
void display_list(Node* head)
{
int count = 0;
if(head == NULL)
{
return;
}
if(head->flist.next == &head->flist)
{
printf("*****data empty!*****\n");
Pause();
return ;
}
printf("\n\n");
printf("-----------------------[ All flight info ]-----------------------\n");
printf(TITLE);
Node* pos;
list_for_each_entry(pos,&head->flist,flist)
{
Print_Format(pos);
++count;
}
printf("------------------------------------------------------------------\n");
printf("--------------------[The record total %d]-------------------------\n",count);
Pause();
return;
}
cancel.c文件
/*******************************
**
** Author: Genven_Liang
**
** Date: 2018-08-03
**
** Description: 删除指定航班信息
**
**
*******************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <myhead.h>
/*
* cancel_flight:删除指定航班信息
* @head:链表头结点指针
*
*/
void cancel_flight(Node* head)
{
char number[10] = {0};
int cancel_ret = 0;
printf("Please enter the cancel number:");
scanf("%9s",number);
while(getchar() != '\n');
if(strncmp(number,"000000",6)==0)//开发测试时隐藏的后门,用来强制删除
{
int num = -1,index = 0;
printf("\033c");
printf("######Please enter a serial number:");
scanf("%d",&num);
if(num<=0)
{
return;
}
Node* pos;
list_for_each_entry(pos,&head->flist,flist)
{
++index;
if(index == num)
{
list_del(&pos->flist);
free(pos);
save_list(head,PATHNAME);
return ;
}
}
}
head = load_data(head,PATHNAME);
cancel_ret = cancel_flight_by_number(head,number);
if(cancel_ret == 1)
{
printf("********cancel sucessful!*********\n");
}
else if(cancel_ret == 0)
{
printf("**********Sorry! Not Find number:[%s] flight ******\n",number);
}
else if(cancel_ret == -1)
{
printf("********cancel error!*********\n");
}
Pause();
}
/*
* cancel_flight_by_number:根据航班编号删除航班信息
* @head:链表头结点指针
* @number:航班编号
* return value:成功返回1,不存在该航班信息返回0,异常返回-1
*/
int cancel_flight_by_number(Node* head,char number[])
{
char is_has = 'n';
char choice = 'n';
if(head == NULL)
{
return -1;
}
Node* pos;
list_for_each_entry(pos,&head->flist,flist)
{
if(is_equal(&pos->info,number,1,0) == 0)
{
is_has = 'y';
break;
}
}
if(is_has == 'y')
{
printf("-------The number [%s] flight has been found!------\n",number);
printf(TITLE);
Print_Format_Flight(&pos->info);
printf("---------------------------------------------------\n");
printf("*******Confirm cancel?[y/n]:");
choice = getchar();
if(choice == 'Y' || choice == 'y')
{
list_del(&pos->flist);
free(pos);
if(save_list(head,PATHNAME) == 1)
{
return 1;
}
return -1;
}
}
return 0;
}
common.c文件
/*******************************
**
** Author: Genven_Liang
**
** Date: 2018-08-03
**
** Description: 辅助函数
**
**
*******************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <myhead.h>
/*
* is_equal:判断目标字符转是否与航班信息对应的字段一致
* @flt:进行比较的航班结构体指针
* @target:目标字符串
* @type:指定比较的是航班信息的哪个字段,为1比较航班编号,为2比较目的地点,为3比较日期。为4比较票价
* @len:指定匹配的字符个数,如果是0,就默认全字比较航班信息字段,否则就按目标字符串的长度进行比较
* return value:正常情况下返回字符串比较的结果,异常返回-2
*/
int is_equal(Flight *flt,char target[],int type,int len)
{
int cmp_ret = -2;
len = len == 0 ? 10 : strlen(target);
if(len == 0)
{
return -2;
}
switch(type)
{
case 1: cmp_ret = strncmp((*flt).number,target,len);
break;
case 2: cmp_ret = strncmp((*flt).destaddr,target,len);
break;
case 3: cmp_ret = strncmp((*flt).date,target,len);
break;
case 4: cmp_ret = my_strcmp((*flt).price,target,10);
break;
default:
break;
}
return cmp_ret;
}
/*
* my_strcmp:右对齐比较两个数字字符串
* @s1:数字字符串1
* @s2:数字字符串2
* @len:指定匹配的字符个数
* return value:正常情况下返回字符串比较的结果
* Description:比如"89"比较"123",先转为"089"和"123"再比较
*/
int my_strcmp(const char *s1,const char*s2,int len)
{
int len1 = strlen(s1);
int len2 = strlen(s2);
char str1[len] = {'0'};
char str2[len] = {'0'};
int i;
for(i = 0;i<len1;++i)
{
str1[len-len1+i] = s1[i];
}
for(i = 0;i<len2;++i)
{
str2[len-len2+i] = s2[i];
}
return strncmp(str1,str2,len);
}
/*
* is_exist:判断链表数据中是否含有目标字符串
* @head:链表头结点指针
* @number:目标字符串
* return value:含有返回1,不含有返回0,异常返回-1,链表数据为空返回0
*/
int is_exist(Node* head,char number[])
{
// head = load_data(PATHNAME);
if(head == NULL)
{
return -1;
}
if(head->flist.next == &head->flist)
{
return 0;
}
Node* pos;
list_for_each_entry(pos,&head->flist,flist)
{
if(strcmp(pos->info.number,number) == 0)
{
return 1;
}
}
return 0;
}
/*
* Pause:暂停以下,等待键入
*
*/
void Pause()
{
//while(getchar() != '\n');
printf("******Please enter any key to continue!*******");
getchar();
}
/*
* about:打印作者信息
*
*/
void about()
{
printf("\033c");
printf(" \t***************************************\n");
printf(" \t*** @copyright by Genven_Liang ***\n");
printf(" \t***************************************\n\n");
Pause();
}
/*
* login:登录函数
*
*/
void login()
{
char ch = '0';
int flg = 0;
unsigned int times = 3;
int mask[] = {0x2B023,0x2B79E,0xA26A95,0x2BA59,0x2BF81,0x2018D0,0x1237FF1};//掩码
long long pwd = 0;
system("stty -icanon");//不缓冲,使用getchar(),键入一个字符立即结束,不等待回车
system("stty -echo");//不回显
printf("\033c");//清屏
while(times--)
{
printf("Liang#Please enter password:");
while(ch != '\n')
{
ch = getchar();
if(ch >='0' && ch <= '9')
{
pwd = pwd*10 + ch-'0';
printf("*");
}
else if(ch == 127 && pwd > 0)
{
printf("\b \b");
pwd /= 10;
}
}
ch = '0';
if((pwd^mask[times]) == (178157+mask[times+2]^times*times*2018080137/317+flg++-mask[times*times]) )
{
if( times*mask[times]/0x51D == ( flg >> WEISHU - 1 ) && flg == 0x2B131^ mask[times] )
{
system("stty icanon");
system("stty echo");//回显
return;
}
else
{
flg = 0x111;
}
pwd = 0L;
}
if(times>0)
{
printf("\n***Password Error: you have %d chances to try again!!! \n",times);
}
else
{
printf("\n** You have no more chances! Exit the Programe!\n **");
}
}
system("stty icanon");
system("stty echo");
exit(0);
}
file.c文件
/*******************************
**
** Author: Genven_Liang
**
** Date: 2018-08-03
**
** Description: 文件操作
**
**
*******************************/
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <myhead.h>
/*
* clear_data:清空文件内容
* @pathname:文件路径
*
*/
void clear_data(const char* pathname)
{
//while(getchar() != '\n');
printf("*****Confirm clear data?[y/n]:");
char ch = getchar();
if(ch == 'Y' || ch == 'y')
{
FILE *fp = fopen(pathname,"w+"); //以"w+"方式打开文件,不存在则创建,存在则清空原来的数据
if(!fp)
{
printf("[row%d]open file failed!\n",__LINE__);
}
else
{
fclose(fp);
printf("*****Clear data successful!*****\n");
}
Pause();
}
}
/*
* load_data:读取文件内容填充到链表
* @head:链表头节点指针
* @pathname:文件路径
* return value:链表头节点指针
*/
Node* load_data(Node* head,const char* pathname)
{
free_list(head);
FILE* pf = fopen(pathname, "r");
if(!pf)
{
printf("******Can't open file %s *****\n ",PATHNAME);
Pause();
return head;
}
if(fgetc(pf) == EOF)//读取第一个字符,判断是否是文件结束标志EOF(end of file)
{
fclose(pf);
return head;
}
int flag = 0;
rewind (pf);//重置文件指针到开始位置
Node *new_node = NULL;
Flight new_flight;
do
{
flag = 0;
//每一读取一个字节,读取sizeof(Flight)次,fread返回实际读取到的字节数
if(fread(&new_flight,1,sizeof(Flight), pf) == sizeof(Flight))
{
flag = 1;
new_node = create_node(&new_flight);
if(new_node == NULL)
{
return NULL;
}
add_node(head,new_node);
}
}while(flag);
fclose(pf);
return head;
}
/*
* save_list:将链表的数据保存到文件中
* @head:链表头节点指针
* @pathname:文件路径
* return value:保存成功返回1,失败返回-1
*/
int save_list(Node* head,const char* pathname)
{
FILE* pf = fopen(PATHNAME, "w+");
if (!pf)
{
return -1;
}
Node* pos;
list_for_each_entry(pos,&head->flist,flist)
{
//每一写入一个字节,写sizeof(Flight)次,fwrite返回实际写入的字节数
if( fwrite(pos, 1, sizeof(Flight), pf) != sizeof(Flight))
{
fclose(pf);
return -1;
}
}
fclose(pf);
return 1;
}
list.c文件
/*******************************
**
** Author: Genven_Liang
**
** Date: 2018-08-03
**
** Description: 链表操作
**
**
*******************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <myhead.h>
/*
* free_list:释放链表内存空间,(头指针不释放)
* @head:链表头结点指针
*
*/
void free_list(Node* head)
{
if(head==NULL || head->flist.next == &(head->flist))
{
return ;
}
Node* np;
struct list* list = &(head->flist),*pos,*n;
list_for_each_safe(pos,n,list)
{
np = list_entry(pos,Node,flist);
list_del(pos);
free(np);
}
INIT_LIST_HEAD(&head->flist);
}
/*
* init_list:初始化链表
* return value:返回一个头结点指针
*/
Node* init_list()
{
Node* head = (Node*)malloc(sizeof(Node));
if(head == NULL)
{
printf("row[%d]:failed malloc!\n",__LINE__);
return NULL;
}
INIT_LIST_HEAD(&head->flist);
return head;
}
/*
* add_node:向链表添加节点
* @head:链表头结点指针
* @new_node:要插入的新节点指针
*/
void add_node(Node* head,Node* new_node)
{
if(head == NULL)
{
return;
}
list_add(&new_node->flist,&head->flist);
}
/*
* create_node:创建新的节点
* @flight:新的航班信息结构体指针
* return value:成功:返回指向新节点的指针,失败返回NULL;
*/
Node* create_node(Flight *flight)
{
Node* new_node = (Node*)malloc(sizeof(Node));
if(new_node==NULL)
{
printf("[row:%d]:malloc failed!\n",__LINE__);
Pause();
return NULL;
}
new_node->info = *flight;
INIT_LIST_HEAD(&new_node->flist);
return new_node;
}
/*
* create_flight:创建新的航班信息结构体,并初始化为0
* return value:成功:新的航班信息结构体指针,失败返回NULL;
*/
Flight* create_flight()
{
Flight *new_flight = (Flight*)malloc(sizeof(Flight));
if(new_flight==NULL)
{
printf("[row%d]:failed malloc!\n",__LINE__);
Pause();
return NULL;
}
memset(new_flight,0,sizeof(Flight));
return new_flight;
}
/*
* input_flight_info:为新节点录入信息并添加到链表
* @head:链表头结点指针
*/
void input_flight_info(Node* head)
{
char choice = 'n';
char tmp[10] = {0};
Flight new_flight;
while(1)
{
printf("Please input flight number:");
scanf("%9s",new_flight.number);
if(is_exist(head,new_flight.number))
{
printf("***** Number:%s is already exist!*****\n",new_flight.number);
}
else
{
printf("Please input flight start address:");
scanf("%9s",new_flight.staddr);
printf("Please input flight destination address:");
scanf("%9s",new_flight.destaddr);
printf("Please input flight date:");
scanf("%9s",new_flight.date);
printf("Please input flight time:");
scanf("%9s",new_flight.time);
printf("Please input flight type:");
while(getchar() != '\n');
scanf("%9s",tmp);
new_flight.type = *tmp;
printf("Please input flight price:");
scanf("%9s",new_flight.price);
Node* new_node = create_node(&new_flight);
if(new_node == NULL)
{
return;
}
add_node(head,new_node);
}
printf("*****Continue input?[y/n] :");
while(getchar() != '\n');
choice = getchar();
if(choice != 'Y' && choice != 'y')
{
break;
}
}
int save_ret = 0;
printf("*****Save to file?[y/n]:");
while(getchar() != '\n');
choice = getchar();
if(choice == 'Y' || choice == 'y')
{
save_ret = save_list(head,PATHNAME);
if(save_ret == 1)
{
printf("*****Save successful!*****\n");
}
else
{
printf("*****Save failed!*****\n");
}
Pause();
}
}
modify.c文件
/*******************************
**
** Author: Genven_Liang
**
** Date: 2018-08-03
**
** Description: 修改指定航班信息
**
**
*******************************/
#include <stdio.h>
#include <string.h>
#include <myhead.h>
/*
* modify_flight:修改航班信息
* @head:链表头结点指针
*/
void modify_flight(Node* head)
{
char number[10] = {0};
int mdf_ret = 0;
printf("Please enter the modify number:");
scanf("%9s",number);
while(getchar() != '\n');
head = load_data(head,PATHNAME);
mdf_ret = modify_flight_by_number(head,number);
if(mdf_ret == 1)
{
printf("********Modify sucessful!*********\n");
}
else if(mdf_ret == 0)
{
printf("**********Sorry! Not Find number:[%s] flight ******\n",number);
}
else if(mdf_ret == -1)
{
printf("********Modify error!*********\n");
}
Pause();
}
/*
* modify_flight_by_number:根据航班编号修改航班信息
* @head:链表头结点指针
* @number:航班编号
* return value:成功返回1,不存在该航班信息返回0,异常返回-1
*/
int modify_flight_by_number(Node* head,char number[])
{
char is_has = 'n';
char choice = 'n';
if(head == NULL)
{
return -1;
}
Node* pos;
list_for_each_entry(pos,&head->flist,flist)
{
if(is_equal(&pos->info,number,1,0) == 0)
{
is_has = 'y';
break;
}
}
if(is_has == 'y')
{
Flight flt;
printf("-------The number [%s] flight has been found!------\n",number);
printf(TITLE);
Print_Format_Flight(&pos->info);
printf("---------------------------------------------------\n");
printf(" *****enter '0' to unchange *****\n");
printf("===Modify start address:[%s] to:",pos->info.staddr);
scanf("%9s",flt.staddr);
if(strcmp(flt.staddr,"0") == 0)
{
strcpy(flt.staddr,pos->info.staddr);
}
getchar();
printf("===Modify destnation address:[%s] to:",pos->info.destaddr);
scanf("%9s",flt.destaddr);
if(strcmp(flt.destaddr,"0") == 0)
{
strcpy(flt.destaddr,pos->info.destaddr);
}
getchar();
printf("===Modify start date:[%s] to:",pos->info.date);
scanf("%9s",flt.date);
if(strcmp(flt.date,"0") == 0)
{
strcpy(flt.date,pos->info.date);
}
getchar();
printf("===Modify time:[%s] to:",pos->info.time);
scanf("%9s",flt.time);
if(strcmp(flt.time,"0") == 0)
{
strcpy(flt.time,pos->info.time);
}
getchar();
printf("===Modify type:[%c] to:",pos->info.type);
scanf("%c",&flt.type);
if(flt.type == '0')
{
flt.type = pos->info.type;
}
getchar();
printf("===Modify ticket price:[%s] to:",pos->info.price);
scanf("%9s",flt.price);
if(strcmp(flt.price,"0")==0)
{
strcpy(flt.price,pos->info.price);
}
getchar();
printf("*******Confirm modify?[y/n]:");
choice = getchar();
if(choice == 'Y' || choice == 'y')
{
strcpy(flt.number,pos->info.number);
pos->info = flt;
if(save_list(head,PATHNAME) == 1)
{
return 1;
}
return -1;
}
}
return 0;
}
search.c文件
/*******************************
**
** Author: Genven_Liang
**
** Date: 2018-08-03
**
** Description: 查找航班信息
**
**
*******************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <myhead.h>
/*
* search_flight:查询指定航班信息
* @head:链表头结点指针
*/
void search_flight(Node* head)
{
char choice = '1';
while(1)
{
search_menu();
choice = getchar();
while(getchar() != '\n');
switch(choice)
{
case '1':call_search_list(head,1);
break;
case '2':call_search_list(head,2);
break;
case '3':call_search_list(head,3);
break;
case '0': return;
break;
default:
break;
}
}
}
/*
* call_search_list:接收要查找的目标字符串,并调用search_list();
* @ head:链表头结点指针
* @ type:指定查询的是航班信息的哪个字段,为1查询航班编号,为2查询目的地点,为3查询日期。
* Description:以'^'开头的是进行贪心查找,只要前面一致则匹配
*/
void call_search_list(Node* head,int type)
{
char target[10] = {0};
char* str_type[3] = {"number","destnation","date"};
int is_find = 0;
printf("\033c");
printf("******you can search more begin with '^' *********\n");
printf("Please enter the search %s:",str_type[type-1]);
scanf("%9s",target);
while(getchar() != '\n');
if(*target != '^')
{
Flight flt = search_list(head,target,type);
if(is_equal(&flt,target,type,0) == 0)
{
is_find = 1;
printf("-------The [%s] [%s] flight has been found!------\n",str_type[type-1],target);
printf(TITLE);
Print_Format_Flight(&flt);
printf("---------------------------------------------------\n");
Pause();
}
}
else
{
char targ[10] = {0};
strcpy(targ,target+1);
Node *tmp_head = search_list_more(head,targ,type);
if(tmp_head != NULL)
{
is_find = 1;
display_list(tmp_head);
free_list(tmp_head);
free(tmp_head);
}
}
if(is_find == 0)
{
printf("**********Sorry! Not Find %s:[%s] flight ******\n",str_type[type-1],target);
Pause();
}
}
/*
* search_list:根据指定类型在链表中全字匹配查找目标字符串
* @ head:链表头结点指针
* @ target:目标字符串
* @ type:指定查询的是航班信息的哪个字段,为1查询航班编号,为2查询目的地点,为3查询日期。
* return value:成功返回查找到的航班信息结构体,失败返回航班号、目的地、日期全部为空的航班信息结构体;
*/
Flight search_list(Node* head,char target[],int type)
{
Flight flt = {.number = "",.destaddr = "",.date = ""};
if(head == NULL|| head->flist.next == &head->flist)
{
return flt;
}
Node* pos;
list_for_each_entry(pos,&head->flist,flist)
{
if(is_equal(&pos->info,target,type,0) == 0)
{
return pos->info;
}
}
return flt;
}
/*
* search_list_more:根据指定类型在链表中贪心查找目标字符串
* @ head:链表头结点指针
* @ target:目标字符串
* @ type:指定查询的是航班信息的哪个字段,为1查询航班编号,为2查询目的地点,为3查询日期。
* return value:成功返回查找到的新的链表头结点指针(包含匹配的多个航班信息结构体信息),失败返回NULL;
*/
Node* search_list_more(Node* head,char target[],int type)
{
Node* tmp_head = init_list();
if(head == NULL)
{
return NULL;
}
Node* pos,*new_node = NULL;
list_for_each_entry(pos,&head->flist,flist)
{
if(is_equal(&pos->info,target,type,1) == 0)
{
new_node = (Node*)malloc(sizeof(Node));
if(new_node == NULL)
{
free_list(tmp_head);
free(tmp_head);
return NULL;
}
new_node->info = pos->info;
list_add(&new_node->flist,&tmp_head->flist);
}
}
return tmp_head;
}
sort.c文件
/*******************************
**
** Author: Genven_Liang
**
** Date: 2018-08-03
**
** Description: 对航班信息进行排序
**
**
*******************************/
#include <stdio.h>
#include <string.h>
#include <myhead.h>
/*
*sort_flight:对航班信息进行排序
* @ head:链表头结点指针
* return value:返回排序后的链表头结点指针
*/
Node* sort_flight(Node* head)
{
char choice = '1';
while(1)
{
sort_menu();
choice = getchar();
while(getchar() != '\n');
switch(choice)
{
case '1':sort_list(head,1);
break;
case '2':sort_list(head,2);
break;
case '3':sort_list(head,3);
break;
case '4':sort_list(head,4);
break;
case '0': return head;
break;
defaulti:
break;
}
}
return head;
}
/*
*sort_flight:对航班信息进行排序
* @ type:指定按照的是航班信息的哪个字段进行排序,为1按照航班编号,为2按照目的地点,为3按照日期。为4按照票价
*/
void sort_list(Node* head,int type)
{
load_data(head,PATHNAME);
if(head == NULL)
{
return;
}
Node* pos_i,*pos_j,*flg;
Flight tmp;
char target[10] = {0};
for(pos_i = list_entry((head->flist).next,Node,flist);&pos_i->flist != head->flist.prev;
pos_i = list_entry(pos_i->flist.next,Node,flist))
{
flg = pos_i;
for(pos_j = list_entry(pos_i->flist.next,Node,flist);&pos_j->flist != &head->flist;
pos_j = list_entry(pos_j->flist.next,Node,flist))
{
if(type == 1)
{
strcpy(target,pos_j->info.number);
}
else if(type == 2)
{
strcpy(target,pos_j->info.destaddr);
}
else if(type == 3)
{
strcpy(target,pos_j->info.date);
}
else if(type == 4)
{
strcpy(target,pos_j->info.price);
}
if(is_equal(&(flg->info),target,type,0)>0)
{
flg = pos_j;
}
}
if(flg!=pos_i)
{
tmp = pos_i->info;
pos_i->info = flg->info;
flg->info = tmp;
}
}
char* str_type[3] = {"number","destnation","date"};
printf("----------------------- Sort by %s -----------------------\n",str_type[type-1]);
display_list(head);
return;
}
Makefile文件
make:
gcc src/*.c -o main -I include
五、总结
1、还有很多细节没有处理,比如输入的合法性检测。。。
2、Makefile文件使用不规范。
3、工程结构、函数封装等。。。有待提高。。。
4、注:打包成动态库版本,运行程序前需要将库文件放到/usr/lib/路径下。