0


【C语言进阶】【小项目】实现一个通讯录【C语言知识点汇总项目】通过这个项目,掌握C语言重要知识点

【C语言进阶】【小项目】实现一个通讯录【C语言知识点汇总项目】通过这个项目,掌握C语言重要知识点

欢迎来到#西城s的博客,今天,博主带着大家用C实现一个通讯录!干货满满不要错过噢!

作者: #西城s
这是我的主页:@小小Programmer
在食用这篇博客之前,博主在这里介绍一下其它高质量的编程学习栏目:
数据结构专栏:数据结构 这里包含了博主很多的数据结构学习上的总结,每一篇都是超级用心编写的,有兴趣的伙伴们都支持一下吧!
算法专栏:算法 这里可以说是博主的刷题历程,里面总结了一些经典的力扣上的题目,和算法实现的总结,对考试和竞赛都是很有帮助的!
力扣刷题专栏:Leetcode想要冲击ACM、蓝桥杯或者大学生程序设计竞赛的伙伴,这里面都是博主的刷题记录,希望对你们有帮助!

在这里插入图片描述
先赞后看好习惯 打字不容易,这都是很用心做的,希望得到支持你 大家的点赞和支持对于我来说是一种非常重要的动力。看完之后别忘记关注我哦!️️️

这个小项目几乎包含了C语言学习阶段所有知识点,实现了这个项目,我们的C语言,就没问题了!

本篇为不收藏必后悔篇~

我们要实现的通讯录的功能:

  1. 可以动态开辟空间存放联系人的信息。
  2. 联系人的信息包括名字、性别、年龄、电话、地址。
  3. 同时,我们要实现通讯录中:增加,删除,查找,修改联系人的功能,打印联系人的功能。
  4. 联系人的信息可以通过文件进行保存。

实现过程目录

前言

实现这种类似的简易通讯录有很多种方式,这里博主选用的是顺序表来进行实现,其实博主认为,使用链表是最好的,但是我们如果是刚学习完C语言的伙伴,应该是还没有开始学习数据结构的,所以这里我们用最简单的——顺序表,也就是结构体数组来实现这个通讯录。
当然,如果对链表有兴趣的伙伴,可以通过博主提供的传送门过去食用~
【链表】单链表的介绍和基本操作(C语言实现)【保姆级别详细教学】
【链表】双向链表的介绍和基本操作(C语言实现)【保姆级别详细教学】
当然,它们也收录在博主:数据结构这个专栏里面。

当然,在本期博客中,我们要所用到的核心知识有:动态内存的管理,结构体和文件。博主以前总结过这些知识点,这里提供传送门,如果伙伴们在阅读的时候遇到困难,不妨食用完博主这几篇总结再来实现这个小项目,这几篇博客同样是干货满满噢!
【算法】【C语言进阶】C语言字符串操作宝藏级别汇总 strtok函数 strstr函数该怎么用?【超详细的使用解释和模拟实现】
【文件】C语言文件操作及其使用总结篇【初学者保姆级别福利】
【动态内存】C语言动态内存管理及使用总结篇【初学者保姆级福利】

实现通讯录总体框架

当然,我们实现的时候采用分模块实现的方式。
创建3个源文件:

test.c

总体测试源文件(main函数的位置)

contact.c

实现接口

contact.h

接口的声明

首先我们来看通讯录的结构

#defineNAME_MAX20//一个联系人名字的最大空间#defineSEX_MAX5//性别#defineTELE_MAX12//电话#defineADDR_MAX30//地址  #defineDEFAULT_SZ3//默认初始容量大小-后面有需要会接着增容//一个人的信息的结构typedefstructPeoInfo{char name[NAME_MAX];//名字char sex[SEX_MAX];//性别int age;//年龄char tele[TELE_MAX];//电话char addr[ADDR_MAX];//地址}PeoInfo;//通讯录结构//顺序表实现typedefstructContact{
    PeoInfo* data;int sz;//记录当前通讯录里面有几个人int capacity;//记录最大容量}Contact;//实现的结构名称//让代码的可读性提升了enumOption{//利用枚举,给接口所对应的数字换成有意义的单词,提升可读性
    EXIT,
    ADD,
    DEL,
    SEARCH,
    MODIFY,
    SORT,
    PRINT
};

确定好总体结构之后,我们回到test.c文件里面,开始创建通讯录。

