目录

动态通讯录的实现

一、实验的目的和意义

二、实验内容描述

三、功能描述

四、数据结构

1、三大模块

2、结构设计

3、动态开辟

4、文件操作

5、主要函数

五、流程图及模块算法

1.Contacct 程序运行流程图

2、AddContct(增加)函数流程图

3、DelContct(删除)函数流程图

4、SearchContct(查找)函数流程图

5、ModifyContct(修改)函数流程图

6、SortContct(排序)函数流程图

六、实验测试结果

七、实验总结

八、源代码

1、DynamicContact.h

2、DynamicContact.c

3、test.c

最后


动态通讯录的实现

一、实验的目的和意义

1、巩固和加深对C语言知识的理解

2、学会使用编译器的各种调试

3、提高解决实际问题的能力

二、实验内容描述

通讯录,是用来存放联系人的信息,它在如今电子信息发展的社会中是不可或缺的。联系人的信息主要包括名字、性别、年龄、地址等。

本次课程设计使用C语言来实现通讯录,正常的通讯录应具备以下主要功能:

增:增加联系人

删:删除联系人

查:查找联系人

改:修改联系人的某项信息

显示:显示通讯录所有联系人的信息

排序:对通讯录中的联系人进行排序

三、功能描述

通讯录的主要功能为增加联系人、删除联系人、查找联系人、修改联系人的信息等等

下面具体描述各功能的作用:

1、增加:可以添加联系人,其信息主要包括名字、性别、年龄、电话、地址

2、删除:输入想要删除联系人的名字进行删除,联系人查找存在且删除后则提示删除成功,联系人查找不存在则提示要删除的联系人不存在,或者通讯录为空则输出通讯录已空,无法删除

3、查找:输入想要查找的联系人的名字,联系人存在则打印出联系人的全部信息,否则提示联系人不存在

4、修改:输入想要修改联系人信息的名字,先对联系人查找,联系人存在则对需要修改的信息进行修改,联系人不存在则显示联系人不存在

5、显示:显示通讯录所有联系人的信息

6、排序:对通讯录中的联系人按名字、年龄进行排序,并且显示排序后通讯录中的联系人

四、数据结构

1、三大模块

通讯录大致分为三大模块,详情如下:

文件名 作用
DynamicContact.h 通讯录的函数声明、头文件声明及各种声明
DynamicContact.c 通讯录函数接口的实现
test.c 通讯录函数功能测试

2、结构设计

定义一个结构体 PeoInfo ,结构体包括名字、性别、年龄、电话、地址,另一个结构体 Contact 嵌套着 PeoInfo 这个结构体,用于创建通讯录,类似于顺序表。

typedef struct PeoInfo
{char name[NAME_MAX];char sex[SEX_MAX];int age;char tele[TELE_MAX];char addr[ADDR_MAX];
}PeoInfo;typedef struct Contact
{PeoInfo* data;//存放联系人的信息int count;//通讯录中已经保存的信息个数int capacity;//记录通讯录当前的最大容量
}Contact;


3、动态开辟

1、通讯录的联系人可以用数组储存,但是考虑到空间浪费的问题,就要对需要空间的多少进行动态开辟。

比如用数组进行储存,开辟了1000个空间,但实际上只用了10个空间,剩余的空间就会造成很大大的浪费。

但是使用动态开辟空间,需要多大的空间就开辟出多大的空间,对开辟的空间不会造成很大的浪费。

这时候就要动态内存函数,通讯录中使用 malloc 函数和 realloc 函数。

2、

两个内存函数的区别,想了解详细的可以去 C++ 官网查阅。

C++ 官网:cplusplus.com - The C++ Resources Networkhttp://www.cplusplus.com/


4、文件操作

通讯录结束运行后,存储好的联系人的信息也随之销毁了。

我们想要在程序结束运行后,联系人的信息依旧保存,这时候就要运用C语言文件操作相关的知识,在程序结束运行之前把联系人保存在一个文件中,这样联系人的信息就可以存储不被销毁。

通讯录数据以二进制的方式储存。

通讯录代码中使用如下两个:

如图:contact.data 就是通讯录退出程序前保留的数据


5、主要函数

