通讯录应用程序开发指南

news2024/12/24 20:26:16

目录

一、前言

二、构建通讯录应用程序

2.1通讯录框架

(1)打印菜单

(2) 联系人信息的声明

(3)创建通讯录

(4)初始化通讯录

2.2功能实现 

(1)增加联系人

(2)显示联系人

(3)删除联系人

(4)查找联系人

(5)修改联系人

(6)排序联系人

三、通讯录的优化

3.1 文件存储

🌴保存信息到文件中:

🌴加载文件中的信息到通讯录:

3.2 动态开辟内存

🌴创建通讯录 :

🌴初始化通讯录: 

🌴增加联系人:

 🌴销毁通讯录:

四、源码


一、前言

在日常生活中,我们经常需要管理大量的联系人信息,包括电话号码、电子邮件地址等。通讯录应用程序成为了我们生活中不可或缺的一部分,它可以帮助我们高效的管理和查找联系人信息。在本篇博客中,我们将探讨如何使用C语言编写一个简单的通讯录应用程序。通过学习这个实例,我们将了解如何使用C语言来处理数据、实现基本的增删查改功能,并且获得实际的编程实际经验。

二、构建通讯录应用程序

本篇博客所实现的通讯录有如下功能:

  1. 可以保存100个人(人数由自己控制)的信息;
  2. 增加联系人的信息;
  3. 删除指定联系人的信息;
  4. 查找指定联系人的信息;
  5. 修改指定联系人的信息;
  6. 显示所有联系人的信息
  7. 排序通讯录的信息。

联系人的信息有:名字、年龄、性别、电话、住址。

2.1通讯录框架

(1)打印菜单

为了能够实现人机交互,我们需要打印菜单以供用户选择想要实现的功能。

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

enum Option
{
	EXIT,//0
	ADD,//1
	DEL,//2
	SEARCH,//3
	MODIFY,//4
	SHOW,//5
	SORT//6
};

int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请输入您的选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			break;
		case DEL:
			break;
		case SEARCH:
			break;
		case MODIFY:
			break;
		case SHOW:
			break;
		case SORT:
			break;
		case EXIT:
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误,请重新选择!\n");
			break;
		}

	} while (input);

	return 0;
}

🌴打印效果:

(2) 联系人信息的声明

#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30

typedef struct PeoInfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}PeoInfo;

(3)创建通讯录

#define MAX 100

typedef struct Contact
{
	PeoInfo data[MAX];//存放联系人的数据
	int sz;//记录当前通讯录中存放的人的信息个数
}Contact;

(4)初始化通讯录

void InitContact(Contact* pc)
{
	assert(pc);//保证指针的有效性

	memset(pc->data, 0, sizeof(pc->data));
	pc->sz = 0;
}

2.2功能实现 

(1)增加联系人

void AddContact(Contact* pc)
{
	assert(pc);
    
    //判断通讯录是否已满
	if (pc->sz == MAX)
	{
		printf("通讯录已满,无法增加\n");
		return;
	}
	//增加信息
	printf("请输入联系人的姓名:");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入联系人的年龄:");
	scanf("%s", &(pc->data[pc->sz].age));
	printf("请输入联系人的性别:");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入联系人的电话:");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入联系人的地址:");
	scanf("%s", pc->data[pc->sz].addr);

	pc->sz++;
	printf("联系人添加成功\n");
}

🌴效果:

(2)显示联系人

联系人增加成功后,我们想看到他的所有信息,这时候我们就可以让他显示在屏幕上。 

