不会写通讯录,你就是“文”盲

2023-11-16

目录

一、通讯录的实现(静态版)

1.1文件的创建

1.2通讯录要存放的信息

1.3通讯录的功能

1.4通讯录的创建

1.5菜单打印以及基本逻辑的实现

 1.6初始化通讯录

 1.7增加联系人

1.8显示联系人

 1.9删除联系人

 1.10查找联系人

 1.11修改联系人

 1.12按名字排序

1.13完整代码

二、通讯录的实现(动态版)

2.1通讯录的创建

2.2初始化通讯录

2.3增加联系人

 2.4完整代码


前言:这篇文章博主带着大家一步一步实现通讯录,让你不在是“文”盲。

一、通讯录的实现(静态版)

1.1文件的创建


                test.c               测试通讯录 

                contcat.h        函数和类型的声明

                contcat.c        函数的实现

在实现通讯录的程序中,我们使用多文件编程,真是为什么呢?

多文件编程的好处:

1.方便代码复用:模块化的代码可以很方便的迁移到其他项目中。

2.方便分工合作:各个功能模块分成多个文件同时编辑,可以有效地提高团队分工合作的效率 

3.便于后续维护:当程序出现错误时,可以分模块进行排查,可以提高效率,使程序更加容易管理 

头文件的作用

我们可以将函数、数据的声明,宏的定义,库函数所用到的头文件放在一起,在源文件中只要引用

#include “contact.h”就可以实现,这样可以减少代码的重复编写,提高效率。 

1.2通讯录要存放的信息

我们要是一个可以存放100个人信息的通讯录 

创建一个结构体,结构体中放我们要存的信息,姓名、年龄、性别、电话号、住址。

typedef struct PeoInfo
{
	char name[10];
	int age;
	char sex[5];
	char tele[12];
	char addr[15];
}PeoInfo;

1.3通讯录的功能

1.增加联系人                                                        2.删除联系人

3.查找联系人                                                        4.修改联系人

5.显示所有联系人                                                 6.对联系人排序

1.4通讯录的创建

        PeoInfo  date[100];

        int  sz = 0;

我们创建好可以存放100个人的通讯录后,还要创建一个变量sz来记录通讯录中存放的人数,所以这两个变量要绑定在一起。我们在创建一个结构体,这样在传参时会更方便。

typedef struct Contact
{
	PeoInfo date[100];
	int sz;
}Contact;

1.5菜单打印以及基本逻辑的实现

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

void test()
{
	int input = 0;
	Contact con;		//通讯录
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			break;
		case 2:
			break;
		case 3:
			break;
		case 4:
			break;
		case 5:
			break;
		case 6:
			break;
		case 0:
			printf("退出通讯录\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
}

int main()
{
	test();
	return 0;
}

在case语句里,别人使用我们的代码并不知道1,2,3……代表的是什么功能,所以我们可以使用枚举,让使用者了解我们的功能,提高代码可读性

优化代码: 

enum OPTION
{
	Exit,
	Add,
	Del,
	Serach,
	Modify,
	Show,
	Sort
 };
        case Add:
			break;
		case Del:
			break;
		case Serach:
			break;
		case Modify:
			break;
		case Show:
			break;
		case Sort:
			break;
		case Exit:
			printf("退出通讯录\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;

 1.6初始化通讯录

初始化通讯录,我们要改变里面的内容,所以我们要传指针过去。注意要在头文件中对函数声明。

  

void InitContact(Contact* pc)
{
	memset(pc->date, 0, sizeof(pc->date));
	pc->sz = 0;
}

 1.7增加联系人

我们要考虑通讯录有没有满,如果没有满添加的联系人放到下标sz的地方。我们要使用pc指针,所以用assert断言指针是否有效。

void AddContact(Contact* pc)
{
    assert(pc);
	if (pc->sz == MAX)
	{
		printf("通讯录已满,无法添加\n");
		return;
	}

	printf("请输入名字:>");
	scanf("%s", pc->date[pc->sz].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->date[pc->sz].name));
	printf("请输入性别:>");
	scanf("%s", pc->date[pc->sz].sex);
	printf("请输入电话:>");
	scanf("%s", pc->date[pc->sz].tele);
	printf("请输入地址:>");
	scanf("%s", pc->date[pc->sz].addr);
	
	pc->sz++;
	printf("添加成功\n");
}

1.8显示联系人

我们只是显示联系人的数据,不会修改通讯录中的内容,所以在声明时用const修饰:

        void ShowContact(const Contact* pc);

void ShowContact(const Contact* pc)
{
	assert(pc);
	//打印标题
	printf("%-10s\t%-4s\t%-5s\t%-12s\t%-10s\n", "姓名", "年龄", "性别", "电话", "地址");
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-10s\t%-4d\t%-5s\t%-12s\t%-10s\n", pc->date[i].name,
			                                   pc->date[i].age,
			                                   pc->date[i].sex,
			                                   pc->date[i].tele,
			                                   pc->date[i].addr);
	}
}

