【C语言】——动态内存管理与文件操作,后面加一个通讯录福利,万字解读,看完你会有一个全新认识

这篇具有很好参考价值的文章主要介绍了【C语言】——动态内存管理与文件操作,后面加一个通讯录福利,万字解读,看完你会有一个全新认识。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一.动态内存管理

1.为什么有动态内存管理

2.malloc和free

 2.calloc和realloc

3.柔性数组

二.文件操作

1.为什么使用文件

 2.二进制文件和文本文件

 3.文件的打开和关闭

4.文件的顺序读写

5.文件缓冲区

三.通讯录

 1.预处理

 2.基本框架

3.初始化函数

4.增加联系人

 5.显示联系人

6.删除联系人

7.修改联系人

8.搜索联系人

9.保存通讯录

10.排序 

 11.销毁通讯录


前言:由于通讯录与这两个知识点有关联,所以直接一起写,这样比较容易理解通讯录里面的部分操作。(其实我就是想偷点懒) 如果想看个别内容,直接跳转就行了

一.动态内存管理

1.为什么有动态内存管理

因为我们在定义数组的时候,数组大小已经固定,不能调整,这里引用动态内存开辟,让我们自己申请和释放空间,比较灵活

2.malloc和free

 void*malloc(size_t size)

这个函数向内存申请一个连续可用的空间,并且返回指向这块空间的指针

如果开辟失败,返回一个空指针,所以返回值要做检查

很多时候我们都用到强制类型转换,因为他返回值的类型是void *

这里的size为0的话,(我也不好说因为我没测过),malloc是标准未定义的,取决于编译器

void free(void *ptr)

 free函数用来释放动态开辟内存

要注意两个点

当ptr的内存不是动态开辟的时候,那么free函数行为是未定义的,所以我们在使用的时候要搭配开辟内存的函数来使用

如果这个指针本来就是空指针,那么这个函数啥事也不用做

两个结合使用

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
int main()
{
	int num;
	cin >> num;
	int* ptr = NULL;
	ptr = (int*)malloc(sizeof(int) * num);
	if (ptr == NULL)//判断是否为空指针
		return 0;
	else
		for (int i = 0; i < num; i++) {//放数据进去
			*(ptr + i) = 1;
		}
	for (int i = 0; i < num; i++) {
		cout << *(ptr + i) << " ";
	}
	free(ptr);
	ptr = NULL;//这里是必须的,不然会导致有野指针的出现,危害非常大,反正记住用完free之后后面跟一个变为空指针的操作
	return 0;
}

这里打印的结果就是10个1,有怀疑的去试试就知道了 

 2.calloc和realloc

void *calloc(size_t  num ,  size_t size)

calloc和上面的malloc非常相似,但是比它更加高级,那就是在返回地址之前会把空间初始化为全0。它的功能就是把num个大小的空间初始化为0。所以也就是函数的参数和功能的一些不一样

void *realloc(void *ptr,size_t size)

 realloc就非常灵活了,它的功能就是把动态内存开辟的空间进行大小调整,这里对不是动态内存的空间应该是不能调整的,ptrs是要调整的内存地址,size是调整之后的大小