#include"contact.h"//通讯录//自己写一个小目录voidmenu(){printf("----------------------------\n");printf("*          THE MENU        *\n");printf("----------------------------\n");printf("*          1.add           *\n");printf("*          2.del           *\n");printf("*          3.search        *\n");printf("*          4.modify        *\n");printf("*          5.sort          *\n");printf("*          6.print         *\n");printf("*          0.exit          *\n");printf("----------------------------\n");}void_test(){int _input =0;//创建通讯录
    Contact con;//初始化通讯录//所以我们要改造这个初始化函数,给它三个struct的空间_initContact(&con);//这里同时也要把东西加载进去do{system("cls");//这个是格式优化,我们可以暂时不管menu();printf("there is %d PeoInfos in the Contact\n", con.sz);printf("----------------------------\n");printf("please choose:>");scanf("%d",&_input);switch(_input){case ADD://ADD,DEL这些博主都通过枚举的方式,给它们赋好值了_addContact(&con);//增加联系人break;case DEL:_delContact(&con);//删除联系人break;case SEARCH:_searchContact(&con);//查找联系人break;case MODIFY:_modifyContact(&con);//修改联系人break;case SORT://_sortByAge(&con);//按照年龄排序-这个博主就不带大家实现了,其余的结构博主都给大家写好了,这个可以自己尝试一下break;case PRINT:_printContact(&con);break;case EXIT://改成动态版本之后,要一个接口来销毁通讯录//退出通讯录之前,我们还需要将内容保存一下_saveContact(&con);_destroyContact(&con);printf("exit contact\n");system("pause");exit(-1);break;default:printf("err\n");//选择错误system("pause");break;}}while(_input);}intmain(){_test();return0;}

我们可以测试一下我们的目录:
在这里插入图片描述

当然,写到这里,我们的实现接口是还没有写的,等一下我们要一一实现!

核心接口实现

初始化通讯录接口

初始化注意事项:

  • 首先我们需要开辟出3(一开始设定好的默认值)的空间,全部置为0
  • 然后,我们还要加载以前保存下来的文件(contact.bat)里的内容
  • 加载的时候,要检查当前通讯录的容量是否够放,所以我们还需要一个检查容量,并在不够时增容的一个函数:_checkCapacity(),这个博主在后面的讲解带大家实现,在这里大家先写好,我们一会儿实现。
//加载通讯录void_loadContact(Contact* pc){//打开文件
    FILE* pf =fopen("contact.dat","rb");if(pf ==NULL){perror("_loadContact::fopen");return;}//读文件
    PeoInfo tmp ={0};while(fread(&tmp,sizeof(PeoInfo),1, pf)){//放进去_checkCapacity(pc);//检查容量是否够放
        pc->data[pc->sz]= tmp;
        pc->sz++;}//关闭文件fclose(pf);
    pf =NULL;}//改造成文件的版本void_initContact(Contact* pc){assert(pc);
    pc->sz =0;
    pc->capacity = DEFAULT_SZ;//创建默认个数的空间先
    pc->data =(PeoInfo*)malloc(pc->capacity *sizeof(PeoInfo));if(pc->data ==NULL){perror("init::malloc");exit(-1);}memset(pc->data,0, pc->capacity *sizeof(PeoInfo));//加载文件信息到通讯录_loadContact(pc);}

增加联系人接口

思路很简单,一个一个信息输入,放进去即可,但是要注意:增加的时候先检查容量。

//增加联系人void_addContact(Contact* pc){assert(pc);//满了要增容_checkCapacity(pc);//录入信息printf("please input the name:");scanf("%s", pc->data[pc->sz].name);printf("please input the age:");scanf("%d",&(pc->data[pc->sz].age));printf("please input the sex:");scanf("%s", pc->data[pc->sz].sex);printf("please input the tele_num:");scanf("%s", pc->data[pc->sz].tele);printf("pleae input the address:");scanf("%s", pc->data[pc->sz].addr);

    pc->sz++;//通讯录人物数量记得++printf("----------------------------\n");printf("successfully added!\n");printf("----------------------------\n");printf("\n");system("pause");}

检查并增加容量接口

**同样:思路非常的简单,不够了,再开辟一个即可!
这里注意

realloc()

函数的使用!**

//增容void_checkCapacity(Contact* pc){if(pc->sz == pc->capacity){
        PeoInfo* tmp =(PeoInfo*)realloc(pc->data,(pc->capacity +2)*sizeof(PeoInfo));if(tmp !=NULL){
            pc->data = tmp;}
        pc->capacity +=2;printf("contact is successfully enlarged!\n");printf("---------------------------------\n");}}

打印接口

一个简单的顺序表的遍历即可实现,当然我们要花点功夫让它们打印得更美观!

