实验课题——最全手机通信录实现版本(【含注释】848行代码)!!!(包括模糊查询、分类查找、模拟拨号、qsort函数实现排序、文件存储、防误触等功能)

这篇具有很好参考价值的文章主要介绍了实验课题——最全手机通信录实现版本(【含注释】848行代码)!!!(包括模糊查询、分类查找、模拟拨号、qsort函数实现排序、文件存储、防误触等功能)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

简介:

基本要求:

代码的实现:

1、Contact.h

2、test.c

3、Cantact.c

运行效果图:

部分复杂函数流程图


前两周是本人的实验周,抽到的课题是“手机通信录的实现”,课题大致如下:

简介:

(1)用C/C++设计出模拟手机通信录系统,实现对手机中的通信录进行管理。

(2)将通讯录用文件存储,人员信息包括:姓名、手机号码、家庭电话号码、办公电话、电子邮件、分组。

(3)其中:手机号码、家庭电话号码、办公电话不能同时为空;分组说明:未知、同事、亲戚、朋友、家人、同学等还可以自己创建分组

(4)文件类型可以是文本文件或二进制文件。

基本要求:

(1)首先向客户展示一个欢迎界面,并提醒客户输入任意键进入主菜单,在菜单中客户进行操作选择,而且客户操作完后还可以根据需求进行返回主菜单进行其他操作。

(2)增加功能:

能录入新人员记录。

(3)查看功能:
选择此功能时,当选中某类时,显示出此类所有数据中的姓名和电话号码。

(4)拔号功能:
能显示出通信录中所有人的姓名,当选中某个姓名时,屏幕上模拟打字机的效果依次显示出此人的电话号码中的各个数字。

(5)修改功能: .
选中某个人的姓名时,可对此人的相应数据进行修改。

我一看,嚯哟!这个课题好简单啊!除了“分类查找”和“拨号”是我没写过的,剩下的功能不都是最基础的吗?主要涉及到的知识点不就是些:数组应用、指针和结构体嘛!

可是转念一想,不行,写的那么简单,和别的组没有区分度,不方便老师打分呢~(bushi)

再说了,这个程序一天就可以写完,再算上写实验报告和画函数图解也最多不过一周的事,不是对不起这两周的实验周吗?(对不起,后来博主被狠狠打脸了。老师要求很严格,不仅被要求补充了一些代码,最后写实验报告的时候简直被折磨的不行,流程图重画了好几遍……实验报告一共也就写了那么整整15个小时吧)

于是我决定,要写就写个详细的通信录程序。不仅补充上了“分类查找”和“模拟拨号(类似打印机)”这两个功能,我还增加了一些别的小功能:

1、“模糊查询”(即你要找“Jackson”这个联系人的信息,输入“Jack”,通信录会跳出所以名字含这个字符串的联系人信息。对于中文名也是可以的,比如你想找“如花”,输入“如”字按回车,它会跳出一堆“如花”、“如玉”......);

2、qsort函数实现排序:可以选择按照姓名、年龄和电话号码排序。

3、防误触:听上去好像很厉害,其实很简单,只有三行代码就搞定了。(不过是让用户再次确认自己的选择避免造成不可挽回的损失罢了)。

总之,断断续续地,花了三天时间,我终于把这个小程序写完了。它现在一共有11个功能,博主暂时想不到别的了,大家如果有好的想法可以提出来。

其实它还不是特别完备,只是一个静态的版本,我打算有时间的话把它改造成一个动态的版本,这就要涉及到我们的malloc、calloc 、free 和 realloc 函数了。

扯远了,现在让我们来看看这个通信录吧:

代码的实现:

1、Contact.h

宏定义的设置可以方便我们以后的修改。

#pragma once
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#include<windows.h>
#define MAX_NAME 10
#define MAX_SEX 5
#define MAX_HOME_NUM 12
#define MAX_NUM 12
#define MAX_OFFICE 15
#define MAX_DATA 100
#define MAX_E_MAIL 20
#define MAX_CLASSIFICATION 10
//创建联系人结构体
struct Peoinfo
{
	char name[MAX_NAME];	
	char sex[MAX_SEX];
	char home_num[MAX_HOME_NUM];
	char cell_num[MAX_NUM];
	int age;
	char office_number[MAX_OFFICE];
	char e_mail[MAX_E_MAIL];
	char classification[MAX_CLASSIFICATION];
};

//创建通讯录结构体
struct Contact
{
	struct Peoinfo data[MAX_DATA];//存放数据
	int sz;//记录通讯录中的有效信息个数
	//int capcity;
};

//把上次存在文件中的信息加载过来
void LoadContact(struct Contact* pc);
//初始化通讯录
void init_contact(struct Contact* con);
//添加联系人
void addContact(struct Contact* con);
//删除联系人
void deleteContact(struct Contact* con);
//修改联系人
void modifyContact(struct Contact* con);
//寻找联系人
static int find(const struct Contact* con, char* name);
//查找联系人
void searchContact(struct Contact* con);
//显示联系人信息
void showContact(struct Contact* con);
//排序联系人(按照年龄、名字)
void sortContact(struct Contact con);
//清空联系人
void clearContact(struct Contact* con);
//查看某一类联系人
void checkContact(struct Contact* con);
//保存联系人
void saveContact(struct Contact* con);
//拨号
void dialContact(struct Contact* con);
//把上次存在文件中的信息加载过来
//void LoadContact(struct Contact* pc);
//模糊查询联系人信息
void fuzzy_search(struct Contact* contact);

