您现在的位置是:首页 >技术教程 >C语言—通讯录网站首页技术教程

C语言—通讯录

The August 2024-06-17 11:26:54
简介C语言—通讯录

通讯录的创建

通讯录中是存放人的信息的,人的信息包括:姓名、年龄、性别、电话、住址。可以把人的信息定义成结构体,因为每个联系人的信息都有这几个要素。

#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 12
#define MAX_ADDR 30

//类型的定义
typedef struct PeoInfo   //定义人的信息类型
{
	char name[MAX_NAME];
	char sex[MAX_SEX];
	int age;
	char tele[MAX_TELE];
	char addr[MAX_ADDR];
}PeoInfo;

注:用#define定义的标识符常量,使用修改时可以降低维护成本。如联系人的信息中名字的宽度为20,以便之后需要修改时只需修改一处,而不是修改全部用到名字的宽度为20的地方。

定义完结构体类型之后,创建通讯录(通讯录需要能够存放1000个人的信息)可以利用人信息类型创建元素为1000的数组。但是当要操作通讯录中联系人的信息内容时,比如增加联系人信息,这时就需要知道通讯录中的联系人是否已经到达上限或者需要知道在哪个位置添加人的信息(需要知道当前通讯录中有几个人的信息),如果达到上限就无法再添加联系人。综上通讯录在维护时需要存放数据的空间和通讯录中当前总共有几个元素,将这两个变量放到一起定义成结构体通讯录。这样就避免了执行每个功能时都要相同地传入两个变量(联系人信息,已有联系人个数)方便传参。

//通讯录定义
typedef struct Contact
{
	PeoInfo data[MAX];//存放添加进来的人的信息
	int sz;//记录的是当前通讯录中有效信息的个数
}Contact;

通讯录的初始化

通讯录创建完之后,需要将通讯录进行初始化。内存空间清零并将记录的是当前通讯录中有效信息的个数清零

//通讯录初始化
void InitContact(Contact* pc)
{
	pc->sz = 0;
	//memset();  - 内存设置
	memset(pc->data, 0, sizeof(pc->data));
}

通讯录添加联系人信息

添加联系人时需要注意如果通讯录满了就不能再添加了,如果通讯录没满需要注意通讯录添加联系人信息的位置正好是已知记录当前通讯录中有效信息的个数所在联系人信息数组的下标的位置。当添加完联系人信息之后需要对当前通讯录中有效信息的个数进行加一。

// 增加联系人
void AddContact(Contact* pc)
{
	if (pc->sz == MAX)
	{
		printf("通讯录已满,无法添加
");
		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("增加成功
");
}

通讯录删除特定联系人信息

通讯录删除特定联系人信息如果通讯录为空则不能删除,如果通讯录不为空,则需要判断要删除的联系人是否存在于通讯录中(查找要删除的人)。如果要删除的联系人存在于通讯录中则删除。

查找函数是通过联系人的名字在通讯录中进行查找,查找的过程就是排除的过程。通过遍历进行查找,如果找到了返回通讯录中联系人信息所在的下标,否则返回-1。

通讯录删除特定联系人信息的方式有两种:
在这里插入图片描述
注:

  • 第一种方式在删除的时候需要将要删除联系人信息的位置用后一个联系人信息的位置进行覆盖即可,依次类推,直到将最后一个联系人信息的位置覆盖到倒数第二个联系人信息的位置即可。不需要将最后一个联系人的信息也覆盖这是毫无意义的,因为删除完信息之后通讯录中有效信息的个数会减一这时也就看不到最后一个联系人信息了。这样也可以避免数组越界访问
  • 虽然第二种方法操作起来比较简单,移动的次数也更少,但是还是使用第一种方法进行删除,因为第二种方法会捣乱联系人的先后顺序。

最后删除完指定联系人信息后需要将当前通讯录中有效信息的个数减一。

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

	return -1;//找不到
}

void DelContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };

	if (pc->sz == 0)
	{
		printf("通讯录为空,无需删除
");
		return;
	}
	printf("请输入要删除人的名字:>");
	scanf("%s", name);

	//1. 查找要删除的人
	//有/没有
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要删除的人不存在
");
		return;
	}
	//2. 删除
	int i = 0;
	for (i = pos; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}

	pc->sz--;
	printf("删除成功
");
}


通讯录查找特定联系人信息

在通讯录查找特定联系人信息,如果找到将查找函数返回的通讯录中联系人信息所在下标并打印通讯录中特定联系人信息的内容。如果未找到则将打印要查找的人不存在。

void SearchContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	printf("请输入要查找人的名字:>");
	scanf("%s", name);

	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要查找的人不存在
");
		return;
	}
	else
	{
		printf("%-20s	%-5s	%-5s	%-12s	%-20s
", "名字", "年龄", "性别", "电话", "地址");
		//打印数据
		printf("%-20s	%-5d	%-5s	%-12s	%-20s
",
			pc->data[pos].name,
			pc->data[pos].age,
			pc->data[pos].sex,
			pc->data[pos].tele,
			pc->data[pos].addr);
	}
}

通讯录修改特定联系人信息

在通讯录中查找特定联系人信息,如果找到了则对其特定联系人信息进行修改(重新录入)。如果未找到则打印要修改的人不存在。

void ModifyContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	printf("请输入要修改人的名字:>");
	scanf("%s", name);

	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要修改的人不存在
");
		return;
	}
	else
	{
		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].tele);
		printf("请输入地址:>");
		scanf("%s", pc->data[pos].addr);

		printf("修改成功
");
	}
}

通讯录排序联系人信息

排序联系人信息可以通过qosrt函数进行排序,这里只需要写一个自定义的比较函数即可。


//自定义比较函数
static int CmpByName(const void* e1, const void* e2)
{
	return strcmp((const char*)e1, (const char*)e2);
}


void SortContact(struct Contact* pc)
{
	qsort(pc->data, pc->sz, sizeof(PeoInfo), CmpByName);//排序
	printf("排序成功
");
}

通讯录打印联系人信息

当前通讯录中有效信息的个数有几个,通讯录中联系人信息就打印几个。

void PrintContact(const Contact* pc)
{
	int i = 0;
	//打印标题
	printf("%-20s	%-5s	%-5s	%-12s	%-20s
", "名字", "年龄", "性别", "电话", "地址");
	//打印数据
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-20s	%-5d	%-5s	%-12s	%-20s
",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].tele,
			pc->data[i].addr);
	}
}

通讯录整体代码

test.c

#define _CRT_SECURE_NO_WARNINGS 1

//通讯录-静态版本
//1.通讯录中能够存放1000个人的信息
//每个人的信息:
//名字+年龄+性别+电话+地址
//2. 增加人的信息
//3. 删除指定人的信息
//4. 修改指定人的信息
//5. 查找指定人的信息
//6. 排序通讯录的信息



#include "contact.h"

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

enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SORT,
	PRINT
};

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 SORT:
			//排序
			SortContact(&con);
			break;
		case PRINT:
			//打印
			PrintContact(&con);
			break;
		case EXIT:	
			//退出
			printf("退出通讯录
");
			break;
		default:
			printf("选择错误,重新选择
");
			break;
		}
	} while (input);

	return 0;
}

contact.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"

//通讯录初始化
void InitContact(Contact* pc)
{
	pc->sz = 0;
	//memset();  - 内存设置
	memset(pc->data, 0, sizeof(pc->data));
}




// 增加联系人
void AddContact(Contact* pc)
{
	if (pc->sz == MAX)
	{
		printf("通讯录已满,无法添加
");
		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("增加成功
");
}



void PrintContact(const Contact* pc)
{
	int i = 0;
	//打印标题
	printf("%-20s	%-5s	%-5s	%-12s	%-20s
", "名字", "年龄", "性别", "电话", "地址");
	//打印数据
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-20s	%-5d	%-5s	%-12s	%-20s
",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].tele,
			pc->data[i].addr);
	}
}

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

	return -1;//找不到
}

void DelContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };

	if (pc->sz == 0)
	{
		printf("通讯录为空,无需删除
");
		return;
	}
	printf("请输入要删除人的名字:>");
	scanf("%s", name);

	//1. 查找要删除的人
	//有/没有
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要删除的人不存在
");
		return;
	}
	//2. 删除
	int i = 0;
	for (i = pos; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}

	pc->sz--;
	printf("删除成功
");
}


void SearchContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	printf("请输入要查找人的名字:>");
	scanf("%s", name);

	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要查找的人不存在
");
		return;
	}
	else
	{
		printf("%-20s	%-5s	%-5s	%-12s	%-20s
", "名字", "年龄", "性别", "电话", "地址");
		//打印数据
		printf("%-20s	%-5d	%-5s	%-12s	%-20s
",
			pc->data[pos].name,
			pc->data[pos].age,
			pc->data[pos].sex,
			pc->data[pos].tele,
			pc->data[pos].addr);
	}
}


void ModifyContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	printf("请输入要修改人的名字:>");
	scanf("%s", name);

	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要修改的人不存在
");
		return;
	}
	else
	{
		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].tele);
		printf("请输入地址:>");
		scanf("%s", pc->data[pos].addr);

		printf("修改成功
");
	}
}



//自定义比较函数
static int CmpByName(const void* e1, const void* e2)
{
	return strcmp((const char*)e1, (const char*)e2);
}


void SortContact(struct Contact* pc)
{
	qsort(pc->data, pc->sz, sizeof(PeoInfo), CmpByName);//排序
	printf("排序成功
");
}

contact.h

#pragma once


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

#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 12
#define MAX_ADDR 30


#define MAX 1000




//类型的定义
typedef struct PeoInfo
{
	char name[MAX_NAME];
	char sex[MAX_SEX];
	int age;
	char tele[MAX_TELE];
	char addr[MAX_ADDR];
}PeoInfo;

//通讯录的定义
typedef struct Contact
{
	PeoInfo data[MAX];//存放添加进来的人的信息
	int sz;//记录的是当前通讯录中有效信息的个数
}Contact;



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

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

//打印联系人信息
void PrintContact(const Contact* pc);

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

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

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


//排序联系人信息
void SortContact(struct Contact* pc);


注:

  • test.c是用于测试通讯录的模块、contact.c用于通讯录模块的函数实现、contact.h用于通讯录模块的类型定义以及函数声明
  • 使用枚举可以增加代码的可读性,避免程序员写代码以及阅读代码时不明确代码其中的的具体意义。
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。