C进阶:通讯录(动态版本 + 文件操作)附源码

C/C++
164
0
0
2024-04-30

一.通讯录思路

1.创建结构体类型,其中包含通讯录中联系人的信息; 该信息可以包括:姓名,年龄,性别,电话,地址等;2.创建一个结构体存储通讯录;3.写一个简易的菜单来表明通讯录的功能; 包括但不限于: 添加add,删除del,查找search,修改modigy,排序sort,打印通讯录print等;4.通过函数来实现这些功能;

二.三个文件的建立

对于较复杂的一些代码,我们最好分文件写,这样可以使代码更清晰,可读性也更高; 在写通讯录的代码之前,我们需要先建立三个文件,分别是: 1.头文件 : contact.h (用于函数的声明等)2.源文件 :contact.c (用于函数的实现)3.源文件 : test.c (用于主函数的书写)

三.所需要使用的变量的创建(包含在头文件contact.h中)

为了后面方便改动,我们定义宏来确定一些大小;

代码:

代码语言:javascript

复制

//所需头文件的包含
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//一些定义的表示大小的宏
#define MAX_NAME 20
#define MAX_SEX  10
#define MAX_TEL  20
#define MAX_ADDR 30

#define DEFAULT_SZ 3  //默认通讯录容量
#define INC_SZ     2  //每次增容的大小


//定义每个联系人的信息
typedef struct peoinfo
{
	char name[MAX_NAME]; //姓名
	int age;  //年龄
	char sex[MAX_SEX];  //性别
	char tel[MAX_TEL];  //电话
	char addr[MAX_ADDR];  //地址
}peoinfo;


//存储每个联系人
typedef struct contact
{
	peoinfo* data;  //定义指针变量,方便后续动态内存开辟,进行通讯录扩容操作
	int sz;     //通过下标访问数组
	int capacity;  // 记录通讯录容量
}contact;

四.主函数的书写 (包含在 test.c 中)

1.首先要写个简易的菜单来展示通讯录功能; 2.然后利用 do ..... while 结构实现通讯录的操作; 3.还要创建一个通讯录变量 contact con ; 4. 写一个函数 ( Innitcontact (函数的实现在 contact.c 中)(包含文件的读取)) 初始化通讯录变量 con (在此时进行动态内存开辟,使用 calloc/malloc 函数)

主函数代码:

代码语言:javascript

复制

//头文件的包含
#include "contact.h"


//菜单
void menu()
{
	printf("*****************************************************************\n");
	printf("**********          1.add                 2.del        **********\n");
	printf("**********          3.search              4.modify     **********\n");
	printf("**********          5.see                 6.sort       **********\n");
	printf("**********                    0.exit                   **********\n");
	printf("*****************************************************************\n");

	
}
//利用枚举变量使代码表达的意思更清晰
enum option
{
	EXIT, //默认从0开始
	ADD,  //1
	DEL,  //2
	SEARCH,  //3
	MODIFY,  //4
	SEE,  //5
	SORT  //6
};