2、test.c

这里想要解释一下为什么要加一个枚举常量。(后面的Contact.c也添加了一个枚举,目的是一样的。)

枚举的使用增加了我们代码的可读性和维护性:

有时候在写一些代码时,比如写这个菜单,我们用了1来代表add,0代表exit,但是在后续代码中,1和0的真实含义有时难以被区分。所以如果用枚举的话,后续在case 后面加常量的时候就可以直接写add,这样,代码的可读性就增强了不少)。

注意!我们的防误触操作就设置在此处,因为它实在是太简单了,没有单独为它写一个函数的必要呢。

(和大家讲个笑话,活跃一下气氛。在界面设计这里呢,本来博主有一点自己的小私心,想要提醒老师我有模糊查询这个功能,让她夸夸我来着,但是她好像并不care,反而对我层层嵌套调用函数的addContact子功能青睐有加。)

#define _CRT_SECURE_NO_WARNINGS

#include "contact.h"
void Meue()
{
	printf("***亲爱的用户,欢迎您使用通信录!***\n");
	printf("***温馨提示,本通信录支持模糊查询的功能哦!***\n");
	printf("************************************\n");
	printf("*****   1.add       2.delete   *****\n");
	printf("*****   3.modify    4.search   *****\n");
	printf("*****   5.show      6.sort     *****\n");
	printf("*****   7.clear     8.check    *****\n");
	printf("*****   9.save      10.dial    *****\n");
    printf("*****   11.fuzzy_search        *****\n");	
	printf("*****   0.exit                 *****\n");
	printf("************************************\n");
}
int main()
{
	int input = 0;
	enum number
	{
		EXIT,//0
		ADD,//1
	    DELE,//2
		MODIFY,
		SEARCH,
		SHOW,
		SORT,
		CLEAR,
		CHECK,
		SAVE,
		DIAL,
		FUZZY_SEARCH,
	};
	struct Contact con;//通信录
	init_contact(&con);//初始化通信录
	LoadContact(&con);//把上次存在文件中的信息加载过来
	do
	{
		Meue();
		printf("请选择:");
		scanf_s("%d", &input);
		switch (input)
		{
		case EXIT:
			//这里设置一个防误触的功能,提醒用户再次确认是否要保存一下联系人信息再退出
			printf("请问需要保存一下通讯录的信息再退出吗?\n");
			printf("**********   1.保存一下   0.直接退出  **********\n");
			int q = 0;
			scanf("%d", &q);
			if (q==0)
			{
				printf("退出通信录!\n");
				break;
			} 
			saveContact(&con);
			printf("退出通信录!\n");
			break;
		case ADD:
			addContact(&con);
			break;
		case DELE:
			deleteContact(&con);
			break;
		case MODIFY:
			modifyContact(&con);
			break;
		case SEARCH:
			searchContact(&con);
			break;
		case SHOW:
			showContact(&con);
			break;
		case SORT:
			sortContact(con);
			break;
		case CLEAR:
			//这里设置一个防误触的功能,提醒用户再次确认是否要清空联系人信息
			printf("请问您确定要清空联系人信息吗?一旦清空,无法找回!\n");
			printf("*************   1.确定清空   0.取消  *************\n");
			int x = 0;
			scanf("%d",&x);
			if (x==1) 
			{
				clearContact(&con);
			}
			break;
		case CHECK:
			checkContact(&con);
			break;
		case SAVE:
			saveContact(&con);
			break;
		case DIAL:
			dialContact(&con);
			break;
		case FUZZY_SEARCH:
			fuzzy_search(&con);
			break;
		default:
			printf("输入错误!\n");
			break;
		}
	} while (input);
	return 0;
}

3、Cantact.c

这个源文件定义了每一个子函数的实现,还添加了两个小的 find 函数帮助个别子函数的实现。

注解都写了,大家可以好好看一下:

#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
//把上次存在文件中的信息加载过来
void LoadContact(struct Contact* pc)
{
	//打开文件
	FILE* pf = fopen("D:\\C语言2\\手机通信录实现\\contact.dat", "rb");
	if (pf == NULL)
	{
		perror("LoadContact::fopen");
		return;
	}
	//读文件
	struct Peoinfo tmp = { 0 };
	while (fread(&tmp, sizeof(struct Peoinfo), 1, pf))
	{
		pc->data[pc->sz] = tmp;
		pc->sz++;
	}

	//关闭文件
	fclose(pf);
	pf = NULL;
}
//初始化通讯录
void init_contact(struct Contact* pc)
{
	assert(pc);
	pc->sz = 0;
	memset(pc->data, 0, MAX_DATA * sizeof(struct Peoinfo));
}
//add中判断是否存在相同姓名联系人
int repetition_name(struct Contact * con, char* len)
{
	int ret = find(con, len);
	int i = 0;
	if (ret == -1)
		return 3;
	else
	{
		int repe;
		printf("已存在同名联系人,请选择:>\n");
		printf("*** 0.重新输入 1.覆盖  2.新建 ***\n");
		scanf("%d", &repe);
		switch (repe)
		{
		case 0:
			return 0;
		case 1:
			i = 0;
			for (i = 0; i < con->sz - ret; i++)
			{
				con->data[ret + i] = con->data[ret + i + 1];
			}
			con->sz--;
			printf("覆盖联系人成功!\n");
			return 1;
		case 2:
			return 2;
		}
	}
}
//add中判断是否存在相同号码联系人
int repetition_num(struct Contact* con, char* len)
{
	int ret = findnum(con, len);
	int i = 0;
	if (ret == -1)
		return 2;
	else
	{
		int repe;
		printf("已存在相同号码的联系人,请选择:>\n");
		printf("*** 0.重新输入 1.覆盖  ***\n");//号码是无法相同的,所以不要新建
		scanf("%d", &repe);
		switch (repe)
		{
		case 0:
			return 0;
		case 1:
			i = 0;
			for (i = 0; i < con->sz - ret; i++)
			{
				con->data[ret + i] = con->data[ret + i + 1];
			}
			con->sz--;
			printf("覆盖联系人成功!\n");
			return 1;
		}
	}
}
//add中用于判断电话号码中是否存在非数字字符
int isnumber(const char* ps)
{
	while (*ps != '\0')
	{
		if (*ps < '0' || *ps > '9')
		{
			return 0;
		}
		ps++;
	}
	if (*ps == '\0')
	{
		return 1;
	}
}
//新建联系人
void new(struct Contact* con, char* len)
{
	char new[MAX_NAME] = {0};
    strcpy(new, con->data[con->sz].name);
}
//添加联系人
void addContact(struct Contact* con)
{
	assert(con);
	int ret;
	int k ;
	char new[MAX_NAME] = {0};
	if ((con->sz) == MAX_DATA)
	{
		printf("通讯录已满!无法增加\n");
		return;
	}
	printf("请输入名字:>");	
	do
	{
		scanf("%s", con->data[con->sz].name);//数组名本身就是首元素地址
		k = repetition_name(con, con->data[con->sz].name);
		if(k==0)
			printf("请重新输入!\n");
		if (k == 2)
		{
			printf("请输入新的备注:>");
			scanf("%s",new );
			strcat(con->data[con->sz].name,new);//在名字后添加备注
		}
	} while (!k);

	printf("请输入性别:>");
	scanf("%s", con->data[con->sz].sex);
	printf("请输入家庭电话:>");
	//判断是否有非数字字符
	do
	{
		ret = 1;
		scanf("%s", con->data[con->sz].home_num);
		if (!isnumber(con->data[con->sz].home_num))
			printf("提示!输入的号码中存在非数字字符,请重新输入!\n");
		else
			ret = 0;
	} while (ret);
	//因为是家庭号码,所以此处不需要判断是否已有相同号码联系人存在

	printf("请输入个人电话:>");
	do
	{
		ret = 1;
		scanf("%s", con->data[con->sz].cell_num);
		if (!isnumber(con->data[con->sz].cell_num))
			printf("提示!输入的号码中存在非数字字符,请重新输入!\n");
		else
			ret = 0;
	} while (ret);
	//判断是否已有相同号码联系人存在
	do
	{
		k = 1;
		k = repetition_num(con, con->data[con->sz].cell_num);
		if (!k)
		{ 
			printf("请重新输入!\n");
			scanf("%s", con->data[con->sz].cell_num);
			k = 1;
		}
		else
			k = 0;
	} while (k);

	printf("请输入年龄:>");
	scanf("%d", &(con->data[con->sz].age));//这里需要取地址
	printf("请输入办公电话:>");
	do
	{
		ret = 1;
		scanf("%s", con->data[con->sz].office_number);
		if (!isnumber(con->data[con->sz].office_number))
			printf("提示!输入的号码中存在非数字字符,请重新输入!\n");
		else
			ret = 0;
	} while (ret);
	//因为是办公号码,所以此处不需要判断是否已有相同号码联系人存在 

	printf("请输入邮箱:>");
	scanf("%s", con->data[con->sz].e_mail);
	printf("请输入分类:>\n");
	printf("您可以在以下选项中进行选择并输入:>\n");
	printf("同事  亲戚  朋友  家人  同学  老师  其他\n");
	scanf("%s", con->data[con->sz].classification);
	con->sz++;
	printf("添加联系人成功!\n");
}
//删除联系人
void deleteContact(struct Contact* con)
{
	if (con->sz == 0)
	{
		printf("通讯录为空,无法删除!\n");
		return;
	}
	char name[MAX_NAME];
	printf("请输入要删除的联系人:");
	scanf("%s", name);
	int ret = find(con, name);
	if (ret == -1)
		printf("未找到该联系人!\n");
	else
	{
		int i = 0;
		for (i = 0; i < con->sz - ret; i++)
		{
			con->data[ret + i] = con->data[ret + i + 1];
		}
		con->sz--;
		printf("删除联系人成功!\n");
	}
}
//修改联系人
void modifyContact(struct Contact* con)
{
	char name[MAX_NAME];
	printf("请输入要修改的联系人:");
	scanf("%s", name);
	int ret = find(con, name);
	if (ret == -1)
		printf("未找到该联系人!\n");
	else
	{
		int n = 0;
		do
		{
			int ret;
			int k;
			printf("请选择你想要修改的信息:\n");
			printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5s\t%-15s\t%-20s\t%-10s\n",
				"0.退出修改","1.姓名", "2.性别", "3.家庭电话", "4.个人电话", "5.年龄", "6.办公电话", "7.邮箱", "8.分类");
			scanf("%d", &n);
			switch (n)
			{
			case NAME:
				printf("请输入你想修改的姓名:");
				do
				{
					scanf("%s", con->data[con->sz].name);//数组名本身就是首元素地址
					k = repetition_name(con, con->data[con->sz].name);
					if (k == 0)
						printf("请重新输入!\n");
					if (k == 2)
					{
						printf("请输入新的备注:>");
						scanf("%s", new);
						strcat(con->data[con->sz].name, new);//在名字后添加备注
					}
				} while (!k);

				printf("修改成功!\n");
				break;
			case SEX:
				printf("请输入你想修改的性别:");
				scanf("%s", con->data[ret].sex);
				break;
			case HOME_NUM:
				printf("请输入你想修改的家庭电话:");
				//判断是否有非数字字符
				do
				{
					ret = 1;
					scanf("%s", con->data[con->sz].home_num);
					if (!isnumber(con->data[con->sz].home_num))
						printf("提示!输入的号码中存在非数字字符,请重新输入!\n");
					else
						ret = 0;
				} while (ret);
				//因为是家庭号码,所以此处不需要判断是否已有相同号码联系人存在
				break;
			case CELL_NUM:
				printf("请输入你想修改的手机号码:");
				do
				{
					ret = 1;
					scanf("%s", con->data[con->sz].cell_num);
					if (!isnumber(con->data[con->sz].cell_num))
						printf("提示!输入的号码中存在非数字字符,请重新输入!\n");
					else
						ret = 0;
				} while (ret);
				//判断是否已有相同号码联系人存在
				do
				{
					k = 1;
					k = repetition_num(con, con->data[con->sz].cell_num);
					if (!k)
					{
						printf("请重新输入!\n");
						scanf("%s", con->data[con->sz].cell_num);
						k = 1;
					}
					else
						k = 0;
				} while (k);

				break;
			case AGE:
				printf("请输入你想修改的年龄:");
				scanf("%d", &con->data[ret].age);//不是数组,需要写地址符
				break;
			case OFFICE_NUMBER:
				printf("请输入你想修改的办公电话:");
				do
				{
					ret = 1;
					scanf("%s", con->data[con->sz].office_number);
					if (!isnumber(con->data[con->sz].office_number))
						printf("提示!输入的号码中存在非数字字符,请重新输入!\n");
					else
						ret = 0;
				} while (ret);
				//因为是办公号码,所以此处不需要判断是否已有相同号码联系人存在 
				break;
			case E_MAIL:
				printf("请输入你想修改的电子邮箱:");
				scanf("%s", con->data[ret].e_mail);
				break;
			case CLASSFICATION:
				printf("请输入你想修改的分组:");
				scanf("%s", con->data[ret].classification);
				break;
			case LEAVE:
				printf("不修改退回页面\n");
				break;
			default:
				printf("无效操作数!\n");
			}
		} while (n);
	}
}
    
    //下面这些代码是表示每次修改都要重新输入该联系人的所有信息的,
    //因为不太方便,所以改造了一下,
    //改成上面那样,只用修改自己想要修改的信息

    //else
    //{
	//	printf("请输入姓名:");
	//	scanf("%s", con->data[ret].name);
	//	printf("请输入性别:");
	//	scanf("%s", con->data[ret].sex);
	//	printf("请输入电话:");
	//	scanf("%s", con->data[ret].home_num);
	//	printf("请输入电话:");
	//	scanf("%s", con->data[ret].cell_num);
	//	printf("请输入年龄:");
	//	scanf("%d", &(con->data[ret].age));
	//	printf("请输入办公电话:");
	//	scanf("%s", con->data[ret].office_number);
	//	printf("请输入邮箱:");
	//	scanf("%s", con->data[ret].e_mail);
	//	printf("请输入分类:");
	//	scanf("%s", con->data[ret].classification);
	//	printf("修改联系人成功!\n");
    //}