注意:有 ‘ - ’ 是左对齐,没有 ‘ - ’ 是右对齐。

 1.9删除联系人

我们要考虑通信录中是否存在要删除的联系人,所以我们定义一个flag标签。

void DelContact(Contact* pc)
{
	assert(pc);
    if (pc->sz == 0)
	    {
		    printf("通讯录为空,无法删除\n");
	    }
	char name[20] = { 0 };
	int del = 0;
	int flag = 0;
	printf("要删除的联系人:>");
	scanf("%s", name);
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->date[i].name, name) == 0)
		{
			del = i;
			flag = 1;
			break;
		}
	}

	if (flag == 0)
	{
		printf("要删除的联系人不存在\n");
		return;
	}

	for (i = del; i < pc->sz - 1; i++)
	{
		pc->date[i] = pc->date[i + 1];
	}

	pc->sz--;
	printf("成功删除联系人\n");
}

在删除,查找,修改的功能中都有查找的程序,所以我们可以把查找的功能封装成一个函数,更加方便 。

优化代码:

int FindByname(Contact* pc, char name[])
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->date[i].name, name) == 0)
		{
			return i;
		}
	}

	return -1;
}



void DelContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除\n");
	}
	char name[20] = { 0 };
	int flag = 0;
	printf("要删除的联系人:>");
	scanf("%s", name);


	int del = FindByname(pc, name);
	if (del == -1)
	{
		printf("要删除的联系人不存在\n");
		return;
	}

	int i = 0;
	for (i = del; i < pc->sz - 1; i++)
	{
		pc->date[i] = pc->date[i + 1];
	}

	pc->sz--;
	printf("成功删除联系人\n");
}

 1.10查找联系人

使用上面封装好的查找的函数,如果我们要查找的人存在,就把信息打印在屏幕上。

void SearchContact(const Contact* pc)
{
	assert(pc);
	char name[20] = { 0 };
	printf("请输入要查找人的名字:>");
	scanf("%s", name);
	int pos = FindByname(pc, name);
	if (pos == -1)
	{
		printf("要查找的人不存在\n");
	}
	else
	{
		printf("%-10s\t%-4s\t%-5s\t%-12s\t%-10s\n", "姓名", "年龄", "性别", "电话", "地址");

		printf("%-10s\t%-4d\t%-5s\t%-12s\t%-10s\n", pc->date[pos].name,
				                                 	pc->date[pos].age,
				                                    pc->date[pos].sex,
				                                    pc->date[pos].tele,
				                                    pc->date[pos].addr);
		
	}

}

 1.11修改联系人

使用上面封装好的查找的函数,要修改的人存在就重新录入它的信息。

void ModifyContact(Contact* pc)
{
	assert(pc);
	char name[20] = { 0 };
	printf("请输入要修改的人的名字:>");
	scanf("%s", name);
	int pos = FindByname(pc, name);
	if (pos == -1)
	{
		printf("要修改的人不存在\n");
	}
	else
	{
		printf("请输入名字:>");
		scanf("%s", pc->date[pos].name);
		printf("请输入年龄:>");
		scanf("%d", &(pc->date[pos].age));
		printf("请输入性别:>");
		scanf("%s", pc->date[pos].sex);
		printf("请输入电话:>");
		scanf("%s", pc->date[pos].tele);
		printf("请输入地址:>");
		scanf("%s", pc->date[pos].addr);
	}
	printf("修改成功\n");
}

 1.12按名字排序

