通讯录(静态版本)!

在生活中,我们的手机都有电话簿,里面可以存放联系人的相关信息(名字,性别,年龄,电话,地址等内容)。那接下来,这篇文章就来讲一下用C语言实现通讯录的静态版本。

目录

1. 总体框架和构思

  1.1 总体框架代码(声明):

  1.2 总体框架代码:

2. 实现对通讯录的每个操作

2.1 实现模块:初始化通讯录 — InitContact();

2.1.1 声明部分

2.1.2 定义部分

2.2 实现模块:添加联系人信息 — AddPeople()

2.2.1 声明部分

2.2.2 定义部分

2.3 实现模块:删除联系人信息 — DelPeople()

2.3.1 声明部分

2.3.2 定义部分

2.4 实现模块:查找联系人 — FindPeople()

2.4.1 声明部分

2.4.2 定义部分

2.5 实现模块:查询联系人 — SearchPeople()

2.5.1 声明部分

2.5.2 定义部分

2.6 实现模块:修改联系人信息 — ModPeople()

2.6.1 声明部分

2.6.2 定义部分

2.7 实现模块:显示通讯录 — Display()

2.7.1 声明部分

2.7.2 定义部分

2.8 实现模块:清空联系人 — ClsContact()

2.8.1 声明部分

2.8.2 定义部分

2.9 实现模块:给联系人按名字排升序 — NameSort()

2.9.1 声明部分

2.9.2 定义部分

3. 源代码


1. 总体框架和构思

我们常说,一个程序员在完成一个项目时,真正写代码的时间是少于50%的,为什么?

那是因为他们把大把的时间都用在构思上。(说穿了,就是想都没想好,怎么写的出来!)

所以在写通讯录时要先思考。(任何一个项目都要经过这样一个过程!)

首先,一个联系人的信息是多样化的,故最好的存放方式,就是把一个联系人的信息存放的一个结构体里去。(这里个结构体只存放一个人具体的信息)

然后,再用一个结构体数组,用来存放1000个人的信息。到这里大家是不是以为通讯录的创建是不是完成了!当然没有,因为我们在构思实现通讯录中的一些具体操作时(添加联系人,删除联系人等),会发现,我们需要时刻知道通讯录当时联系人的个数,这 样在操作时就能随着通讯录里面内容的改变而发生改变。最终发现用一个结构体来当通讯录,里面存放着一个放着联系人信息的结构体数组,还存放着通讯录当下联系人的个数。

最后由于我们对通讯录的操作是多次的,所以这里整个操作就是在一个循环里,并且里面用选择语句来实现对通讯录不同的操作。

1.1 总体框架代码(声明):

//在contact.h头文件中声明的内容

#include<stdio.h>

#define NAME_MAX  20     //最大名字的长度
#define SEX_MAX   5      //性别最大长度
#define NUMBER_MAX 20    //电话最大长度
#define ADDRESS_MAX 20   //地址最大长度

#define PEOPLE_MAX 1000  //通讯录里面最大能存放多少个人的信息

//存放每一个人的具体信息
struct PeoInfo
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	int age;
	char number[NUMBER_MAX];
	char address[ADDRESS_MAX];
};

//通讯录
struct Contact
{
	struct PeoInfo Data[PEOPLE_MAX];     //存放1000个通讯人的信息
	int sz;                         //记录当前通讯录里还有多少人
};

1.2 总体框架代码:

#include"contact.h"
//通讯录面板
void menu()
{
	printf("************************************\n");
	printf("******    0.exit     1.add    ******\n");
	printf("******    2.del      3.search ******\n");
	printf("******    4.modify   5.dis    ******\n");
	printf("******    6.cls      7.sort   ******\n");
	printf("************************************\n");
}

//用来存放对通讯录的操作
enum board
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	DIS,
	CLS,
	SORT
};

int main()
{
	int input = 0;      //接收选项
	//创建一个通讯录
	struct Contact con = { 0 };
	//初始化通讯录
	InitContact(&con);
	do
	{	
		//打印个面板
		menu();
		printf("请输入选项》");
		scanf("%d", &input);
		switch (input)
		{
		case EXIT:                  
			printf("退出通讯录!\n");
			break;
		case ADD:               //添加联系人
			AddPeople(&con);
			break;
		case DEL:               //删除联系人
			DelPeople(&con);
			break;
		case SEARCH:            //查询联系人
			SearchPeople(&con);
			break;
		case MODIFY:            //修改联系人
			ModPeople(&con);
			break;
		case DIS:               //显示通讯录
			Display(&con);
			break;
		case CLS:               //清空联系人
			ClsContact(&con);
			break;
		case SORT:              //给联系人按名字排升序
			NameSort(&con);
			break;
		default:
			printf("选项错误,重新选择!\n");
			break;
		}
	} while (input);

	return 0;
}