//寻找联系人是否存在——因为有多个功能都需要我们先去确认是否存在联系人,
//所以干脆把这个功能作为一个函数独立出去
static int find(const struct Contact* con, char* name)
//加上static之后就不会被别人看到,只能在该源文件使用
{
	int i = 0;
	for (i = 0; i < con->sz; i++)
	{
		if (0 == strcmp(con->data[i].name, name))
			return i;
	}
	return -1;//i==con->sz
}
static int findnum(const struct Contact* con, char* number)
//同样的,查找联系人电话我们也把它独立出来
{
	int i = 0;
	for (i = 0; i < con->sz; i++)
	{
		if (0 == strcmp(con->data[i].cell_num, number))
			return i;
	}
	return -1;//i==con->sz
}
//查找联系人
void searchContact(struct Contact* con)
{
	assert(con);
	char name[20] = { 0 };
	char number[12] = {0};
	int n;
	printf("请问您想要通过那种方式查找联系人:\n");
	printf("***    1.姓名    2.电话号码    ***\n");
	int ret=0;
	scanf("%d",&n);
	switch (n)
	{
	    case 1:
			printf("请输入要查找的联系人姓名:");
			scanf("%s", &name);
			ret = find(con, name);
			if (ret == -1)
				printf("未找到该联系人!\n");
			else
			{
				printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5s\t%-15s\t%-20s\t%-10s\n",
					"姓名", "性别","家庭电话", "个人电话", "年龄", "办公电话", "邮箱", "分类");
				printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5d\t%-15s\t%-20s\t%-10s\n",
					con->data[ret].name, con->data[ret].sex, con->data[ret].home_num,
					con->data[ret].cell_num, con->data[ret].age, con->data[ret].office_number,
					con->data[ret].e_mail, con->data[ret].classification);
			}
			break;
		case 2:
			printf("请输入要查找的联系人的电话号码:");
			scanf("%s", &number);
			ret = findnum(con, number);
			if (ret == -1)
				printf("未找到该联系人!\n");
			else
			{
				printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5s\t%-15s\t%-20s\t%-10s\n",
					"姓名","性别", "家庭电话", "个人电话", "年龄", "办公电话", "邮箱", "分类");
				printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5d\t%-15s\t%-20s\t%-10s\n",
					con->data[ret].name, con->data[ret].sex, con->data[ret].home_num,
					con->data[ret].cell_num, con->data[ret].age, con->data[ret].office_number,
					con->data[ret].e_mail, con->data[ret].classification);
			}
			break;

	}
	
}
//显示联系人
void showContact(struct Contact* con)
{
	assert(con);
	int i = 0;
	//姓名      性别   家庭电话      个人电话           年龄          办公电话      邮箱                  分类
	//zhangsan  男     1245676789    13245123123        20            12538912332   67125677121@136.com   家人
	printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5s\t%-15s\t%-20s\t%-10s\n",
		"姓名", "性别","家庭电话", "个人电话", "年龄", "办公电话", "邮箱", "分类");
	for (i = 0; i < con->sz; i++)
	{
		printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5d\t%-15s\t%-20s\t%-10s\n",
			con->data[i].name, con->data[i].sex, con->data[i].home_num,
			con->data[i].cell_num, con->data[i].age, con->data[i].office_number,
			con->data[i].e_mail, con->data[i].classification);
	}

}
//按姓名排序
int name_cmp(const void* e1, const void* e2)
{
	return strcmp(((struct Peoinfo*)e1)->name, ((struct Peoinfo*)e2)->name);
}
//按办公电话排序
int office_number_cmp(const void* e1, const void* e2)
{
	return strcmp(((struct Peoinfo*)e1)->office_number,((struct Peoinfo*)e2)->office_number);
}
//按年龄排序
int age_cmp(const void* e1, const void* e2)
{
	return ((struct Peoinfo*)e1)->age - ((struct Peoinfo*)e2)->age;
}
//排序通讯录
void sortContact(struct Contact con)
{
	printf("********* 请选择排序方式:**********\n");
	printf("********* 1.姓名         ***********\n");
	printf("********* 2.办公电话     ***********\n");
	printf("********* 3.年龄         ***********\n");
	printf("************************************\n");
	int a = 0;
	scanf("%d", &a);
	switch (a)
	{
	case 1:
		qsort(con.data, con.sz, sizeof(con.data[0]), name_cmp);
		break;
	case 2:
		qsort(con.data, con.sz, sizeof(con.data[0]), office_number_cmp);
		break;
	case 3:
		qsort(con.data, con.sz, sizeof(con.data[0]), age_cmp);
		break;
	default:
		printf("输入错误\n");
		break;
	}
	int i = 0;
	printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5s\t%-15s\t%-20s\t%-10s\n",
		"姓名","性别", "家庭电话", "个人电话", "年龄", "办公电话", "邮箱", "分类");
	for (i = 0; i < con.sz; i++)
	{
		printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5d\t%-15s\t%-20s\t%-10s\n",
			con.data[i].name, con.data[i].sex, con.data[i].home_num,
			con.data[i].cell_num, con.data[i].age, con.data[i].office_number,
			con.data[i].e_mail, con.data[i].classification);
	}
}
//清空联系人
void clearContact(struct Contact* con)
{
	con->sz = 0;
	printf("清空联系人成功!\n");
}