case Sort:
		//按名字排序
		qsort(con.date, con.sz, sizeof(PeoInfo), cmp_by_name);
        break;


int cmp_by_name(const void* p1, const void* p2)
{
	return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);
}

1.13完整代码

contact.h

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <assert.h>

#define MAX 100

typedef struct PeoInfo
{
	char name[20];
	int age;
	char sex[5];
	char tele[12];
	char addr[15];
}PeoInfo;


typedef struct Contact
{
	PeoInfo date[MAX];
	int sz;
}Contact;

enum OPTION
{
	Exit,
	Add,
	Del,
	Serach,
	Modify,
	Show,
	Sort
 };

//函数声明

//初始化
void InitContact(Contact* pc);

//增加联系人
void AddContact(Contact* pc);

//显示联系人
void ShowContact(const Contact* pc);

//删除联系人
void DelContact(Contact* pc);

//查找联系人
void SearchContact(const Contact* pc);

//修改联系人
void ModifyContact(Contact* pc);

//排序
int cmp_by_name(const void* p1, const void* p2);

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

void test()
{
	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 Serach:
			SearchContact(&con);
			break;
		case Modify:
			ModifyContact(&con);
			break;
		case Show:
			ShowContact(&con);
			break;
		case Sort:
			//按名字排序
			qsort(con.date, con.sz, sizeof(PeoInfo), cmp_by_name);
			break;
		case Exit:
			printf("退出通讯录\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
}

int main()
{
	test();
	return 0;
}

contact.c

#include "contact.h"

void InitContact(Contact* pc)
{
	memset(pc->date, 0, sizeof(pc->date));
	pc->sz = 0;
}


void AddContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == MAX)
	{
		printf("通讯录已满,无法添加\n");
		return;
	}

	printf("请输入名字:>");
	scanf("%s", pc->date[pc->sz].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->date[pc->sz].age));
	printf("请输入性别:>");
	scanf("%s", pc->date[pc->sz].sex);
	printf("请输入电话:>");
	scanf("%s", pc->date[pc->sz].tele);
	printf("请输入地址:>");
	scanf("%s", pc->date[pc->sz].addr);
	
	pc->sz++;
	printf("添加成功\n");
}


void ShowContact(const Contact* pc)
{
	assert(pc);
	//打印标题
	printf("%-10s\t%-4s\t%-5s\t%-12s\t%-10s\n", "姓名", "年龄", "性别", "电话", "地址");
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-10s\t%-4d\t%-5s\t%-12s\t%-10s\n", pc->date[i].name,
			                                   pc->date[i].age,
			                                   pc->date[i].sex,
			                                   pc->date[i].tele,
			                                   pc->date[i].addr);
	}
}


int FindByname(Contact* pc, char name[])
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->date[i].name, name) == 0)
		{
			return i;
		}
	}

	return -1;
}


void DelContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除\n");
	}
	char name[20] = { 0 };
	int flag = 0;
	printf("要删除的联系人:>");
	scanf("%s", name);
	/*int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->date[i].name, name) == 0)
		{
			del = i;
			flag = 1;
			break;
		}
	}

	if (flag == 0)
	{
		printf("要删除的联系人不存在\n");
		return;
	}*/

	int del = FindByname(pc, name);
	if (del == -1)
	{
		printf("要删除的联系人不存在\n");
		return;
	}

	int i = 0;
	for (i = del; i < pc->sz - 1; i++)
	{
		pc->date[i] = pc->date[i + 1];
	}

	pc->sz--;
	printf("成功删除联系人\n");
}



void SearchContact(const Contact* pc)
{
	assert(pc);
	char name[20] = { 0 };
	printf("请输入要查找人的名字:>");
	scanf("%s", name);
	int pos = FindByname(pc, name);
	if (pos == -1)
	{
		printf("要查找的人不存在\n");
	}
	else
	{
		printf("%-10s\t%-4s\t%-5s\t%-12s\t%-10s\n", "姓名", "年龄", "性别", "电话", "地址");

		printf("%-10s\t%-4d\t%-5s\t%-12s\t%-10s\n", pc->date[pos].name,
				                                 	pc->date[pos].age,
				                                    pc->date[pos].sex,
				                                    pc->date[pos].tele,
				                                    pc->date[pos].addr);
		
	}

}