这里调整会把这块空间移到新的空间上去,不是原来这块空间了,用法会在通讯录里面有操作,这里就不举例了(因为要写的内容太多了,再也不拖更了

3.柔性数组

柔性数组其实也就是用上面的内存函数在操作,没啥惊奇的,用的也不多,因为有可以替代的东西,但是它的好处就是方便内存的释放,至于运行的快慢,应该也就一点点,没啥可在意的

还有就是用sizeof去计算这种结构的大小是不算这个数组的,切记

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
typedef struct stu {
	int i;
	int a[0];
}stu;//柔性数组
int main()
{
	int i = 0;
	stu* p = (stu*)malloc(sizeof(stu) + 100 * sizeof(int));//这里稍微去理解一下,因为int i也占了4个字节,加后面的100个是数组大小
	p->i = 100;
	for (int i = 0; i < 100; i++) {
		p->a[i] = i;
	}
	for (int i = 0; i < 100; i++) {
		cout << p->a[i] << " ";
	}
	free(p);
	p = NULL;

}

二.文件操作

1.为什么使用文件

因为我们敲代码一般是写算法题,如果是做项目或者其他需要保存的操作,就需要把数据存起来,一般程序退出,我们数据就不见了,所以要把他们保存在文件里面

这里说明一下程序文件(后缀为.c),目标文件(后缀为.obj),可执行文件(后缀为.exe),小时候我下东西的时候,下完以后老去点后缀为obj的文件 (因为看不懂),后面的自己想

 2.二进制文件和文本文件

这里的最简单的理解就是,二进制文件看不懂,文本文件看得懂

二进制文件是把直接把计算机存的二进制直接丢进去,不加转换的那种,文本是以ASCll码存储的,更深一点就是,一个10000二进制是4字节,因为他是整型嘛,整型4字节,没毛病,文本是5字节,因为一个字符一个字节,因为他是ASCll码存的,一个1二进制,4字节,文本,1字节,所以,两者是有区别的,细品

 3.文件的打开和关闭

文件正读写之前,应该先打开文件,结束之前关闭文件,也就是return 0之前把它关闭,这里有一个FILE 结构体类型,我们需要创建一个FILEd类型的指针变量,这个变量指向某个文件的信息区,然后这个文件信息区可以间接访问到它关联的文件

 文件的打开需要一个fopen函数,关闭需要一个fclose函数

其中有很多打开模式,这里我没图,你们书上应该有,比如什么"w","r","wb"..什么的,这里就不一一说明了,书上写的很详细
"r"(只读)    为了输入数据,打开一个已经存在的文本文件    出错                
"w"(只写)    为了输出数据,打开一个文本文件    建立一个新的文件
"a"(追加)    向文本文件添加数据    建立一个新的文件
"rb"(只读)    为了输入数据,打开一个二进制文件    出错
"wb"(只写)    为了输出数据,打开一个二进制文件    建立一个新的文件
"ab"(追加)    向一个二进制文件尾添加数据    出错
"r+"(读写)    为了读和写,打开一个文本文件    出错
"w+"(读写)    为了读和写,建立一个新的文本文件    建立一个新的文件
"a+"(读写)    打开一个文本文件,在文件尾进行读写    建立一个文件
"rb+"(读写)    为了读和写,打开一个二进制文件    出错
"wb+"(读写)    为了读和写,建立一个新的二进制文件    建立一个新的文件
"ab+"(读写)    打开一个二进制文件,在文件尾进行读写    建立一个新的文件

这些内容会在通讯录里面使用,这样更加有印象

4.文件的顺序读写

函数名    功能    适用性
fgetc()    字符输入函数    所有输入流
fputc()    字符输出函数    所有输出流
fgets()    文本行输入函数    所有输入流
fputs()    文本行输出函数    所有输出流
fscanf()    格式化输入函数    所有输入流
fprintf()    格式化输出函数    所有输出流
fread()    二进制输入    文件
fwrite()    二进制输出    文件
 

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
int main()
{
	FILE* pf = fopen("data.text", "wb");wb没有文件自己创建一个文件,“w”,需要你自己手动创建
	if (pf == NULL) {
		perror("fopen");//这里是把错误信息打印
		return 0;
	}
	fputc('a',pf);
	fputc('b',pf);
	fclose(pf);
	return 0;
}

【C语言】——动态内存管理与文件操作,后面加一个通讯录福利,万字解读,看完你会有一个全新认识,c语言,开发语言

可以看到是按顺序存储的,其实输入和输出的区别很多人弄混,也不好记忆,其实输入就是把电脑内存的数据那过来,输出就是把你想输出的东西放到电脑内存里面去,比如我要读一个在电脑内存的数据,那我用读入的函数,去读,然后再用标准输出流函数,打印在电脑屏幕上,这就叫读以上纯个人理解 

5.文件缓冲区

这里其实很好理解,为什么要有缓存区呢,我的理解就是计算机不想程序一直打扰自己工作, 你在写程序的时候,会有一个缓存区给你存,当一定量以后,才一次性存在电脑硬盘中去,这其实和你高中问问题一样的,不会有人遇到不会就拿去问老师吧

三.通讯录

 1.预处理

首先把整个项目分成三个部分,一个是用来测试的地方,一个是用来放头文件的地方,还有一个是用来放函数的具体操作的地方,所以

1.test.cpp(测试)     2.contact.cpp(具体实现)   3.contact .h(头文件)

说这个是因为你如果需要搬运,就自己创这三个东西,然后分别放进去

 2.基本框架

基本框架这里,我们需要一个系统的目录,这个目录会有几个选项,给我们选择,选了之后会干嘛,选错了会干嘛,因为是通讯录,所以我们要创建一个通讯录,这个通讯录有人的基本信息,当然也要有大小,所以我们用上面讲过的动态内存函数去实现它,还有一个就是这个通讯录得有大小显示,放进去几个人是需要知道的,所以我们用第二个结构体去套一个人信息的结构体,这里可能不懂,下面看代码

typedef struct PeoInfo {
	char name[20];
	int age;
	char sex[10];
	char tele[20];
	char adds[30];
}PeoInfo;
//通讯录
typedef struct Contact {
	PeoInfo* data;
	int sz;//当前有几个数据
	int capacity;//最大容量
}Contact;

注意下面这个才是完整的通讯录,要细品,这个结构体的变量的创建在测试板块,下面给出基本框架

#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
void menu() {
	cout << "                                    **********  << 通讯录系统 >>  **********" << endl;
	cout << "                                    **********   1.增加联系人     **********" << endl;
	cout << "                                    **********   2.删除联系人     **********" << endl;
	cout << "                                    **********   3.搜索联系人     **********" << endl;
	cout << "                                    **********   4.修改联系人信息 **********" << endl;
	cout << "                                    **********   5.展示通讯录信息 **********" << endl;
	cout << "                                    **********   6.排序           **********" << endl;
	cout << "                                    **********   0.退出           **********" << endl;

}
void test() {

	Contact con;//创建的通讯录变量
	InitContact(&con);//初始化函数
	int input = 0;
	do {
		menu();
		cout << "请输入你选择的选项:>" << endl;
		cin >> input;
		switch (input)
		{
		case 1:
			AddContact(&con);//增加联系人
			break;
		case 2:
			DelContact(&con);//删除联系人
			break;
		case 3:
			SearchContact(&con);//查找联系人
			break;
		case 4:
			ModContact(&con);//修改联系人
			break;
		case 5:
			ShowContact(&con);//显示联系人
			break;
		case 6:
			SortContact(&con);//排序联系人
			break;
		case 0:
			SaveContact(&con);//保存在电脑硬盘上
			DestroyContact(&con);//退出去前的销毁函数
			cout << "退出系统" << endl;
			break;
		default:
			cout << "选择错误,请重新选择" << endl;
			break;
		}
	} while (input);
}
int main()
{
	test();
	return 0;
}
3.初始化函数
void InitContact(Contact* pc) {
	pc->data = (PeoInfo*)malloc(3 * sizeof(PeoInfo));//动态内存函数去开辟
	if (pc->data == NULL) {
		perror("InitContact");
		return;
	}
	pc->sz = 0;//开辟成功,那么有下面的操作
	pc->capacity = 3;
	LoadContact(pc);//这里是在读入数据的函数,后面说
}

 有了空间下面我们就得去增加联系人

4.增加联系人
//增加联系人
int CheckContact(Contact* pc) {
	if (pc->sz == pc->capacity) {//当sz==capacity的时候就满了
		PeoInfo* prt = (PeoInfo *)realloc(pc->data, (pc->capacity + 2) * sizeof(PeoInfo));
		if (prt == NULL) {
			perror("CheckContact");
			return 0;
		}
		else {
			pc->data = prt;
			pc->capacity += 2;
			cout << "增容成功";
			return 1;
		}
	}
	return 1;//不需要增容也返回1;
}
void AddContact(Contact* pc) {
	if (CheckContact(pc) == 0)//这里是动态的增容,可以更好的节约空间,更加灵活
		cout << "无法增容" << endl;//如果增容失败那下面就不执行了
	else {
		cout << "请输入你要增加人的信息:>" << endl;
		cout << "请输入姓名:>" << endl;
		cin >> pc->data[pc->sz].name;
		cout << "请输入年龄:>" << endl;
		cin >> pc->data[pc->sz].age;
		cout << "请输入性别:>" << endl;
		cin >> pc->data[pc->sz].sex;
		cout << "请输入电话:>" << endl;
		cin >> pc->data[pc->sz].tele;
		cout << "请输入住址:>" << endl;
		cin >> pc->data[pc->sz].adds;
		pc->sz++;//别忘记要++
		cout << "添加联系人成功" << endl;
	}

	
}
 5.显示联系人
void ShowContact(const Contact* pc) {
	printf("%-10s\t%-10s\t%-10s\t%-10s\t%-10s\n", "姓名", "年龄", "性别", "电话", "地址");
	for (int i = 0; i < pc->sz; i++) {
		printf("%-10s\t%-10d\t%-10s\t%-10s\t%-10s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].adds);//这里的\t是为了把他们的距离控制住,不足就补空格
	}
	cout << endl << endl <<endl << endl << endl;//这里我是为了更加好看
}
6.删除联系人
void DelContact(Contact* pc) {
	char name[20];
	cout << "请输入你要删除人的姓名:>" << endl;
	cin >> name;
	int pos = FindByname(pc, name);//你要搜索得先找到这个人
	if (pos == -1) {
		cout << "要删除的人不存在";
		return;
	}
	else {
		for (int i = pos; i < pc->sz - 1; i++) {
			pc->data[i] = pc->data[i + 1];
		}
		pc->sz--;
		cout << "删除成功" << endl;
	}
}

这里有一个查找联系人的函数,因为它很多操作都得用到,所以就单独拿出来,做一个支持函数

int  FindByname(const Contact* pc, char name[]) {
	int pos;
	for (int i = 0; i < pc->sz; i++) {
		if (strcmp(pc->data[i].name, name) == 0) {
			pos = i;
			return pos;//返回它的下表
		}
	}
	return -1;
}
7.修改联系人
void ModContact(Contact* pc) {
	char name[20];
	cout << "请输入你要修改人的姓名;>" << endl;
	cin >> name;
	int pos = FindByname(pc, name);
	if (pos == -1) {
		cout << "修改人不存在" << endl;
		return;
	}
	else {
		int num = 0;
		do {
			cout << "请输入你要修改人的信息" << endl;
			cout << "0.退出 1.姓名 2.年龄 3.性别 4.电话 5.地址" << endl;
			cin >> num;
			switch (num)
			{
			case NAME://这里是枚举类型,该类型说明在contact.h头文件里面
				cout << "请输入姓名" << endl;
				cin >> pc->data[pos].name;
				break;
			case AGE:
				cout << "请输入年龄" << endl;
				cin >> pc->data[pos].age;
				break;
			case SEX:
				cout << "请输入性别" << endl;
				cin >> pc->data[pos].sex;
				break;
			case TELE:
				cout << "请输入电话" << endl;
				cin >> pc->data[pos].tele;
				break;
			case ADDR:
				cout << "请输入地址" << endl;
				cin >> pc->data[pos].adds;
				break;
			case ERRO:
				cout << "不修改退回" << endl;
				break;
			default:
				cout << "操作无效!" << endl;
				break;
			}
		} while (num);
	}
}

这里再次用到了查找函数,这里修改函数的架构和测试模块差不多

8.搜索联系人
void SearchContact(Contact* pc) {
	char name[20];
	cout << "请输入你要查找人的姓名:>" << endl;
	cin >> name;
	int pos=FindByname(pc, name);
	if (pos) {
		printf("%-10s\t%-10s\t%-10s\t%-10s\t%-10s\n", "姓名", "年龄", "性别", "电话", "地址");
			printf("%-10s\t%-10d\t%-10s\t%-10s\t%-10s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].adds);
	}
	else {
		cout << "要查找的人不存在" << endl;
		return;
	}
}

 这里需要把找的人打印出来,所以把查找和搜索分开

9.保存通讯录
void SaveContact(Contact* pc) {
	FILE * pf = fopen("contact.txt", "w");
	if (pf == NULL) {
		perror("SaveContact");
		return;
	}
	for (int i = 0; i < pc->sz; i++) {//这里一个一个写进去
		fwrite(&(pc->data[i]), sizeof(PeoInfo), 1, pf);//这里用的函数,在文件操作有说明,是二进制文件
	}
	cout << "通讯录保存成功" << endl;
	fclose(pf);记得关闭
	pf = NULL;//记得设置为空
}

虽然已经存到电脑上去了,但是你下次运行的时候还是会没有,这就是没有读入的原因,你要把文件里面的数据读入进去,才可以在下次运行程序的时候显示出来,我之前就是犯了这个错误,你们应该不会.

这里会有一个什么时候读入的问题,其实很简单,就是在初始化的时候读入就行了,这样每次运行程序,显示联系人的时候就会有之前的数据

void LoadContact(Contact* pc) {//加载函数
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL) {
		perror("LoadContact");
		return;
	}
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo), 1, pf)) {//这里读入的操作和写的操作有些许不一样,fread读入失败的时候也就是读完的时候,所以用while,它的返回值是size_t

		if (CheckContact(pc) == 0)//这里用增容函数去变化自身大小,因为一开始开辟的内存很小,如果上次数据很多,可能装不下
			return;
		pc->data[pc->sz] = tmp;
		pc->sz++;
	}
	fclose(pf);
	pf = NULL;
}
10.排序 
//排序
int cmp1(PeoInfo e1, PeoInfo e2) {//一个是按名字的字典序排序
	return strcmp(e1.name,e2.name);
}
int cmp2(PeoInfo e1, PeoInfo e2) {//一个是按年龄来排序
	return e1.age > e2.age;
}
void SortContact(Contact* pc) {
	int num = 0;
	cout << "请选择排序方式:>" << endl;
	cout << "1.名字 2.年龄" << endl;
	cin >> num;
	switch (num)
	{
	case 1:
		sort(pc->data, pc->data + pc->sz, cmp1);
		break;
	case 2:
		sort(pc->data, pc->data + pc->sz, cmp2);
		break;
	default:
		cout << "操作无效" << endl;
		break;
	}
}

