IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 抽丝剥茧C语言(高阶)静态通讯录 -> 正文阅读

[C++知识库]抽丝剥茧C语言(高阶)静态通讯录

通讯录目录

用C语言模拟出来一个通讯录,首先要分头文件和源文件的,我这里分了一个头文件和两个源文件:
在这里插入图片描述
test.c这里用于存放主函数和调用其他函数,contacts.c用于存放通讯录的各种功能函数,contacts.h用于存放引用头文件的代码和自定义函数的声明和预处理指令。
首先,我们写的通讯录鸭油7个功能:
添加联系人,删除联系人,修改联系人的信息,查找联系人,展示通讯录联系人,排序通讯录中的联系人,退出通讯录。
test.c

#include "contacts.h"
enum list
{
	exit,//默认值为0
	add,
	del,
	modify,
	find,
	show,
	sort
};
void catalogue()
{
	printf("*********************************\n");
	printf("***   1.add        2.del      ***\n");
	printf("***   3.modify     4.find     ***\n");
	printf("***   5.show       6.sort     ***\n");
	printf("***   0.exit                  ***\n");
	printf("*********************************\n");
}
int main()
{
	int n = 0;
	do
	{
		catalogue();//通讯录菜单
		printf("请选择>");
		scanf("%d", &n);//选择要做什么
		switch (n)
		{
		case exit://退出程序
			printf("退出通讯录");
			break;
		case add://添加联系人

			break;
		case del://删除联系人

			break;
		case find://查找联系人

			break;
		case modify://修改联系人信息

			break;
		case show://展示联系人

			break;
		case sort://排序通讯录

			break;
		default:
			printf("输入错误请重新输入\n");
		}
	} while (n);
	return 0;
}

Contacts.c

#include "contacts.h"

Contacts.h

#include <stdio.h>

运行起来看一下效果:

在这里插入图片描述
下面我们就着手安排剩下的功能。

初始化通讯录

首先我们要想一下,通讯录里面的联系人个人信息都有什么,我自己定义的有,名字,年龄,性别,电话,住址。
因为通讯录里面要储存一些联系人,联系人又分这些信息,那么我们用构造体来定义一个联系人再合适不过。
Contacts.h

//定义的结构体
typedef struct person
{
	char name[20];//名字
	int age;//年龄
	char sex[20];//性别
	char phone[20];//电话
	char location[20];//住址
}person;

这是联系人的类型,那么一个通讯录我们假设能储存一百个人,那么还需要有一个变量来计算一下通讯录当前有多少人才行。
Contacts.h

typedef struct contacts
{
	person data[100];//存放人信息的位置
	int count;//记录通讯录的人数
}contacts;

这里因为data和count是维护整个通讯录的关键变量,count是根据date里面的元素数量变化而变化,放在一个结构体里面更方便用。
然后整个程序就是这样子的:
Contacts.h

#include <stdio.h>
#include <string.h>
//定义的结构体
typedef struct person
{
	char name[20];//名字
	int age;//年龄
	char sex[20];//性别
	char phone[20];//电话
	char location[20];//住址
}person;

typedef struct contacts
{
	person data[100];//存放人信息的位置
	int count;//记录通讯录的人数
}contacts;
//函数声明区
void initialize(contacts* pc);//初始化通讯录

Contacts.c

#include "contacts.h"
void initialize(contacts* pc)
{
	pc->count = 0;//将计数的变量初始化为0
	memset(pc->data, 0, sizeof(pc->data));//将数组里面的内容都初始化为0
}

test.c

#include "contacts.h"
enum list
{
	exit,//默认值为0
	add,
	del,
	modify,
	find,
	show,
	sort
};
void catalogue()
{
	printf("*********************************\n");
	printf("***   1.add        2.del      ***\n");
	printf("***   3.modify     4.find     ***\n");
	printf("***   5.show       6.sort     ***\n");
	printf("***   0.exit                  ***\n");
	printf("*********************************\n");
}
int main()
{
	int n = 0;
	contacts con;//通讯录
	initialize(&con);//初始换通讯录
	do
	{
		catalogue();//通讯录菜单
		printf("请选择>");
		scanf("%d", &n);//选择要做什么
		switch (n)
		{
		case exit://退出程序
			printf("退出通讯录");
			break;
		case add://添加联系人

			break;
		case del://删除联系人

			break;
		case find://查找联系人

			break;
		case modify://修改联系人信息

			break;
		case show://展示联系人

			break;
		case sort://排序通讯录

			break;
		default:
			printf("输入错误请重新输入\n");
		}
	} while (n);
	return 0;
}