void ModifyContact(Contact* pc)
{
	assert(pc);
	char name[20] = { 0 };
	printf("请输入要修改的人的名字:>");
	scanf("%s", name);
	int pos = FindByname(pc, name);
	if (pos == -1)
	{
		printf("要修改的人不存在\n");
	}
	else
	{
		printf("请输入名字:>");
		scanf("%s", pc->date[pos].name);
		printf("请输入年龄:>");
		scanf("%d", &(pc->date[pos].age));
		printf("请输入性别:>");
		scanf("%s", pc->date[pos].sex);
		printf("请输入电话:>");
		scanf("%s", pc->date[pos].tele);
		printf("请输入地址:>");
		scanf("%s", pc->date[pos].addr);
	}
	printf("修改成功\n");
}

int cmp_by_name(const void* p1, const void* p2)
{
	return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);
}

二、通讯录的实现(动态版)

改造的目标:

1.通讯录的大小不是固定的,大小是可以调整的。

2.默认初始能放三个人的信息,如果不够,每次增加两个人的信息。

2.1通讯录的创建

动态版本就不用数组来创建,使用malloc函数创建空间。还需要一个变量来存储我们通讯录的最大容量,当存储的信息到达最大容量,我们可以增容。

typedef struct Contact
{
	PeoInfo* date;    //指向存放数据的空间
	int sz;            //当前通讯录存储的信息的个数
    int cap;           //通讯录当前最大容量 
}Contact;    

2.2初始化通讯录

使用动态内存函数要引用头文件

        #include  <stdlib.h>

我们初始为开始可以存放三个人的信息。 

void InitContact(Contact* pc)
{
	assert(pc);
	pc->date = (PeoInfo*)malloc(3 * sizeof(PeoInfo));
	if (pc->date == NULL)
	{
		perror("InitContact");
        return;
	}
	pc->sz = 0;
	pc->cap = DEFAULT_SZ;
}

2.3增加联系人

在动态版本中不存在填满的情况,我们要判断增容。在填满的情况下,每次增加两个。我们使用的初始容量和要增加的量可以使用define定义。

#define DEFAULT_SZ 3
#define INC_SZ 2

如果增容成功或不需要增容,返回1,增加联系人;如果增容失败,返回0。

int CheckCapacity(Contact* pc)
{
	if (pc->sz == pc->cap)
	{
		PeoInfo* ptr=(PeoInfo*)realloc(pc->date, (pc->cap + INC_SZ) * sizeof(PeoInfo));
		if (ptr == NULL)
		{
			perror("CheckCapacity");
			return 0;
		}
		else
		{
			pc->date = ptr;
			pc->cap += INC_SZ;
			printf("增容成功\n");
			return 1;
		}
	}
	return 1;
}



void AddContact(Contact* pc)
{
	assert(pc);
	if (0 == CheckCapacity(pc))
	{
		return;
	}

	printf("请输入名字:>");
	scanf("%s", pc->date[pc->sz].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->date[pc->sz].age));
	printf("请输入性别:>");
	scanf("%s", pc->date[pc->sz].sex);
	printf("请输入电话:>");
	scanf("%s", pc->date[pc->sz].tele);
	printf("请输入地址:>");
	scanf("%s", pc->date[pc->sz].addr);

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

 2.4完整代码

contact,h

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

#define MAX 100
#define DEFAULT_SZ 3
#define INC_SZ 2

typedef struct PeoInfo
{
	char name[20];
	int age;
	char sex[5];
	char tele[12];
	char addr[15];
}PeoInfo;


typedef struct Contact
{
	PeoInfo* date;    //指向存放数据的空间
	int sz;            //当前通讯录存储的信息的个数
	int cap;           //通讯录当前最大容量 
}Contact;

enum OPTION
{
	Exit,
	Add,
	Del,
	Serach,
	Modify,
	Show,
	Sort
};

//函数声明

//初始化
void InitContact(Contact* pc);

//增加联系人
void AddContact(Contact* pc);

//显示联系人
void ShowContact(const Contact* pc);