这里要注意传参的数据类型,我之前弄错了很多,这里的sort应该是可以传地址的,传地址更加好,不至于系统的开销过大

 11.销毁通讯录
void DestroyContact(Contact* pc) {
	free(pc->data);
	pc->data = NULL;
	pc->sz = 0;
	pc->capacity = 0;
	cout << "销毁成功" << endl;
}//这里的销毁很简单,把所有的数据处理一遍就好

 这里你应该对这通讯录有了大概的了解了

下面给出三个完整模板

1.test.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
void menu() {
	cout << "                                    **********  << 通讯录系统 >>  **********" << endl;
	cout << "                                    **********   1.增加联系人     **********" << endl;
	cout << "                                    **********   2.删除联系人     **********" << endl;
	cout << "                                    **********   3.搜索联系人     **********" << endl;
	cout << "                                    **********   4.修改联系人信息 **********" << endl;
	cout << "                                    **********   5.展示通讯录信息 **********" << endl;
	cout << "                                    **********   6.排序           **********" << endl;
	cout << "                                    **********   0.退出           **********" << endl;

}
void test() {

	Contact con;
	InitContact(&con);
	int input = 0;
	do {
		menu();
		cout << "请输入你选择的选项:>" << endl;
		cin >> input;
		switch (input)
		{
		case 1:
			AddContact(&con);
			break;
		case 2:
			DelContact(&con);
			break;
		case 3:
			SearchContact(&con);
			break;
		case 4:
			ModContact(&con);
			break;
		case 5:
			ShowContact(&con);
			break;
		case 6:
			SortContact(&con);
			break;
		case 0:
			SaveContact(&con);
			DestroyContact(&con);
			cout << "退出系统" << endl;
			break;
		default:
			cout << "选择错误,请重新选择" << endl;
			break;
		}
	} while (input);
}
int main()
{
	test();
	return 0;
}

 2.contact.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"