void ShowContact(const Contact* pc)
{
	assert(pc);

	//判断通讯录是否为空,如果为空,则无需打印
	if (pc->sz == 0)
	{
		printf("通讯录为空!\n");
		return;
	}

	//为了增加美观性,打印标题行
	printf("%-20s%-5s%-5s%-15s%-30s\n", "姓名", "年龄", "性别", "电话", "地址");
	for (int i = 0; i < pc->sz; i++)
	{
		printf("%-20s%-5d%-5s%-15s%-30s\n", 
			pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
	}
}

🌴效果:

(3)删除联系人

我们发现,不管是删除联系人,还是修改联系人,我们首先要找到这个联系人,所以我们还要写一个查找联系人的函数。 查找联系人的过程就是将这个通讯录遍历一遍,找到它的每个元素,然后跟我们要查找的这个人相比较,如果相同,就返回这个元素的下标,如果找不到,就返回-1。

//查找联系人
int FindByContact(Contact* pc, char name[])
{
	assert(pc);

	for (int i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

//删除联系人的信息
void DelContact(Contact* pc)
{
	assert(pc);
	char name[NAME_MAX];

	//判断通讯录是否为空,如果为空,则无需删除
	if (pc->sz == 0)
	{
		printf("通讯录为空,无需删除\n");
		return;
	}

	//查找联系人
	printf("请输入要删除联系人的名字:");
	scanf("%s", name);
	int ret = FindByContact(pc, name);
	if (ret == -1)
	{
		printf("查无此人\n");
		return;
	}
	//删除联系人
	for (int i = ret; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除成功\n");
}

 🌴效果:

(4)查找联系人

void SearchContact(Contact* pc)
{
	assert(pc);
	char name[NAME_MAX];
	printf("请输入要查找人的姓名:");
	scanf("%s", name);
	int ret = FindByContact(pc, name);
	if (ret == -1)
	{
		printf("查无此人\n");
		return;
	}
	//显示联系人
	printf("%-20s%-5s%-5s%-15s%-30s\n", "姓名", "年龄", "性别", "电话", "地址");
	printf("%-20s%-5d%-5s%-15s%-30s\n",
		pc->data[ret].name, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].tele, pc->data[ret].addr);
}

  🌴效果:

(5)修改联系人

void ModifyContact(Contact* pc)
{
	int input = 0;
	assert(pc);
	char name[NAME_MAX];
	printf("请输入要修改人的姓名:");
	scanf("%s", name);
	int ret = FindByContact(pc, name);
	if (ret == -1)
	{
		printf("查无此人\n");
		return;
	}
	//修改信息
	do
	{
		printf("请选择要修改的信息:%s %s %s %s %s %s\n", "1.姓名", "2.年龄", "3.性别", "4.电话", "5.地址", "0.退出");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("请输入要修改人的姓名:\n");
			scanf("%s", pc->data[ret].name);
			printf("修改成功\n");
			break;
		case 2:
			printf("请输入要修改人的年龄:\n");
			scanf("%d", &(pc->data[ret].age));
			printf("修改成功\n");
			break;
		case 3:
			printf("请输入要修改人的性别:\n");
			scanf("%s", pc->data[ret].sex);
			printf("修改成功\n");
			break;
		case 4:
			printf("请输入要修改人的电话:\n");
			scanf("%s", pc->data[ret].tele);
			printf("修改成功\n");
			break;
		case 5:
			printf("请输入要修改人的地址:\n");
			scanf("%s", pc->data[ret].addr);
			printf("修改成功\n");
			break;
		case 0:
			printf("退出修改\n");
			break;
		default:
			printf("修改项中没有此信息,请重新选择\n");
			break;
		}
	} while (input);
}

 🌴效果:

 

(6)排序联系人

//比较函数,用于qsort排序
int compareByAge(const void* a, const void* b)
{
	return ((PeoInfo*)a)->age - ((PeoInfo*)b)->age;
}

//排序联系人
void SortContactAge(Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,无需排序!\n");
		return;
	}
	qsort(pc->data, pc->sz, sizeof(PeoInfo), compareByAge);
	printf("%-20s%-5s%-5s%-15s%-30s\n", "姓名", "年龄", "性别", "电话", "地址");
	for (int i = 0; i < pc->sz; i++)
	{
		printf("%-20s%-5d%-5s%-15s%-30s\n",
			pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
	}

	printf("排序成功!\n");
}

  🌴效果:

三、通讯录的优化

当我们将上面实现的通讯录运行起来后,我们会发现以下几点问题:

  1. 录入的信息等程序结束后,就不存在了,这是因为数据是存放在内存中的,只要程序退出,或者掉电,都会丢失。
  2. 我们可以发现通讯录的大小是固定的100个元素,可以存放100个人的信息,但如果信息太多,空间就会有点小,不够用;而信息太少,空间又会太大,造成空间的浪费。

那该怎么解决呢?

  • 对于第1点,我们可以使用文件存储或数据库存储的方式来保存录入的联系人信息。
  • 对于第2点,我们可以用动态内存开辟的方式来开辟空间。

3.1 文件存储

🌴保存信息到文件中:

//保存信息到文件中去
void SaveContact(Contact* pc)
{
	//打开文件
	FILE* pf = fopen("contact.txt", "wb");
	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 Checkcapacity(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))
	{
		Checkcapacity(pc);
		pc->data[pc->sz] = tmp;
		pc->sz++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}


//文件版本的初始化函数
void InitContact(Contact* pc)
{
	assert(pc);//保证指针的有效性

	pc->sz = 0;
	pc->capacity = DEFAULT_SZ;
	pc->data = calloc(DEFAULT_SZ, sizeof(PeoInfo));
	if (pc->data == NULL)
	{
		perror("InitContact->calloc");
		return;
	}
	//加载文件中的信息到通讯录
	LoadContact(pc);
}

3.2 动态开辟内存

  1. 让通讯录刚开始时存放3个人的信息。
  2. 空间如果放满,可以增加容量,每次增加2个人的信息的空间。

🌴创建通讯录 :

 将data数组改为指针变量用来接收calloc函数开辟空间后的地址;增加一个变量capacity用来记录通讯录的当前容量,如果存放的信息满3个人,则增加容量。

//动态通讯录的版本
typedef struct Contact
{
	PeoInfo* data;//存放数据
	int sz;//记录当前通讯录中存放的人的信息个数
	int capacity;//记录的是通讯录的当前容量
}Contact;

🌴初始化通讯录: 

将通讯录容量初始化为3,这里可以定义宏,以方便修改,再用calloc函数开辟空间。

//动态版本
#define DEFAULT_SZ 3

void InitContact(Contact* pc)
{
	assert(pc);//保证指针的有效性

	pc->sz = 0;
	pc->capacity = DEFAULT_SZ;
	pc->data = calloc(DEFAULT_SZ , sizeof(PeoInfo));
	if (pc->data == NULL)
	{
		perror("InitContact->calloc");
		return;
	}
}

🌴增加联系人:

当通讯录满了以后,我们要考虑增容的问题,所以还要修改增加函数,将每次要增加的容量也定义为宏,方便修改。

//动态版本
#define DEFAULT_INC 2

void Checkcapacity(Contact* pc)
{
	if (pc->sz == pc->capacity)
	{
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + DEFAULT_INC) * sizeof(PeoInfo));
		if (ptr == NULL)
		{
			pc->data = ptr;
			pc->capacity += DEFAULT_INC;
	        printf("增容成功!\n");
		}
		else
		{
			perror("AddContact->recalloc");
			return;
		}
	}
}

 void AddContact(Contact* pc)
{
	assert(pc);
	//增加容量
	Checkcapacity(pc);
	
	//增加信息
	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].tele);
	printf("请输入联系人的地址:");
	scanf("%s", pc->data[pc->sz].addr);

	pc->sz++;
	printf("联系人添加成功\n");
}

 🌴销毁通讯录:

