当前位置:首页 » 《关注互联网》 » 正文

通讯录小程序(C语言)_Solitudefire的博客

21 人参与  2022年01月18日 08:19  分类 : 《关注互联网》  评论

点击全文阅读


通讯录小程序(C语言)

  • 程序介绍
  • 实现思路和内容概括
  • 代码实现
    • 打印菜单
    • 定义通讯录
    • 初始化通讯录函数
    • 添加联系人函数
    • 显示通讯录函数
    • 查找通讯录函数
    • 删除联系人
    • 查找指定联系人
    • 修改指定联系人信息
    • 排序(按姓名)
  • 完整代码
    • contact.h
    • contact.c
    • test.c
  • 运行展示
  • 总结

程序介绍

通过前面学习我们可以实现通讯录小程序的代码,首先,我们需要创建一个通讯录,通讯录中存放1000个人的信息,信息包括:名字,性别,年龄,电话,住址。通讯录主要由5个功能:增加联系人、删除联系人、修改联系人、查找联系人、按名称子排序。下面我们来看实现过程。

实现思路和内容概括

首先我们将完整的代码分为3个部分——contact.h(头文件)、contact.c(函数部分)、test.c(主函数实现部分)。我们会创建一个大的框架,将菜单放入其中,菜单有7个选项:1.add 2.del 3.search 4.modify 5.show 6.sort 0.exit
输入“1”,添加联系人信息,输入“2”,删除指定联系人信息,输入“3”,查找指定联系人信息(按姓名查找并打印),输入“4”,修改指定联系人信息(按姓名查找),输入“5”,打印当前的通讯录所有联系人,输入“6”,将通讯录所有联系人按姓名排序。输入“0”,退出通讯录。

代码实现

打印菜单

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");
	printf("****************************\n");
}
enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT
};

int main()
{
	int input=0;
	//创建一个通讯录
	struct 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:
			SortContactByName(&con);
			break;
		case EXIT:
			printf("退出通讯录。\n");
			break;
		default:
			printf("选择错误!\n");
			break;
		}
	} while (input);
	return 0;
}

我们利用枚举类型将EXIT,ADD,DEL,SEARCH,MODIFY,SHOW,SORT放入其中,因为枚举类型中的成员属于常量所以具有常量的属性,我们可以利用此属性运用到switch上,这样就提高了代码的可读性。利用do while循环,我们先打印menu()函数,再利用input变量,只要输入非0,都会打印菜单,只是效果不同。

定义通讯录

//描述人的信息
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define MAX 1000
struct PeoInfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
};
//通讯录
struct Contact
{
	struct PeoInfo data[MAX];//1000个人的信息存放进data数组中
	int sz ;//记录当前存放进通讯录中的有效信息的个数
};

定义一个通讯录需要两个结构体,struct PeoInfo结构体是描述一个人的信息,struct Contact结构体是通讯录本身,我们将struct PeoInfo中的个人信息存放在struct Contact结构体中以实现联系,也就是struct Contact的成员data[1000]是struct PeoInfo结构体类型,data[1000]是一个结构体类型的数组,里面有name[20],age,sex[5],tele[12],addr[30]。

初始化通讯录函数

void InitContact(struct Contact* pc)
{
	pc->sz = 0;//默认没有信息
	//memset(pc->data, 0, MAX * sizeof(struct PeoInfo));
	memset(pc->data, 0, sizeof(pc->data));
}

当我们定义一个通讯录结构体时,数值都是随机值,因此我们需要初始化,将通讯录所有的信息数据都变成“0”,这里使用了memset()函数,我们在内存函数博客中介绍了这个函数,不在细说。具体实现原理可以看前面的博客内存函数(C语言)

添加联系人函数

void AddContact(struct Contact* pc)
{
	if (pc->sz == MAX)
	{
		printf("通讯录已满!\n");
	}
	else
	{
		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 );
		//提示添加成功
		printf("添加成功\n");
		pc->sz++;
	}
}

AddContact()函数,首先先进行判断,sz(记录当前存放进通讯录中的有效信息的个数)是否等于MAX(1000),如果有,则打印通讯录已满,如果没有则按要求输入信息,并提示添加成功,sz++。

显示通讯录函数

void ShowContact(struct Contact* pc)
{
	int i = 0;
	printf("%15s\t%5s\t%8s\t%15s\t%30s\n\n", "name", "age", "sex", "tele", "addr");
	for (i = 0; i < pc->sz; i++)
	{
		//打印每一个数据
		printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].tele,
			pc->data[i].addr);
	}
}

