Linux-C 航班信息管理程序练习

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/路径下。

猜你喜欢

转载自blog.csdn.net/nanfeibuyi/article/details/81070533