用c语言实现一个通信录

来源:互联网 发布:波士顿矩阵ppt模板 编辑:程序博客网 时间:2024/05/01 22:33


这个题目要求我们实现一个通讯录,该通讯录要满足以下功能(全部使用c语言知识):

1、添加联系人(姓名,性别,年龄,电话,地址);

2、删除联系人(按名字);

3、查找(按名字);

4、修改(所有属性);

5、浏览所有联系人;

6、清空联系人列表;

7、排序(按名字);

8、其容量为动态增长的,即:当通讯录已满的情况下,在你进行添加时,它会动态增长。

注意:上述某些功能还可以更为完善,比如可以按其它属性进行删查排序。

除此之外:我们知道通讯录最重要也是最主要的功能就是对信息的保存,所以这就要求我们使用文件操作,即:在每次关闭的时候将本次的所有输入保存到文件,而在每次打开时将上次关闭前保存的内容读取到通讯录。


我们先给出通讯录的完整代码,然后对其部分逻辑进行简要分析。

注意:c语言中,写大的工程时,一般将头文件、函数实现、和main函数写到不同的源文件中,这样能使结构更加清晰,也方便其它操作。


头文件部分

contact.h

//条件编译#ifndef __CONTACT_H__#define __CONTACT_H__//头文件列表#include <stdio.h>#include <windows.h>#include <assert.h>#include <string.h>//忽略警告#pragma warning(disable:4996)//宏#define INITCAP 128//初始化长度#define INCREMENT 32//自增长度#define FILE_NAME "contact_back"//打开文件名//声明://联系人结构体typedef struct person{char name[32];//姓名 性别 年龄 电话 地址char sex[8];unsigned char age;char phone[16];char adds[64];}person_t, *person_p, **person_pp;//通讯录结构体typedef struct contact{int cap;//最大长度int size;//当前长度person_p contactList;//联系人列表}contact_t, *contact_p, **contact_pp;//函数声明void initContact(contact_pp c);//初始化通讯录void addContact(contact_p c, person_p p);//添加联系人void showContact(contact_p c);//打印联系人列表void delContact(contact_p c, char *del_name);//删除void emptyContact(contact_p c);//清空void destroyContact(contact_p c);//摧毁通讯录int  searchContact(contact_p c, char *search_name);//查找void sortContact(contact_p c);//排序void modContact(contact_p c);//修改void helpContact();//帮助void exitContact(contact_p c);//退出int  isContactEmpty(contact_p c);//判空int fileLoad(contact_p c);//下载到项目int fileStore(contact_p c);//储存到文件#endif __CONTACT_H__ 


主函数

main.c

#include "contact.h"//菜单static void meun(){printf("\n");printf("Welcome...\n");printf("-----------------------------------  CONTACTS  --------------------------------\n");printf("--           1.Add                                2.Delect                   --\n");printf("--           3.Search                             4.Edit                     --\n");printf("--           5.Show                               6.Empty                    --\n");printf("--           7.Sort                               8.Help                     --\n");printf("--           0.Exit                                                          --\n");printf("--           作者qq:248620932,ID:果冻,欢迎交流... =_=                     --\n");printf("-------------------------------------------------------------------------------\n");printf("\n");}//添加static void myAdd(contact_p c){person_t p;assert(c);printf("Please input information<name,sex,age,phone,addr>:\n");scanf("%s %s %d %s %s", p.name, p.sex, &p.age, p.phone, p.adds);addContact(c, &p);}//删除static void myDel(contact_p c){char del_name[32];int n = 0;assert(c);if(isContactEmpty(c)){printf("Contact is empty!\n");return ;}printf("Please input the name whicth you want delect:");scanf("%s", del_name);printf("\nAre you sure delect: %s ?\n", del_name);while(1){printf("----------------\n");printf("| 1.YES | 2.NO |\n");printf("----------------\n");scanf("%d", &n);if( 1 == n){delContact(c, del_name);return ;}else if( 2 == n ){return;}else{printf("Error ! \n");}}}//查找static void mySearch(contact_p c){char search_name[32];int pos = 0;int i = 0;assert(c);if(isContactEmpty(c)){printf("Contact is empty!\n");return ;}printf("Please input rhe name whicth you want to search:");scanf("%s", search_name);pos = searchContact(c, search_name);if(-1 == pos){printf("Not find!\n");}else{printf("------------------------------------------------------------------------------\n");printf("| name      | sex  | age | phone           | adds                            |\n");printf("| %-10s| %-5s| %-4d| %-16s| %-32s|\n",c->contactList[i].name, \c->contactList[i].sex,c->contactList[i].age, \c->contactList[i].phone,c->contactList[i].adds);printf("------------------------------------------------------------------------------\n");}}int main(){int s = -1;//选择控制变量contact_p myContact = NULL;//声明通讯录system("color 2");initContact(&myContact);//初始化while(1){ meun();printf("Please select<0~7>:");fflush(stdin);scanf("%d", &s);switch(s){case 1:system("cls");myAdd(myContact);//添加联系人system("pause");break;case 2:system("cls");myDel(myContact);//删除联系人system("pause");break;case 3:system("cls");mySearch(myContact);//查找并打印联系人system("pause");break;case 4:system("cls");modContact(myContact);//修改联系人system("pause");break;case 5:system("cls");showContact(myContact);//显示联系人列表system("pause");break;case 6:system("cls");emptyContact(myContact);//清空通讯录system("pause");break;case 7:system("cls");sortContact(myContact);//排序通讯录system("pause");break;case 8:system("cls");helpContact();//帮助system("pause");break;case 0:system("cls");exitContact(myContact);//退出break;default:printf("ERROR SELECTION !!!\n");//错误选择system("pause");break;}system("cls");//清屏}return 0;}


