通讯录全部采用C语言实现,用链表实现增加、删除、修改、查找等功能,还有命令解析函数(将输入分解成主命令、姓名、电话),联系人信息是保存在文件中,每次程序运行和结束时都会读取文件中的信息。
节点里定义的都是指针,增加新节点时要开辟新的内存,删除节点时要记得及时释放内存,防止内存溢出。
头文件
:头文件中是宏定义和函数原型声明。
#ifndef _MAIN_H_
#define _MAIN_H_
#include
#include
#include
#include
typedef struct node{ //定义节点类型,采用的双向链表,删除和插入比较方便
char *name;
char *telephone;
struct node *next;
struct node *prior;
}NODE, *PNODE;
#define ADD 1
#define DELETE 2
#define FIND 3
#define LIST 4
#define MODIFY 5
#define QUIT 6
#define HELP 7
PNODE creat_head();//创建头结点
void display(const PNODE head);
void add(const PNODE head, char *name, char *telephone);//增加联系人
int analyse(char *buf, char *cmd, char *name, char *telephone);//解析指令
void delete(const PNODE head, char *name);//删除联系人
PNODE find(PNODE head, char *name);//查找联系人
void modify(PNODE head, char *name, char *telephone);//修改联系人
void help();//显示操作信息
int read_list(PNODE head);//程序运行时,将保存在文件中的联系人信息读取出来
void write_list(PNODE head);//程序结束时,将链表中的联系人写入文件中保存起来
#endif
main.c文件
:主要是程序的执行流程,代码简洁明了。
#include"main.h"
int main(){
char buf[40] = {0};
char cmd[20] = {0};
char name[20] = {0};
char telephone[20] = {0};
help();
PNODE head = creat_head();//创建头结点,不含有效信息
read_list(head); //将文件中保存的数据读取出来
int i;
while(1){
fgets(buf, sizeof(buf), stdin);
buf[strlen(buf) - 1] = 0; //fgets()函数会把换行符读入,将最后一个字符置为0
i = analyse(buf, cmd, name, telephone); //将输入的命令解析成指令、姓名、电话号码
//根据命令解析函数返回的值,调用不同的函数,实现不同的功能man
switch(i){
case ADD: add(head, name, telephone);
break;
case DELETE: delete(head, name);
break;
case FIND: find(head, name);
break;
case LIST: display(head);
break;
case MODIFY: modify(head, name, telephone);
break;
case QUIT: write_list(head); //将链表的数据写进文件中
exit(0);
break;
case HELP: help();
break;
}
}
return 0;
}
list.c文件
:此文件中是各函数的定义。
#include"main.h"
PNODE creat_head(){//创建头结点
PNODE head = (PNODE)malloc(sizeof(NODE));
head->name = (char *)malloc(6);
head->telephone = (char *)malloc(6);
head->name = "head";
head->telephone = "-111";
head->next = head;
head->prior = head;
return head;
}
void display(const PNODE head){//打印通讯录
PNODE pnew = head->next;
while(pnew != head){
printf("%s:%s\n", pnew->name, pnew->telephone);
pnew = pnew->next;
}
}
void add(const PNODE head, char *name, char *telephone){//增加联系人
//开辟一个新节点并赋值
PNODE pnode = (PNODE)malloc(sizeof(NODE));
pnode->name = (char *)malloc(strlen(name));
pnode->telephone = (char *)malloc(strlen(telephone));
strcpy(pnode->name, name);
strcpy(pnode->telephone, telephone);
//插入新节点
pnode->next = head->next;
head->next->prior = pnode;
head->next = pnode;
pnode->prior = head;
}
int analyse(char *buf, char *cmd, char *name, char *telephone){//解析指令,将输入的指令分割
char *p;
char *q;
//解析输入信息为命令、姓名、电话号码。strchr(char *a, char b),
//返回字符串a中第一个字符b的地址,没有就返回NULL。
if((p = strchr(buf, ' ')) != NULL){
*p = 0;
strcpy(cmd, buf);
if((q = strchr(p+1, ' ')) != NULL){
*q = 0;
strcpy(name, p+1);
strcpy(telephone, q+1);
}
else {
strcpy(name, p+1);
}
}
else{
strcpy(cmd, buf);
}
//判断此次输入的是哪条指令,并返回相应的值
if(strcmp(cmd, "add") == 0){
return ADD;
}
else if(strcmp(cmd, "delete") == 0){
return DELETE;
}
else if(strcmp(cmd, "find") == 0){
return FIND;
}
else if(strcmp(cmd, "list") == 0){
return LIST;
}
else if(strcmp(cmd, "modify") == 0){
return 5;
}
else if(strcmp(cmd, "quit") == 0){
return QUIT;
}
else if(strcmp(cmd, "help") == 0){
return HELP;
}
else{
return -99;
}
}
void delete(const PNODE head, char *name){//删除指定联系人
PNODE pnode = find(head, name);
if(pnode != NULL){
pnode->next->prior = pnode->prior;
pnode->prior->next = pnode->next;
//注意要free三次,因为这都是自己开辟的内存,要及时释放
free(pnode->name);
free(pnode->telephone);
free(pnode);
printf("Delete Success\n");
}
}
PNODE find(PNODE head, char *name){//查找联系人
PNODE pnode = head->next;
while((strcmp(pnode->name, name) != 0) && (pnode != head)){
pnode = pnode->next;
}
if(strcmp(pnode->name, name) == 0){//名字匹配成功则返回地址,失败则返回NULL
printf("find success:%s %s\n", pnode->name, pnode->telephone);
return pnode;
}
else{
printf("No Person\n");
return NULL;
}
}
void modify(PNODE head, char *name, char *telephone){//修改联系人
PNODE pnode = find(head, name);
if(pnode != NULL){
strcpy(pnode->telephone, telephone);
printf("modify success:%s %s\n",pnode->name, pnode->telephone);
}
}
void help(){//显示操作命令的详细信息
printf("\n\n");
printf("|********************************************************|\n");
printf("|* Address Book *|\n");
printf("|* Instruction Format: command name telephone *|\n");
printf("|* 1.add a contact: add name telephone *|\n");
printf("|* 2.delete a contact: delete name *|\n");
printf("|* 3.modify a contact: modify name new_telephone *|\n");
printf("|* 4.find a contact: find name *|\n");
printf("|* 5.show all contact: list *|\n");
printf("|* 6.sign out: quit *|\n");
printf("|********************************************************|\n");
printf("\n\n");
}
void write_list(PNODE head){ //退出前将链表的数据写入文件中保存起来
PNODE pnew = head->next;
FILE *fp = fopen("address.txt", "w");
while(pnew != head){
fputs(pnew->name, fp);
fputs(" ", fp);
fputs(pnew->telephone, fp);
fputs("\n", fp);
pnew = pnew->next;
}
fclose(fp);
}
int read_list(PNODE head){ //每次启动通讯录时,将文件中的联系人信息加载进来
char buf[40];
char *p;
FILE *fp = fopen("address.txt", "r");
//如果当前没有address.txt文件,就返回
if(fp == NULL){
return 0;
}
//一次读取一行,即一个联系人的信息
while(fgets(buf, sizeof(buf),fp) != NULL){
buf[strlen(buf) - 1] = 0; //将读出除的换行符去掉
//将读取的一行数据,分割成姓名和电话号码
if((p = strchr(buf, ' ')) == NULL){
printf("read address fail\n");
return 0;
}
*p = 0;
add(head, buf, p+1);
}
}