int main()
{
	int input = 0;
	contact con;   //通讯录变量创建
	//初始化联系人数组,包含从文件中读取联系人信息
	Innitcontact(&con);
	do
	{
		menu();
		printf("请选择:>");
		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 SEE:
			printcontact(&con);  //打印通讯录
			break;
		case SORT:
			sortcontact(&con);  //排序
			break;
		case EXIT:
			savecontact(&con);  //保存通讯录,将联系人信息写入文件中
			destroycontact(&con);  //销毁通讯录
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误,重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

Innitcontact 函数:

代码语言:javascript

复制

//将文件中的联系人信息读入
void download(contact* pc)
{
	FILE* pf = fopen("D:\\C\\c-code\\CONTACT\\CONTACT\\contact.txt", "r");  //以只读的方式打开文件
	if (pf == NULL)  //判断文件是否打开成功
	{
		perror("fopen");
		return;
	}
	
	peoinfo tmp = { 0 };
	while (fread(&tmp, sizeof(peoinfo), 1, pf))
	{
		inccapacity(pc);  //增容函数
		pc->data[pc->sz] = tmp;  //将联系人信息写入 data 中
		pc->sz++;  //记录写入联系人的数量
	}
	fclose(pf);  //关闭文件
	pf = NULL;
}

//动态初始化联系人
void Innitcontact(contact* pc)
{
	pc->data = (peoinfo*)calloc(DEFAULT_SZ, sizeof(peoinfo));  //动态内存开辟,实现通讯录的动态
	if (pc->data == NULL)  //判断内存开辟是否成功
	{
		perror("Innitcontact");
		return;
	}
	pc->sz = 0;  //初始化通讯录实时容量,也可用作下标
	pc->capacity = DEFAULT_SZ;  //初始化容量
	download(pc);  //加载文件中联系人的信息
}

五.通讯录功能的实现(在 contact.c 中)

1.添加联系人 addcontact
在添加联系人之前,我们先要判断通讯录是否已满,若已满则调用增容函数,之后在进行联系人信息的添加;

增容函数 inccapacity 代码:

代码语言:javascript

复制

//是否增容
void inccapacity(contact* pc)
{
	if (pc->sz == pc->capacity)
	{
		printf("通讯录已满,开始增容\n");
	    peoinfo* ptr = (peoinfo*)realloc(pc->data,(DEFAULT_SZ+INC_SZ)*sizeof(peoinfo));  //利用 realloc 进行内存的再次动态开辟,实现通讯录的增容
		
		if(ptr == NULL)  //判断内存是否开辟成功
		{
			printf("增容失败\n");
			perror("inccapacity");
			return;
		}
		else
		{
			pc->data = ptr;   //将扩容后的通讯录首地址赋给原来的通讯录
			pc->capacity += INC_SZ;  //容量增加
			printf("增容成功\n");
		}
	}
}

添加联系人函数 addcontact 代码:

代码语言:javascript

复制

//添加联系人
void addcontact(contact* pc)
{
	int input = 0;
	do
	{
		
		printf("按1继续,按0返回:>");  //利用 do ... while 结构实现联系人的多次添加
		scanf("%d", &input);
		
		switch (input)
		{
		case 1:
			inccapacity(pc);  //判断容量是否已满,若已满,则进行增容
			printf("开始添加\n");  //联系人各种信息的录入
			printf("请输入姓名:>");
			scanf("%s", pc->data[pc->sz].name);
			printf("请输入年龄:>");
			scanf("%d", &(pc->data[pc->sz].age));
			printf("请输入性别:>");
			scanf("%s", pc->data[pc->sz].sex);
			printf("请输入电话:>");
			scanf("%s", pc->data[pc->sz].tel);
			printf("请输入地址:>");
			scanf("%s", pc->data[pc->sz].addr);
			pc->sz++;  //添加成功后,通讯录实时容量增加1
			printf("添加成功\n");
			break;
		case 0:
			printf("返回\n");
			return;
			break;
		default:
			printf("选择错误,重新选择\n");
			break;
		}
	} while (input);
}
2.删除联系人 delcontact
1.在删除前我们需要先判断通讯录中是否有数据,若没有则无法删除;2.输入要删除的对象,所以我们需要写一个姓名的查找函数,返回其所在的下标,供后续删除使用;3.删除联系人,即从返回的下标开始,使其之后的每一个元素向前移动一个位置;

查找函数 find 代码:

代码语言:javascript

复制

//查找联系人
int find(char tmp[], contact* pc)
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(tmp, pc->data[i].name) == 0)  //因为姓名是字符串,所以利用字符串比较函数
		{
			return i;  //查找成功返回其下标
		}
	}
	return -1;  //失败则返回-1
}

delcontact 代码:

代码语言:javascript

复制

//删除联系人
void delcontact(contact* pc)
{
	char tmp[MAX_NAME];  
	int pos = 0, i = 0;
	if (pc->sz == 0)  //判断通讯录有无数据
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	while (1)
	{
	again:
		printf("请输入要删除的人的姓名:>");
		scanf("%s", tmp);
		pos = find(tmp, pc);  //查找要删除人的下标
		if (pos == -1)
		{
			printf("要删除的人不存在,重新输入\n");
			goto again;
		}
		else
			break;
	}
	printf("开始删除\n");
	for (i = pos; i < pc->sz - 1; i++)  //从返回的下标 pos 开始 ,之后的每个元素向前移动一位
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;  //删除成功即通讯录的实时容量减去1
	printf("删除成功\n");
}
3.查询联系人 searchcontact
1.在查询前需要判断通讯录中是否有数据,若无数据,则无法查询;2.可以调用前面的查找函数;3.查询到后打印该联系人信息,并提示查询成功;

searchcontact 代码:

代码语言:javascript

复制