函数实现部分

contact.c

#include "contact.h"//判空//空:1//不空:0int isContactEmpty(contact_p c){assert(c);return c->size == 0 ? 1 : 0;}//初始化void initContact(contact_pp c){assert(c);//申请通讯录空间*c = (contact_p)malloc(sizeof(contact_t));if(NULL == *c){perror("malloc");exit(1);}//申请成员空间(*c)->contactList = (person_p)malloc(sizeof(person_t)*INITCAP);if(NULL == (*c)->contactList){perror("malloc");exit(2);}//初始化长度和容量(*c)->cap = INITCAP;(*c)->size = 0;fileLoad(*c);}//从文件读取通讯录信息int fileLoad(contact_p c){FILE *fp;person_t p;int i = 0;assert(c);//打开文件fp = fopen(FILE_NAME,"rb");if(NULL == fp){perror("fopen");return -2;}while(1){//读取到pfread(&p, sizeof(person_t), 1, fp);if(0 != feof(fp)){break;}//将读取的添加到通讯录addContact(c, &p);}fclose(fp);return 0;}//判满//满:1 //未满:0static int isContactFull(contact_p c){assert(c);return c->size >= c-> cap ? 1 : 0;}//自增static int incContact(contact_p c){person_p new_c = NULL;assert(c);//申请新空间new_c = (person_p)realloc(c->contactList, (c->cap+INCREMENT)*sizeof(person_t));if(NULL == new_c){perror("realloc");return 0;}//将新空间分配给旧空间c->contactList = new_c;c->cap += INCREMENT;printf("Is full, increse success!\n");return 1;}//添加联系人void addContact(contact_p c, person_p p){assert(c);assert(p);//如果不空直接添加,如果空就先自增再添加if(!isContactFull(c) || incContact(c)){c->contactList[c->size] = *p;c->size++;}}//查找//是空的:打印空//没找到:返回 -1//找到:返回下标int searchContact(contact_p c, char *search_name){int i = 0;assert(c);assert(search_name);//通讯录是空的if(isContactEmpty(c)){printf("Contact is empty!\n");}for(i = 0; i < c->size; i++){if( 0 == strcmp(c->contactList[i].name, search_name) ){break;}}//没找到if(i == c->size){return -1;}//找到返回下标return i;}//按名字排序void sortContact(contact_p c){int i = 0;int j = 0;int pos = 0;person_t temp;assert(c);//是空的就不用排if(isContactEmpty(c)){printf("Contact is empty!\n");return ;}//不空用冒泡法按名字排序for(i = c->size-1; i>0; i--){for(j = 0; j<i; j++){if(1 == strcmp(c->contactList[j].name, c->contactList[j+1].name)){temp = c->contactList[j];c->contactList[j] = c->contactList[j+1];c->contactList[j+1] = temp;pos = 1;}}if(0 == pos){break;}}printf("Done...\n");}//修改联系人void modContact(contact_p c){char name[32];int i = 0;char key_mod[8];assert(c);if(isContactEmpty(c)){printf("Contact is empty!\n");return ;}//输入要修改的人的名字printf("Please input the name whicth you want to modify:");scanf("%s", name);//查找要修改人的下标i = searchContact(c, name);if(-1 == i){printf("Not find!\n");return ;}//打印信息printf("------------------------------------------------------------------------------\n");printf("| name      | sex  | age | phone           | adds                            |\n");printf("| %-10s| %-5s| %-4d| %-16s| %-32s|\n",c->contactList[i].name, \c->contactList[i].sex,c->contactList[i].age, \c->contactList[i].phone,c->contactList[i].adds);printf("------------------------------------------------------------------------------\n");//输入要修改的关键字printf("Please input the infor whicth you want to modify:");fflush(stdin);scanf("%s", key_mod);//寻找要修改的关键字//如果要修改名字if(0 == strcmp("name", key_mod)){printf("Please input new name:");fflush(stdin);//注意要清空输入缓冲区scanf("%s", c->contactList[i].name);printf("Done...\n");return ;}//如果要修改性别if(0 == strcmp("sex", key_mod)){printf("Please input new sex:");fflush(stdin);scanf("%s", c->contactList[i].sex);printf("Done...\n");return ;}//如果要修改年龄if(0 == strcmp("age", key_mod)){printf("Please input new age:");fflush(stdin);scanf("%d", &c->contactList[i].age);printf("Done...\n");return ;}//如果要修改电话号码if(0 == strcmp("phone", key_mod)){printf("Please input new phone:");fflush(stdin);scanf("%s", c->contactList[i].phone);printf("Done...\n");return ;}//如果要修改地址if(0 == strcmp("adds", key_mod)){printf("Please input new adds:");fflush(stdin);scanf("%s", c->contactList[i].adds);printf("Done...\n");return ;}//没有找到要修改的关键字printf("ERROR!!\n");}//删除void delContact(contact_p c, char *del_name){int i = 0;int j = 0;assert(c);i = searchContact(c, del_name);if(-1 == i){printf("Not find!\n");return ;}//将后面的成员前移for(j = i;j<c->size; j++){c->contactList[j] = c->contactList[j+1];}c->size--;printf("Done...\n");}//清空通讯录void emptyContact(contact_p c){assert(c);//直接将当前大小置0c->size = 0;printf("Done...\n");}//打印信息void showContact(contact_p c){int i = 0;assert(c);if(isContactEmpty(c)){printf("Contact is empty!\n");return ;}printf("\ntotal:%d\n", c->size);//打印总人数//打印详细信息printf("------------------------------- contacts -------------------------------------\n");printf("| name      | sex  | age | phone           | adds                            |\n");printf("------------------------------------------------------------------------------\n");for(; i < c->size; i++){printf("| %-10s| %-5s| %-4d| %-16s| %-32s|\n",c->contactList[i].name, \c->contactList[i].sex,c->contactList[i].age, \c->contactList[i].phone,c->contactList[i].adds);}printf("------------------------------------------------------------------------------\n\n");} //帮助(使用手册)void helpContact(){printf("\n");printf("-----------------------------------  HELP  -----------------------------------\n");printf("| You could use this app store up some information about your friends.       |\n");printf("| 1、you can add information by choose ( 1 ).                                |\n");printf("| 2、you can delect someone by choose ( 2 ).                                 |\n");printf("| 3、you can search someone by choose ( 3 ).                                 |\n");printf("| 4、you can change some's information by choose ( 4 ).                      |\n");printf("| 5、you can show information list by choose ( 5 ).                          |\n");printf("| 6、you can empty all information by choose ( 6 ).                          |\n");printf("| 7、you can sort people by choose ( 7 ).                                    |\n");printf("------------------------------------------------------------------------------\n\n");}//储存到文件int fileStore(contact_p c){FILE *fp;int i = 0;assert(c);//打开文件fp = fopen(FILE_NAME,"wb");if(NULL == fp){perror("fopen");return -1;}//一次储存一个人大小的内容for(; i<c->size; i++){fwrite(c->contactList+i, sizeof(person_t), 1, fp);}fclose(fp);return 0;}//摧毁通讯录void destroyContact(contact_p c){assert(c);fileStore(c);//写入到文件free(c->contactList);//释放联系人列表c->contactList = NULL;free(c);//释放整体c = NULL;}//退出void exitContact(contact_p c){int n = 0;printf("\nAre you sure quit ?\n");while(1){printf("----------------\n");printf("| 1.YES | 2.NO |\n");printf("----------------\n");scanf("%d", &n);if( 1 == n){destroyContact(c);exit(0);}else if( 2 == n ){return;}else{printf("Error ! \n");}}}