//删除联系人
void DelContact(Contact* pc);

//查找联系人
void SearchContact(const Contact* pc);

//修改联系人
void ModifyContact(Contact* pc);

//排序
int cmp_by_name(const void* p1, const void* p2);

//释放
void DestoryContact(Contact* pc);

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

void test()
{
	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 Serach:
			SearchContact(&con);
			break;
		case Modify:
			ModifyContact(&con);
			break;
		case Show:
			ShowContact(&con);
			break;
		case Sort:
			//按名字排序
			qsort(con.date, con.sz, sizeof(PeoInfo), cmp_by_name);
			break;
		case Exit:
			DestoryContact(&con);
			printf("退出通讯录\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
}

int main()
{
	test();
	return 0;
}

contact.c

#include "contact.h"


void InitContact(Contact* pc)
{
	assert(pc);
	pc->date = (PeoInfo*)malloc(DEFAULT_SZ * sizeof(PeoInfo));
	if (pc->date == NULL)
	{
		perror("InitContact");
		return;
	}
	pc->sz = 0;
	pc->cap = DEFAULT_SZ;
}


int CheckCapacity(Contact* pc)
{
	if (pc->sz == pc->cap)
	{
		PeoInfo* ptr=(PeoInfo*)realloc(pc->date, (pc->cap + INC_SZ) * sizeof(PeoInfo));
		if (ptr == NULL)
		{
			perror("CheckCapacity");
			return 0;
		}
		else
		{
			pc->date = ptr;
			pc->cap += INC_SZ;
			printf("增容成功\n");
			return 1;
		}
	}
	return 1;
}


void AddContact(Contact* pc)
{
	assert(pc);
	if (0 == CheckCapacity(pc))
	{
		return;
	}

	printf("请输入名字:>");
	scanf("%s", pc->date[pc->sz].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->date[pc->sz].age));
	printf("请输入性别:>");
	scanf("%s", pc->date[pc->sz].sex);
	printf("请输入电话:>");
	scanf("%s", pc->date[pc->sz].tele);
	printf("请输入地址:>");
	scanf("%s", pc->date[pc->sz].addr);

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

void ShowContact(const Contact* pc)
{
	assert(pc);
	//打印标题
	printf("%-10s\t%-4s\t%-5s\t%-12s\t%-10s\n", "姓名", "年龄", "性别", "电话", "地址");
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-10s\t%-4d\t%-5s\t%-12s\t%-10s\n", pc->date[i].name,
			pc->date[i].age,
			pc->date[i].sex,
			pc->date[i].tele,
			pc->date[i].addr);
	}
}


int FindByname(Contact* pc, char name[])
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->date[i].name, name) == 0)
		{
			return i;
		}
	}

	return -1;
}


void DelContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除\n");
	}
	char name[20] = { 0 };
	int flag = 0;
	printf("要删除的联系人:>");
	scanf("%s", name);
	/*int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->date[i].name, name) == 0)
		{
			del = i;
			flag = 1;
			break;
		}
	}

	if (flag == 0)
	{
		printf("要删除的联系人不存在\n");
		return;
	}*/

	int del = FindByname(pc, name);
	if (del == -1)
	{
		printf("要删除的联系人不存在\n");
		return;
	}

	int i = 0;
	for (i = del; i < pc->sz - 1; i++)
	{
		pc->date[i] = pc->date[i + 1];
	}

	pc->sz--;
	printf("成功删除联系人\n");
}



void SearchContact(const Contact* pc)
{
	assert(pc);
	char name[20] = { 0 };
	printf("请输入要查找人的名字:>");
	scanf("%s", name);
	int pos = FindByname(pc, name);
	if (pos == -1)
	{
		printf("要查找的人不存在\n");
	}
	else
	{
		printf("%-10s\t%-4s\t%-5s\t%-12s\t%-10s\n", "姓名", "年龄", "性别", "电话", "地址");

		printf("%-10s\t%-4d\t%-5s\t%-12s\t%-10s\n", pc->date[pos].name,
			pc->date[pos].age,
			pc->date[pos].sex,
			pc->date[pos].tele,
			pc->date[pos].addr);

	}

}