2. 实现对通讯录的每个操作

2.1 实现模块:初始化通讯录 — InitContact();

2.1.1 声明部分

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

2.1.2 定义部分

//初始化通讯录
void InitContact(struct Contact* pc)
{
	pc->sz = 0;  //归零,表示通讯录里没有人

	//使用memset函数对存放联系人的数组初始化
	//memset(pc->Data, 0, sizeof(struct PeoInfo) * PEOPLE_MAX); //方法1:便于理解
	memset(pc->Data, 0, sizeof(pc->Data)); //方法2:sizeof(数组名) - 求整个数组的大小

}

这里具体是用方法1,还是方法2,可以根据自己的理解来选择。(在能理解的基础上,方法2无疑是更好一些的。)

2.2 实现模块:添加联系人信息 — AddPeople()

2.2.1 声明部分

//添加联系人信息
void AddPeople(struct Contact* pc);

2.2.2 定义部分

//添加联系人信息
void AddPeople(struct Contact* pc)
{
	struct PeoInfo temp = { 0 };     //用来临时存放单个人的信息
	
	if (pc->sz == PEOPLE_MAX)        //查看当前通讯录是否已满
	{
		printf("通讯录已满!\n");
	}
	else
	{
		printf("请输入姓名:");
		scanf("%s", temp.name);      //scanf("%s", pc->Data[pc->sz].name);
		printf("请输入性别:");
		scanf("%s", temp.sex);       //scanf("%s", pc->Data[pc->sz].sex);
		printf("请输入年龄:");
		scanf("%d", &temp.age);      //scanf("%d", &(pc->Data[pc->sz].age));
		printf("请输入电话号码:");
		scanf("%s", temp.number);    //scanf("%s", pc->Data[pc->sz].number);
		printf("请输入地址:");
		scanf("%s", temp.address);   //scanf("%s", pc->Data[pc->sz].address);

		pc->Data[pc->sz] = temp;      //把这个人的信息真正存放到通讯录中
		pc->sz++;                     //总人数加1
		printf("添加成功!\n");

	}
}

这里采用了一种简便的方法,创建了一个临时的可以存放联系人信息的结构体变量,这样我们在输入数据时,先把信息存放到临时变量中,最后把这个临时变量放到真正的通讯录里,然后当前人数加一。

同样也可以直接对通讯录键盘输入,但是这样写的话不是很好理解,并且很繁琐。不过这样就不用创建临时变量和最后对通讯录进行赋值了。

2.3 实现模块:删除联系人信息 — DelPeople()

2.3.1 声明部分

//删除联系人信息
void DelPeople(struct Contact* pc);

2.3.2 定义部分

//删除联系人信息
void DelPeople(struct Contact* pc)
{
	if (pc->sz == 0)           //判断通讯录是否为空
	{
		printf("通讯录为空,删除失败!\n");
	}
	else
	{
		char name[NAME_MAX] = { 0 };      //临时存放要删除的联系人名字

		printf("请输入要删除联系人的名字:");
		scanf("%s", name);
		//查找该联系人
		int ret = FindPeople(pc, name);   
        //自定义查找联系人函数,找到返回下标,否则返回 -1

		if (ret == -1)                    
		{
			printf("该联系人不存在!\n");
		}
		else
		{
			int j = 0;
			for (j = ret; j < pc->sz - 1; j++)   
           //从查找的联系人开始,把后面的联系人整体向前移动一位
			{
				pc->Data[j] = pc->Data[j + 1];    //把该联系人的信息给覆盖掉
			}
			pc->sz--;                             //当前联系人数量减一
			printf("删除成功!\n");
		}
	}
}

由于在删除联系人的函数中,我们有用到了一个查找联系人函数,所以下面就把这个函数模块写出来。

2.4 实现模块:查找联系人 — FindPeople()

2.4.1 声明部分

//查找联系人
int FindPeople(struct Contact* pc, char* name);

2.4.2 定义部分

//查找联系人
int FindPeople(struct 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;       //没找到,返回 -1
}

2.5 实现模块:查询联系人 — SearchPeople()

2.5.1 声明部分

//查找联系人并打印其信息
void SearchPeople(struct Contact* pc);

2.5.2 定义部分