//打印通讯录void_printContact(const Contact* pc){assert(pc);//打印int i =0;printf("\n");printf("%-20s %-5s %-5s %-12s %-30s\n","姓名","年龄","性别","电话","地址");for(i =0; i < pc->sz; i++){printf("%-20s %-5d %-5s %-12s %-30s\n", pc->data[i].name, pc->data[i].age,
            pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);}printf("\n");system("pause");}

在这里插入图片描述

查找,删除,修改联系人信息接口

这几个接口我们写在一起,因为删除,修改,我们总要找到这个人吧,所以其实它们都需要用到一个叫做 通过联系人名字查找联系人的一个接口。

思路也非常的简单,但是有很多细节,我们在写的时候注意一下即可,具体我们看注释。

//通过名字查找人的信息//如果找到这个人,返回在顺序表中的下标i,如果没找到,返回-1int_findByName(const Contact* pc,char* name){assert(pc);int i =0;for(i =0; i < pc->sz; i++){if(strcmp(pc->data[i].name, name)==0){return i;}}return-1;}//删除指定联系人信息void_delContact(Contact* pc){assert(pc);if(pc->sz ==0){//里面没有联系人,不能删除printf("null Contact! err!\n");system("pause");return;}//删除//1.找到char name[NAME_MAX]={0};printf("please input the name:");scanf("%s", name);int pos =_findByName(pc, name);//找到了,返回下标;找不到,返回负一if(pos ==-1){//找不到printf("cannot find the PeoInfo,err!");system("pause");return;}//2.删除//这里要稍微分析清楚,是sz-1,不要越界了for(int j = pos; j < pc->sz -1; j++){
        pc->data[j]= pc->data[j +1];}
    pc->sz--;//这个不要忘记了printf("successfully deleted\n");system("pause");}//查找一个人的信息void_searchContact(const Contact* pc){char name[NAME_MAX]={0};printf("please input the name:>");scanf("%s", name);int pos =_findByName(pc, name);if(pos ==-1){printf("cannot find the PeoInfo,err!");return;}printf("--------------------------------------------------\n");printf("the info is:\n");printf("%-20s %-5s %-5s %-12s %-30s\n","姓名","年龄","性别","电话","地址");printf("%-20s %-5d %-5s %-12s %-30s\n", pc->data[pos].name, pc->data[pos].age,
        pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr);printf("--------------------------------------------------\n");system("pause");}void_modifyContact(Contact* pc){printf("whose Info do you want to modify:\n");char name[NAME_MAX]={0};scanf("%s", name);int pos =_findByName(pc, name);//找一下这个人,看能不能找到if(pos ==-1){//找不到printf("cannot find the PeoInfo,err!\n");printf("--------------------------------------------------\n");system("pause");return;}//找到了-修改//修改printf("--------------------------------------------------\n");printf("you are modifing %s's info\n", pc->data[pos].name);printf("please input the name:");scanf("%s", pc->data[pos].name);printf("please input the age:");scanf("%d",&(pc->data[pos].age));printf("please input the sex:");scanf("%s", pc->data[pos].sex);printf("please input the tele_num:");scanf("%s", pc->data[pos].tele);printf("pleae input the address:");scanf("%s", pc->data[pos].addr);printf("\n");printf("successfully modified!\n");printf("--------------------------------------------------\n");printf("\n");system("pause");}

保存联系人信息、退出通讯录接口

这里我们又要用到文件的知识了,把当前通讯录的信息写到文件里去。

//保存通讯录void_saveContact(const Contact* pc){
    FILE* pf =fopen("contact.dat","wb");//以二进制的形式写进去if(pf ==NULL){perror("_saveContact::fopen");return;}//写文件for(int i =0; i < pc->sz; i++){//一个一个写进去fwrite(pc->data+i,sizeof(PeoInfo),1,pf);}printf("sucessfully saved!\n");printf("--------------------------------------------------\n");//关闭文件fclose(pf);
    pf =NULL;}//销毁通讯录void_destroyContact(Contact* pc){free(pc->data);
    pc->data =NULL;
    pc->capacity =0;
    pc->sz =0;}

完整代码展示

