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

news2024/11/25 16:49:38

本文主要讲解通讯录的代码;

需要拥有结构体,动态内存开辟,文件操作的知识;

目录

🐲一.通讯录思路

🕊️二.三个文件的建立

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

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

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

🦄1.添加联系人  addcontact 

🤖2.删除联系人  delcontact

👻3.查询联系人 searchcontact

🦞4.修改联系人信息  modifycontact

🐯5.打印通讯录  printcontact

🦁6.排序通讯录  sortcontact

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

🐲保存函数  savecontact

😸销毁函数  destroycontact

🤖七.源码

👻contact.h

🕊️contact.c

🪶test.c


一.通讯录思路

1.创建结构体类型,其中包含通讯录中联系人的信息;

   该信息可以包括:姓名,年龄,性别,电话,地址等;

2.创建一个结构体存储通讯录;

3.写一个简易的菜单来表明通讯录的功能;

   包括但不限于: 添加add,删除del,查找search,修改modigy,排序sort,打印通讯录print等;

4.通过函数来实现这些功能;

二.三个文件的建立

对于较复杂的一些代码,我们最好分文件写,这样可以使代码更清晰,可读性也更高;

在写通讯录的代码之前,我们需要先建立三个文件,分别是:

1.头文件 :   contact.h (用于函数的声明等)

2.源文件 :contact.c (用于函数的实现)

3.源文件 :   test.c (用于主函数的书写)


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

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

代码:

//所需头文件的包含
#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 函数)

主函数代码:

//头文件的包含
#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 函数:

//将文件中的联系人信息读入
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  代码:

//是否增容
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 代码:

//添加联系人
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  代码:

//查找联系人
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  代码:

//删除联系人
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  代码:

//查找联系人
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  代码:

//修改联系人
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

这并不难,直接看代码:

//打印通讯录
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 变量的创建:

typedef struct sort
{
	peoinfo* sort;
}sort;

sortcontact  代码:

//排序通讯录
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

//保存文件中的联系人信息
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

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

剩下的步骤很简单了,话不多说直接上源码;

七.源码

contact.h

#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

#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

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

😼😸通讯录的讲解就到这儿了,如有错误或是建议,欢迎小伙伴们指出;🐲🕊️

🥰🤩希望小伙伴们可以支持支持博主啊,你们的支持对我很重要哦;😆😀

😁😄谢谢你的阅读;😊😍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/154167.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从0到1完成一个Vue后台管理项目(十三、信息列表页面实现:对话框新增、DateTimePicker 日期时间选择器)

往期 从0到1完成一个Vue后台管理项目&#xff08;一、创建项目&#xff09; 从0到1完成一个Vue后台管理项目&#xff08;二、使用element-ui&#xff09; 从0到1完成一个Vue后台管理项目&#xff08;三、使用SCSS/LESS&#xff0c;安装图标库&#xff09; 从0到1完成一个Vu…

JavaScript 事件流

文章目录JavaScript 事件流概述事件冒泡简介onclick() 事件冒泡addEventListener() 事件冒泡stopPropagation() 阻止事件冒泡事件捕获简介addEventListener() 事件捕获W3C标准事件流取消事件默认行为取消使用对象属性绑定的事件的默认行为取消使用addEventListener()绑定的事件…

社科院与杜兰大学金融管理硕士项目你有了解吗?每年招生一期错过申请太可惜了

社科院与杜兰大学金融管理硕士是个什么项目&#xff1f;社科院是所学校吗&#xff0c;怎么都没听说过。杜兰大学又是哪里的学校&#xff1f;前几天有位咨询的同学抛出这些疑问&#xff0c;着实让我不知如何给予回答。像社科院这么低调的院校太少了。社科院全称是中国社会科学院…

错题 5jxn 8253,neg指令,知CPU频率求经典总线周期,如何取一个字,字扩展指令CBW扩展要求,知道相对位移量求转移后指令偏移地址

1&#xff1a;8253工作于方式1时&#xff0c;输出负脉冲的宽度等于() A:计数初值N-1个CLK脉冲宽度 B:计数初值N1个CLK脉冲宽度C:计数初值N个CLK脉冲宽度 D:计数初值(2N-1)/2个CLK脉冲宽度 方式0和方式1 波形相同&#xff08;计数过程中低&#xff0c;计数完高&#xff09;&…

Pytorch 暂退法(Dropout)

在2014年&#xff0c;斯里瓦斯塔瓦等人 (Srivastava et al., 2014) 就如何将毕晓普的想法应用于网络的内部层提出了一个想法&#xff1a; 在训练过程中&#xff0c;他们建议在计算后续层之前向网络的每一层注入噪声。 因为当训练一个有多层的深层网络时&#xff0c;注入噪声只会…

八、Gtk4-GtkBuilder and UI file

1 New, Open and Save button 在上一节中&#xff0c;我们制作了一个非常简单的编辑器。它在程序开始时读取文件&#xff0c;在程序结束时将文件写出来。它可以工作&#xff0c;但不是很好。如果我们有“新建”、“打开”、“保存”和“关闭”按钮就更好了。本节介绍如何在窗口…

【年度总结】2022不忘初心,砥砺前行 2023纵有疾风起,人生不言弃。

