通讯录的实现

  • 通讯录的实现逻辑

在这里插入图片描述

  • 结构体的实现
struct person{
	char name[NAME_LENGTH];
	char phone[PHONE_LENGTH];
	struct person *next;
	struct person *prev;
};

struct contacts{
	struct person *people;
	int count;
};
  • 支持层链表插入、删除的实现——用宏定义的方式
#define LIST_INSERT(item, list) do {						\
	(item)->prev = NULL;									\
	(item)->next = list;									\
	if ((list) != NULL) (list)->prev = item;				\
	(list) = item;											\
}while(0)

#define LIST_REMOVE(item, list) do {								\
	if ((item)->prev != NULL) (item)->prev->next = (item)->next;	\
	if ((item)->next != NULL) (item)->next->prev = (item)->prev;	\
	if (list == item) list = (item)->next;							\
	(item)->prev = (item)->next = NULL;								\
}while(0)
  • 接口层链表的操作
int person_insert(struct person **ppeople, struct person *ps){
	if (ps == NULL) return -1;
	LIST_INSERT(ps, *ppeople);
	return 0;
}

int person_delete(struct person **ppeople, struct person *ps){
	if (ps == NULL) return -1;
	LIST_REMOVE(ps, *ppeople);
	return 0;
}

struct person* person_search(struct person *people, const char *name){
	struct person *item = NULL;
	for (item = people; item != NULL; item = item->next){
		if (!strcmp(name, item->name))	// 字符串比较,相等返回零,小于返回负数,大于返回正数。
			break;
	}
	return item;
}

int person_traversal(struct person *people){
	struct person *item = NULL;
	for (item = people; item != NULL; item = item->next){
		INFO("name: %s, phone: %s\n", item->name, item->phone);
	}
	return 0;
}
  • 接口层文件的操作
    其中对保存文件的读取用到了有限状态机,这个和之前写过的一本小说英文单词个数的统计很像,链接如下:link.
    初始状态是0,由于保存通讯录的格式是:
    name: xxx, phone: 123456789
    所以当此时的字符是" “时状态变为1,开始读取字符,直到读取到”,"状态再转变为0。
//fopen : 打开一个文件 
//fclose :  关闭文件
//fprintf : 按照指定格式写文件
//fflush : 同步到磁盘中 
//feof : 是否读到结尾 
//fgets : 按行读文件

int save_file(struct person *people, const char *filename){
	FILE *fp = fopen(filename, "w");
	if (fp == NULL) return -1;

	struct person *item = NULL;
	for (item = people; item != NULL; item = item->next){
		// 保存到缓存中
		fprintf(fp, "name: %s, phone: %s\n", item->name, item->phone);	
		// 刷新,保存到磁盘上
		fflush(fp);	
	}
	fclose(fp);
}

int parser_token(char *buffer, int length, char *name, char *phone){
	if (buffer == NULL) return -1;
	// 有限状态机
	if (length < MIN_TOKEN_LENGTH) return -2;
	int i = 0, j = 0, status = 0;
	for (; buffer[i] != ','; i++){
		if (buffer[i] == ' '){
			status = 1;
		}else if (status == 1){
			name[j++] = buffer[i];
		}
	}

	j = 0, status = 0;
	i += 2;	// 跳过一个空格
	for (; i < length; i++){
		if (buffer[i] == ' '){
			status = 1;
		}else if (status == 1){
			phone[j++] = buffer[i];
		}
	}
	INFO("file token: %s --> %s\n", name, phone);
	return 0;
}

int load_file(struct person **ppeople, int *count, const char *filename){
	FILE *fp = fopen(filename, "r");
	if (fp == NULL) return -1;
	while (!feof(fp)){	// 如果不是结尾,返回0
		char buffer[BUFFER_LENGTH] = {0};
		fgets(buffer, BUFFER_LENGTH, fp);	// 按行读
		char name[NAME_LENGTH] = {0};
		char phone[PHONE_LENGTH] = {0};
		int length = strlen(buffer);
		if (0 !=parser_token(buffer, strlen(buffer), name, phone)){
			continue;
		}

		struct person *p = (struct person*)malloc(sizeof(struct person));
		if (p == NULL) return -2;
		//memcpy(目的, 源, 字节数)	内存拷贝函数
		memcpy(p->name, name, NAME_LENGTH);
		memcpy(p->phone, phone, PHONE_LENGTH);

		person_insert(ppeople, p);
		(*count)++;
	}
	fclose(fp);
	return 0;
}
  • 业务层
    实现插入、删除、遍历、查找、保存、读取几个功能,外加菜单显示。
int insert_entry(struct contacts *cts){

	if (cts == NULL) return -1;
	
	struct person *p = (struct person*)malloc(sizeof(struct person));
	if (p == NULL) return -2;
	
	//name
	INFO("Please Input Name: \n");
	scanf("%s", p->name);	//scanf 长度大于16会溢出 
	

	//phone
	INFO("Please Input Phone: \n");
	scanf("%s", p->phone);

	//add person
	if (0 != person_insert(&cts->people, p)){
		free(p);
		return -3;
	}
	cts->count++;
	INFO("Insert Success\n");
	return 0;


}