在这里插入图片描述
这里我们初始化完成了。
这里要说一下,我们传结构体就要传结构体的地址,因为能节省内存。
(这里忘记添加assert函数来断言了,下面补上了)。

添加联系人和展示通讯录的联系人

添加联系人首先要先判断通讯录是不是人数已经满了,然后在contacts结构体中的person data[100]存放联系人的信息,从data[0]开始,那么count就是计算有多少个联系人,一开始也是0,多一个就++,那么count也对应了data数组的下标存放位置。
存放进去之后我们顺便也写一下打印函数,打印就很简单了,定义一个变量来当数组下标,小于count就可以了。
contacts.h

//函数声明区
void initialize(contacts* pc);//初始化通讯录
void addcontact(contacts* pc);//输入联系人信息
void showcontact(const contacts* pc);//打印通讯录,因为打印不需要修改里面的数值,所以用const修饰一下更安全

contacts.c

void addcontact(contacts* pc)
{
	assert(pc != NULL);//断言pc指向的位置不是空指针
	if (pc->count == MAX)
	{
		printf("通讯录已满\n");
		return 0;
	}
	printf("姓名:");
	scanf("%s", pc->data[pc->count].name);//这里注意一下,数组名是首元素地址,所以不用取地址了
	printf("年龄:");
	scanf("%d", &(pc->data[pc->count].age));
	printf("性别:");
	scanf("%s", pc->data[pc->count].sex);
	printf("电话号:");
	scanf("%s", pc->data[pc->count].phone);
	printf("家庭住址:");
	scanf("%s", pc->data[pc->count].location);
	pc->count++;
	printf("增加成功\n");
}

void showcontact(const contacts* pc)
{
	assert(pc != NULL);
	int i = 0;
	printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20\t\n", "姓名", "年龄","性别","电话号","家庭住址");
	for (i = 0; i < pc->count; i++)
	{
		printf("%-20s\t%-20d\t%-20s\t%-20s\t%-20\t\n", 
			pc->data[i].name, 
			pc->data[i].age, 
			pc->data[i].sex, 
			pc->data[i].phone, 
			pc->data[i].location);
	}
}

test.c

int main()
{
	int n = 0;
	contacts con;//通讯录
	initialize(&con);//初始换通讯录
	do
	{
		catalogue();//通讯录菜单
		printf("请选择>");
		scanf("%d", &n);//选择要做什么
		switch (n)
		{
		case exit://退出程序
			printf("退出通讯录");
			break;
		case add://添加联系人
			addcontact(&con);
			break;
		case del://删除联系人

			break;
		case find://查找联系人

			break;
		case modify://修改联系人信息

			break;
		case show://展示联系人
			showcontact(&con);
			break;
		case sort://排序通讯录

			break;
		default:
			printf("输入错误请重新输入\n");
		}
	} while (n);
	return 0;
}

来看一下效果:
在这里插入图片描述

删除联系人,修改联系人,查找联系人

这三个放在一起写比较方便,因为修改和删除需要先查找有没有这个联系人才可以操作,查找功能更不用说。
首先要写一个查找联系人的函数,用strcmp函数来查找你输入的名字在通讯录里有无。
删除联系人的函数:
contacts.c

int find_out(char* p1 , contacts* p2)
{
	assert(p1 != NULL);
	assert(p2 != NULL);
	int i = 0;
	for (i = 0; i < p2->count; i++)
	{
		if (!strcmp(p1, p2->data[i].name))//如果相等就返回0,前面加了!操作符,所以非零条件不成立
			return i;
	}
	return -1;
}

int delcontact(contacts* pc)
{
	assert(pc != NULL);
	char name[20] = { 0 };
	printf("输入此人姓名\n");
	scanf("%s", name);
	int i = find_out(name, pc);
	if (i == -1)
	{
		printf("无此人信息\n");
		return 1;
	}
	pc->count = pc->count - 1;
	while (i < pc->count)
	{
		pc->data[i] = pc->data[i + 1];//删除的过程
		i++;
	}
	printf("删除成功");
}

其实删除人的过程很简单,你选定的元素是data[i],然后被data[i+1]覆盖,data[i+1]被data[i+2]覆盖以此循环。
因为通过一个查找的逻辑找到了此人,所以通讯录的人就会少一人,那么count就会减一,这样让i<count就不会有问题了,如果count不减少,i=99,count=100,就会造成数组的越界访问,这样不好处理,所以我们直接让count- -,这样i最多也就是98,i+1=99;至于data[99]这个位置的元素怎么办,不用理会,上面的添加联系人和展示通讯录都是count进行很重要的操作,新添加的联系人会覆盖掉原来末尾中没有被位移的联系人信息;如果没有添加展示联系人的话根本不会打印出来末尾的那个联系人。
修改联系人就更容易了,直接将原来联系人的信息覆盖掉就可以了,等于无循环版本添加联系人函数。
修改联系人的函数:
contacts.c