test.c
#define_CRT_SECURE_NO_WARNINGS1#include"contact.h"//通讯录//改成动态版本voidmenu(){printf("----------------------------\n");printf("*          THE MENU        *\n");printf("----------------------------\n");printf("*          1.add           *\n");printf("*          2.del           *\n");printf("*          3.search        *\n");printf("*          4.modify        *\n");printf("*          5.sort          *\n");printf("*          6.print         *\n");printf("*          0.exit          *\n");printf("----------------------------\n");}void_test(){int _input =0;//创建通讯录
    Contact con;//初始化通讯录//所以我们要改造这个初始化函数,给它三个struct的空间_initContact(&con);//这里同时也要把东西加载进去do{system("cls");menu();printf("there is %d PeoInfos in the Contact\n", con.sz);printf("----------------------------\n");printf("please choose:>");scanf("%d",&_input);switch(_input){case ADD:_addContact(&con);break;case DEL:_delContact(&con);break;case SEARCH:_searchContact(&con);break;case MODIFY:_modifyContact(&con);break;case SORT://_sortByAge(&con);//按照年龄排序break;case PRINT:_printContact(&con);break;case EXIT://改成动态版本之后,要一个接口来销毁通讯录//改造成文件版本_saveContact(&con);_destroyContact(&con);printf("exit contact\n");system("pause");exit(-1);break;default:printf("err\n");system("pause");break;}}while(_input);}intmain(){_test();return0;}

contact.h
#pragmaonce#include<stdio.h>#include<memory.h>#include<assert.h>#include<string.h>#include<stdlib.h>#defineNAME_MAX20//一个联系人名字的最大空间#defineSEX_MAX5//性别#defineTELE_MAX12//电话#defineADDR_MAX30//地址  #defineDEFAULT_SZ3//默认初始容量大小-后面有需要会接着增容//一个人的信息typedefstructPeoInfo{char name[NAME_MAX];char sex[SEX_MAX];int age;char tele[TELE_MAX];char addr[ADDR_MAX];}PeoInfo;//静态版本#if0typedefstructContact{
    PeoInfo data[MAX];//可以存放1000个人的信息int sz;//记录通讯录种已经保存的信息个数}Contact;#endiftypedefstructContact{
    PeoInfo* data;//可以存放int sz;int capacity;//记录最大容量}Contact;//实现的结构名称//让代码的可读性提升了enumOption{
    EXIT,
    ADD,
    DEL,
    SEARCH,
    MODIFY,
    SORT,
    PRINT
};void_initContact(Contact* pc);void_addContact(Contact* pc);void_printContact(const Contact* pc);void_delContact(Contact* pc);void_searchContact(const Contact* pc);void_modifyContact(Contact* pc);void_sortByAge(Contact* pc);void_destroyContact(Contact* pc);void_saveContact(const Contact* pc);