void ModifyContact(Contact* pc)
{
	assert(pc);
	char name[20] = { 0 };
	printf("请输入要修改的人的名字:>");
	scanf("%s", name);
	int pos = FindByname(pc, name);
	if (pos == -1)
	{
		printf("要修改的人不存在\n");
	}
	else
	{
		printf("请输入名字:>");
		scanf("%s", pc->date[pos].name);
		printf("请输入年龄:>");
		scanf("%d", &(pc->date[pos].age));
		printf("请输入性别:>");
		scanf("%s", pc->date[pos].sex);
		printf("请输入电话:>");
		scanf("%s", pc->date[pos].tele);
		printf("请输入地址:>");
		scanf("%s", pc->date[pos].addr);
	}
	printf("修改成功\n");
}

int cmp_by_name(const void* p1, const void* p2)
{
	return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);
}


void DestoryContact(Contact* pc)
{
	free(pc->date);
	pc->date = NULL;
	pc->cap = 0;
	pc->sz = 0;
}

本次的内容到这里就结束啦。希望大家阅读完可以有所收获,同时也感谢各位读者三连支持。文章有问题可以在评论区留言,博主一定认真认真修改,以后写出更好的文章。 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

不会写通讯录,你就是“文”盲 的相关文章

  • 如何将这段 javascript 代码重写为 C++11?

    这是我在 Javascript Definitive Guide 中看到的 javascript 闭包代码 我想把它写成C 11 var uniqueID1 function var id 0 return function return
  • 什么定义了类型的大小?

    ISO C 标准规定 sizeof char lt sizeof short lt sizeof int lt sizeof long 我在 BIT Linux mint 19 1 上使用 GCC 8 大小为long int is 8 我正
  • 如何在 ASP.NET MVC 中将 XML 文件发送到客户端

    在 ASP NET MVC 中 我有一个数据库表 我想在某个视图页面上有一个按钮 如果某个用户单击该按钮 我的应用程序将生成包含数据库中所有行的 XML 文件 然后 应将包含 XML 的文件发送到客户端 以便用户看到下载弹出窗口 同样 我希
  • 如何使用 Entity Framework 和 Identity 解决对象处置异常 ASP.NET Core

    我正在尝试编写一个控制器 该控制器接收来自 AJAX 调用的请求并通过 DBContext 对数据库执行一些调用 但是 当我发出命令时var user await GetCurrentUserAsynch 在对 DBContext 的任何调
  • Boost MPI 在监听列表时不会释放资源?

    这是一个后续问题如何释放 boost mpi request https stackoverflow com questions 44078901 how do i free a boostmpirequest 我在监听列表而不是单个项目时
  • 对 ExecuteNonQuery() 的单次调用是原子的

    对 ExecuteNonQuery 的单次调用是否是原子的 或者如果单个 DbCommand 中有多个 sql 语句 那么使用事务是否有意义 请参阅我的示例以进行说明 using var ts new TransactionScope us
  • C# 中 PKCS11Interop 库的线程安全使用 [已关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在使用 PKCS11Interop 在 HSM 内执行密钥管理操作 我使用的 HSM 是 Thales PCI Express 下面是
  • 如何从不同的线程访问控件?

    如何从创建控件的线程以外的线程访问控件 避免跨线程错误 这是我的示例代码 private void Form1 Load object sender EventArgs e Thread t new Thread foo t Start p
  • 从内存流播放视频文件

    只是好奇看看这是否可能 我有一个 Windows 应用程序 它从我的电脑上的 avi 文件读取所有字节 然后将其存储在 byte 中 现在我的内存中有 avi 文件 我想直接从内存将其加载到某种视频播放器控件中 我尝试过使用 wmplaye
  • 为什么像 BindingList 或 ObservableCollection 这样的类不是线程安全的?

    我一次又一次发现自己必须编写 BindingList 和 ObservableCollection 的线程安全版本 因为当绑定到 UI 时 这些控件无法从多个线程更改 我想理解的是why情况就是这样 这是设计错误还是故意的 问题是设计一个线
  • 如何使用 CUDA/Thrust 对两个数组/向量根据其中一个数组中的值进行排序

    这是一个关于编程的概念问题 总而言之 我有两个数组 向量 我需要对一个数组 向量进行排序 并将更改传播到另一个数组 向量中 这样 如果我对 arrayOne 进行排序 则对于排序中的每个交换 arrayTwo 也会发生同样的情况 现在 我知
  • 模板与非模板类,跨编译器的不同行为

    我在一些应用程序中使用编译时计数器 它确实很有用 昨天我想用 gcc 编译一个程序 我之前使用的是 msvc 并且计数器的行为在模板类中发生了变化 它在模板类中不再工作 过于简化的代码 Maximum value the counter c
  • 检查两个函数或成员函数指针的签名是否相等

    我编写了一些代码来检查自由函数的签名是否等于成员函数的签名等 它比较提取的返回类型和函数参数 include
  • 列表到优先队列

    我有一个 C 大学编程项目 分为两个部分 在开始第二部分时应该使用priority queues hash tables and BST s 我 至少 在优先级队列方面遇到了麻烦 因为它迫使我自己重做第一部分中已经实现的许多代码 该项目是关
  • 如何在 C++ 运行时更改 QML 对象的属性?

    我想在运行时更改 QML 对象的文本 我尝试如下 但文本仍然为空 这是后端类 class BackEnd public QObject Q OBJECT Q PROPERTY QString userFieldText READ userF
  • 本地时间的内存需要释放吗?

    void log time t current time 0 tm ptm localtime current stuf 只是想确定 我是否需要在方法结束时释放 tm 指针分配的内存 不 你不应该释放它 该结构是静态分配的 检查文档 htt
  • Windows 上本机 C++ 应用程序中的自动死代码检测?

    背景 我有一个用原生 C 编写的应用程序 花了几年的时间 大约有 60 KLOC 有很多函数和类已经死了 可能有 10 15 就像下面提出的类似的基于 Unix 的问题 我们最近开始对所有新代码进行单元测试 并尽可能将其应用于修改后的代码
  • 调试错误:在 vc++ 项目中使用 COM 时发生 所需的运行时?

    我为我的工作创建了一个 COM 组件 我也注册了该组件 在我的系统上 我有两个虚拟机工作站 在我的第一个工作站中 它运行良好 在我的第二个工作站中 它显示一个包含消息的错误框该程序需要一段时间并以不寻常的方式关闭 请联系应用程序管理员 我认
  • 实体框架读取列但阻止其更新

    给定一个数据库表 其中有一列包含历史数据但不再填充 实体框架中是否有一种方法可以读取该列 但在使用相同的模型对象时防止它被更新 例如我有一个对象 public class MyObject public string CurrentData
  • 强制函数调用的顺序?

    假设我有一个抽象基类 并且我想要一个必须由派生类实现的纯虚方法 但我想确保派生方法以特定顺序调用函数 我可以做什么来强制执行它 I E base class virtual void doABC 0 virtual void A 0 vir