int find_out(char* p1 , contacts* p2)
{
	assert(p1 != NULL);
	assert(p2 != NULL);
	int i = 0;
	for (i = 0; i < p2->count; i++)
	{
		if (!strcmp(p1, p2->data[i].name))//如果相等就返回0,前面加了!操作符,所以非零条件不成立
			return i;
	}
	return -1;
}

int modifycontact(contacts* pc)
{
	assert(pc != NULL);
	printf("输入此人姓名\n");
	char name[20] = { 0 };
	scanf("%s", name);
	int i = find_out(name, pc);
	if (i == -1)
	{
		printf("无此人信息\n");
		return 1;
	}
	printf("请输入要修改的信息\n");
	printf("姓名:");
	scanf("%s", pc->data[i].name);
	printf("年龄:");
	scanf("%d", &(pc->data[i].age));
	printf("性别:");
	scanf("%s", pc->data[i].sex);
	printf("电话号:");
	scanf("%s", pc->data[i].phone);
	printf("家庭住址:");
	scanf("%s", pc->data[i].location);
	printf("修改成功\n");
}

查找联系人的函数就是展示通讯录函数的无循环版本。
这是查找联系人的函数:
contacts.c

int find_out(char* p1 , contacts* p2)
{
	assert(p1 != NULL);
	assert(p2 != NULL);
	int i = 0;
	for (i = 0; i < p2->count; i++)
	{
		if (!strcmp(p1, p2->data[i].name))//如果相等就返回0,前面加了!操作符,所以非零条件不成立
			return i;
	}
	return -1;
}

int findcontact(contacts* pc)
{
	assert(pc != NULL);
	printf("输入此人姓名\n");
	char name[20] = { 0 };
	scanf("%s", name);
	int i = find_out(name, pc);
	if (i == -1)
	{
		printf("无此人信息\n");
		return 1;
	}
	printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20\t\n", "姓名", "年龄", "性别", "电话号", "家庭住址");
	printf("%-20s\t%-20d\t%-20s\t%-20s\t%-20\t\n",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].phone,
			pc->data[i].location);
}

这是代码运行的效果(写一点调试一点,这样就会让代码的bug容易修复):
在这里插入图片描述

排序通讯录

排序我也按照通讯录中联系人的名字来排序,这就用到了之前的函数,qsort。
contacts.c

int estimate(const void* p1, const void* p2)
{
	return strcmp(((person*)p1)->name, ((person*)p2)->name);//比较的是联系人中姓名的大小
}
void sortcontact(contacts* pc)
{
	assert(pc != NULL);
	qsort(pc->data, pc->count, sizeof(person), estimate);//利用接收estimate函数的返回值然后排序data数组里面的元素
	printf("排序成功\n");
}

看看是否有问题:
在这里插入图片描述
没问题。

完整的代码

contacts.h

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

#define MAX 100//通讯录最大人数
//定义的结构体
typedef struct person
{
	char name[20];//名字
	int age;//年龄
	char sex[20];//性别
	char phone[20];//电话
	char location[20];//住址
}person;

typedef struct contacts
{
	person data[100];//存放人信息的位置
	int count;//记录通讯录的人数
}contacts;
//函数声明区
void initialize(contacts* pc);//初始化通讯录
void addcontact(contacts* pc);//输入联系人信息
void showcontact(const contacts* pc);//打印通讯录
int delcontact(contacts* pc);//删除联系人
int modifycontact(contacts* pc);//修改联系人信息
int findcontact(contacts* pc);//查找联系人
void sortcontact(contacts* pc);//排序通讯录

contacts.c

#include "contacts.h"

int find_out(char* p1, contacts* p2)
{
	assert(p1 != NULL);
	assert(p2 != NULL);
	int i = 0;
	for (i = 0; i < p2->count; i++)
	{
		if (!strcmp(p1, p2->data[i].name))//如果相等就返回0,前面加了!操作符,所以非零条件不成立
			return i;
	}
	return -1;
}
void initialize(contacts* pc)
{
	assert(pc != NULL);
	pc->count = 0;//将计数的变量初始化为0
	memset(pc->data, 0, sizeof(pc->data));//将数组里面的内容都初始化为0
}