当我们要退出通讯录的时候,要将realloc函数开辟的空间释放掉。

//销毁通讯录
void DestoryContact(Contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->sz = 0;
	pc->capacity = 0;
}

四、源码

🌻(test.c )

#include "Contact.h"

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

enum Option
{
	EXIT,//0
	ADD,//1
	DEL,//2
	SEARCH,//3
	MODIFY,//4
	SHOW,//5
	SORT//6
};

int main()
{
	int input = 0;
	//创建通讯录
	Contact con;//通讯录
	//初始化通讯录
	InitContact(&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 SHOW:
			ShowContact(&con);
			break;
		case SORT:
			SortContactAge(&con);
			break;
		case EXIT:
			//保存信息到文件
			SaveContact(&con);
			//销毁通讯录
			DestoryContact(&con);
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误,请重新选择!\n");
			break;
		}

	} while (input);

	return 0;
}

 🌻(contact.h)

#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>

#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30

#define MAX 100

#define DEFAULT_SZ 3
#define DEFAULT_INC 2

typedef struct PeoInfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}PeoInfo;

//创建通讯录
//静态通讯录的版本
//typedef struct Contact
//{
//	PeoInfo data[MAX];//存放数据
//	int sz;//记录当前通讯录中存放的人的信息个数
//}Contact;