//查看某一类联系人
void checkContact(struct Contact* con)
{
	char classification[10];
	int jude = 0;
	do 
	{
		printf("人员信息如下:\n");
		printf("同事  亲戚  朋友  家人  同学  老师  其他\n");
		printf("请输入查看人员的类别:\n");
		scanf("%s", classification);
		//用来判断输入字符串是否符合分类名称
		char* judgeclass[7] = { "同事",  "亲戚", "朋友","家人","同学","老师","其他" };
		for (jude = 0; jude < 7; jude++)
		{
			if ((strcmp(judgeclass[jude], classification) == 0))
				break;
		}
		if (jude == 7)
		{
			printf("您输入的分类名错误,请重新输入!>\n");
		}
	} while (jude==7);
	for(int ssz= con->sz - 1;ssz>=0;ssz--)
	{
		if (strcmp((con->data[ssz].classification), classification) == 0)
		{
			printf("%-10s\t%-12s\t%-12s\t%-15s\n", "姓名", "家庭电话", "个人电话", "办公电话");
			printf("%-10s\t%-12s\t%-12s\t%-15s\n",
				con->data[ssz].name, con->data[ssz].home_num,
				con->data[ssz].cell_num, con->data[ssz].office_number);

		}
	}
		printf("查找结束!\n");
}
//保存联系人
void saveContact(struct Contact* con)
{
		FILE* pf = fopen("D:\\C语言2\\手机通信录实现\\contact.dat", "wb");
		if (pf == NULL)
		{
			//显示错误信息,表示是在saveContact函数内的这个地方出错了!
			perror("SaveContact::fopen");
			return;
		}
		//写数据
		int i = 0;
		for (i = 0; i < con->sz; i++)
		{
			//&(con->data[i])可以写成con->data+i,更简单
			fwrite(con->data + i, sizeof(struct Peoinfo), 1, pf);
		}
		//关闭文件
		fclose(pf);
		pf = NULL;
		//简单提示一下
		printf("保存成功!\n");
}