//查找联系人
void searchcontact(contact* pc)
{
	char name[MAX_NAME];
	int pos = 0;
	if (pc->sz == 0)    //判断通讯录中是否有数据
	{
		printf("通讯录为空,无法查询\n");
		return;
	}
	while (1)
	{
		again:
		printf("请输入要查找人的姓名:>");
		scanf("%s", name);
		pos = find(name, pc);  //调用 fing 函数,并返回其下标
		if (pos == -1)
		{
			printf("查无此人,重新查询\n");  //查询失败则继续
			goto again;
		}
		else
			break;
	}
	printf("查询成功\n");
	printf("%-20s\t%-5s\t%-10s\t%-20s\t%-30s\n", "姓名", "年龄", "性别", "电话", "地址");   //打印该联系人的信息
	printf("%-20s\t%-5d\t%-10s\t%-20s\t%-30s\n", pc->data[pos].name,
												 pc->data[pos].age,
												 pc->data[pos].sex,
												 pc->data[pos].tel,
												 pc->data[pos].addr);
	
}
4.修改联系人信息 modifycontact
1.判断通讯录中是否有数据,若无数据,则无法修改;2.输入要修改人的姓名,调用函数 find ,返回其下标;3.开始修改,即从新录入该联系人信息;

modifycontact 代码:

代码语言:javascript

复制

//修改联系人
void modifycontact(contact* pc)
{
	if (pc->sz == 0)  //判断通讯录是否有数据
	{
		printf("通讯录为空,无法修改\n");
		return;
	}
	char name[MAX_NAME];
	int pos = 0;
	while (1)
	{
		again:
		printf("请输入要修改的联系人的姓名:>");
		scanf("%s", name);
		pos = find(name, pc);  //返回要修改的联系人的下标
		if (pos == -1)
		{
			printf("要修改的联系人不存在,重新输入\n");
			goto again;
		}
		else
			break;
	}
	printf("开始修改\n");  //修改联系人信息
	printf("请输入姓名:>");
	scanf("%s", pc->data[pos].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pos].age));
	printf("请输入性别:>");
	scanf("%s", pc->data[pos].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pos].tel);
	printf("请输入地址:>");
	scanf("%s", pc->data[pos].addr);
	printf("修改成功\n");
}
5.打印通讯录 printcontact

这并不难,直接看代码:

代码语言:javascript

复制

//打印通讯录
void printcontact(contact* pc)
{
	int i = 0;
	printf("%-20s\t%-5s\t%-10s\t%-20s\t%-30s\n", "姓名", "年龄", "性别", "电话", "地址");  //打印的格式可以根据个人喜好来
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-20s\t%-5d\t%-10s\t%-20s\t%-30s\n", pc->data[i].name,
													 pc->data[i].age,
													 pc->data[i].sex,
													 pc->data[i].tel,
													 pc->data[i].addr);
	}
}
6.排序通讯录 sortcontact
1.首先判断通讯录中的数据是否足以支持排序,若没有数据,或就1个数据,那么都无需排序;2.利用排序算法,完成通讯录的排序;3.需要有交换元素的步骤,那么就需要创建中间变量(在 contact.h 中创建)来实现交换;4.该变量可以设置成结构体变量,成员包括与data 同类型的变量 sort ,既然与 data 同类型那么就需要对其初始化;

sort 变量的创建:

代码语言:javascript

复制

typedef struct sort
{
	peoinfo* sort;
}sort;

sortcontact 代码:

代码语言:javascript

复制

//排序通讯录
void sortcontact(contact* pc)
{
	if (pc->sz < 2)
	{
		printf("通讯录数据不足,无法排序\n");  //判断是否支持排序
		return;
	}
	int i = 0, j = 0;
	sort S;  //变量的创建
	S.sort= (peoinfo*)calloc(pc->capacity, sizeof(peoinfo));  //sort 的初始化
	if (S.sort == NULL) //判断动态内存是否开辟成功
	{
		perror("sortcontact");
		return;
	}
	printf("开始排序\n");
	for (i = 0; i < pc->sz - 1; i++)   //排序算法
	{
		for (j = i + 1; j < pc->sz; j++)
		{
			if (strcmp(pc->data[i].name, pc->data[j].name) > 0)
			{
				S.sort[i] = pc->data[i];  //交换元素
				pc->data[i] = pc->data[j];
				pc->data[j] = S.sort[i];
			}
		}
	}
	printf("排序成功\n");
	free(S.sort);  //排序成功后释放所开辟的内存
	S.sort = NULL;  //将指针置空,防止使用野指针
}

