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;
}