//拨号功能
void dialContact(struct Contact* con)
{
	if (con->sz == 0)
	{
		printf("通信录中没有联系人信息!\n");
		return;
	}

	printf("通讯录中所有联系人如下:\n");
	for (int i = 0; i < con->sz; i++)
	{
		printf("%d . 姓名:%s\n", i + 1, con->data[i].name);
	}
	int choice = 0;
	printf("请选择您要拨打电话的联系人编号(输入0返回主菜单):");
	scanf("%d", &choice);
	if (choice < 0 || choice > con->sz)
	{
		printf("输入的编号有误,请重新选择!\n");
		dialContact(con);//返回拨号函数选择处
		return;
	}
	if (choice == 0)
	{
		return;
	}
	printf("您选择的联系人是:%s\n", con->data[choice - 1].name);
	printf("个人电话:");
	// 模拟打字机效果逐个显示电话号码中的数字
	for (int i = 0; i < strlen(con->data[choice - 1].cell_num); i++)
	{
		printf("%c", con->data[choice - 1].cell_num[i]);
		Sleep(300);  // 每个数字之间停顿一段时间
	}
	printf("\n");
	printf("家庭电话:");
	// 模拟打字机效果逐个显示电话号码中的数字
	for (int i = 0; i < strlen(con->data[choice - 1].home_num); i++)
	{
		printf("%c", con->data[choice - 1].home_num[i]);
		Sleep(300);  // 每个数字之间停顿一段时间
	}
	printf("\n");
	printf("办公电话:");
	// 模拟打字机效果逐个显示电话号码中的数字
	for (int i = 0; i < strlen(con->data[choice - 1].office_number); i++)
	{
		printf("%c", con->data[choice - 1].office_number[i]);
		Sleep(300);  // 每个数字之间停顿一段时间
	}
	printf("\n");
}

// 子函数,实现模糊查找功能
void fuzzy_search(struct Contact* contact)
{
	assert(contact);
	char fuzzy_name[10] = {0};
	printf("请输入想要查询的联系人的姓名:\n");
	scanf("%s",fuzzy_name);
	char* key = fuzzy_name;
	// 检查通讯录中是否有联系人信息,如果没有,无法进行模糊查询
	if (contact->sz == 0)
	{
		printf("通讯录中没有联系人信息!\n");
		return;
	}

	int index[MAX_DATA];
	int count = 0;

	// 遍历通讯录中的每个联系人
	for (int i = 0; i < contact->sz; i++)
	{
		struct Peoinfo* person = &contact->data[i];
		// 在联系人的各个字段中查找是否包含要查找的字符串key
		if (strstr(person->name, key))
		{
			printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5s\t%-15s\t%-20s\t%-10s\n",
				"姓名", "性别", "家庭电话", "个人电话", "年龄", "办公电话", "邮箱", "分类");
			printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5d\t%-15s\t%-20s\t%-10s\n",
				person->name, person->sex, person->home_num, person->cell_num, person->age, person->office_number,
				person->e_mail, person->classification);
			index[count++] = i;
		}
	}
		// 如果没有找到匹配的联系人,则输出提示信息
		if (count == 0)
		{
			printf("未找到匹配的联系人!\n");
		}
		else
		{
			printf("共找到 %d 个匹配的联系人,分别为:", count);
			for (int i = 0; i < count; i++)
			{
				printf("第%d个联系人 ", index[i]+1);
			    //让联系人看起来是从第1个开始排序的,即下标0处跳过
			}
			printf("\n");
		}
}

运行效果图:

1、增加联系人

switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

 总的显示给大家看一下:

switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

 现在假设我们重新输入,来看看如果出现名字相同的联系人,程序会有什么反应吧:

switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

 switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

 switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

 switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