在ShowContact()函数中,我们先打印标题"name", “age”, “sex”, “tele”, “addr”,然后利用for循环将信息一一对应标题都打印下来。

查找通讯录函数

int FindContactByName(const struct Contact* pc, const char *name)
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	//找不到
	return -1;
}

FindContactByName()函数的基本实现是通过strcmp()函数实现的,利用for循环,找到查找的名字于通讯录名字相等的此时i的值,并返回i的值,此时i的值正是data数组的下标,方便后续操作,关于strcmp()函数实现原理可以看以前博客字符与字符串函数(C语言)。

删除联系人

void DelContact(struct Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	char name[NAME_MAX] = { 0 };
	printf("请输入要删除人的名字:>");
	scanf("%s", name);
	//查找
	int pos = FindContactByName(pc, name);
	if (pos == -1)
	{
		printf("指定的联系人不存在\n");
	}
	else
	{
		//删除
		int j = 0;
		for (j = pos; j < pc->sz-1; j++)
		{
			pc->data[j] = pc->data[j + 1];
		}
		pc->sz--;
		//提示
		printf("删除成功\n");
	}
}

DelContact()函数和AddContact()函数类似,但是比添加联系人要复杂,删除联系人先再找到指定的联系人,在进行操作,因此,DelContact()函数中运用了查找通讯录函数,利用名字进行比较找出指定的联系人,在进行删除时,并不是直接删除,而是利用后一个信息将前一个信息的覆盖,如此达到删除联系人的信息。

查找指定联系人

void SearchContact(const struct Contact* pc)
{
	char name[NAME_MAX] = { 0 };
	printf("输入要查找人的名字:>");
	scanf("%s", name);
	int pos = FindContactByName(pc, name);
	if (-1 == pos)
	{
		printf("查无此人\n");
	}
	else
	{
		printf("%15s\t%5s\t%8s\t%15s\t%30s\n\n", "name", "age", "sex", "tele", "addr");
		printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
			pc->data[pos].name,
			pc->data[pos].age,
			pc->data[pos].sex,
			pc->data[pos].tele,
			pc->data[pos].addr);
	}
}

SearchContact()函数是在FindContactByName()函数的基础之上增加了打印的功能,如果没有查找到指定的联系人打印“查无此人”,否则打印出该联系人的所有信息。

修改指定联系人信息

void ModifyContact(struct Contact* pc)
{
	char name[NAME_MAX] = { 0 };
	printf("输入要修改人的名字:>");
	scanf("%s", name);
	int pos = FindContactByName(pc, name);
	if (-1 == pos)
	{
		printf("要修改的人不存在\n");
	}
	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);
	}
}

ModifyContact()函数是利用FindContactByName()函数先将想要修改的联系人找到,然后输入新的所有信息来覆盖原来的信息。

排序(按姓名)

int cmp_name(const void* e1, const void* e2)
{
	return strcmp(((struct Contact*)e1)->data->name , ((struct Contact*)e2)->data->name);
}
void SortContactByName(struct Contact* pc)
{
	qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_name);
	printf("排序成功\n");
}

排序运用到了qsort()函数,这个函数可以排序任意类型的数据,因此结构体也可以。但是需要引用到头文件#include<stdlib.h>
qsort()函数:
形式:void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) )
解释:qsort函数实现了一种快速排序算法,用于对num元素数组进行排序,每个元素的宽度为字节。参数base是指向要排序的数组的基的指针。qsort用已排序的元素覆盖此数组。参数compare是指向用户提供的例程的指针,该例程比较两个数组元素并返回指定其关系的值。
也就是说,*base是一个指针,num是要排序的个数,width是排序元素的大小,int (__cdecl *compare )(const void *elem1, const void *elem2 ) 是一个函数,这个函数就是用来判断怎样比较的。以写的代码为例,pc是指针指向的是struct Contact con结构体,pc->sz是记录当前存放进通讯录中的有效信息的个数,也就对应了打印的个数,sizeof(pc->data[0])是个人信息的结构体的大小,cmp_name()函数是按名字来进行排序。

完整代码

contact.h

#include<string.h>
#include <stdio.h>
#include<stdlib.h>
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define MAX 1000

//描述人的信息
struct PeoInfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
};
//通讯录
struct Contact
{
	struct PeoInfo data[MAX];//1000个人的信息存放进data数组中
	int sz ;//记录当前存放进通讯录中的有效信息的个数
};