六.退出通讯录 (即input==0时)

1.在退出通讯录之前需要保存通讯录的数据,写一个保存函数 savecontact;2.保存好后销毁通讯录,写一个销毁函数 destroycontact;3.退出通讯录;
保存函数 savecontact

代码语言:javascript

复制

//保存文件中的联系人信息
void savecontact(contact* pc)
{
	FILE* pf = fopen("D:\\C\\c-code\\CONTACT\\CONTACT\\contact.txt", "w");  //以只写的方式打开文件
	if (pf == NULL)  //判断文件是否打开成功
	{
		perror("savecontact");
		return;
	}
	int i = 0;
	for (i = 0; i < pc->sz; i++)   
	{
		fwrite(pc->data + i, sizeof(peoinfo), 1, pf);  //向文件中写入通讯录的数据
	}
	fclose(pf);  //数据写完后,关闭文件
	pf = NULL;
}
销毁函数 destroycontact

代码语言:javascript

复制

//销毁通讯录
void destroycontact(contact* pc)
{
	pc->sz = 0;
	pc->capacity = DEFAULT_SZ;  //容量回复默认值
	free(pc->data);  //释放之前开辟的内存
	pc->data = NULL;  //指针置空,防止野指针的出现
}
剩下的步骤很简单了,话不多说直接上源码;

七.源码

contact.h

代码语言:javascript

复制

#pragma once

//所需头文件的包含
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//一些定义的表示大小的宏
#define MAX_NAME 20
#define MAX_SEX  10
#define MAX_TEL  20
#define MAX_ADDR 30

#define DEFAULT_SZ 3  //默认通讯录容量
#define INC_SZ     2  //每次增容的大小


//定义每个联系人的信息
typedef struct peoinfo
{
	char name[MAX_NAME]; //姓名
	int age;  //年龄
	char sex[MAX_SEX];  //性别
	char tel[MAX_TEL];  //电话
	char addr[MAX_ADDR];  //地址
}peoinfo;


//存储每个联系人
typedef struct contact
{
	peoinfo* data;  //定义指针变量,方便后续动态内存开辟,进行通讯录扩容操作
	int sz;     //通过下标访问数组
	int capacity;  // 记录通讯录容量
}contact;

typedef struct sort
{
	peoinfo* sort;
}sort;

//动态初始化通讯录
void Innitcontact(contact* pc);

//打印通讯录
void printcontact(contact* pc);

//是否增容
void inccapacity(contact* pc);


//读入文件中的联系人信息
void download(contact* pc);

//保存文件中的联系人信息
void savecontact(contact* pc);

//销毁通讯录
void destroycontact(contact* pc);

//添加联系人
void addcontact(contact* pc);

//删除联系人
void delcontact(contact* pc);

//查找联系人
void searchcontact(contact* pc);

//修改联系人
void modifycontact(contact* pc);

//排序通讯录
void sortcontact(contact* pc);
contact.c

代码语言:javascript

复制

#define _CRT_SECURE_NO_WARNINGS

#include "contact.h"

//将文件中的联系人信息读入
void download(contact* pc)
{
	FILE* pf = fopen("D:\\C\\c-code\\CONTACT\\CONTACT\\contact.txt", "r");  //以只读的方式打开文件
	if (pf == NULL)  //判断文件是否打开成功
	{
		perror("fopen");
		return;
	}
	
	peoinfo tmp = { 0 };
	while (fread(&tmp, sizeof(peoinfo), 1, pf))
	{
		inccapacity(pc);  //增容函数
		pc->data[pc->sz] = tmp;  //将联系人信息写入 data 中
		pc->sz++;  //记录写入联系人的数量
	}
	fclose(pf);  //关闭文件
	pf = NULL;
}

//保存文件中的联系人信息
void savecontact(contact* pc)
{
	FILE* pf = fopen("D:\\C\\c-code\\CONTACT\\CONTACT\\contact.txt", "w");  //以只写的方式打开文件
	if (pf == NULL)  //判断文件是否打开成功
	{
		perror("savecontact");
		return;
	}
	int i = 0;
	for (i = 0; i < pc->sz; i++)   
	{
		fwrite(pc->data + i, sizeof(peoinfo), 1, pf);  //向文件中写入通讯录的数据
	}
	fclose(pf);  //数据写完后,关闭文件
	pf = NULL;
}