//初始化
//加载通讯录
int CheckContact(Contact* pc);
void LoadContact(Contact* pc) {
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL) {
		perror("LoadContact");
		return;
	}
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo), 1, pf)) {
		if (CheckContact(pc) == 0)
			return;
		pc->data[pc->sz] = tmp;
		pc->sz++;
	}
	fclose(pf);
	pf = NULL;
}
void InitContact(Contact* pc) {
	pc->data = (PeoInfo*)malloc(3 * sizeof(PeoInfo));
	if (pc->data == NULL) {
		perror("InitContact");
		return;
	}
	pc->sz = 0;
	pc->capacity = 3;
	LoadContact(pc);
}
//增加联系人
int CheckContact(Contact* pc) {
	if (pc->sz == pc->capacity) {
		PeoInfo* prt = (PeoInfo *)realloc(pc->data, (pc->capacity + 2) * sizeof(PeoInfo));
		if (prt == NULL) {
			perror("CheckContact");
			return 0;
		}
		else {
			pc->data = prt;
			pc->capacity += 2;
			cout << "增容成功";
			return 1;
		}
	}
	return 1;
}
void AddContact(Contact* pc) {
	if (CheckContact(pc) == 0)
		cout << "无法增容" << endl;
	else {
		cout << "请输入你要增加人的信息:>" << endl;
		cout << "请输入姓名:>" << endl;
		cin >> pc->data[pc->sz].name;
		cout << "请输入年龄:>" << endl;
		cin >> pc->data[pc->sz].age;
		cout << "请输入性别:>" << endl;
		cin >> pc->data[pc->sz].sex;
		cout << "请输入电话:>" << endl;
		cin >> pc->data[pc->sz].tele;
		cout << "请输入住址:>" << endl;
		cin >> pc->data[pc->sz].adds;
		pc->sz++;
		cout << "添加联系人成功" << endl;
	}

	
}
//展示联系人
void ShowContact(const Contact* pc) {
	printf("%-10s\t%-10s\t%-10s\t%-10s\t%-10s\n", "姓名", "年龄", "性别", "电话", "地址");
	for (int i = 0; i < pc->sz; i++) {
		printf("%-10s\t%-10d\t%-10s\t%-10s\t%-10s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].adds);
	}
	cout << endl << endl <<endl << endl << endl;
}
//删除联系人
int  FindByname(const Contact* pc, char name[]) {
	int pos;
	for (int i = 0; i < pc->sz; i++) {
		if (strcmp(pc->data[i].name, name) == 0) {
			pos = i;
			return pos;
		}
	}
	return -1;
}
void DelContact(Contact* pc) {
	char name[20];
	cout << "请输入你要删除人的姓名:>" << endl;
	cin >> name;
	int pos = FindByname(pc, name);
	if (pos == -1) {
		cout << "要删除的人不存在";
		return;
	}
	else {
		for (int i = pos; i < pc->sz - 1; i++) {
			pc->data[i] = pc->data[i + 1];
		}
		pc->sz--;
		cout << "删除成功" << endl;
	}
}
//搜索联系人
void SearchContact(Contact* pc) {
	char name[20];
	cout << "请输入你要查找人的姓名:>" << endl;
	cin >> name;
	int pos=FindByname(pc, name);
	if (pos) {
		printf("%-10s\t%-10s\t%-10s\t%-10s\t%-10s\n", "姓名", "年龄", "性别", "电话", "地址");
			printf("%-10s\t%-10d\t%-10s\t%-10s\t%-10s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].adds);
	}
	else {
		cout << "要查找的人不存在" << endl;
		return;
	}
}
//修改联系人
void ModContact(Contact* pc) {
	char name[20];
	cout << "请输入你要修改人的姓名;>" << endl;
	cin >> name;
	int pos = FindByname(pc, name);
	if (pos == -1) {
		cout << "修改人不存在" << endl;
		return;
	}
	else {
		int num = 0;
		do {
			cout << "请输入你要修改人的信息" << endl;
			cout << "0.退出 1.姓名 2.年龄 3.性别 4.电话 5.地址" << endl;
			cin >> num;
			switch (num)
			{
			case NAME:
				cout << "请输入姓名" << endl;
				cin >> pc->data[pos].name;
				break;
			case AGE:
				cout << "请输入年龄" << endl;
				cin >> pc->data[pos].age;
				break;
			case SEX:
				cout << "请输入性别" << endl;
				cin >> pc->data[pos].sex;
				break;
			case TELE:
				cout << "请输入电话" << endl;
				cin >> pc->data[pos].tele;
				break;
			case ADDR:
				cout << "请输入地址" << endl;
				cin >> pc->data[pos].adds;
				break;
			case ERRO:
				cout << "不修改退回" << endl;
				break;
			default:
				cout << "操作无效!" << endl;
				break;
			}
		} while (num);
	}
}
//保存通讯录
void SaveContact(Contact* pc) {
	FILE * pf = fopen("contact.txt", "w");
	if (pf == NULL) {
		perror("SaveContact");
		return;
	}
	for (int i = 0; i < pc->sz; i++) {
		fwrite(&(pc->data[i]), sizeof(PeoInfo), 1, pf);
	}
	cout << "通讯录保存成功" << endl;
	fclose(pf);
	pf = NULL;
}
//排序
int cmp1(PeoInfo e1, PeoInfo e2) {
	return strcmp(e1.name,e2.name);
}
int cmp2(PeoInfo e1, PeoInfo e2) {
	return e1.age > e2.age;
}
void SortContact(Contact* pc) {
	int num = 0;
	cout << "请选择排序方式:>" << endl;
	cout << "1.名字 2.年龄" << endl;
	cin >> num;
	switch (num)
	{
	case 1:
		sort(pc->data, pc->data + pc->sz, cmp1);
		break;
	case 2:
		sort(pc->data, pc->data + pc->sz, cmp2);
		break;
	default:
		cout << "操作无效" << endl;
		break;
	}
}
//销毁
void DestroyContact(Contact* pc) {
	free(pc->data);
	pc->data = NULL;
	pc->sz = 0;
	pc->capacity = 0;
	cout << "销毁成功" << endl;
}

3.contact.h 

#pragma once
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
enum Con {//这里是个枚举类型,
	ERRO,//0
	NAME,//1
	SEX,//2
	AGE,//3
	TELE,//4
	ADDR//5

};
typedef struct PeoInfo {
	char name[20];
	int age;
	char sex[10];
	char tele[20];
	char adds[30];
}PeoInfo;
//通讯录
typedef struct Contact {
	PeoInfo* data;
	int sz;
	int capacity;
}Contact;

//函数声明
//初始化函数
void InitContact(Contact* pc);
//增加联系人
void AddContact(Contact* pc);
//展示联系人
void ShowContact(const Contact* pc);
//删除联系人
void DelContact(Contact* pc);
//搜索联系人
void SearchContact(Contact* pc);
//修改联系人
void ModContact(Contact* pc);
//保村通讯录
void SaveContact(Contact* pc);
//排序
void SortContact(Contact* pc);
//销毁
void DestroyContact(Contact* pc);

 看到这里了,希望本篇文章对你会有所帮助,创造不易,给一个小小的关注吧,后面可能会更新数据结构和相应的算法内容,因为这些内容写起来比较枯燥

 文章来源地址https://www.toymoban.com/news/detail-839276.html

到了这里,关于【C语言】——动态内存管理与文件操作,后面加一个通讯录福利,万字解读,看完你会有一个全新认识的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 文件操作介绍及C语言实现通讯录管理系统3.0最终版(文件操作版本)

    上一篇文章我们学习了动态内存开辟的相关知识点,并用动态内存函数优化了我们的通讯录,但通讯录还有需要改进的地方,比如,正常情况下的通讯录,应该可以一直保存联系人信息,而不是退出就清空了,这就需要我们实实在在的保存下来一个通讯录。 接下来我会给大家

    2023年04月08日
    浏览(59)
  • C语言动态内存练习:【通讯录(动态内存版本)实现】

    前面我们写了一个静态数组版本的通讯录,再结合刚学习的动态内存管理的知识,我们现在来实现一个动态内存版本的通讯录。 动态内存版本的通讯录,主要还是为了解决静态数组版本的通讯录空间太大导致的内存浪费和空间太小不够存放的问题。 扩容策略: 为通讯录设置

    2023年04月13日
    浏览(72)
  • 【C语言】实现通讯录(动态+文件)

    在之前三子棋和扫雷的基础上,本篇文章博主将给大家逐步分析实现通讯录,介绍通讯录的每个功能( 动态增长和文件保存 )。 —————————————————————— test.c - 测试通讯录 Contact.c - 函数的实现 Contact.h - 函数和类型的声明 以多文件的形式分模块写的

    2024年02月13日
    浏览(57)
  • 【C语言】——通讯录(静态-动态增长-文件储存)

      目录 前言: 一:整体框架 关于通讯录结构体的创建  二:通讯录的功能实现(静态) 2.1初始化通讯录 2.2增加联系人 2.3打印通讯录 2.4删除联系人  2.5 查找联系人 2.6修改联系人  2.7排序联系人 三:通讯录优化——动态内存  3.1通讯录的创建 3.2初始化通讯录  3.3增加联系

    2024年02月07日
    浏览(43)
  • C语言之通讯录的实现(静态版,动态版,文件版)

    个人主页(找往期文章包括但不限于本期文章中不懂的知识点): 我要学编程(ಥ_ಥ)-CSDN博客 目录 静态通讯录的实现逻辑  test.c:通讯录的逻辑实现 Contact.h:函数的声明与头文件的包含 Contact.c:函数的实现  通讯录源码:  test.c: Contact.c: Contect.h: 动态版通讯录  test.c: Co

    2024年04月13日
    浏览(42)
  • C语言进阶之文件操作及改造通讯录

    我们前面学习结构体时,写通讯录的程序,当通讯录运行起来的时候,可以给通讯录中增加、删除数据,此时数据是存放在内存中,当程序退出的时候,通讯录中的数据自然就不存在了,等下次运行通讯录程序的时候,数据又得重新录入,如果使用这样的通讯录就很难受。

    2024年02月16日
    浏览(43)
  • c语言:通讯录管理系统(文件版本)

    前言: 本通讯录管理系统一共三个版本,除此文章以外还有如下俩个版本,大家可以根据需求自取: 基础增删查改功能版本 :c语言:通讯录管理系统(增删查改)-CSDN博客 动态分配内存版本 :c语言:通讯录管理系统(动态分配内存版)-CSDN博客         本文是在基础的通

    2024年02月07日
    浏览(50)
  • C语言小项目——通讯录高阶(文件管理版)

    通讯录初阶: 点这里 通讯录中阶: 点这里 contact.c test.c contact.c contact.h

    2024年02月17日
    浏览(46)
  • C语言 — 动态内存管理(动态内存函数)

    本期分为三篇介绍动态内存管理相关内容,关注博主了解更多 博主博客链接:https://blog.csdn.net/m0_74014525 本期介绍动态内存函数,函数如何使用、函数格式、在使用在所需要的注意点及C/C++程序的内存开辟区域 第一篇:C语言 — 动态内存管理(动态内存函数) 第二篇:C语言

    2024年02月14日
    浏览(47)
  • 「探索C语言内存:动态内存管理解析」

    🌠先赞后看,不足指正!🌠 🎈这将对我有很大的帮助!🎈 📝所属专栏:C语言知识 📝阿哇旭的主页:Awas-Home page 目录   引言 1. 静态内存 2. 动态内存 2.1 动态内存开辟函数 2.1.1 malloc函数 2.1.2 calloc函数 2.1.3 realloc函数 2.2 动态内存释放函数 2.2.1 free函数 3. 动态内存的常见

    2024年04月28日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包