//初始化通讯录
void InitContact(Contact* p);//销毁通讯录
void DestroyContact(Contact* p);//添加联系人
void AddContact(Contact* p);//删除联系人
void DelContact(Contact* p);//查找联系人
void SearchContact(const Contact* p);//修改联系人信息
void ModifyContact(Contact* p);//打印联系人
void PrintContact(const Contact* p);//排序
void SortContact(const Contact* p);//保存通讯录的信息到文件
void SaveContact(const Contact* pc);//加载文件信息到通讯录中
void LoadContact(Contact* p);

五、流程图及模块算法

1.Contacct 程序运行流程图

2、AddContct(增加)函数流程图

3、DelContct(删除)函数流程图

4、SearchContct(查找)函数流程图

5、ModifyContct(修改)函数流程图

6、SortContct(排序)函数流程图

画流程图使用的工具diagrams.net (draw.io)https://www.draw.io/index.html

六、实验测试结果

声明一点,请输入字符,不要输入中文


1、通讯录代码正常运行

2、进行添加联系人,正常运行

3、对联系人进行删除,正常运行

4、对联系人进行修改,正常运行

5、对联系人进行排序,正常运行

七、实验总结

本次课程设计我选择的是设计通讯录管理系统。

总的来说,这次的课程设计使我体会较大的是应用比理论学习难得多,它涉及到各种实际问题,但是也加深了我对知识的理解和运用,也深知只有多写代码、练习等才能写出一个好的程序。


1、

在代码方面,所有代码运行都没有问题,就排序函数无法运行,进行排序程序就会崩掉,进行一个下午的调试才找到代码误

进行排序就崩掉,显示 0xC0000005: 读取位置 xxx时发生访问冲突

看到错误提示,我已经想到指针发生越界了,调试一下午才找到错误,如图

2、

这次课程设计也是一次很好的对自我检查,让我知道哪一个方面存在不足,对知识的了解还不够深入,对一些学过的知识没有很好的掌握。

3、

在编写代码时需要小心谨慎,否则就会写出很多的 bug。在调试上,这次课程设计加强了我对代码的调试能力。

八、源代码

源代码 gitee 上也有,需要的可以自行查看

链接code_c/DynamicContact/DynamicContact · Maple_fylqh/code - 码云 - 开源中国 (gitee.com)https://gitee.com/Maple_fylqh/code/tree/master/code_c/DynamicContact/DynamicContact​​​​​​


1、DynamicContact.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS //vs 编译器需要,其他编译器不需要,可自行删去//动态版通讯录#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <Windows.h>//类型声明//PeoInit结构体所用
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
//通讯录初始状态的容量大小
#define DEFAULT_SZ 3//枚举选项enum Option //test函数所用的枚举
{EXIT,ADD,DEL,SEARCH,MODIFY,SORT,PRINT
};enum Modify //修改联系人所用的枚举
{EXIT0,NAME,SEX,AGE,TELE,ADDR
};//结构体声明typedef struct PeoInfo
{char name[NAME_MAX];char sex[SEX_MAX];int age;char tele[TELE_MAX];char addr[ADDR_MAX];
}PeoInfo;typedef struct Contact
{PeoInfo* data;//存放联系人的信息int count;//通讯录中已经保存的信息个数int capacity;//记录通讯录当前的最大容量
}Contact;//函数声明//初始化通讯录
void InitContact(Contact* p);//销毁通讯录
void DestroyContact(Contact* p);//添加联系人
void AddContact(Contact* p);//删除联系人
void DelContact(Contact* p);//查找联系人
void SearchContact(const Contact* p);//修改联系人信息
void ModifyContact(Contact* p);//打印联系人
void PrintContact(const Contact* p);//排序
void SortContact(const Contact* p);//保存通讯录的信息到文件
void SaveContact(const Contact* pc);//加载文件信息到通讯录中
void LoadContact(Contact* p);


2、DynamicContact.c

#include "DynamicContact.h"//排序所用菜单
void menu2()
{printf("********************************\n");printf("******  1.name    2.age   ******\n");printf("******  0.exit            ******\n");printf("********************************\n");
}
//修改联系人所用的菜单
void menu1()
{printf("********************************\n");printf("******  1.name    2.sex   ******\n");printf("******  3.age     4.tele  ******\n");printf("******  5.addr    0.exit  ******\n");printf("********************************\n");}//检测通讯录容量
void CheckCapacity(Contact* p)
{assert(p);if (p->capacity == p->count){PeoInfo* tmp = (PeoInfo*)realloc(p->data, (p->capacity + 2) * sizeof(PeoInfo));if (p->data != NULL){p->data = tmp;}else{perror("CheckCapacity::realloc");return;}p->capacity += 2;printf("增容成功\n");}
}//初始化通讯录
void InitContact(Contact* p)
{assert(p);p->count = 0;p->capacity = DEFAULT_SZ;p->data = (PeoInfo*)malloc(p->capacity * sizeof(PeoInfo));if (p->data == NULL){perror("InitContact::malloc");return;}memset(p->data, 0, p->capacity * sizeof(PeoInfo));//把PeoInit全部初始化为0//加载文件信息到通讯录中LoadContact(p);
}//销毁通讯录
void DestroyContact(Contact* p)
{free(p->data);p->data = NULL;p->capacity = 0;p->count = 0;printf("销毁成功\n");
}//添加联系人
void AddContact(Contact* p)
{//检查容量CheckCapacity(p);//录入信息printf("请输入名字:>");scanf("%s", p->data[p->count].name);printf("请输入性别:>");scanf("%s", p->data[p->count].sex);printf("请输入年龄:>");scanf("%d", &(p->data[p->count].age));printf("请输入电话:>");scanf("%s", p->data[p->count].tele);printf("请输入地址:>");scanf("%s", p->data[p->count].addr);p->count++;printf("添加成功\n\n");
}//查找,找到了返回下标,找不到返回 -1
int FindName(const Contact* p, char name[])
{assert(p);int i = 0;for (i = 0; i < p->count; i++){if (0 == strcmp(p->data[i].name, name)){return i;}}return -1;
}//删除联系人
void DelContact(Contact* p)
{assert(p);if (0 == p->count){printf("通讯录已空,无法删除\n");return;}char name[NAME_MAX];printf("请输入要查找的名字:>");scanf("%s", name);int position = FindName(p, name);//查找if (-1 == position){printf("要删除的联系人不存在\n\n");return;}//删除int i = 0;for (i = position; i < p->count - 1; i++){p->data[i] = p->data[i + 1];}p->count--;printf("删除成功\n\n");
}//查找联系人
void SearchContact(const Contact* p)
{assert(p);char name[NAME_MAX];printf("请输入要查找的名字:>");scanf("%s", name);int position = FindName(p, name);//查找if (-1 == position){printf("要查找的联系人不存在\n\n");return;}printf("\n-----------------------------------------------\n");printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%-10s %-5s %-5d %-12s %-30s\n", p->data[position].name, p->data[position].sex, p->data[position].age, p->data[position].tele, p->data[position].addr);printf("\n-----------------------------------------------\n\n");
}//修改联系人信息
void ModifyContact(Contact* p)
{assert(p);int intput = 0;char name[NAME_MAX];printf("请输入要修改联系人的名字:>");scanf("%s", name);int position = FindName(p, name);//查找if (-1 != position){printf("\n-----------------------------------------------\n");printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%-10s %-5s %-5d %-12s %-30s\n", p->data[position].name, p->data[position].sex,p->data[position].age, p->data[position].tele, p->data[position].addr);printf("\n-----------------------------------------------\n\n");do{menu1();printf("请输入要修改的选项:>");scanf("%d", &intput);switch (intput){case NAME:printf("请修改名字:>");scanf("%s", p->data[position].name);printf("修改成功\n\n");break;case SEX:printf("请修改性别:>");scanf("%s", p->data[position].sex);printf("修改成功\n\n");break;case AGE:printf("请修改年龄:>");scanf("%d", &(p->data[position].age));printf("修改成功\n\n");break;case TELE:printf("请修改电话号码:>");scanf("%s", p->data[position].tele);printf("修改成功\n\n");break;case ADDR:printf("请修改地址:>");scanf("%s", p->data[position].addr);printf("修改成功\n\n");break;case EXIT0:printf("退出修改\n\n");break;default:printf("选择错误,请重新选择\n\n");break;}} while (intput);}else{printf("所要修改的联系人不存在\n\n");return;}
}//打印联系人
void PrintContact(const Contact* p)
{assert(p);int i = 0;printf("\n-----------------------------------------------\n");printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "性别", "年龄", "电话", "地址");for (i = 0; i < p->count; i++){printf("%-10s %-5s %-5d %-12s %-30s\n", p->data[i].name, p->data[i].sex,p->data[i].age, p->data[i].tele, p->data[i].addr);}printf("-----------------------------------------------\n\n");
}int cmp_name(const void* e1, const void* e2)
{return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);
}int cmp_age(const void* e1, const void* e2)
{return (((struct PeoInfo*)e1)->age - ((struct PeoInfo*)e2)->age);
}//排序
void SortContact(const Contact* p)
{assert(p);int intput = 0;do{menu2();printf("请选择需要排序的选项:>");scanf("%d", &intput);switch (intput){case 1:qsort(p->data, p->count, sizeof(struct PeoInfo), cmp_name);printf("按名字排序成功\n\n");break;case 2:qsort(p->data, p->count, sizeof(struct PeoInfo), cmp_age);printf("按年龄排序成功\n\n");break;case 0:printf("退出排序\n\n");break;default:printf("选择错误,请重新选择\n\n");break;}} while (intput);}//保存通讯录的信息到文件
void SaveContact(const Contact* p)
{//打开并创建文件FILE* pf = fopen("contact.data.txt", "w");//w:只写,if (pf == NULL){perror("SaveContact::fopen");return;}//写文件int i = 0;for (i = 0; i < p->count; i++){fwrite(p->data + i, sizeof(PeoInfo), 1, pf);}//关闭文件fclose(pf);pf = NULL;
}//加载文件信息到通讯录中
void LoadContact(Contact* p)
{//打开文件FILE* pf = fopen("contact.data.txt", "r");//r:只读if (pf == NULL){perror("LoadContact::fopen");return;}//读文件PeoInfo tmp = { 0 };while (fread(&tmp, sizeof(PeoInfo), 1, pf)){CheckCapacity(p);p->data[p->count] = tmp;p->count++;}//关闭文件fclose(pf);pf = NULL;}


3、test.c

#include "DynamicContact.h"void menu()
{printf("================================\n");printf("*********** Contact ************\n");printf("================================\n");printf("***     1.add     2.del      ***\n");printf("***     3.search  4.modify   ***\n");printf("***     5.sort    6.print    ***\n");printf("***     0.exit               ***\n");printf("================================\n");}
void test()
{int intput = 0;Contact con;//创建通讯录InitContact(&con);//初始化通讯录do{menu();printf("请选择:>");scanf("%d", &intput);switch (intput){case ADD:AddContact(&con);break;case DEL:DelContact(&con);break;case SEARCH:SearchContact(&con);break;case MODIFY:ModifyContact(&con);break;case SORT:SortContact(&con);break;case PRINT:PrintContact(&con);break;case EXIT:SaveContact(&con);//销毁通讯录之前把数据存入文件中DestroyContact(&con);printf("退出通讯录\n");break;default:printf("输入错误,请重新输入\n\n");break;}} while (intput);
}
int main(){test();return 0;
}

最后

文章到这就结束了,希望对你有帮助,觉得文章不错就点个赞吧。

文章有什么问题可以留言,感谢支持!!

【C语言进阶】C语言程序设计:动态通讯录(顺序表实现)相关推荐

  1. 约瑟夫环c语言代码顺序存储,顺序表实现约瑟夫环地问题,C语言.doc

    顺序表实现约瑟夫环地问题,C语言 计算机科学与工程学院 PAGE PAGE 2 <算法与数据结构>试验报告 计算机科学与工程学院 <算法与数据结构>试验报告[一] 专业班级 1 ...

  2. C语言进阶(七)——动态内存管理

    文章目录 动态内存管理 前言 一.为什么存在动态内存分配? 二.动态内存函数的介绍 1.malloc函数的介绍 2.free函数的介绍 3.malloc函数和free的配合使用 4.calloc函数的 ...

  3. c语言进阶——c语言题目训练

    题目一: 5位运动员参加了10米台跳水比赛,有人让他们预测比赛结果: A选手说:B第二,我第三: B选手说:我第二,E第四: C选手说:我第一,D第二: D选手说:C最后,我第三: E选手说:我第四, ...

  4. 用C语言写的一个顺序表实现图书馆书籍管理

    Function: 增add_book() 删delete_book() 改modify_book() 查check_book() 实现吧! **************************/ # ...

  5. 约瑟环c语言,顺序表实现约瑟环的问题,C语言.doc

    计算机科学与工程学院 <算法与数据结构>试验报告[一] 专业班级 10级计算机工程02 试验地点 计算机大楼计工教研室 学生学号 1005080222 指导教师 蔡琼 学生姓名 肖宇博 试 ...

  6. c语言用顺序表写一个学生管理系统,用顺序表实现学生信息管理系统

    #include #include #include #define MAXSIZE 100 typedef struct{ char no[20]; // 学号 char name[20]; // ...

  7. 数据结构 顺序表实现手机通讯录

    代码 #include <stdio.h> #include <malloc.h> #include <string.h> #include <stdlib. ...

  8. 数据结构的起航,用C语言实现一个简约却不简单的顺序表!(零基础也能看懂)

    目录 0.前言 1.线性表 2.顺序表 2.1什么是顺序表 2.2 顺序表结构体设计 2.3 顺序表的初始化 2.4 顺序表的销毁 2.5* 顺序表的尾插 2.6* 顺序表的尾删 2.7 顺序表的头插 ...

  9. 【C语言进阶深度学习记录】十六 静态库与动态库的创建与使用

    上一篇文章学习了编译的过程,点击链接查看:[C语言进阶深度学习记录]十五 编译过程简介,每一个C源文件编译后将会生成目标文件,那么这些目标文件,还需要链接起来,生成可执行文件. 文章目录 1 链接的意 ...

最新文章

  1. Flutter开发之PageView指示器(31)
  2. 欧文分校计算机新sat多少分录取,加州大学欧文分校SAT成绩要求是多少?
  3. MobaXterm使用
  4. matlab驱动器有什么用,mongo-matlab-driver如何使用
  5. 假设以带头结点的循环链表表示队列_关于反转链表,看这一篇就够了!
  6. 牛客网【每日一题】4月29日题目精讲 Symmetric Matrix
  7. 蓝桥杯7届c语言 c组答案,第七届蓝桥杯C语言C组-(自己懂的题目)
  8. 【Java】浅析Java位移运算符<<、>>、>>>
  9. 通过u盘装window7
  10. jacob 详解 语音_JAVA 实现Jacob语音播报
  11. 【嵌入式系统—ARM指令集】快速了解
  12. 用TA学吉他,下个双11再也不孤单-吉他音阶实战 (三)
  13. html link 怎么设置密码,tplink路由器手机怎么设置密码?
  14. 实战小项目——基于STM32的蓝牙小车
  15. socks5代理IP的几种测试工具
  16. vmware虚拟机运行速度卡慢原因分析及解决办法大全(二)
  17. 从前端到未来,前端发展闲聊
  18. 小学计算机社团活动简报,多彩社团活动,幸福校园生活——单集镇新河小学开展社团活动简讯...
  19. 极智AI | 昇腾 CANN ATC 模型转换
  20. 猿创征文|基于鲁棒控制理论的微电网优化调度(Matlab代码实现)

热门文章

  1. 桌面word文档变成了html,我电脑上的Word文档都变成网页形式了怎么回事?
  2. 联想G40-30安装win7
  3. LeetCode部分刷题笔记!!!JavaScript!!!
  4. 图纸上标注的是实际尺寸吗_CAD比例画图时,图上标的尺寸,是实际尺寸还是图上尺寸啊?...
  5. 史上最污的技术解读,我竟然秒懂了(上)
  6. 0.96英寸128*64 OLED显示二维码
  7. MSM8998(高通835处理器)外接指纹识别传感器linux驱动如何与设备树进行匹配
  8. 马兰戈尼晶圆干燥系统
  9. vue 使用three.js 实现3D渲染
  10. 【Unity主程手记(摘录)】第一章(二) - Dictory 底层源码剖析