来看看新建同名联系人后的小米和小米(1)吧: switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

 那电话号码相同的呢?可以新建吗?当然不行,和姓名相同时的代码略有不同:switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

 如果选择覆盖呢?switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

 小米不见了呢!(对不起,小米):switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

 当然,我们迷人的addContact函数还有一个功能,就是会判断你输入的三个电话号码中是否存在非数字字符,来看一下吧:switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

2、删除联系人

switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

 总的显示给大家看一下:switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

 3、修改联系人信息:

switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

  总的显示给大家看一下:switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

4、寻找单个联系人 switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

 5、显示整个通讯录(刚刚已经展示过了)

6、排序

switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

 switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

 switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

7、清除所有联系人switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

 8、按分类查找某一类的联系人 

switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

 9、保存到文件里

switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

 已经保存到当前目录下了:switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

10、模拟拨号(它是像打印机一样慢慢一个数字一个数字打印的,这里演示不了)

switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

11、模糊查询 switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

12、把上次已经存好在文件中的信息加载过来:

当初次使用时:switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

 如果已有信息(这里博主为了演示,把刚刚上面举的例子都删除了,所以现在的数据是博主又重新输入的,和上面的联系人信息存在不同,请见谅):

switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

 现在已经保存好了:switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

我们重启程序看看:switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法 成功读取了呢! 

好了!以上就是我的手机通信录的整个代码实现。

如果你认真看到这里,说明你应该对它的实现很感兴趣吧。

心动不如行动!实践是很重要的!现在,打开电脑,开始码代码吧。

博主建议,各位兄台先自己实现一下,如果遇到逻辑不通的地方,可以画一个图解帮助自己理解,

实在是遇到不理解的地方可以再回来看看。自己写一遍真的不一样!!!

部分复杂函数流程图

最后,因为两个结构体的关系有一点不好理解,所以博主画了一个总的说明图(图1):

switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

                                                                      图1

下面是一些稍微复杂的函数的流程图(实验报告要求要画,我觉得比代码难搞1000倍!超累的!!!)

添加联系人函数:用于将新的联系人信息添加到通讯录中。该功能包括输入联系人的各项信息,然后将这些信息保存到通讯录中。在保存之前,可能需要进行一些验证和处理,例如检查通讯录是否已满、检查是否存在重复的姓名或电话号码等。

该函数用于将新的联系人信息添加到通讯录中。该功能包括输入联系人的各项信息,然后将这些信息保存到通讯录中。在保存之前,可能需要进行一些验证和处理,例如检查通讯录是否已满、检查是否存在重复的姓名、存入电话号码前先判断输入的是否为数字、是否存在重复的电话号码等,如图2-1-1所示。其中,添加联系人函数用到了5个小的功能函数,它们在“修改联系人函数”时也会再次被调用。find函数流程图用来寻找整个通信录中是否有该名字的字符串,如图2-1-2所示;findnum函数流程图用来寻找整个通信录中是否已有相同号码的字符串,如图2-1-3所示;isnumber函数流程图,用来判断输入号码中是否含有非数字字符,如图2-1-4所示;repetition_name函数流程图,用于判断是否有相同姓名的联系人,如图2-1-5所示;repetition_num函数,用于判断是否有相同号码的联系人,如图2-1-6所示。

switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

图2-1-1 添加联系人功能(第1种实现)

switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

                                                   图2-1-2 fun函数(查找同名联系人)

switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

                图2-1-3 funnum函数(查找相同号码联系人)

switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

                                             图2-1-4 isnumber函数(判断是否有非数字字符)

 switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

                                                                 图2-1-5 repetition_name函数 

switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

                                                                  图2-1-6 repetition_num函数

 修改联系人信息函数:在已有的通讯录中修改联系人的相关信息的函数。要求用户输入要修改的联系人姓名作为唯一标识信息,然后遍历整个通讯录,查找是否存在该联系人。如果存在该联系人,用户可以根据需要选择需要修改的信息并进行修改,修改后的信息会被更新到通讯录中,如果没有找到该联系人,则会给出相应的提示信息。

在已有的通信录中修改联系人的相关信息的函数,先判断通信录是否为空,若为空则提醒用户并退出,不为空则要求用户输入要修改的联系人姓名,作为唯一标识信息,然后遍历整个通信录,查找是否存在该联系人。若存在该联系人,用户可以根据需要选择需要修改的信息并进行修改,修改后的信息会被更新到通信录中,若没有找到该联系人,则会给出相应的提示信息。流程图如图3所示。

switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法 查找特定联系人函数:根据姓名或号码查找特定联络人信息。这个功能允许用户通过输入联系人的姓名或号码来查找该联系人的信息,如果找到,则返回该联系人的详细信息,否则返回查找失败的信息。

查找特定联系人信息流程图如图5所示。 

switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

                                                        如图5  查找特定联系人信息

模糊查询函数:在通讯录中根据关键字模糊搜索联系人信息的功能。该功能可以让用户快速查找到包含特定关键字的联系人信息。根据输入的关键字,遍历通讯录中的所有联系人信息,查找包含关键字的联系人信息并输出。 

模糊查询函数如图6所示

switch模糊查询,进阶C语言,小游戏,通讯录的实现,智能手机,c语言,算法

                                                                    图6  模糊查询函数

