【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;
}

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

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);

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

 

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值