//查找联系人并打印其信息
void SearchPeople(struct Contact* pc)
{
	char name[NAME_MAX] = { 0 };     //临时存放需要查询的联系人的名字
	if (pc->sz == 0)        //判断通讯录是否为空
	{
		printf("通讯录为空,查询失败!\n");
	}
	else
	{
		printf("请输入联系人的名字:");
		scanf("%s", name);
		int ret = FindPeople(pc, name);  //查找该联系人
		if (ret == -1)
		{
			printf("该联系人不存在!\n");
		}
		else
		{
			//打印该联系人的具体信息
			printf("%10s\t%2s\t%4s\t%8s\t%10s\n\n",
				"name", "sex", "age", "number", "address");
			printf("%10s\t%2s\t%4d\t%8s\t%10s\n",
				pc->Data[ret].name, pc->Data[ret].sex, pc->Data[ret].age,
				pc->Data[ret].number, pc->Data[ret].address);
		}
	}
}

2.6 实现模块:修改联系人信息 — ModPeople()

2.6.1 声明部分

//修改指定联系人信息
void ModPeople(struct Contact* pc);

2.6.2 定义部分

//修改指定联系人信息
void ModPeople(struct Contact* pc)
{
	char name[NAME_MAX] = { 0 };
	if (pc->sz == 0)      //先判断是不是空的通讯录
	{
		printf("通讯录为空,修改失败!\n");
	}
	else
	{
		printf("请输入需要修改的联系人名字:");
		scanf("%s", name);
		int ret = FindPeople(pc, name);    //查找该联系人,并返回其下标
		if (ret == -1)
		{
			printf("该联系人不存在!\n");
		}
		else
		{
			//和添加联系人信息一样,创建一个临时变量,用来存放我要输入的信息
			struct PeoInfo temp = { 0 };

			//逐条输入
			printf("请输入新的名字:");
			scanf("%s", temp.name);
			printf("请输入新的性别:");
			scanf("%s", temp.sex);
			printf("请输入新的年龄:");
			scanf("%d", &temp.age);
			printf("请输入新的电话:");
			scanf("%s", temp.number);
			printf("请输入新的地址:");
			scanf("%s", temp.address);

			//覆盖掉原来联系人的信息
			pc->Data[ret] = temp;

			//提示一下
			printf("修改成功!\n");
		}
	}
}

2.7 实现模块:显示通讯录 — Display()

2.7.1 声明部分

//显示通讯录
void Display(struct Contact* pc);

2.7.2 定义部分

//显示通信录里的联系人
void Display(struct Contact* pc)
{
	printf("%10s\t%2s\t%4s\t%8s\t%10s\n\n", 
		"name", "sex", "age", "number", "address");
	int i = 0;
	for (i = 0; i < pc->sz; i++) //当前有多少联系人,就循环多少次
	{
		printf("%10s\t%2s\t%4d\t%8s\t%10s\n", 
			pc->Data[i].name, pc->Data[i].sex, pc->Data[i].age, 
			pc->Data[i].number, pc->Data[i].address);
	}
}

2.8 实现模块:清空联系人 — ClsContact()

2.8.1 声明部分

//清空所有联系人
void ClsContact(struct Contact* pc);

2.8.2 定义部分

//清空所有联系人
void ClsContact(struct Contact* pc)
{
	if (pc->sz == 0)   //判断通讯录里有没有联系人
	{
		printf("没有联系人,清除失败!\n");
	}
	else
	{ 
		//直接初始化通讯录
		InitContact(pc);
		printf("清除成功!\n");
	}
}

这里函数内部,其实就是重新调用了一次初始化通讯录模块 — InitContact()。

2.9 实现模块:给联系人按名字排升序 — NameSort()

2.9.1 声明部分

//以名字排序通讯录 - 升序
void NameSort(struct Contact* pc);

2.9.2 定义部分

//按名字升序排通讯录
int name_sort(const void* e1, const void* e2)
{
	return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);
}

//以名字排序通讯录 - 升序
void NameSort(struct Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录为空,排序失败!\n");
	}
	else
	{
		//使用qsort快速排序,name_sort为自定义比较函数
		qsort(pc->Data, pc->sz, sizeof(struct PeoInfo), name_sort);
		printf("排序成功!(升序)!\n");
	}
}

由于这里使用的是 qsort()排序,所以需要自己把它的比较函数给写出来,才能真正使用它。

3. 源代码

contact.h文件的内容:

#pragma once

#include<stdio.h>

#include<string.h>

#include<stdlib.h>