本次内容到这里就结束啦!谢谢认真看到这里的你呀!文章来源地址https://www.toymoban.com/news/detail-734496.html

到了这里,关于实验课题——最全手机通信录实现版本(【含注释】848行代码)!!!(包括模糊查询、分类查找、模拟拨号、qsort函数实现排序、文件存储、防误触等功能)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【移动端表格组件】uniapp简单实现H5,小程序,APP多端兼容表格功能,复制即用,简单易懂【详细注释版本】

    由于最近需要做移动端的项目 有个pc端的后台系统里面需要移一部分页面过来 而里面就有很多的表格,我就开始惯例网上先找前人栽的树,我好乘凉 然后找了一圈发现,不管是主流的移动端ui库或者网上自己写的帖子,或者uniapp的插件网站 都没有看到符合我要求的表格,然

    2024年02月02日
    浏览(113)
  • HC-05蓝牙模块连接到安卓手机,实现通信

    准备好的硬件:1、usb转ttl模块   2、hc-05模块 准备好的软件:1、pc端 串口调试助手 2、手机软件 蓝牙调试器(推荐)  3、ch340 软件下载链接:串口调试助手:UartAssist串口调试助手 V5.0.2-软件工具-野人家园 (cmsoft.cn)                          蓝牙调试器:https://pan.baidu.co

    2023年04月10日
    浏览(68)
  • arduino nano 简单实现蓝牙模块与手机进行通信

            目前很多通信方式都需要外附手柄,控制器,接收器,体积比较大,用起来不够方便。那么,对于距离要求不高的控制小项目,蓝牙通信一定是不二之选。         基础的编程思想和基础的C语言或Python语言知识,单片机原理的基础知识。         一般蓝牙模块需要

    2023年04月08日
    浏览(35)
  • 如何实现单片机与手机的远距离通信

    云服务器中转可以实现单片机与手机的远距离通信 只要有互联网连接,通过云服务器中转,单片机和手机无论处于地球的哪一个角落都可以进行通信,这就是物联网的魅力了。 单片机如何接入互联网? 单片机通过WIFI模块的协助接入互联网。 单片机通过UART接口与WIFI模块连接

    2024年03月12日
    浏览(53)
  • 蓝牙通信 Android开发实现手机间通过蓝牙传输文件

    MainActivity.java 根据以上代码的结构和功能,我会将它们分为以下几部分: 权限请求和检查 requestPermissions() 方法 checkLocationPermission() 方法 onRequestPermissionsResult() 方法 初始化和设置 onCreate() 方法 onStart() 方法 onActivityResult() 方法 蓝牙设备搜索和配对 discoverDevices() 方法 与列表交互

    2024年03月27日
    浏览(51)
  • Arduino蓝牙模块与手机通信---实现蓝牙控制LED

    当使用 Arduino 进行蓝牙通信时,我们可以轻松地实现与其他蓝牙设备之间的数据交换。蓝牙通信在各种物联网和远程控制应用中非常有用,因为它提供了无线连接和简便的数据传输。在本篇博客中,我们将介绍如何在 Arduino 上设置蓝牙通信,并进行基本的数据传输。 1. 介绍

    2024年02月08日
    浏览(53)
  • uniapp - [最新] 超详细实现支付宝小程序获取手机号、个人信息,支付宝弹框授权拿到用户手机号与昵称头像等信息完整流程(详细示例源码与注释,一键复制快速应用到项目中)

    网上的文章乱七八糟的都不行,新手小白很难看懂,本篇文章通俗易懂。 本博客实现了在uniapp 支付宝小程序项目中,从 0-1 描述了如何授权获取用户的手机号和头像昵称信息,一看就能懂 你可以跟着教程一步步走,从支付宝后台配置再到详细的示例,稍微改改参数就能快速

    2024年02月06日
    浏览(135)
  • 通过usb利用adb实现android手机和pc机通信

    1、 adb forward 原理概述 adb forward 的功能是建立一个转发 如:adb forward tcp:8000 tcp:9000 的意思是,将PC端的 8000 端口收到的数据,转发给手机中的 9000 端口。 但是光执行这个命令还不能转发数据,还需要完成下面两个步骤才能传数据: (a)在手机端,建立一个端口为9000的 serv

    2024年01月22日
    浏览(48)
  • (2)STM32+ESP8266+手机网络助手实现AP模式通信

    根据手头要实现的需求, 我需要通过手机端向32端发送指令,32端进行判断执行,所以采用esp8266的AP模式,将esp8266模块本身作为热点服务器,手机端作为客户端,连接热点WiFi发送数据 。 STM32rct6板、esp8266(ESP-01S)、手机端网络助手app wifi模块直接与TTL转串口模块相连即可,RX

    2024年02月07日
    浏览(55)
  • unity2022版本 实现手机虚拟操作杆

    在许多移动游戏中,虚拟操纵杆是一个重要的用户界面元素,用于控制角色或物体的移动。本文将介绍如何在Unity中实现虚拟操纵杆,提供了一段用于移动控制的代码。我们将讨论不同类型的虚拟操纵杆,如固定和跟随,以及如何在实际游戏中使用这些操纵杆。 1. 添加一个

    2024年02月08日
    浏览(59)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包