//销毁通讯录
void destroycontact(contact* pc)
{
	pc->sz = 0;
	pc->capacity = DEFAULT_SZ;  //容量回复默认值
	free(pc->data);  //释放之前开辟的内存
	pc->data = NULL;  //指针置空,防止野指针的出现
}

//动态初始化联系人
void Innitcontact(contact* pc)
{
	pc->data = (peoinfo*)calloc(DEFAULT_SZ, sizeof(peoinfo));  //动态内存开辟,实现通讯录的动态
	if (pc->data == NULL)  //判断内存开辟是否成功
	{
		perror("Innitcontact");
		return;
	}
	pc->sz = 0;  //初始化通讯录实时容量,也可用作下标
	pc->capacity = DEFAULT_SZ;  //初始化容量
	download(pc);  //加载文件中联系人的信息
}


//打印通讯录
void printcontact(contact* pc)
{
	int i = 0;
	printf("%-20s\t%-5s\t%-10s\t%-20s\t%-30s\n", "姓名", "年龄", "性别", "电话", "地址");  //打印的格式可以根据个人喜好来
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-20s\t%-5d\t%-10s\t%-20s\t%-30s\n", pc->data[i].name,
													 pc->data[i].age,
													 pc->data[i].sex,
													 pc->data[i].tel,
													 pc->data[i].addr);
	}
}

//是否增容
void inccapacity(contact* pc)
{
	if (pc->sz == pc->capacity)
	{
		printf("通讯录已满,开始增容\n");
	    peoinfo* ptr = (peoinfo*)realloc(pc->data,(DEFAULT_SZ+INC_SZ)*sizeof(peoinfo));  //利用 realloc 进行内存的再次动态开辟,实现通讯录的增容
		
		if(ptr == NULL)  //判断内存是否开辟成功
		{
			printf("增容失败\n");
			perror("inccapacity");
			return;
		}
		else
		{
			pc->data = ptr;   //将扩容后的通讯录首地址赋给原来的通讯录
			pc->capacity += INC_SZ;  //容量增加
			printf("增容成功\n");
		}
	}
}

//查找联系人
int find(char tmp[], contact* pc)
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(tmp, pc->data[i].name) == 0)  //因为姓名是字符串,所以利用字符串比较函数
		{
			return i;  //查找成功返回其下标
		}
	}
	return -1;  //失败则返回-1
}

//添加联系人
void addcontact(contact* pc)
{
	int input = 0;
	do
	{
		
		printf("按1继续,按0返回:>");  //利用 do ... while 结构实现联系人的多次添加
		scanf("%d", &input);
		
		switch (input)
		{
		case 1:
			inccapacity(pc);  //判断容量是否已满,若已满,则进行增容
			printf("开始添加\n");  //联系人各种信息的录入
			printf("请输入姓名:>");
			scanf("%s", pc->data[pc->sz].name);
			printf("请输入年龄:>");
			scanf("%d", &(pc->data[pc->sz].age));
			printf("请输入性别:>");
			scanf("%s", pc->data[pc->sz].sex);
			printf("请输入电话:>");
			scanf("%s", pc->data[pc->sz].tel);
			printf("请输入地址:>");
			scanf("%s", pc->data[pc->sz].addr);
			pc->sz++;  //添加成功后,通讯录实时容量增加1
			printf("添加成功\n");
			break;
		case 0:
			printf("返回\n");
			return;
			break;
		default:
			printf("选择错误,重新选择\n");
			break;
		}
	} while (input);
}

//删除联系人
void delcontact(contact* pc)
{
	char tmp[MAX_NAME];  
	int pos = 0, i = 0;
	if (pc->sz == 0)  //判断通讯录有无数据
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	while (1)
	{
	again:
		printf("请输入要删除的人的姓名:>");
		scanf("%s", tmp);
		pos = find(tmp, pc);  //查找要删除人的下标
		if (pos == -1)
		{
			printf("要删除的人不存在,重新输入\n");
			goto again;
		}
		else
			break;
	}
	printf("开始删除\n");
	for (i = pos; i < pc->sz - 1; i++)  //从返回的下标 pos 开始 ,之后的每个元素向前移动一位
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;  //删除成功即通讯录的实时容量减去1
	printf("删除成功\n");
}