//初始化通讯录
void InitContact(struct Contact* pc);
//增加联系人
void AddContact(struct Contact* pc);
//显示通讯录
void ShowContact(struct Contact* pc);
//删除联系人
void DelContact(struct Contact* pc);
//查找指定联系人
void SearchContact(const struct Contact* pc);
//修改指定联系人
void ModifyContact(struct Contact* pc);
//按姓名排序通讯录
void SortContactByName(struct Contact* pc);

用#define定义的常量能够方便代码的修改,增加了代码的维护性。

contact.c

#include"contact.h"
void InitContact(struct Contact* pc)
{
	pc->sz = 0;//默认没有信息
	//memset(pc->data, 0, MAX * sizeof(struct PeoInfo));
	memset(pc->data, 0, sizeof(pc->data));
}

void AddContact(struct Contact* pc)
{
	if (pc->sz == MAX)
	{
		printf("通讯录已满!\n");
	}
	else
	{
		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 );
		//提示添加成功
		printf("添加成功\n");
		pc->sz++;
	}
}


void ShowContact(struct Contact* pc)
{
	int i = 0;
	printf("%15s\t%5s\t%8s\t%15s\t%30s\n\n", "name", "age", "sex", "tele", "addr");
	for (i = 0; i < pc->sz; i++)
	{
		//打印每一个数据
		printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].tele,
			pc->data[i].addr);
	}
}

int FindContactByName(const struct Contact* pc, const 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(struct Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	char name[NAME_MAX] = { 0 };
	printf("请输入要删除人的名字:>");
	scanf("%s", name);
	//查找
	int pos = FindContactByName(pc, name);
	if (pos == -1)
	{
		printf("指定的联系人不存在\n");
	}
	else
	{
		//删除
		int j = 0;
		for (j = pos; j < pc->sz-1; j++)
		{
			pc->data[j] = pc->data[j + 1];
		}
		pc->sz--;
		//提示
		printf("删除成功\n");
	}
}

void SearchContact(const struct Contact* pc)
{
	char name[NAME_MAX] = { 0 };
	printf("输入要查找人的名字:>");
	scanf("%s", name);
	int pos = FindContactByName(pc, name);
	if (-1 == pos)
	{
		printf("查无此人\n");
	}
	else
	{
		printf("%15s\t%5s\t%8s\t%15s\t%30s\n\n", "name", "age", "sex", "tele", "addr");
		printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
			pc->data[pos].name,
			pc->data[pos].age,
			pc->data[pos].sex,
			pc->data[pos].tele,
			pc->data[pos].addr);
	}
}


void ModifyContact(struct Contact* pc)
{
	char name[NAME_MAX] = { 0 };
	printf("输入要修改人的名字:>");
	scanf("%s", name);
	int pos = FindContactByName(pc, name);
	if (-1 == pos)
	{
		printf("要修改的人不存在\n");
	}
	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);
	}
}
int cmp_name(const void* e1, const void* e2)
{
	return strcmp(((struct Contact*)e1)->data->name , ((struct Contact*)e2)->data->name);
}
void SortContactByName(struct Contact* pc)
{
	qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_name);
	printf("排序成功\n");
}

存放用到的所有函数,需要引用头文件#include"contact.h"。

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");
	printf("****************************\n");
}
enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT
};

int main()
{
	int input=0;
	//创建一个通讯录
	struct 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:
			SortContactByName(&con);
			break;
		case EXIT:
			printf("退出通讯录。\n");
			break;
		default:
			printf("选择错误!\n");
			break;
		}
	} while (input);
	return 0;
}

主函数部分,这个部分也是实现部分,进入函数,先创建一个通讯录struct Contact con,然后初始化,再根据所选的input,进行个系列的操作,以此达到通讯录的增删改查等功能。

运行展示

在这里插入图片描述

总结

关于通讯录其实还有很多改进的地方,这只是最简易的版本,还可以加入文件导入,动态版本等等,相对于改进的版本,这是最简易也是最好理解的。有难度的在于qsort()函数的理解,当然我们也可以采用自己实现的排序冒泡或者快排都可以。好了通讯录小程序也可以说的上将C语言中语法的大部分内容都用了一边,对于编程能力的提升和语法的理解是有着很大的帮助的,希望大家能够抽出时间将代码敲上一敲。如果有什么错误或者建议,希望各位能够提出建议,谢谢各位!


点击全文阅读


本文链接:http://zhangshiyu.com/post/33453.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1