void addcontact(contacts* pc)
{
	assert(pc != NULL);//断言pc指向的位置不是空指针
	if (pc->count == MAX)
	{
		printf("通讯录已满\n");
		return 0;
	}
	printf("姓名:");
	scanf("%s", pc->data[pc->count].name);
	printf("年龄:");
	scanf("%d", &(pc->data[pc->count].age));
	printf("性别:");
	scanf("%s", pc->data[pc->count].sex);
	printf("电话号:");
	scanf("%s", pc->data[pc->count].phone);
	printf("家庭住址:");
	scanf("%s", pc->data[pc->count].location);
	pc->count++;
	printf("增加成功\n");
}

void showcontact(const contacts* pc)
{
	assert(pc != NULL);
	int i = 0;
	printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20\t\n", "姓名", "年龄", "性别", "电话号", "家庭住址");
	for (i = 0; i < pc->count; i++)
	{
		printf("%-20s\t%-20d\t%-20s\t%-20s\t%-20\t\n",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].phone,
			pc->data[i].location);
	}
}

int delcontact(contacts* pc)
{
	assert(pc != NULL);
	char name[20] = { 0 };
	printf("输入此人姓名\n");
	scanf("%s", name);
	int i = find_out(name, pc);
	if (i == -1)
	{
		printf("无此人信息\n");
		return 1;
	}
	pc->count = pc->count - 1;
	while (i < pc->count)
	{
		pc->data[i] = pc->data[i + 1];
		i++;
	}
	printf("删除成功\n");
}

int modifycontact(contacts* pc)
{
	assert(pc != NULL);
	printf("输入此人姓名\n");
	char name[20] = { 0 };
	scanf("%s", name);
	int i = find_out(name, pc);
	if (i == -1)
	{
		printf("无此人信息\n");
		return 1;
	}
	printf("请输入要修改的信息\n");
	printf("姓名:");
	scanf("%s", pc->data[i].name);
	printf("年龄:");
	scanf("%d", &(pc->data[i].age));
	printf("性别:");
	scanf("%s", pc->data[i].sex);
	printf("电话号:");
	scanf("%s", pc->data[i].phone);
	printf("家庭住址:");
	scanf("%s", pc->data[i].location);
	printf("修改成功\n");
}

int findcontact(contacts* pc)
{
	assert(pc != NULL);
	printf("输入此人姓名\n");
	char name[20] = { 0 };
	scanf("%s", name);
	int i = find_out(name, pc);
	if (i == -1)
	{
		printf("无此人信息\n");
		return 1;
	}
	printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20\t\n", "姓名", "年龄", "性别", "电话号", "家庭住址");
	printf("%-20s\t%-20d\t%-20s\t%-20s\t%-20\t\n",
		pc->data[i].name,
		pc->data[i].age,
		pc->data[i].sex,
		pc->data[i].phone,
		pc->data[i].location);
}
int estimate(const void* p1, const void* p2)
{
	return strcmp(((person*)p1)->name, ((person*)p2)->name);
}
void sortcontact(contacts* pc)
{
	assert(pc != NULL);
	qsort(pc->data, pc->count, sizeof(person), estimate);
	printf("排序成功\n");
}

test.c

#include "contacts.h"
enum list
{
	EXIT,
	ADD,
	DEL,
	MODIFY,
	FIND,
	SHOW,
	SORT
};
void catalogue()
{
	printf("*********************************\n");
	printf("***   1.add        2.del      ***\n");
	printf("***   3.modify     4.find     ***\n");
	printf("***   5.show       6.sort     ***\n");
	printf("***   0.exit                  ***\n");
	printf("*********************************\n");
}
int main()
{
	int n = 0;
	contacts con;//通讯录
	initialize(&con);//初始换通讯录
	do
	{
		catalogue();//通讯录菜单
		printf("请选择>");
		scanf("%d", &n);//选择要做什么
		switch (n)
		{
		case EXIT://退出程序
			printf("退出通讯录\n");
			break;
		case ADD://添加联系人
			addcontact(&con);
			break;
		case DEL://删除联系人
			delcontact(&con);
			break;
		case FIND://查找联系人
			findcontact(&con);
			break;
		case MODIFY://修改联系人信息
			modifycontact(&con);
			break;
		case SHOW://展示联系人
			showcontact(&con);
			break;
		case SORT://排序通讯录
			sortcontact(&con);
			break;
		default:
			printf("输入错误请重新输入\n");
		}
	} while (n);
	return 0;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-17 16:02:42  更:2022-07-17 16:03:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/12 6:59:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码