层次结构:底层(双向链表)-->接口层-->业务逻辑层(1添加联系人,2打印联系人,3删除联系人,4查找联系人,5保存到文件,6从文件中加载联系人);
#include<stdio.h> #include<stdlib.h> #include<string.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(item==list) list=item->next; \ item->prev=item->next=NULL; \ } while(0) //end //联系人结构体 struct person{ char name[NAME_LENGTH]; char phone[PHONE_LENGTH]; //双向链表 struct person *next; struct person *prev; }; //通讯录结构体 struct contacts{ struct person *people; int count; }; //菜单枚举 enum{ OPER_INSERT=1, OPER_PRINT,//2 OPER_DELETE,//3 OPER_SEARCH,//4 OPER_SAVE,//5 OPER_LOAD//5 }; //interface 接口层 //插入联系人 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(item->name,name))//item->name和name相等返回0 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; } //保存到文件 int save_file(struct person *people,const char *filename){ FILE *fp=fopen(filename,"w");//只读 if(fp==NULL)return -1;//判断是否打开成功 struct person *item=NULL;//注意:将循环变量定义在外面,避免在Linux环境下编译报错 for(item=people;item!=NULL;item=item->next){ fprintf(fp,"name: %s,phone: %s\n",item->name,item->phone);//写到缓存中 fflush(fp);//从缓存刷新到文件中 } fclose(fp);//关闭文件 return 0; } //解析文件,提取姓名,电话 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,state=0; for(i=0;buffer[i]!=',';i++){ if(buffer[i]==' ')state=1; else if(state==1){ name[j++]=buffer[i]; } } state=0,j=0; for(;i<length;i++){ if(buffer[i]==' ')state=1; else if(state==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)){ char buffer[BUFFER_LENGTH]={0}; fgets(buffer,BUFFER_LENGTH,fp); int length=strlen(buffer); INFO("length:%d\n",length); char name[NAME_LENGTH]={0}; char phone[PHONE_LENGTH]={0}; if(0!=parser_token(buffer,length,name,phone)){ continue; } struct person *p=(struct person*)malloc(sizeof(struct person)); if(p==NULL)return -2; memcpy(p->name,name,NAME_LENGTH); memcpy(p->phone,phone,PHONE_LENGTH); person_insert(ppeople,p); (*count)++; } fclose(fp); return 0; } //end //业务逻辑层 //添加联系人 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); //phone INFO("Please Input phone: \n"); scanf("%s",p->phone); //add people if(0!= person_insert(&cts->people,p)){ free(p); return -3; } cts->count ++; INFO("Insert success\n"); return 0; } //打印联系人 int traversal_entry(struct contacts*cts){ if(cts==NULL) return -1; person_traversal(cts->people); return 0; } //删除联系人 int delete_entry(struct contacts*cts){ if(cts==NULL) return -1; //name char name[NAME_LENGTH]={0}; INFO("Please Input name: \n"); scanf("%s",name); //person struct person *ps=person_search(cts->people,name); if(ps==NULL) { INFO("%s don't Exit",name); return -2; } //delete person_delete(&cts->people,ps); return 0; } //查找联系人 int search_entry(struct contacts*cts){ if(cts==NULL) return -1; //name char name[NAME_LENGTH]={0}; INFO("Please Input name: \n"); scanf("%s",name); //person struct person *ps=person_search(cts->people,name); if(ps==NULL) { INFO("%s don't Exit \n",name); return -2; } 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 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 filename:\n"); char filename[NAME_LENGTH]={0}; scanf("%s",filename); load_file(&cts->people, &cts->count, filename); } //end //菜单界面 int menu_info(void){ INFO("\n\n***************************************************\n"); INFO("*****1.Add Person\t2.Print People*************\n"); INFO("*****3.Del Person\t4.Search Person************\n"); INFO("*****5.Save People\t6.Load People**************\n"); INFO("*****Other Key for Exiting Program*****************\n"); INFO("***************************************************\n\n"); return 0; } //主函数 int main(){ struct contacts *cts=(struct contacts*)malloc(sizeof(struct contacts)); memset(cts,0,sizeof(struct contacts)); while(1){ menu_info(); int select=0; scanf("%d",&select); switch(select){ case OPER_INSERT: insert_entry(cts); break; case OPER_PRINT: traversal_entry(cts); break; case OPER_DELETE: delete_entry(cts); break; case OPER_SEARCH: search_entry(cts); break; case OPER_SAVE: save_entry(cts); break; case OPER_LOAD: load_entry(cts); break; default: goto exit; } } exit: free(cts); return 0; }
主菜单: