C语言通讯录大作业,支持永久数据储存,无内存浪费。

相关部分介绍

本工程用到库文件stdio.h 、stdlib.h 、string.h 、error.h
对于内存的管理使用了动态内存分配,每存入一个人的信息,就分配相应大小的空间。
相对于其他工程关闭程序后就会丢失信息,本工程支持文件操作,关闭系统时会将录入的信息写入一个contact.txt文件中,下次打开系统时又会录入信息。

代码详解

contact.h

项目头文件,声明了两个结构体

struct contact
{char name[8];  //姓名char sex[8];    //性别int age;        //年龄char ID[12];    //电话
};struct NumofCon
{int Num;   //作用是表示现在有几个人的信息被存到通讯录中,方便开辟内存struct contact p[];//柔性数组,可以使用动态内存开辟空间
};

contact.c

这个源文件是代码的主要部分,相关功能的函数全都存储在这里

第一个函数:通讯录初始化函数

struct NumofCon* Contact_Init(void)
{struct NumofCon* ps = (struct NumofCon*) malloc(4+32*1);if(ps == NULL){printf("%s\n",strerror(errno));}ps->Num = 0;return ps;
}

该函数返回一个struct NumofCon型的指针,对应第二个声明的结构体第一行就是这个代码最重要的一部分,开辟一个4+321字节大小的内存,并把他的指针传给ps,如果开辟失败就返回空指针,printf就会打印失败原因。注意,strerror(errno);函数使用需要应用errno.h头文件。
开辟字节的大小要取决于struct NumofCon结构体的大小。
将ps指向的结构体里的Num成员赋值成0,因为还没有信息被储存。

第二个函数:向通讯录中增加信息

struct NumofCon* contact_add(struct NumofCon* ps)
{ps->Num++;struct NumofCon* ps2 = (struct NumofCon*) realloc(ps,4+32*(ps->Num));if(ps2 == NULL){printf("%s\n",strerror(errno));}int i = ps2->Num-1;printf("请输入姓名:");scanf("%s",ps2->p[i].name);printf("请输入姓别:");scanf("%s",ps2->p[i].sex);printf("请输入年龄:");scanf("%d",&(ps2->p[i].age));printf("请输入电话:");scanf("%s",ps2->p[i].ID);ps = ps2;ps2 = NULL;return ps;
}

Num加一,告诉系统有新人要存入。Num的值取决于通讯录内有多少人。
使用realloc函数调整开辟内存的大小,并把新的地址传给ps2,用if语句判断是否开辟成功。
定义i作为柔性数组的下标,下标的值为Num-1。
接下来就是信息录入过程,使用了结构体嵌套调用,没有什么可讲的。
我重点要说一下最后几行,为什么要多定义一个ps2来储存地址呢?这和realloc函数的特性有关。realloc函数是调整动态内存空间大小的函数,他的参数有两个,一个是你要修改的地址,二是要修改的大小。假如要增加十个字节,如果ps指向的空间后面有足够大小的空间,那新修改的地址就不会改变,但是如果后面空间不够增加10个字节,系统就会在其他位置另起炉灶,并把原先的内容拷贝到新的地址里,并且释放原来的空间。当内存调整失败,返回空指针,直接用ps接受,那我们就没法找回原先空间的地址,程序崩溃。所以ps2是一个保险选项,防止由于内存开辟失败导致原有空间位置丢失。当函数执行到最后,ps2的使命结束,在置为空指针,防止越界访问。

第三个函数,查询,第四个函数,打印所有成员

void contact_find(struct NumofCon* ps)
{int i=0;char name[8];printf("请输入要寻找的人物姓名:");scanf("%s",name);while(strcmp(name,ps->p[i].name)){i++;}printf("姓名:%s\n",ps->p[i].name);printf("姓别:%s\n",ps->p[i].sex);printf("年龄:%d\n",ps->p[i].age);printf("电话:%s\n",ps->p[i].ID);
}void contact_Printall(struct NumofCon* ps)
{for(int i = 0;i<ps->Num; i++){printf("Num:%d\n",i+1);printf("姓名:%s\n",ps->p[i].name);printf("姓别:%s\n",ps->p[i].sex);printf("年龄:%d\n",ps->p[i].age);printf("电话:%s\n",ps->p[i].ID);}
}

没有什么好说的,只有查询函数用了一个库函数strcmp,声明在string.h中

第五个函数,删除

struct NumofCon* contact_delete(struct NumofCon* ps)
{int i=0;char name[8];printf("请输入要删除的人物姓名:");scanf("%s",name);while(strcmp(name,ps->p[i].name)){i++;if(i>ps->Num-1){printf("没有此人信息\n");return ps;}}for(;i < ps->Num; i++){strcpy(ps->p[i].name, ps->p[i+1].name);strcpy(ps->p[i].sex, ps->p[i+1].sex);ps->p[i].age = ps->p[i+1].age;strcpy(ps->p[i].ID, ps->p[i+1].ID);}ps->Num = ps->Num - 1;struct NumofCon* ps2 = (struct NumofCon*) realloc(ps,4+32*(ps->Num));if(ps2 == NULL){printf("%s\n",strerror(errno));}ps = ps2;ps2 = NULL;printf("%s的信息已经移除\n",name);return ps;
}

这个函数的重点是删除一个人后要把ps->Num的值减一,并且调整内存大小,后面成员的位置依次向前36个字节

到这里通讯录的主要功能已经完成,现在要做数据的永久储存,也就是把信息导入文件中,防止关闭程序后信息丢失。

保存数据到contact.txt文件中

void contact_serve(struct NumofCon* ps)
{FILE* pf = fopen( "contact.txt", "w");int i = 0;if(pf == NULL){printf("%s\n",strerror(errno));}while(i < ps->Num){fprintf(pf, "%d ",i+1);fprintf(pf, "%s ",ps->p[i].name);fprintf(pf, "%s ",ps->p[i].sex);fprintf(pf, "%d ",ps->p[i].age);fprintf(pf, "%s\n",ps->p[i].ID);i++;}fclose(pf);
}

注意,要在代码当前路径建立一个文件contact.txt,否则程序报错。

读取文件信息

struct NumofCon* Contact_read(struct NumofCon* ps)
{struct contact file;int Num = 1;int check = Num-1;FILE* pf = fopen("contact.txt", "r");if(pf == NULL){printf("%s\n",strerror(errno));}char ch = fgetc(pf);if(ch == EOF)Num = 0;rewind(pf);while(Num){fscanf(pf, "%d", &Num);if(check == Num)break;check = Num;fscanf(pf, "%s", file.name);fscanf(pf, "%s", file.sex);fscanf(pf, "%d", &(file.age));fscanf(pf, "%s", file.ID);ps = (struct NumofCon*) realloc(ps,4+32*Num);ps->Num = Num;strcpy(ps->p[Num-1].name, file.name);strcpy(ps->p[Num-1].sex, file.sex);ps->p[Num-1].age = file.age;strcpy(ps->p[Num-1].ID, file.ID);}fclose(pf);return ps;
}

上面两个代码涉及到文件操作系统,较为复杂,篇幅原因,我会新写一篇文章来介绍。

main.c

将上面代码都放在头文件声明后就可以写主函数了,该系统为模块化,主函数相对简单

#include <stdio.h>
#include "contact.h"int main()
{int i;struct NumofCon* Con = Contact_Init();Con = Contact_read(Con);do{system("pause");system("cls");printf("------------CONTACT-------------\n");printf("-----1.添加---------2.查询------\n");printf("-----3.显示---------4.删除------\n");printf("------------0.退出--------------\n");printf("--------------------------------\n");printf("输入指令");scanf("%d",&i);if(i == 1)Con = contact_add(Con);if(i == 2)contact_find(Con);if(i == 3)contact_Printall(Con);if(i == 4)Con = contact_delete(Con);}while(i);contact_serve(Con);return 0;
}

功能演示




一定要通过指令0退出,不然无法保存信息
现在我们打开文件看看


再次打开程序,直接使用3命令打印

我们没有录入信息,可是系统直接读取了信息,是因为系统将文件里的信息读取了。
也可以直接在contact文件中添加人物,但要遵守格式。

这就是相关代码的讲解,我会把工程上传,需要自取。
https://download.csdn.net/download/Mr_Hanc_Tiskor/15533285

有关文件的那两个函数和柔性数组我也会在下一篇文章讲解。
如果本文对你有帮助,别忘了点赞哦。欢迎大家留言讨论与大佬们的建议。

完美C语言通讯录(含代码)相关推荐

  1. c语言学生信息管理ppt,学生信息管理系统(C语言、含代码解释).ppt

    学生信息管理系统(C语言.含代码解释) 第3章 脂类代谢 脂类的分布与生理功能 脂类的消化与吸收 血脂 甘油三酯的中间代谢 类脂代谢 脂类代谢紊乱 3.1 脂类的分布和生理功能 3.1.1 脂类的分布 ...

  2. 动图图解C语言插入排序算法,含代码分析

    C语言文章更新目录 C语言学习资源汇总,史上最全面总结,没有之一 C/C++学习资源(百度云盘链接) 计算机二级资料(过级专用) C语言学习路线(从入门到实战) 编写C语言程序的7个步骤和编程机制 C ...

  3. 动图图解C语言选择排序算法,含代码分析

    C语言文章更新目录 C语言学习资源汇总,史上最全面总结,没有之一 C/C++学习资源(百度云盘链接) 计算机二级资料(过级专用) C语言学习路线(从入门到实战) 编写C语言程序的7个步骤和编程机制 C ...

  4. c语言八数码A星算法代码解析,八数码问题c语言a星算法详细实验报告含代码解析...

    八数码问题c语言a星算法详细实验报告含代码解析 (13页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 14.9 积分 一.实验内容和要求 八数码问题:在3 ...

  5. c语言成绩管理程序设计,成绩管理程序设计报告(含代码C语言

    <成绩管理程序设计报告(含代码C语言>由会员分享,可在线阅读,更多相关<成绩管理程序设计报告(含代码C语言(19页珍藏版)>请在人人文库网上搜索. 1.大连民族学院计算机科学与 ...

  6. c语言实现简单通讯录(仅代码)

    C语言实现简单通讯录(仅代码) 头文件部分 #pragma once //头文件区域 #include<stdio.h> #include<Windows.h> #includ ...

  7. plc变频器c语言,如何通过PLC控制变频器进行电机转速控制,含代码!

    原标题:如何通过PLC控制变频器进行电机转速控制,含代码! 一.项目描述 按下电动机启动按钮,电动机启动运行在5Hz所对应的转速:延时10s后,电动机升速运行在10Hz对应的转速,再延时10s后,电动 ...

  8. 用python描述车_使用Python探索二手车市场(含代码)

    原标题:使用Python探索二手车市场(含代码) 感谢关注天善智能,走好数据之路↑↑↑ 欢迎关注天善智能,我们是专注于商业智能BI,人工智能AI,大数据分析与挖掘领域的垂直社区,学习,问答.求职一站式 ...

  9. VMware Workstation 11.0.0多国语言(含简体中文)+永久激活密钥

    2019独角兽企业重金招聘Python工程师标准>>>  VMware Workstation 11.0.0多国语言(含简体中文)+永久激活密钥 (2014-12-03 08:2 ...

  10. 【QMT】给QMT量化交易软件安装和调用第三方库(举例通达信pytdx,MyTT,含代码)

    给QMT量化交易软件安装和调用第三方库(举例通达信pytdx,MyTT,含代码) 一.安装QMT 二.给QMT安装python 三.给QMT的python环境安装第三方库 1.准备python虚拟环境 ...

最新文章

  1. 读淘宝商品描述页源码delphi版
  2. Linux命令集合(更新中。。。)
  3. boost::contract模块实现equal的测试程序
  4. 为什么mysql 5.7.24启停不显示错误信息?log-error_verbosity参数
  5. 北京金融局、通州区政府与蚂蚁金服战略合作 共防系统性金融风
  6. spring AOP 讲解
  7. asp.net三层架构制作新闻管理_程序员蜕变为架构师必须要知道的「架构理论」...
  8. vs 生成com组件 其他电脑_VS也可以这样进行快捷安装
  9. [渝粤教育] 中国地质大学 事故应急救援 复习题 (2)
  10. 使用pienv安装python虚拟环境(学习记录)
  11. javascript 实现1加到100
  12. 全面解读Marshmallow
  13. [bigdata] 基于docker 打开hadoop
  14. 01 Tomcat 的manger配置
  15. 将沁园春长沙写出来使用html css,高一语文新教材教案全集 第一课 沁园春 长沙...
  16. 从混合云到云原生 KubeSphere 3.0先把书读厚,再把书读薄
  17. 计算机房排风系统,机房新风系统新风量的计算及选型.xls
  18. 硬核!终于有人把CRC讲清楚了!
  19. 浅析IPTV盒子和OTT盒子,如何选择?
  20. 抖音上二次元虚拟主播直播方案

热门文章

  1. CAT1 4G+以太网开发板腾讯云手机微信小程序显示温度和下发控制
  2. 教师职称考计算机模块,2015教师职称计算机考试模块.doc
  3. java走梅花桩_PGIS周中赛:梅花桩4队混战 PERO17杀饮恨 STK拿下本局
  4. 转:This Android SDK requires Andr...ate ADT to the latest
  5. 微信公众平台源码分享,把你的生意做到微信里
  6. 敏感词过滤算法Aho-Corasick
  7. Springboot内置tomcat优化
  8. 伍德里奇计量经济学导论pdf_伍德里奇 计量经济学导论 第三章第三节 2 OLS无偏定理...
  9. 螺旋模型 增量模型_螺旋模型| 软件工程
  10. 网易云计算机系统有限公司,网易云音乐