//动态通讯录的版本
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 ModifyContact(Contact* pc);

//排序联系人
void SortContactAge(Contact* pc);

//销毁通讯录
void DestoryContact(Contact* pc);

//保存信息到文件中
void SaveContact(Contact* pc);

//加载文件中的信息到通讯录
void LoadContact(Contact* pc);

 🌻(contact.c)

#include "Contact.h"

//初始化通讯录
// 静态版本
//void InitContact(Contact* pc)
//{
//	assert(pc);//保证指针的有效性
//
//	memset(pc->data, 0, sizeof(pc->data));
//	pc->sz = 0;
//}

void Checkcapacity(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))
	{
		Checkcapacity(pc);
		pc->data[pc->sz] = tmp;
		pc->sz++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}


//文件版本的初始化函数
void InitContact(Contact* pc)
{
	assert(pc);//保证指针的有效性

	pc->sz = 0;
	pc->capacity = DEFAULT_SZ;
	pc->data = calloc(DEFAULT_SZ, sizeof(PeoInfo));
	if (pc->data == NULL)
	{
		perror("InitContact->calloc");
		return;
	}
	//加载文件中的信息到通讯录
	LoadContact(pc);
}

动态版本的初始化函数
//void InitContact(Contact* pc)
//{
//	assert(pc);//保证指针的有效性
//
//	pc->sz = 0;
//	pc->capacity = DEFAULT_SZ;
//	pc->data = calloc(DEFAULT_SZ , sizeof(PeoInfo));
//	if (pc->data == NULL)
//	{
//		perror("InitContact->calloc");
//		return;
//	}
//}

//增加联系人信息
//静态版本
//void AddContact(Contact* pc)
//{
//	assert(pc);
//
//	//判断通讯录是否已满
//	if (pc->sz == MAX)
//	{
//		printf("通讯录已满,无法增加\n");
//		return;
//	}
//	//增加信息
//	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].tele);
//	printf("请输入联系人的地址:");
//	scanf("%s", pc->data[pc->sz].addr);
//
//	pc->sz++;
//	printf("联系人添加成功\n");
//}

void Checkcapacity(Contact* pc)
{
	if (pc->sz == pc->capacity)
	{
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + DEFAULT_INC) * sizeof(PeoInfo));
		if (ptr != NULL)
		{
			pc->data = ptr;
			pc->capacity += DEFAULT_INC;
			printf("增容成功!\n");
		}
		else
		{
			perror("AddContact->recalloc");
			return;
		}
	}
}

//动态版本
 void AddContact(Contact* pc)
{
	assert(pc);
	//增加容量
	Checkcapacity(pc);
	
	//增加信息
	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].tele);
	printf("请输入联系人的地址:");
	scanf("%s", pc->data[pc->sz].addr);

	pc->sz++;
	printf("联系人添加成功\n");
}