#define NAME_MAX  20     //最大名字的长度
#define SEX_MAX   5      //性别最大长度
#define NUMBER_MAX 20    //电话最大长度
#define ADDRESS_MAX 20   //地址最大长度

#define PEOPLE_MAX 1000  //通讯录里面最大能存放多少个人的信息

//存放每一个人的具体信息
struct PeoInfo
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	int age;
	char number[NUMBER_MAX];
	char address[ADDRESS_MAX];
};

//通讯录
struct Contact
{
	struct PeoInfo Data[PEOPLE_MAX];     //存放1000个通讯人的信息
	int sz;                         //记录当前通讯录里还有多少人
};

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

//添加联系人信息
void AddPeople(struct Contact* pc);

//删除联系人信息
void DelPeople(struct Contact* pc);

//显示通讯录
void Display(struct Contact* pc);

//查找联系人
int FindPeople(struct Contact* pc, char* name);

//查找联系人并打印其信息
void SearchPeople(struct Contact* pc);

//修改指定联系人信息
void ModPeople(struct Contact* pc);

//以名字排序通讯录 - 升序
void NameSort(struct Contact* pc);

//清空所有联系人
void ClsContact(struct Contact* pc);

contact.c的内容:

#include"contact.h"

//初始化通讯录
void InitContact(struct Contact* pc)
{
	pc->sz = 0;  //归零,表示通讯录里没有人

	//使用memset函数对存放联系人的数组初始化
	//memset(pc->Data, 0, sizeof(struct PeoInfo) * PEOPLE_MAX);   
    //方法1:便于理解

	memset(pc->Data, 0, sizeof(pc->Data));                        
    //方法2:sizeof(数组名) - 求整个数组的大小

}

//添加联系人信息
void AddPeople(struct Contact* pc)
{
	struct PeoInfo temp = { 0 };     //用来临时存放单个人的信息
	
	if (pc->sz == PEOPLE_MAX)
	{
		printf("通讯录已满!\n");
	}
	else
	{
		//printf("请输入姓名:");
		//scanf("%s", pc->Data[pc->sz].name);
		//printf("请输入性别:");
		//scanf("%s", pc->Data[pc->sz].sex);
		//printf("请输入年龄:");
		//scanf("%d", &(pc->Data[pc->sz].age));
		//printf("请输入电话号码:");
		//scanf("%s", pc->Data[pc->sz].number);
		//printf("请输入地址:");
		//scanf("%s", pc->Data[pc->sz].address);

		printf("请输入姓名:");
		scanf("%s", temp.name);      
		printf("请输入性别:");
		scanf("%s", temp.sex);       
		printf("请输入年龄:");
		scanf("%d", &temp.age);      
		printf("请输入电话号码:");
		scanf("%s", temp.number);    
		printf("请输入地址:");
		scanf("%s", temp.address);

		pc->Data[pc->sz] = temp;      //把这个人的信息真正存放到通讯录中
		pc->sz++;                     //总人数加1
		printf("添加成功!\n");

	}
}

//删除联系人信息
void DelPeople(struct Contact* pc)
{
	if (pc->sz == 0)           //判断通讯录是否为空
	{
		printf("通讯录为空,删除失败!\n");
	}
	else
	{
		char name[NAME_MAX] = { 0 };      //临时存放要删除的联系人名字

		printf("请输入要删除联系人的名字:");
		scanf("%s", name);

		//查找该联系人
		int ret = FindPeople(pc, name);   
        //自定义查找联系人函数,找到返回下标,否则返回 -1

		if (ret == -1)                    
		{
			printf("该联系人不存在!\n");
		}
		else
		{
			int j = 0;
			for (j = ret; j < pc->sz - 1; j++)    
            //从查找的联系人开始,把后面的联系人整体向前移动一位
			{
				pc->Data[j] = pc->Data[j + 1];    //把该联系人的信息给覆盖掉
			}
			pc->sz--;                             //当前联系人数量减一
			printf("删除成功!\n");
		}
	}
}

//查找联系人
int FindPeople(struct 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;     //没找到,返回 -1
}

//显示通信录里的联系人
void Display(struct Contact* pc)
{
	printf("%10s\t%2s\t%4s\t%8s\t%10s\n\n", 
		"name", "sex", "age", "number", "address");
	int i = 0;
	for (i = 0; i < pc->sz; i++) //当前有多少联系人,就循环多少次
	{
		printf("%10s\t%2s\t%4d\t%8s\t%10s\n", 
			pc->Data[i].name, pc->Data[i].sex, pc->Data[i].age, 
			pc->Data[i].number, pc->Data[i].address);
	}
}