int print_entry(struct contacts *cts){

	if (cts == NULL) return -1;

	//cts->people
	person_traversal(cts->people);


}

int delete_entry(struct contacts *cts){
	if (cts == NULL) return -1;

	// name

	INFO("Please Input Name: \n");
	char name[NAME_LENGTH] = {0};
	scanf("%s", name);

	//person
	struct person *ps = person_search(cts->people, name);
	if (ps == NULL){
		INFO("Person don't Exit\n");
		return -2;
	}

	//delete
	person_delete(&cts->people, ps);
	free(ps);
	
	return 0;
}

int search_entry(struct contacts *cts){
	if (cts == NULL) return -1;
	//name
	INFO("Please Input Name: \n");
	char name[NAME_LENGTH] = {0};
	scanf("%s", name);
	//person
	struct person *ps = person_search(cts->people, name);
	if (ps == NULL){
		INFO("Person don't Exit\n");
		return -2;
	}
	//search
	INFO("name: %s, phone: %s\n", ps->name, ps->phone);
	return 0;
}

int save_entry(struct contacts *cts){
	if (cts == NULL) return -1;
	INFO("Please Input Save Filename : \n");
	char filename[NAME_LENGTH] = {0};
	scanf("%s", filename);
	save_file(cts->people, filename);
}

int load_entry(struct contacts *cts){
	if (cts == NULL) return -1;
	INFO("Please Input Load Filename : \n");
	char filename[NAME_LENGTH] = {0};
	scanf("%s", filename);
	load_file(&cts->people, &cts->count, filename);
}

void menu_info(void){
	INFO("\n\n*******************************************************\n");
	INFO("*******1.Add Person\t\t2.Print People*********\n");
	INFO("*******3.Del Person\t\t4.Search Person********\n");
	INFO("*******5.Save Peeople\t\t6.Load People**********\n");
	INFO("*******Other Key for Exiting Program*******************\n");
	INFO("*******************************************************\n\n");
}
  • 整体代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define NAME_LENGTH			16
#define PHONE_LENGTH		32
#define BUFFER_LENGTH		128
#define MIN_TOKEN_LENGTH	5

#define INFO			printf

#define LIST_INSERT(item, list) do {						\
	(item)->prev = NULL;									\
	(item)->next = list;									\
	if ((list) != NULL) (list)->prev = item;				\
	(list) = item;											\
}while(0)

#define LIST_REMOVE(item, list) do {								\
	if ((item)->prev != NULL) (item)->prev->next = (item)->next;	\
	if ((item)->next != NULL) (item)->next->prev = (item)->prev;	\
	if (list == item) list = (item)->next;							\
	(item)->prev = (item)->next = NULL;								\
}while(0)

struct person{

	char name[NAME_LENGTH];
	char phone[PHONE_LENGTH];

	struct person *next;
	struct person *prev;

};

struct contacts{

	struct person *people;
	int count;

};

enum {
	OPEN_INSERT = 1,
	OPEN_PRINT,
	OPEN_DELETE,
	OPEN_SEARCH,
	OPEN_SAVE,
	OPEN_LOAD
};


// 接口层,以下四个函数
int person_insert(struct person **ppeople, struct person *ps){
	if (ps == NULL) return -1;
	LIST_INSERT(ps, *ppeople);
	return 0;
}

int person_delete(struct person **ppeople, struct person *ps){
	if (ps == NULL) return -1;
	LIST_REMOVE(ps, *ppeople);
	return 0;
}

struct person* person_search(struct person *people, const char *name){
	struct person *item = NULL;
	for (item = people; item != NULL; item = item->next){
		if (!strcmp(name, item->name))	// 字符串比较,相等返回零,小于返回负数,大于返回正数。
			break;
	}
	return item;
}

int person_traversal(struct person *people){
	struct person *item = NULL;
	for (item = people; item != NULL; item = item->next){
 
		INFO("name: %s, phone: %s\n", item->name, item->phone);

	}
	return 0;
	
}

//fopen : 打开一个文件 
//fclose :  关闭文件
//fprintf : 按照指定格式写文件
//fflush : 同步到磁盘中 
//feof : 是否读到结尾 
//fgets : 按行读文件

int save_file(struct person *people, const char *filename){
	FILE *fp = fopen(filename, "w");
	if (fp == NULL) return -1;

	struct person *item = NULL;
	for (item = people; item != NULL; item = item->next){
		// 保存到缓存中
		fprintf(fp, "name: %s, phone: %s\n", item->name, item->phone);	
		// 刷新,保存到磁盘上
		fflush(fp);	
	}
	fclose(fp);
}