//显示所有联系人的信息
void ShowContact(const Contact* pc)
{
	assert(pc);

	//判断通讯录是否为空,如果为空,则无需打印
	if (pc->sz == 0)
	{
		printf("通讯录为空!\n");
		return;
	}

	//为了增加美观性,打印标题行
	printf("%-20s%-5s%-5s%-15s%-30s\n", "姓名", "年龄", "性别", "电话", "地址");
	for (int i = 0; i < pc->sz; i++)
	{
		printf("%-20s%-5d%-5s%-15s%-30s\n", 
			pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
	}
}

//查找联系人
int FindByContact(Contact* pc, char name[])
{
	assert(pc);

	for (int i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

//删除联系人的信息
void DelContact(Contact* pc)
{
	assert(pc);
	char name[NAME_MAX];

	//判断通讯录是否为空,如果为空,则无需删除
	if (pc->sz == 0)
	{
		printf("通讯录为空,无需删除\n");
		return;
	}

	//查找联系人
	printf("请输入要删除联系人的名字:");
	scanf("%s", name);
	int ret = FindByContact(pc, name);
	if (ret == -1)
	{
		printf("查无此人\n");
		return;
	}
	//删除联系人
	for (int i = ret; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除成功\n");
}

//查找联系人的信息
void SearchContact(Contact* pc)
{
	assert(pc);
	char name[NAME_MAX];
	printf("请输入要查找人的姓名:");
	scanf("%s", name);
	int ret = FindByContact(pc, name);
	if (ret == -1)
	{
		printf("查无此人\n");
		return;
	}
	//显示联系人
	printf("%-20s%-5s%-5s%-15s%-30s\n", "姓名", "年龄", "性别", "电话", "地址");
	printf("%-20s%-5d%-5s%-15s%-30s\n",
		pc->data[ret].name, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].tele, pc->data[ret].addr);
}

//修改联系人
void ModifyContact(Contact* pc)
{
	int input = 0;
	assert(pc);
	char name[NAME_MAX];
	printf("请输入要修改人的姓名:");
	scanf("%s", name);
	int ret = FindByContact(pc, name);
	if (ret == -1)
	{
		printf("查无此人\n");
		return;
	}
	
	do
	{
		printf("请选择要修改的信息:%s %s %s %s %s %s\n", "1.姓名", "2.年龄", "3.性别", "4.电话", "5.地址", "0.退出");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("请输入要修改人的姓名:\n");
			scanf("%s", pc->data[ret].name);
			printf("修改成功\n");
			break;
		case 2:
			printf("请输入要修改人的年龄:\n");
			scanf("%d", &(pc->data[ret].age));
			printf("修改成功\n");
			break;
		case 3:
			printf("请输入要修改人的性别:\n");
			scanf("%s", pc->data[ret].sex);
			printf("修改成功\n");
			break;
		case 4:
			printf("请输入要修改人的电话:\n");
			scanf("%s", pc->data[ret].tele);
			printf("修改成功\n");
			break;
		case 5:
			printf("请输入要修改人的地址:\n");
			scanf("%s", pc->data[ret].addr);
			printf("修改成功\n");
			break;
		case 0:
			printf("退出修改\n");
			break;
		default:
			printf("修改项中没有此信息,请重新选择\n");
			break;
		}
	} while (input);
}

//比较函数,用于qsort排序
int compareByAge(const void* a, const void* b)
{
	return ((PeoInfo*)a)->age - ((PeoInfo*)b)->age;
}

//排序联系人
void SortContactAge(Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,无需排序!\n");
		return;
	}
	qsort(pc->data, pc->sz, sizeof(PeoInfo), compareByAge);
	printf("%-20s%-5s%-5s%-15s%-30s\n", "姓名", "年龄", "性别", "电话", "地址");
	for (int i = 0; i < pc->sz; i++)
	{
		printf("%-20s%-5d%-5s%-15s%-30s\n",
			pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
	}

	printf("排序成功!\n");
}

//销毁通讯录
void DestoryContact(Contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->sz = 0;
	pc->capacity = 0;
}

//保存信息到文件中去
void SaveContact(Contact* pc)
{
	//打开文件
	FILE* pf = fopen("contact.txt", "wb");
	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;
}

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

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

相关文章

RUST与RUSTful简介

RUST与RUSTful 1、背景2、RUST的起源3、RUST与RUSTful4、总结 1、背景 随着互联网&#xff08;Internet&#xff09;的发展&#xff0c;越来越多的人开始意识到&#xff0c;网站即软件&#xff0c;而且是一种新型的软件。这种"互联网软件"采用客户端/服务器&#xff…

el-table设置默认选中报错_this.$refs.singleTable.toggleAllSelection is not a function

直接使用以下的方法&#xff0c;报错信息是_this.$refs.singleTable.toggleAllSelection is not a function this.$refs.singleTable.toggleAllSelection()看了网上的解决方法&#xff0c;加了this.$nextTick,代码如下&#xff0c;但还是报错Error in nextTick: "TypeErr…

ubuntu部署llama2-chinese

ubuntu上安装cuda见之前的blog&#xff0c;已安装cuda12&#xff0c;使用nvcc-V 下载llama2-chinese&#xff1a;GitHub - FlagAlpha/Llama2-Chinese: Llama中文社区&#xff0c;最好的中文Llama大模型&#xff0c;完全开源可商用 conda create -n llamachinese python3.10 pi…

构建高效的研发管理体系

目录 一、什么是研发管理体系 二、研发管理体系有哪些 1、 基于CMMI的研发体系 ​2、基于IPD的研发体系 3、 基于敏捷模式的研发体系 三、研发管理的痛点 四、如何构建高效的研发管理体系 一、什么是研发管理体系 研发管理就是在研发体系结构设计的基础之上&#xff0…

[网络安全]在win2000虚拟机上创建隐藏账户

目录 1.winR->cmd->regedt32 2.新建账号&#xff0c;例如HiddenAccount$($表示在命令行下不现实此用户&#xff09; 3.winR->cmd->regedit 3.将HiddenAccount$删掉 4.最后一步 手工创建隐藏账户 1.你需要一台win2000 2.winR->cmd->regedt32 增加HEY_LOAC…

3A服务器 (hcia)

原理 认证&#xff1a;验证用户是否可以获得网络访问权。 授权&#xff1a;授权用户可以使用哪些服务。 计费&#xff1a;记录用户使用网络资源的情况 实验 步骤 1.配置ip地址 2.配置认证服务器 aaa authentication-scheme datacom&#xff08;认证服务器名字&#xf…

21 Vue3中使用v-for遍历对象数组

概述 使用v-for遍历对象数组在真实的开发中也属于非常常见的用法&#xff0c;需要重点掌握。 因为目前流行的是前后端分离开发&#xff0c;在前后端分离开发中&#xff0c;最常需要处理的就是对象数组类型的数据了。 比如&#xff0c;将员工信息渲染到表格中。 这节课我们就…

如何建立一套完整的私域运营体系?

所有人都告诉你&#xff0c;今年必须做私域&#xff0c;但从没有人说清楚怎么做私域。你以为做私域就像瑞星咖啡一样&#xff0c;随便拉个群、发发券就能年入100个小目标。或者你认为最后还是微商最有效&#xff0c;每天狂刷100条朋友圈。但这样的私域一定活不过30天。因为没有…

回顾丨2023 SpeechHome 第三届语音技术研讨会

下面是整体会议的内容回顾&#xff1a; 18日线上直播回顾 18日上午9:30&#xff0c;AISHELL & SpeechHome CEO卜辉宣布研讨会开始&#xff0c;并简要介绍本次研讨会的筹备情况以及报告内容。随后&#xff0c;CCF语音对话与听觉专委会副主任、清华大学教授郑方&#xff0c…

oracle定位造成卡顿的SQL语句

先查询阻塞的会话号 select event,machine,sql_id,program,blocking_session from dba_hist_active_sess_history where SAMPLE_TIME between TO_TIMESTAMP (2021-08-25 15:25:00, YYYY-MM-DD HH24:MI:SS) and TO_TIMESTAMP (2021-08-25 15:30:00, YYYY-MM-DD HH24:MI:SS) and …

【Linux】进程周边006之进程地址空间

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.程序地址空间 1.1验证地址…

Git 储藏(stash)用法

储藏的基本用法 保存当前的更改 1、查看储藏 git stash list2、更改保存到一个储藏中&#xff1a; git stash save "info"其中&#xff0c;“info” 是可选的注释信息&#xff0c;可以简要描述这个储藏的内容。 3、恢复之前保存的更改 可以使用下面的命令将之前…

Qt之判断一个点是否在多边形内部(射线法)

算法思想: 以被测点Q为端点,向任意方向作射线(一般水平向右作射线),统计该射线与多边形的交点数。如果为奇数,Q在多边形内;如果为偶数,Q在多边形外。计数的时候会有一些特殊情况。这种方法适用于任意多边形,不需要考虑精度误差和多边形点给出的顺序,时间复杂度为O(n)…

Java 第14章 集合 课堂练习

文章目录 HashSet判断是否两次add都能加入成功HashSet编码遍历HashMap判断输出中是否有"abc" HashSet判断是否两次add都能加入成功 HashSet set new HashSet(); set.add(new String("hsp")); set.add(new String("hsp"));第一次可以&#xff0…

HTML期末复习,重要知识点摘录

HTML复习知识点摘录 1.html基本模板 <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>菜鸟教程(runoob.com)</title> </head> <body><h1>我的第一个标题</h1> <p>我的第一个段落。…

Docker 文件和卷 权限拒绝

一 创作背景 再复制Docker影像文件或访问Docker容器内已安装卷上的文件时我们常常会遇到&#xff1a;“权限被拒绝”的错误&#xff0c;在此&#xff0c;您将了解到为什么会出现“权限被拒绝”的错误以及如何解决这个问题。 二 目的 在深入探讨 Docker 容器中的 Permission De…

如何使用Docker搭建青龙面板并结合内网穿透工具发布至公网可访问

文章目录 一、前期准备本教程环境为&#xff1a;Centos7&#xff0c;可以跑Docker的系统都可以使用。本教程使用Docker部署青龙&#xff0c;如何安装Docker详见&#xff1a; 二、安装青龙面板三、映射本地部署的青龙面板至公网四、使用固定公网地址访问本地部署的青龙面板 正文…

TikTok获客工具开发必不可少的功能!

随着TikTok在全球范围内的走红&#xff0c;越来越多的企业开始关注这个平台并尝试从中获取客户&#xff0c;为了满足这一需求&#xff0c;市场上涌现出了许多TikTok获客工具。 这些工具的功能各有千秋&#xff0c;但有一些功能是必不可少的&#xff0c;本文将为您介绍TikTok获…

FMCW雷达仿真:基于L形阵列4D点云获取

摘要&#xff1a;本期内容为3D点云目标获取的延续工作&#xff0c;在距离、速度、方位角估计的基础上&#xff0c;通过设计L型阵列结构&#xff0c;进一步实现目标俯仰角的估计&#xff0c;最终实现目标4-D点云的获取。首先&#xff0c;通过中频信号建立仿真信号模型&#xff0…

MySQL中替换字符串中的指定部分之REPLACE函数

REPLACE函数是用来替换字符串中的指定部分内容的。在本文中&#xff0c;将介绍如何在MySQL中使用REPLACE函数进行字符串替换 REPLACE函数的语法&#xff1a; REPLACE(str, search_str, replace_str) 其中&#xff0c;str是要进行替换操作的字符串&#xff0c;search_str是要搜…