2022 工作 砥砺前行 跨境电商跑路 2022年3月&#xff0c;从一家小跨境电商被动跑路&#xff0c;果断处于迷茫期&#xff0c;被动跑路的最好优势就是有赔偿&#xff0c;哈哈&#xff0c;怎么还有一丢丢高兴呢。简单总结了下在该公司的经历&#xff0c;是之前的老大带我去的&am…

如何通过产品帮助中心减轻客服压力,提高内部人员工作效率

客户的问题一直在重复&#xff0c;客服人员压力山大 客户不愿接听客服电话&#xff0c;产品问题难以解决 下班时间休息日&#xff0c;产品问题找谁问&#xff1f; 这些关于客户服务的老问题们困扰着许多产品方多年 要解决以上问题&#xff0c;更好地满足顾客需求。 搭建帮…

基于javaweb(springboot+mybatis)生活美食分享平台管理系统设计和实现以及文档报告

基于javaweb(springbootmybatis)生活美食分享平台管理系统设计和实现以及文档报告 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java毕设项目精品实战案例《500套》 欢迎…

详解函数指针(●‘◡‘●)☞

本文紧接于http://t.csdn.cn/78wbF 这篇一.函数指针数组\ ( >O< ) /1.书写形式&#xff1a;由函数指针内部*变量名>*变量名[n]&#xff1b; 2.使用&#xff1a;函数指针数组的用途&#xff1a;转移表 例如&#xff1a;模拟计算器&#xff1a;#include<stdio.h> …

用了这么久 IDEA,你还没用过 Live Templates 吗?

大家好&#xff0c;我是风筝&#xff0c;公众号「古时的风筝」&#xff0c;专注于 Java技术 及周边生态。 Live Templates 是什么&#xff0c;听上去感觉挺玄乎的。有的同学用过之后觉得简直太好用了&#xff0c;不能说大大提高了开发效率吧&#xff0c;至少也是小小的提高一下…

Qt创建项目:手把手创建第一个Qt项目

上一节介绍了QtCreator编辑器的页面长什么样子&#xff0c;以及都有哪些功能区&#xff0c;每个功能区都是用来做什么的。这一节我就手把手带大家创建一个Qt项目。 创建项目 点击新建按钮 创建项目有两个入口&#xff0c;一个是在欢迎页面的projects中点击New(新建)按钮&…

未来,勒索软件会呈现何种发展态势?

尽管过去一年里&#xff0c;全世界大约花费了1500亿美元在网络安全领域上&#xff0c;却无法真正阻止黑客攻击。在过去一年里&#xff0c;针对医院、学校、政府的勒索软件越来越多&#xff1b;加密货币领域也有无休止的黑客盗窃事件&#xff1b;还有针对微软、英伟达、Rockstar…

CORS跨域通信

在上一集的坐牢文章中&#xff0c;我们介绍了非官方的很多中方案&#xff0c;其中不乏一些江湖秘术。今天的这个&#xff0c;绝对的正统&#xff0c;纯正的官方打造。我们赶紧来看看。 1.什么是CORS&#xff1f; CORS 是一个 W3C 标准&#xff0c;全称是“跨域资源共享”&…

Prometheus的使用

Prometheus 是一个开放性的监控解决方案&#xff0c;用户可以非常方便的安装和使用 Prometheus 并且能够非常方便的对其进行扩展。 在Prometheus的架构设计中&#xff0c;Prometheus Server 并不直接服务监控特定的目标&#xff0c;其主要任务负责数据的收集&#xff0c;存储并…

ArcGIS Engine基础(31)之使用仿射变换对矢量数据进行空间校正

在生产数据过程中&#xff0c;因每个工程项目都可能有自己的施工坐标系&#xff0c;难免会产生数据提供方与数据使用方采用的坐标系不一致&#xff0c;造成数据在不同坐标系下存在一定偏移、旋转、缩放等&#xff0c;为了让数据能够在新坐标系准确定位&#xff0c;需要进行空间…

kitti数据集理解及可视化

kitti数据集简介 kitti数据集是比较早出来的3D检测方面的数据集&#xff0c;相对来说数据结构简单&#xff0c;适合做单目检测的工作&#xff0c;目前也是业界和学术界常用的公开数据集。 自己最近也在做单目3D检测的工作&#xff0c;所以也分享一些理解&#xff0c;希望能给到…

微服务自动化管理【Docker跨主机集群之Flannel】

环境说明 CentOS7 etcd-v3.4.3-linux-amd64.tar.gz flannel-v0.11.0-linux-amd64.tar.gz 官方文档&#xff1a;https://github.com/coreos/flannel 下载地址&#xff1a;https://github.com/coreos/flannel/releases/download/v0.11.0/flannel-v0.11.0-linux-amd64.tar.gz 1.…

verilog学习笔记- 9)流水灯实验

目录 简介&#xff1a; 实验任务&#xff1a; 硬件设计&#xff1a; 程序设计&#xff1a; 下载验证&#xff1a; 简介&#xff1a; LED&#xff0c;又名发光二极管。LED 灯工作电流很小&#xff08;有的仅零点几毫安即可发光&#xff09;&#xff0c;抗冲击和抗震性能好&…

工业互联网安全漏洞分析

声明 本文是学习github5.com 网站的报告而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 研究背景 在政策与技术的双轮驱动下&#xff0c;工业控制系统正在越来越多地与企业内网和互联网相连接&#xff0c;并与新型服务模式相结合&#xff0c;逐步形成…