int parser_token(char *buffer, int length, char *name, char *phone){
	if (buffer == NULL) return -1;
	// 有限状态机
	if (length < MIN_TOKEN_LENGTH) return -2;
	int i = 0, j = 0, status = 0;
	for (; buffer[i] != ','; i++){
		if (buffer[i] == ' '){
			status = 1;
		}else if (status == 1){
			name[j++] = buffer[i];
		}
	}

	j = 0, status = 0;
	i += 2;
	for (; i < length; i++){
		if (buffer[i] == ' '){
			status = 1;
		}else if (status == 1){
			phone[j++] = buffer[i];
		}
	}

	INFO("file token: %s --> %s\n", name, phone);
	return 0;
	
}

int load_file(struct person **ppeople, int *count, const char *filename){
	FILE *fp = fopen(filename, "r");
	if (fp == NULL) return -1;
	while (!feof(fp)){	// 如果不是结尾,返回0
		char buffer[BUFFER_LENGTH] = {0};
		fgets(buffer, BUFFER_LENGTH, fp);	// 按行读
		char name[NAME_LENGTH] = {0};
		char phone[PHONE_LENGTH] = {0};
		int length = strlen(buffer);
		if (0 !=parser_token(buffer, strlen(buffer), name, phone)){
			continue;
		}

		struct person *p = (struct person*)malloc(sizeof(struct person));
		if (p == NULL) return -2;
		//memcpy(目的, 源, 字节数)	内存拷贝函数
		memcpy(p->name, name, NAME_LENGTH);
		memcpy(p->phone, phone, PHONE_LENGTH);

		person_insert(ppeople, p);
		(*count)++;
	}
	fclose(fp);
	return 0;
}



int insert_entry(struct contacts *cts){

	if (cts == NULL) return -1;
	
	struct person *p = (struct person*)malloc(sizeof(struct person));
	if (p == NULL) return -2;
	
	//name
	INFO("Please Input Name: \n");
	scanf("%s", p->name);	//scanf 长度大于16会溢出 
	

	//phone
	INFO("Please Input Phone: \n");
	scanf("%s", p->phone);

	//add person
	if (0 != person_insert(&cts->people, p)){
		free(p);
		return -3;
	}
	cts->count++;
	INFO("Insert Success\n");
	return 0;


}

int print_entry(struct contacts *cts){

	if (cts == NULL) return -1;

	//cts->people
	person_traversal(cts->people);


}

int delete_entry(struct contacts *cts){
	if (cts == NULL) return -1;

	// name

	INFO("Please Input Name: \n");
	char name[NAME_LENGTH] = {0};
	scanf("%s", name);

	//person
	struct person *ps = person_search(cts->people, name);
	if (ps == NULL){
		INFO("Person don't Exit\n");
		return -2;
	}

	//delete
	person_delete(&cts->people, ps);
	free(ps);
	
	return 0;
}

int search_entry(struct contacts *cts){

	if (cts == NULL) return -1;

	//name

	INFO("Please Input Name: \n");
	char name[NAME_LENGTH] = {0};
	scanf("%s", name);

	//person

	struct person *ps = person_search(cts->people, name);
	if (ps == NULL){
		INFO("Person don't Exit\n");
		return -2;
	}

	//search

	INFO("name: %s, phone: %s\n", ps->name, ps->phone);

	return 0;
}

int save_entry(struct contacts *cts){
	if (cts == NULL) return -1;
	INFO("Please Input Save Filename : \n");
	char filename[NAME_LENGTH] = {0};
	scanf("%s", filename);
	save_file(cts->people, filename);
}

int load_entry(struct contacts *cts){

	if (cts == NULL) return -1;
	INFO("Please Input Load Filename : \n");
	char filename[NAME_LENGTH] = {0};
	scanf("%s", filename);
	load_file(&cts->people, &cts->count, filename);

}

void menu_info(void){

	INFO("\n\n*******************************************************\n");
	INFO("*******1.Add Person\t\t2.Print People*********\n");
	INFO("*******3.Del Person\t\t4.Search Person********\n");
	INFO("*******5.Save Peeople\t\t6.Load People**********\n");
	INFO("*******Other Key for Exiting Program*******************\n");
	INFO("*******************************************************\n\n");

}

int main(){

	struct contacts *cts = (struct contacts *)malloc(sizeof(struct contacts));

	if (cts == NULL) return -1;

	memset(cts, 0, sizeof(struct contacts));

	while(1){

		menu_info();

		int select = 0;
		scanf("%d", &select);
		switch (select){

			case OPEN_INSERT:
				insert_entry(cts);
				break;
				
			case OPEN_PRINT:
				print_entry(cts);
				break;
				
			case OPEN_DELETE:
				delete_entry(cts);
				break;
				
			case OPEN_SEARCH:
				search_entry(cts);
				break;
				
			case OPEN_SAVE:
				save_entry(cts);
				break;
				
			case OPEN_LOAD:
				load_entry(cts);
				break;
			default:
				goto exit;

		}
	}
exit:
	free(cts);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值