//查找联系人
void searchcontact(contact* pc)
{
	char name[MAX_NAME];
	int pos = 0;
	if (pc->sz == 0)    //判断通讯录中是否有数据
	{
		printf("通讯录为空,无法查询\n");
		return;
	}
	while (1)
	{
		again:
		printf("请输入要查找人的姓名:>");
		scanf("%s", name);
		pos = find(name, pc);  //调用 fing 函数,并返回其下标
		if (pos == -1)
		{
			printf("查无此人,重新查询\n");  //查询失败则继续
			goto again;
		}
		else
			break;
	}
	printf("查询成功\n");
	printf("%-20s\t%-5s\t%-10s\t%-20s\t%-30s\n", "姓名", "年龄", "性别", "电话", "地址");   //打印该联系人的信息
	printf("%-20s\t%-5d\t%-10s\t%-20s\t%-30s\n", pc->data[pos].name,
												 pc->data[pos].age,
												 pc->data[pos].sex,
												 pc->data[pos].tel,
												 pc->data[pos].addr);
	
}

//修改联系人
void modifycontact(contact* pc)
{
	if (pc->sz == 0)  //判断通讯录是否有数据
	{
		printf("通讯录为空,无法修改\n");
		return;
	}
	char name[MAX_NAME];
	int pos = 0;
	while (1)
	{
		again:
		printf("请输入要修改的联系人的姓名:>");
		scanf("%s", name);
		pos = find(name, pc);  //返回要修改的联系人的下标
		if (pos == -1)
		{
			printf("要修改的联系人不存在,重新输入\n");
			goto again;
		}
		else
			break;
	}
	printf("开始修改\n");  //修改联系人信息
	printf("请输入姓名:>");
	scanf("%s", pc->data[pos].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pos].age));
	printf("请输入性别:>");
	scanf("%s", pc->data[pos].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pos].tel);
	printf("请输入地址:>");
	scanf("%s", pc->data[pos].addr);
	printf("修改成功\n");
}


//排序通讯录
void sortcontact(contact* pc)
{
	if (pc->sz < 2)
	{
		printf("通讯录数据不足,无法排序\n");  //判断是否支持排序
		return;
	}
	int i = 0, j = 0;
	sort S;  //变量的创建
	S.sort= (peoinfo*)calloc(pc->capacity, sizeof(peoinfo));  //sort 的初始化
	if (S.sort == NULL) //判断动态内存是否开辟成功
	{
		perror("sortcontact");
		return;
	}
	printf("开始排序\n");
	//qsort(pc, pc->sz, sizeof(peoinfo), cmp);
	for (i = 0; i < pc->sz - 1; i++)   //排序算法
	{
		for (j = i + 1; j < pc->sz; j++)
		{
			if (strcmp(pc->data[i].name, pc->data[j].name) > 0)
			{
				S.sort[i] = pc->data[i];  //交换元素
				pc->data[i] = pc->data[j];
				pc->data[j] = S.sort[i];
			}
		}
	}
	printf("排序成功\n");
	free(S.sort);  //排序成功后释放所开辟的内存
	S.sort = NULL;  //将指针置空,防止使用野指针
}
test.c

代码语言:javascript

复制

#define _CRT_SECURE_NO_WARNINGS

//头文件的包含
#include "contact.h"


//菜单
void menu()
{
	printf("*****************************************************************\n");
	printf("**********          1.add                 2.del        **********\n");
	printf("**********          3.search              4.modify     **********\n");
	printf("**********          5.see                 6.sort       **********\n");
	printf("**********                    0.exit                   **********\n");
	printf("*****************************************************************\n");

	
}
//利用枚举变量使代码表达的意思更清晰
enum option
{
	EXIT, //默认从0开始
	ADD,  //1
	DEL,  //2
	SEARCH,  //3
	MODIFY,  //4
	SEE,  //5
	SORT  //6
};

int main()
{
	int input = 0;
	contact con;   //通讯录变量创建
	//初始化联系人数组,包含从文件中读取联系人信息
	Innitcontact(&con);
	do
	{
		menu();
		printf("请选择:>");
		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 SEE:
			printcontact(&con);  //打印通讯录
			break;
		case SORT:
			sortcontact(&con);  //排序
			break;
		case EXIT:
			savecontact(&con);  //保存通讯录,将联系人信息写入文件中
			destroycontact(&con);  //销毁通讯录
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误,重新选择\n");
			break;
		}
	} while (input);
	return 0;
}