随机推荐

  • keil开启代码提示功能

    如下图 设置步骤
  • 嵌入式学习之RTOS编程

    嵌入式学习之RTOS编程 一 题目要求 二 UCOSIII介绍 三 实验过程 1 STM32CubeMX设置 2 移植前准备 3 移植过程 4 构建任务 5 实验结果演示 一 题目要求 学习嵌入式实时操作系统 RTOS 以uc OS III
  • 【Unity】Destroy和DestroyImmediate的区别

    情景 有一个父物体A A有子物体B1 B2 B3 B10等10个子物体 那么现在若想移除B1 B10 该如何 我能想到的最简单是这样做 using UnityEngine using System Collections
  • C++11各编译器支持情况对比

    原文地址 http sd csdn net a 20120813 2808540 html C 11标准在去年8月份获得一致通过 这是自1998年后C 语言第一次大修订 对C 语言进行了改进和扩充 迄今为止已整整一年啦 想知道C 11在这一
  • feign和ribbon同时设置connectTimeout readTimeout,谁会先起作用

    feign client config default connectTimeout 1000000 readTimeout 1200000 hystrix enabled true ribbon eager load enable tru
  • C语言:计算两个数之和

    输入两个整数 计算它们的和 include
  • 3 5的二维数组C语言程序,C语言及程序设计提高例程-33 二维数组元素的引用

    贺老师教学链接 C语言及程序设计提高 本课讲解 输入输出二维数组元素 include int main int s 3 5 i j printf Input 3 5 numbers n for i 0 i lt 3 i for j 0 j
  • Redis 源码分析-数据结构及实现(字典dict)

    Redis字典介绍 Redis是K V型数据库 整个数据库是用字典来存储的 对Redis数据库进行任何增 删 改 查操作 实际就是对字典中的数据进行增 删 改 查操作 字典需要的特征 1 O 1 的时间复杂度取出或插入关联值 2 key 唯
  • wchar_t和char,WCHAR和CHAR的区别和互相转化

    win32应用程序的低层winnt h头文件 ifndef VOID define VOID void typedef char CHAR typedef short SHORT typedef long LONG if defined M
  • 微信公众号 H5 通联支付

    参考 https blog csdn net caimingxian401 article details 96993205 注意 必须使用 setTimeout 箭头函数延迟加载 1 使用 from 表单 提交数据至通联 2 绑定数据 3
  • 512色色谱图

    代码如下
  • 介绍uni-app框架,以及运行原理

    介绍uni app框架 uni app 是一个使用 Vue js 开发所有前端应用的框架 开发者编写一套代码 可发布到iOS Android Web 响应式 以及各种小程序 微信 支付宝 百度 头条 QQ 钉钉 淘宝 某些平台不能提交简单d
  • 干货丨RPA内网验证码识别技巧

    通常在一些网络安全等级比较高的大型客户里面 如银行 政府等 RPA的实现流程基本都是内网环境 没办法使用外网 那么这个时候针对一些客户端或者网银登录的字符型验证码识别 没办法通过UiBot调用公网环境中的OCR组件进行识别 或者使用需要外网
  • 卷积神经网络(CNN)

    卷积神经网络 一 摘要 卷积网络 Convolutional network 也叫神经网络 是一种专门用来处理具有类似网格结构的数据的神经网络 例如时间序列数据和图像数据 可以看做二维的像素网络 卷积网络在诸多应用领域表现得都比较出色 卷积
  • 【数模】预测模型

    一 灰色系统 白色系统 系统信息完全明确 灰色系统 系统部分信息已知 部分信息未知 对在一定范围内变化的 与时间有关的灰色过程进行预测 过程 原始数据找规律 生成强规律性的数据序列 建立微分方程来预测未来趋势 黑色系统 系统的内部信息未知
  • 基于 SSM 框架的学生在线选课系统设计

    系统概述 在线选课系统中包含教师 学生两种用户 学生登录 管理自己的账号信息 修改信息等 增加或移除课程 教师登录 对个人资料进行查看和密码的修改 维护课程信息 增加与删除课程 对学生的分数进行增加 修改和删除的操作 系统基本功能结构 教师
  • Octave 基本操作 from 吴恩达的机器学习

    1 数学运算 注 在octave中是注释符号 2 逻辑操作 XOR 注意 不等于符号的写法是这个波浪线加上等于符号 3 打印 2 直接打印 设置a等于圆周率 如果我要打印该值 那么只需键入a像这样就打印出来了 注 在赋值语句最后加入 号 即
  • IDEA导入SpringBoot项目或者Maven项目(详解大全)

    1 解压项目 解压出后 2 打开IDEA导入项目 点击 找到你的项目 打开项目 选择maven项目 点击finsh按钮 3 启动启动类 无反应 找到原因 是maven的问题 使用maven中clear命令测试出错 4 修改maven配置 这
  • 编译器何时调用默认构造函数

    总的来说 编译器只在它需要的时候才会合成一个默认构造函数 或者扩张所有已存在的构造函数 一个类满足下列其中任何一个条件 1 包含了一个类的对象 这个对象有一个构造函数 包括编译器合成的默认构造函数 2 如果继承自一些基类 其中某些基类有一个
  • 不会写通讯录,你就是“文”盲

    目录 一 通讯录的实现 静态版 1 1文件的创建 1 2通讯录要存放的信息 1 3通讯录的功能 1 4通讯录的创建 1 5菜单打印以及基本逻辑的实现 1 6初始化通讯录 1 7增加联系人 1 8显示联系人 1 9删除联系人 1 10查找联系