//查找联系人并打印其信息
void SearchPeople(struct Contact* pc)
{
	char name[NAME_MAX] = { 0 };     //临时存放需要查询的联系人的名字
	if (pc->sz == 0)        //判断通讯录是否为空
	{
		printf("通讯录为空,查询失败!\n");
	}
	else
	{
		printf("请输入联系人的名字:");
		scanf("%s", name);
		int ret = FindPeople(pc, name);  //查找该联系人
		if (ret == -1)
		{
			printf("该联系人不存在!\n");
		}
		else
		{
			//打印该联系人的具体信息
			printf("%10s\t%2s\t%4s\t%8s\t%10s\n\n",
				"name", "sex", "age", "number", "address");
			printf("%10s\t%2s\t%4d\t%8s\t%10s\n",
				pc->Data[ret].name, pc->Data[ret].sex, pc->Data[ret].age,
				pc->Data[ret].number, pc->Data[ret].address);
		}
	}
}

//修改指定联系人信息
void ModPeople(struct Contact* pc)
{
	char name[NAME_MAX] = { 0 };
	if (pc->sz == 0)      //先判断是不是空的通讯录
	{
		printf("通讯录为空,修改失败!\n");
	}
	else
	{
		printf("请输入需要修改的联系人名字:");
		scanf("%s", name);
		int ret = FindPeople(pc, name);    //查找该联系人,并返回其下标
		if (ret == -1)
		{
			printf("该联系人不存在!\n");
		}
		else
		{
			//和添加联系人信息一样,创建一个临时变量,用来存放我要输入的信息
			struct PeoInfo temp = { 0 };

			//逐条输入
			printf("请输入新的名字:");
			scanf("%s", temp.name);
			printf("请输入新的性别:");
			scanf("%s", temp.sex);
			printf("请输入新的年龄:");
			scanf("%d", &temp.age);
			printf("请输入新的电话:");
			scanf("%s", temp.number);
			printf("请输入新的地址:");
			scanf("%s", temp.address);

			//覆盖掉原来联系人的信息
			pc->Data[ret] = temp;

			//提示一下
			printf("修改成功!\n");
		}
	}
}

//按名字升序排通讯录
int name_sort(const void* e1, const void* e2)
{
	return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);
}

//以名字排序通讯录 - 升序
void NameSort(struct Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录为空,排序失败!\n");
	}
	else
	{
		//使用qsort快速排序
		qsort(pc->Data, pc->sz, sizeof(struct PeoInfo), name_sort);
		printf("排序成功!(升序)!\n");
	}
}

//清空所有联系人
void ClsContact(struct Contact* pc)
{
	if (pc->sz == 0)   //判断通讯录里有没有联系人
	{
		printf("没有联系人,清除失败!\n");
	}
	else
	{ 
		//直接初始化通讯录
		InitContact(pc);
		printf("清除成功!\n");
	}
}

test.c的内容:

#include"contact.h"

//通讯录面板
void menu()
{
	printf("************************************\n");
	printf("******    0.exit     1.add    ******\n");
	printf("******    2.del      3.search ******\n");
	printf("******    4.modify   5.dis    ******\n");
	printf("******    6.cls      7.sort   ******\n");
	printf("************************************\n");
}

//用来存放对通讯录的操作
enum board
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	DIS,
	CLS,
	SORT
};

int main()
{
	int input = 0;      //接收选项
	//创建一个通讯录
	struct Contact con = { 0 };
	//初始化通讯录
	InitContact(&con);
	do
	{	
		//打印个面板
		menu();
		printf("请输入选项》");
		scanf("%d", &input);
		switch (input)
		{
		case EXIT:                  
			printf("退出通讯录!\n");
			break;
		case ADD:               //添加联系人
			AddPeople(&con);
			break;
		case DEL:               //删除联系人
			DelPeople(&con);
			break;
		case SEARCH:            //查询联系人
			SearchPeople(&con);
			break;
		case MODIFY:            //修改联系人
			ModPeople(&con);
			break;
		case DIS:               //显示通讯录
			Display(&con);
			break;
		case CLS:               //清空联系人
			ClsContact(&con);
			break;
		case SORT:              //给联系人按名字排升序
			NameSort(&con);
			break;
		default:
			printf("选项错误,重新选择!\n");
			break;
		}
	} while (input);

	return 0;
}

总结:总的来说,只要清楚了通讯录的大致框架,知道了每个模块的实现思路,最后拼接在一起,实现起来就变得简单了。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值