以下对部分代码做简要分析:


在头文件中我们应该有一个表示联系人的结构体,如下所示:

//联系人结构体typedef struct person{char name[32];//姓名 性别 年龄 电话 地址char sex[8];unsigned char age;char phone[16];char adds[64];}person_t, *person_p, **person_pp;
注意:我们给他typedef了三个名字,分别是结构体类型、结构体一级指针、结构体二级指针,定义指针的目的是在后面声明时避免写更多的 * 


其次我们应该有一个通讯录的结构体,它里面应该保存联系人列表,当前长度以及容量,如下所示:

//通讯录结构体typedef struct contact{int cap;//容量int size;//当前长度person_p contactList;//联系人列表}contact_t, *contact_p, **contact_pp;



在初始化传参时需要注意的问题:

void initContact(contact_pp c){assert(c);//申请通讯录空间*c = (contact_p)malloc(sizeof(contact_t));if(NULL == *c){perror("malloc");exit(1);}//申请成员空间(*c)->contactList = (person_p)malloc(sizeof(person_t)*INITCAP);if(NULL == (*c)->contactList){perror("malloc");exit(2);}//初始化长度和容量(*c)->cap = INITCAP;(*c)->size = 0;fileLoad(*c);}

注意初始化传参时一定要使用二级指针,原因是:malloc返回一个指向所申请到的空间的指针,若使用一级指针传参,则申请到的空间将给形参,该形参在该函数结束时会释放,所以申请到的空间也将丢失,更重要的是,malloc申请到的空间需用free释放,然而你所申请到的空间已经丢失,也就没法释放了,这会造成严重的内存泄漏问题,在一个较大的工程中出现这样的问题是极其严重的,在你不知情的情况下,该程序一直吃你的内存,造成不可预知的后果。使用二级指针可以避免这样的问题,原因是:二级指针保存的是你一级指针的地址,即使你一级指针(指向所申请到的空间)在函数结束时被释放,但二级指针中保存了你的地址,仍然可以通过你的地址拿到你,这就类似于我们之前在交换两个数的内容时,使用一级指针(要交换的两个数的指针)传参一样。

文件操作——从文件读取信息

//从文件读取通讯录信息int fileLoad(contact_p c){FILE *fp;person_t p;int i = 0;assert(c);//打开文件fp = fopen(FILE_NAME,"rb");if(NULL == fp){perror("fopen");return -2;}while(1){//读取到pfread(&p, sizeof(person_t), 1, fp);if(0 != feof(fp)){break;}//将读取的添加到通讯录addContact(c, &p);}fclose(fp);return 0;}

文件操作——将信息写入文件

//写入到文件int fileStore(contact_p c){FILE *fp;int i = 0;assert(c);//打开文件fp = fopen(FILE_NAME,"wb");if(NULL == fp){perror("fopen");return -1;}//一次储存一个人大小的内容for(; i<c->size; i++){fwrite(c->contactList+i, sizeof(person_t), 1, fp);}fclose(fp);return 0;}

注意:几个文件操作函数,下面给出它的原型:

FILE *fopen( const char *filename, const char *mode );

filename为将要打开的文件的名字,mode为打开方式,“rb”:以二进制只读方式打开, “rw”:以二进制只写方式打开,它返回打开文件的地址。


size_t fwrite( const void *buffer, size_t size, size_tcount, FILE *stream );

buffer为被写入的内容,size为被写入信息的大小,count为写入信息的个数,stream为写入的文件,即该函数将buffer中的内容以size大小为单位,每次写入count个,写到stream中;


size_t fread( void *buffer, size_t size, size_t count, FILE *stream );

该函数与fwrite函数类似;


int feof( FILE *stream );

该函数从stream中读取内容,若读取到文件结尾,则返回一个非零值,否则返回0;


int fclose( FILE *stream );

关闭stream文件(流);


通讯录在每次初始化完成后读取文件中的信息,每次释放通讯录前,将通讯录中的信息写到文件中,这样就完成了对联系人的保存。


总结:该通讯录使用c语言中基础的循环结构、选择结构,数组等知识,如:if()else; for(;;)switch()case  :

还有结构体、内存管理、指针、文件操作等知识。


该通讯录是实现中肯定存在错误或者不完美的地方,欢迎大家讨论交流。  >_<


成于坚持,败于止步!


0 0
原创粉丝点击