退出程序时将链表中的数据存入文件,首位存联系人个数,后面依次存联系人信息。
打开程序时取出文件中数据,根据首位存放的个数,来决定插入链表的节点数。
头文件Txl.h
#ifndef _LINK_LIST_H_
#define _LINK_LIST_H_
enum {CANCEL, ID, NAME, TEL, ADDRESS};
typedef enum {TRUE, FALSE, ERROR} BOOL;
enum {QUIT, ADD, DISPLAY, DELETE, SEARCH, CHANGE, SORT};
typedef struct _Data
{
int id; //联系人id
char name[20]; //联系人姓名
long tel; //联系人手机号
char address[20]; //联系人地址
}Data;
typedef struct _Student
{
Data data; //数据域
struct _Student *next; //指针域,指向链表的下一个结点
}Student;
typedef struct _List
{
Student *head; //头结点
}List;
//创建通讯录
List *Creat_List();
//增加联系人
BOOL add_data(List *ls);
//查找联系人
BOOL search_data(List *ls);
//删除联系人
BOOL delete_data(List *ls);
//修改联系人
BOOL modify_data(List *ls);
//打印通讯录
void Display_List(List *ls);
//保存通讯录到文件
BOOL Save_List(List *ls);
//读取通讯录到程序
BOOL LOAD_List(List *ls);
//销毁通讯录
void Destroy_List(List *ls);
#endif //_LINK_LIST_H_
函数文件Txl.c
#include "Txl.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int Student_Count = 0;
//创建通讯录
List *Creat_List()
{
List *ls = (List *)malloc(sizeof(List)/sizeof(char));
if(NULL == ls) //创建链表失败,返回NULL
return NULL;
ls->head = (Student *)malloc(sizeof(Student)/sizeof(char));
if(NULL == ls->head)
{
free(ls); //创建头节点失败,先释放链表空间,再返回NULL
return NULL;
}
ls->head->next = NULL; //创建时第一个节点为空
return ls;
}
//输出单个联系人信息到屏幕
void print_Student(Student *student)
{
if(student == NULL)
return;
printf("%-8d",student->data.id);
printf("%-16s",student->data.name);
printf("%-16ld",student->data.tel);
printf("%s\n",student->data.address);
}
//输出单个联系人到文件
void fprint_Student(Student *student, int fd)
{
if(student == NULL)
return;
int ret = write(fd, &(student->data.id), sizeof(student->data.id));
if(-1 == ret)
{
printf("id写入失败: %d\n", student->data.id);
return;
}
ret = write(fd, student->data.name, sizeof(student->data.name));
if(-1 == ret)
{
printf("姓名写入失败: %s\n", student->data.name);
return;
}
ret = write(fd, &(student->data.tel), sizeof(student->data.tel));
if(-1 == ret)
{
printf("手机号写入失败: %ld\n", student->data.tel);
return;
}
ret = write(fd, student->data.address, sizeof(student->data.address));
if(-1 == ret)
{
printf("住址写入失败: %s\n", student->data.address);
return;
}
}
//尾插
BOOL Insert_Last(List *ls, Data *data)
{
if(NULL == ls)
{
return ERROR;
}
Student *stu = (Student *)malloc(sizeof(Student)/sizeof(char));
if(NULL == stu)
{
return ERROR;
}
stu->data = *data;
stu->next = NULL;
Student *tmp = ls->head;
while(tmp->next)
{
tmp = tmp->next;
}
tmp->next = stu;
return TRUE;
}
//增加联系人
BOOL add_data(List *ls)
{
if(NULL == ls)
return ERROR;
Data data;
system("clear");
printf("输入新联系人ID:");
scanf("%d",&data.id);
printf("输入新联系人姓名:");
scanf("%s",data.name);
printf("输入新联系人手机号:");
scanf("%ld",&data.tel);
printf("输入新联系人地址:");
scanf("%s",data.address);
Insert_Last(ls, &data);
Student_Count++;
return TRUE;
}
//显示所有联系人
BOOL display_data(List *ls)
{
if(NULL == ls) //链表不存在,返回ERROR
return ERROR;
if(ls->head->next == NULL)
{
return FALSE; //链表为空,返回FALSE,通讯录无联系人
}
Student *tmp = ls->head->next;
system("clear");
printf("---------------------------------------------------\n");
printf("id\t");
printf("name\t\t");
printf("tel\t\t");
printf("address\n");
while(tmp != NULL)
{
print_Student(tmp); //遍历联系人列表,同时打印已有联系人信息
tmp = tmp->next;
}
printf("---------------------------------------------------\n");
return TRUE;
}
//删除联系人
BOOL delete_data(List *ls)
{
if(NULL == ls)
return ERROR;
char delete[20]; //删除联系人姓名
BOOL flag = ERROR; //标记删除的状态,TRUE删除成功,FALSE删除失败,ERROR要删除的联系人不存在
system("clear");
printf("请输入删除的联系人姓名:");
scanf("%s", delete); //输入要删除的联系人姓名
Student *tmp = ls->head;
while(tmp->next != NULL) //遍历链表,直到匹配到要删的联系人姓名
{
if(strcmp(tmp->next->data.name, delete) == 0) //匹配成功
{
printf("---------------------------------------------------\n");
printf("id\t");
printf("name\t\t");
printf("tel\t\t");
printf("address\n");
print_Student(tmp->next); //打印匹配到的联系人的所有信息
printf("---------------------------------------------------\n");
char c = 0;
printf("确认删除该联系人yes(y)/no(n)\n");
while(c != 'y' && c!= 'n') //对删除操作进行确认,y确认和n取消,输入其他时要重新输入
{
scanf("\n%c", &c);
if(c == 'y')
{
Student *p = tmp->next; //删除联系人
tmp->next = p->next;
free(p); //释放删除联系人节点的空间
Student_Count--;
flag = TRUE; //flag标记删除成功
}
else if(c == 'n')
{
//如果之前已经删除过其他,不改变flag,依然标记删除成功
if(flag != TRUE)
{
flag = FALSE; //flag标记删除失败
}
}
else
{
printf("输入有误,请重新输入\n");
}
}
if(c == 'y')
{
//如果选择删除,tmp已经移动到了删除的人后一位,用continue跳过tmp = tmp->next这一步
continue;
}
}
tmp = tmp->next;
}
return flag; //返回flag
}
//修改联系人
BOOL modify_data(List *ls)
{
if(NULL == ls)
return ERROR;
char modify_name[20]; //要修改的联系人的姓名
int modify; //要修改的选项
BOOL flag = ERROR; //TRUE修改成功,FALSE修改失败,ERROR要修改的联系人不存在
system("clear");
printf("请输入要修改的联系人的姓名:");
scanf("%s", modify_name); //输入要修改联系人的姓名
Student *tmp = ls->head->next;
while(tmp != NULL) //遍历链表,直到匹配到要修改的联系人姓名
{
if(strcmp(tmp->data.name, modify_name) == 0) //匹配成功
{
//输出当前匹配到的联系人的所有信息
printf("---------------------------------------------------\n");
printf("id\t");
printf("name\t\t");
printf("tel\t\t");
printf("address\n");
print_Student(tmp);
printf("---------------------------------------------------\n");
printf("1.ID\n");
printf("2.姓名\n");
printf("3.手机号\n");
printf("4.家庭地址\n");
printf("0.放弃修改\n");
printf("请输入要修改的选项:");
scanf("%d", &modify); //输入要修改的选项
switch(modify)
{
case ID:
printf("将id修改为:\n");
scanf("%d", &(tmp->data.id));
flag = TRUE;
break;
case NAME:
printf("将姓名修改为:\n");
scanf("%s", tmp->data.name);
flag = TRUE;
break;
case TEL:
printf("将手机号修改为:\n");
scanf("%ld", &(tmp->data.tel));
flag = TRUE;
break;
case ADDRESS:
printf("将家庭地址修改为:\n");
scanf("%s", tmp->data.address);
flag = TRUE;
break;
case CANCEL:
system("clear");
if(flag != TRUE)
flag = FALSE; //取消修改时flag=FALSE,表示修改失败
break;
default:
printf("输入有误,请重新输入\n");
break;
}
}
tmp = tmp->next;
}
return flag;
}
//查找联系人
BOOL search_data(List *ls)
{
if(NULL == ls)
return ERROR;
char search[20] = {0}; //查找的联系人姓名
BOOL flag = FALSE; //标记是否找到,TRUE为找到,FALSE为没找到
system("clear");
printf("请输入查找的联系人姓名:");
scanf("%s", search);
Student *tmp = ls->head->next;
while(tmp != NULL)
{
if(strcmp(tmp->data.name, search) == 0) //匹配到要查找的联系人姓名
{
if(flag != TRUE) //找到第一个时打印输出格式
{
printf("---------------------------------------------------\n");
printf("id\t");
printf("name\t\t");
printf("tel\t\t");
printf("address\n");
flag = TRUE; //flag标记为已找到
}
print_Student(tmp); //打印找到的联系人信息
}
tmp = tmp->next; //tmp指向下一个节点
}
return flag;
}
//保存通讯录
BOOL Save_List(List *ls)
{
int fd = open("document", O_WRONLY | O_TRUNC | O_CREAT, 0766);
if(-1 == fd)
{
return FALSE;
}
if(NULL == ls)
{
return ERROR;
}
int ret = write(fd, &Student_Count, sizeof(int));
Student *tmp = ls->head->next;
int i;
for(i = 0; i < Student_Count; i++)
{
fprint_Student(tmp, fd); //遍历联系人列表,同时打印已有联系人信息
tmp = tmp->next;
}
close(fd);
return TRUE;
}
//读取通讯录到程序
BOOL Load_List(List *ls)
{
int fd = open ("document", O_RDONLY);
if(-1 == fd)
{
return FALSE;
}
int ret = read(fd, &Student_Count, sizeof(int));
if(-1 == ret)
{
return FALSE;
}
int i;
Data data;
for(i = 0; i < Student_Count; i++)
{
ret = read(fd, &(data.id), sizeof(data.id));
if(-1 == ret)
{
printf("id读取失败: %d\n", data.id);
return;
}
ret = read(fd, data.name, sizeof(data.name));
if(-1 == ret)
{
printf("姓名读取失败: %s\n", data.name);
return;
}
ret = read(fd, &(data.tel), sizeof(data.tel));
if(-1 == ret)
{
printf("手机号读取失败: %ld\n", data.tel);
return;
}
ret = read(fd, data.address, sizeof(data.address));
if(-1 == ret)
{
printf("住址读取失败: %s\n", data.address);
return;
}
Insert_Last(ls, &data);
}
return TRUE;
}
//销毁通讯录
void Destroy_List(List *ls)
{
if(NULL == ls)
return ;
Student *tmp = ls->head;
while(tmp->next) //释放链表中各个节点的空间
{
Student *p = tmp->next;
tmp->next = p->next;
free(p);
}
free(ls->head);
free(ls);
}
菜单函数menu.c
#include "Txl.h"
#include <stdio.h>
#include <stdlib.h>
//菜单
void menu(List *ls)
{
int com = 0;
BOOL search_flag;
BOOL delete_flag;
BOOL modify_flag;
while(1)
{
printf("\t**************\n");
printf("\t*1.增加联系人*\n");
printf("\t*2.显示联系人*\n");
printf("\t*3.删除联系人*\n");
printf("\t*4.查找联系人*\n");
printf("\t*5.修改联系人*\n");
printf("\t*0.保存并退出*\n");
printf("\t**************\n");
scanf("%d",&com);
switch(com)
{
case ADD:
{
if(add_data(ls) == TRUE)
{
printf("添加成功!\n");
}
else
{
printf("添加失败!\n");
}
break;
}
case DISPLAY:
{
if(display_data(ls) != TRUE)
{
system("clear");
printf("通讯录目前无联系人\n");;
}
break;
}
case DELETE:
{
delete_flag = delete_data(ls);
if(delete_flag == TRUE)
{
printf("删除成功\n");
}
else if(delete_flag == FALSE)
{
printf("删除失败\n");
}
else if(delete_flag == ERROR)
{
printf("要删除的联系人不存在\n");
}
break;
}
case SEARCH:
{
search_flag = search_data(ls);
if(search_flag == TRUE)
{
printf("---------------------------------------------------\n");
}
if(search_flag != TRUE)
{
printf("未查找到该联系人\n");
}
break;
}
case CHANGE:
{
modify_flag = modify_data(ls);
if(modify_flag == TRUE)
{
printf("修改成功\n");
}
else if(modify_flag == FALSE)
{
printf("修改失败\n");
}
else if(modify_flag == ERROR)
{
printf("要修改的联系人不存在\n");
}
break;
}
case QUIT:
Save_List(ls);
printf("谢谢使用!\n");
return ;
default:
printf("请输入正确的选项\n");
break;
}
}
}
main函数
#include <stdio.h>
#include "Txl.h"
int main()
{
List *ls = Creat_List();
system("clear");
if(NULL == ls)
{
printf("创建通讯录失败\n");
}
else
{
printf("创建通讯录成功\n");
}
Load_List(ls);
menu(ls);
Destroy_List(ls);
return 0;
}