contact.c
#define_CRT_SECURE_NO_WARNINGS1#include"contact.h"//增容void_checkCapacity(Contact* pc){if(pc->sz == pc->capacity){
        PeoInfo* tmp =(PeoInfo*)realloc(pc->data,(pc->capacity +2)*sizeof(PeoInfo));if(tmp !=NULL){
            pc->data = tmp;}
        pc->capacity +=2;printf("contact is successfully enlarged!\n");printf("---------------------------------\n");}}//初始化通讯录(静态)#if0void_initContact(Contact* pc){assert(pc);
    pc->sz =0;memset(pc->data,0,sizeof(pc->data));}#endif//动态版本初始化#if0void_initContact(Contact* pc){assert(pc);
    pc->sz =0;
    pc->capacity = DEFAULT_SZ;
    pc->data =(PeoInfo*)malloc(pc->capacity *sizeof(PeoInfo));if(pc->data ==NULL){perror("init::malloc");exit(-1);}memset(pc->data,0, pc->capacity *sizeof(PeoInfo));}#endif//加载通讯录void_loadContact(Contact* pc){//打开文件
    FILE* pf =fopen("contact.dat","rb");if(pf ==NULL){perror("_loadContact::fopen");return;}//读文件
    PeoInfo tmp ={0};while(fread(&tmp,sizeof(PeoInfo),1, pf)){//放进去_checkCapacity(pc);
        pc->data[pc->sz]= tmp;
        pc->sz++;}//关闭文件fclose(pf);
    pf =NULL;}//改造成文件的版本void_initContact(Contact* pc){assert(pc);
    pc->sz =0;
    pc->capacity = DEFAULT_SZ;
    pc->data =(PeoInfo*)malloc(pc->capacity *sizeof(PeoInfo));if(pc->data ==NULL){perror("init::malloc");exit(-1);}memset(pc->data,0, pc->capacity *sizeof(PeoInfo));//加载文件信息到通讯录_loadContact(pc);}//销毁通讯录void_destroyContact(Contact* pc){free(pc->data);
    pc->data =NULL;
    pc->capacity =0;
    pc->sz =0;}//增加联系人void_addContact(Contact* pc){assert(pc);//if (pc->sz == MAX) {//    printf("Contact is already full,err\n");//    exit(-1);//}//满了要增容_checkCapacity(pc);//录入信息printf("please input the name:");scanf("%s", pc->data[pc->sz].name);printf("please input the age:");scanf("%d",&(pc->data[pc->sz].age));printf("please input the sex:");scanf("%s", pc->data[pc->sz].sex);printf("please input the tele_num:");scanf("%s", pc->data[pc->sz].tele);printf("pleae input the address:");scanf("%s", pc->data[pc->sz].addr);

    pc->sz++;printf("----------------------------\n");printf("successfully added!\n");printf("----------------------------\n");printf("\n");system("pause");}//打印通讯录void_printContact(const Contact* pc){assert(pc);//打印int i =0;printf("\n");printf("%-20s %-5s %-5s %-12s %-30s\n","姓名","年龄","性别","电话","地址");for(i =0; i < pc->sz; i++){printf("%-20s %-5d %-5s %-12s %-30s\n", pc->data[i].name, pc->data[i].age,
            pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);}printf("\n");system("pause");}//通过名字查找人的信息int_findByName(const Contact* pc,char* name){assert(pc);int i =0;for(i =0; i < pc->sz; i++){if(strcmp(pc->data[i].name, name)==0){return i;}}return-1;}//删除指定联系人信息void_delContact(Contact* pc){assert(pc);if(pc->sz ==0){printf("null Contact! err!\n");system("pause");return;}//删除//1.找到char name[NAME_MAX]={0};printf("please input the name:");scanf("%s", name);int pos =_findByName(pc, name);//找到了,返回下标;找不到,返回负一if(pos ==-1){printf("cannot find the PeoInfo,err!");system("pause");return;}//2.删除//这里要稍微分析清楚,是sz-1,不要越界了for(int j = pos; j < pc->sz -1; j++){
        pc->data[j]= pc->data[j +1];}
    pc->sz--;//这个不要忘记了printf("successfully deleted\n");system("pause");}//查找一个人的信息void_searchContact(const Contact* pc){char name[NAME_MAX]={0};printf("please input the name:>");scanf("%s", name);int pos =_findByName(pc, name);if(pos ==-1){printf("cannot find the PeoInfo,err!");return;}printf("--------------------------------------------------\n");printf("the info is:\n");printf("%-20s %-5s %-5s %-12s %-30s\n","姓名","年龄","性别","电话","地址");printf("%-20s %-5d %-5s %-12s %-30s\n", pc->data[pos].name, pc->data[pos].age,
        pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr);printf("--------------------------------------------------\n");system("pause");}void_modifyContact(Contact* pc){printf("whose Info do you want to modify:\n");char name[NAME_MAX]={0};scanf("%s", name);int pos =_findByName(pc, name);if(pos ==-1){printf("cannot find the PeoInfo,err!\n");printf("--------------------------------------------------\n");system("pause");return;}//修改printf("--------------------------------------------------\n");printf("you are modifing %s's info\n", pc->data[pos].name);printf("please input the name:");scanf("%s", pc->data[pos].name);printf("please input the age:");scanf("%d",&(pc->data[pos].age));printf("please input the sex:");scanf("%s", pc->data[pos].sex);printf("please input the tele_num:");scanf("%s", pc->data[pos].tele);printf("pleae input the address:");scanf("%s", pc->data[pos].addr);printf("\n");printf("successfully modified!\n");printf("--------------------------------------------------\n");printf("\n");system("pause");}//保存通讯录void_saveContact(const Contact* pc){
    FILE* pf =fopen("contact.dat","wb");//以二进制的形式写进去if(pf ==NULL){perror("_saveContact::fopen");return;}//写文件for(int i =0; i < pc->sz; i++){//一个一个写进去fwrite(pc->data+i,sizeof(PeoInfo),1,pf);}printf("sucessfully saved!\n");printf("--------------------------------------------------\n");//关闭文件fclose(pf);
    pf =NULL;}

尾声

看到这里,我们的通讯录小项目就完成了!这里面包含了C语言大部分的重要知识点,对复习是很有帮助的。这也是我们学习C语言来为数不多的一个项目。看完这篇博客,是不是感觉自己的C又行了呢哈哈哈。如果你觉得这篇博客对你有帮助,千万不要忘了点赞关注和收藏后再走噢!

标签: c语言

本文转载自: https://blog.csdn.net/Yu_Cblog/article/details/124066894
版权归原作者 #西城s 所有, 如有侵权,请联系我们删除。

“【C语言进阶】【小项目】实现一个通讯录【C语言知识点汇总项目】通过这个项目,掌握C语言重要知识点”的评论:

还没有评论