超详细C语言实现——通讯录

news2024/12/26 23:58:28

目录

一、介绍

二、源代码

test.c:

Contact.c:

Contact.h:

代码运行结果:

三、开始实现

1.基本框架:

2.添加联系人:

3.显示联系人信息:

4.删除联系人信息:

5.查看指定联系人信息:

6.修改联系人信息:

总结



一、介绍

通讯录相信大家都不陌生,既然大家已经来参考或学习了,说明大家已经基本掌握了C语言的基础语法和一些基本套路了,后续有不懂或者建议的地方,欢迎大家在评论区讨论。

二、源代码

test.c:

#include "contact.h"
//测试通讯录

void menu()
{
	printf("**********************************\n");
	printf("****** 1.add      2.del     ******\n");
	printf("****** 3.search   4.modify  ******\n");
	printf("****** 5.show     0.exit    ******\n");
	printf("**********************************\n");
	printf("**********************************\n");
}

void test()
{
	int input = 0;
	Contact con;
	InitContact(&con);//初始化通讯录结构体
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			AddContact(&con);
			break;
		case 2:
			DelContact(&con);
			break;
		case 3:
			SearchContact(&con);
			break;
		case 4:
			ModifyContact(&con);
			break;
		case 5:
			ShowContact(&con);
			break;
		case 0:
			printf("退出成功!\n");
			break;
		default:
			printf("输入无效,请重新选择!\n");
			break;
		}
	} while (input);
}

int main()
{
	test();
	return 0;
}

Contact.c:

//函数的实现
#include "Contact.h"

//初始化通讯录结构体
void InitContact(Contact* p)
{
	memset(p->data, 0, sizeof(p->data));
	p->sz = 0;
}

//增加联系人信息
void AddContact(Contact* p)
{
	//判断通讯录是否塞满
	if (p->sz == Max)
	{
		printf("通讯录已满,无法添加\n");
		return;
	}
	printf("请输入要添加的联系人的姓名:>");
	scanf("%s", p->data[p->sz].name);
	printf("请输入要添加的联系人的性别:>");
	scanf("%s", p->data[p->sz].sex);
	printf("请输入要添加的联系人的电话号码:>");
	scanf("%s", p->data[p->sz].tala);
	printf("请输入要添加的联系人的地址:>");
	scanf("%s", p->data[p->sz].addr);
	p->sz++;
	printf("添加联系人成功!\n");
}


//展示联系人信息
void ShowContact(const Contact* p)
{
	//显示标题
	printf("%-5s\t%-5s\t%-12s\t%-10s\n", "姓名", "性别", "电话号码", "地址");
	for (int i = 0; i < p->sz; i++)
	{
		printf("%-5s\t%-5s\t%-12s\t%-10s\n",
			p->data[i].name,
			p->data[i].sex,
			p->data[i].tala,
			p->data[i].addr);
	}
}


//查找联系人
int Findname(Contact* p, char name1[])
{
	int i = 0;
	for (i = 0; i < p->sz; i++)
	{
		if (strcmp(p->data[i].name, name1) == 0)
		{
			return i;
		}
	}
	//没找到
	return -1;
}


//删除指定联系人信息
void DelContact(Contact* p)
{
	if (p->sz == 0)
	{
		printf("通讯录为空!\n");
		return;
	}
	char name1[Max_name] = { 0 };
	printf("请输入你要删除的联系人姓名:>");
	scanf("%s", name1);
	int del = Findname(p, name1);
	if (del == -1)
	{
		printf("该通讯录不存在这个人!\n");
		return;
	}
	int i = 0;
	for (i = del; i < p->sz - 1; i++)
	{
		p->data[i] = p->data[i + 1];
	}
	p->sz--;
	printf("删除联系人成功!\n");
}

//查找指定联系人
void SearchContact(const Contact* p)
{
	char name[Max_name] = { 0 };
	printf("请输入你要查看的联系人的姓名:>");
	while (getchar()!= '\n');
	scanf("%s", name);
	int i = Findname(p, name);
	if (i == -1)
	{
		printf("该通讯录不存在该联系人\n");
	}
	else
	{
		//显示标题
		printf("%-5s\t%-5s\t%-12s\t%-10s\n", "姓名", "性别", "电话号码", "地址");
		printf("%-5s\t%-5s\t%-12s\t%-10s\n",
				p->data[i].name,
				p->data[i].sex,
				p->data[i].tala,
				p->data[i].addr);
	}
}

//修改联系人信息
void ModifyContact(Contact* p)
{
	char name[Max_name] = { 0 };
	printf("请输入你要修改的联系人的姓名:>");
	while (getchar() != '\n');
	scanf("%s", name);
	int i = Findname(p, name);
	if (i == -1)
	{
		printf("该通讯录不存在该联系人\n");
	}
	else
	{
		printf("请重新输入该联系人的姓名:>");
		scanf("%s", p->data[i].name);
		printf("请重新输入该联系人的性别:>");
		scanf("%s", p->data[i].sex);
		printf("请重新输入该联系人的电话号码:>");
		scanf("%s", p->data[i].tala);
		printf("请重新输入该联系人的地址:>");
		scanf("%s", p->data[i].addr);
	}
	printf("修改成功!\n");
}

Contact.h:

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#define Max 100
#define Max_name 20
#define Max_sex 5
#define Max_tele 12
#define Max_addr 30


//存放函数的类型和声明
#include<string.h>
#include<stdio.h>

typedef struct PeoInfo
{
	char name[Max_name];
	char sex[Max_sex];
	char tala[Max_tele];
	char addr[Max_addr];

}PeoInfo;

//通讯录结构体
typedef struct Contact
{
	PeoInfo data[Max];
	int sz;
}Contact;


//函数声明

//初始化通讯录结构体
void InitContact(Contact* p);

//增加联系人信息
void AddContact(Contact* p);

//展示联系人信息
void ShowContact(Contact* p);

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

//查找指定联系人信息
void SearchContact(const Contact* p);

//修改联系人信息
void ModifyContact(Contact* p);

代码运行结果:

三、开始实现

1.基本框架:

本次实现通讯录,采用多文件的方法进行实现,既然大家学到了通讯录,应该几乎都接触过多文件操作,所谓多文件操作即:

①:函数的声明、define的宏定义、以及结构体的声明等等放在.h文件。(contact.h)

②:函数的定义放在.c文件。(contact.c)

③:main函数和一些基本框架可以单独放在另一个.c文件。(test.c)。

既然是通讯录,我们就需要一个保存通讯录人员的结构体以及保存人员信息的结构体,声明放在contact.h文件中:

①:本次人员信息我们放在结构体PerInfo中,其中给了姓名、性别、电话、地址,大家可以根据自身想法,添加其他信息。

②:然后第二个结构体Contact用于保存联系人,这里以上限为100个联系人为例,所以成员有一个PerInfo结构体数组,然后还有一个整型变量sz用于记录现有人数,增加一个人,sz+1;删除一个人,sz-1。

代码如下:

#pragma once
#define Max 100
#define Max_name 20
#define Max_sex 5
#define Max_tele 12
#define Max_addr 30

typedef struct PeoInfo
{
	char name[Max_name];
	char sex[Max_sex];
	char tala[Max_tele];
	char addr[Max_addr];

}PeoInfo;

//通讯录结构体
typedef struct Contact
{
	PeoInfo data[Max];
	int sz;
}Contact;

然后本次框架依然用do while循环套switch case语句,以便于选择不同的功能,这里我们放在test.c文件中:

#include "contact.h"
//测试通讯录

void menu()
{
	printf("**********************************\n");
	printf("****** 1.add      2.del     ******\n");
	printf("****** 3.search   4.modify  ******\n");
	printf("****** 5.show     0.exit    ******\n");
	printf("**********************************\n");
	printf("**********************************\n");
}

void test()
{
	int input = 0;
	Contact con;
	InitContact(&con);//初始化通讯录结构体
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			break;
		case 2:
			break;
		case 3:
			break;
		case 4:
			break;
		case 5:
			break;
		case 0:
			break;
		default:
			break;
		}
	} while (input);
}

int main()
{
	test();
    return 0;
}

①:因为相关头文件在contact.h文件中,所以不论是在contact.c文件还是在test。c文件中,我们都需要包含一下自己的头文件contact.h。

②:然后为了美观,写一个菜单函数menu,大家可自行设置。

③:首先我们必须要有一个Contact的结构体变量con,然后创建InitContact函数对其成员简单的初始化:

这里数组有100个空间,用循环初始化太麻烦,所以我们用到一个库函数memset,具体介绍可以参考http://t.csdn.cn/wu8iX

④:应该大部分人都使用过do while套switch case,因为这样我们可以根据菜单函数来进行选择,输入不同数字进入不同功能函数,函数结束后又可以循环输入,当输入0时,do while结束,即整个系统结束。

2.添加联系人:

基本框架搭完,我们就可以实现相关函数了,这里小编建议在写这种类似的程序时,最好一个函数一个函数的实现,这样方便调试和改正。

首先实现添加操作,我们创建AddContact函数来实现添加操作,函数源代码如下:

//增加联系人信息
void AddContact(Contact* p)
{
	//判断通讯录是否塞满
	if (p->sz == Max)
	{
		printf("通讯录已满,无法添加\n");
		return;
	}
	printf("请输入要添加的联系人的姓名:>");
	scanf("%s", p->data[p->sz].name);
	printf("请输入要添加的联系人的性别:>");
	scanf("%s", p->data[p->sz].sex);
	printf("请输入要添加的联系人的电话号码:>");
	scanf("%s", p->data[p->sz].tala);
	printf("请输入要添加的联系人的地址:>");
	scanf("%s", p->data[p->sz].addr);
	p->sz++;
	printf("添加联系人成功!\n");
}

①:既然是添加,我们最开始就需要判断通讯录是否填满,若没有填满才继续添加,所以开始用一个if语句,当sz==Max时,即为满。

②:接着只需要依次向对应位置输入数据即可,因为sz表示通讯录现有人数,刚开始为0,而数组的下标也是从0开始,所以直接用sz作为数组下标进行输入数据即可,添加成功后,sz自增1,即表示人数+1,又可用来作为第二次添加时作为数组下标。

③:这里需要注意和理解清楚每个结构体变量和成员以及‘.’操作符和'->'操作符的对应关系。

3.显示联系人信息:

为了方便测试代码是否有误,我们在实现添加操作后就可以先实现展示操作,这样可以检查添加操作是否有误以及后续每完成一个功能,就可以用展示功能来检查。

我们创建函数ShowContact函数来实现展示功能,源代码如下:


//展示联系人信息
void ShowContact(Contact* p)
{
	//显示标题
	printf("%-5s\t%-5s\t%-12s\t%-10s\n", "姓名", "性别", "电话号码", "地址");
    //显示信息
	for (int i = 0; i < p->sz; i++)
	{
		printf("%-5s\t%-5s\t%-12s\t%-10s\n",
			p->data[i].name,
			p->data[i].sex,
			p->data[i].tala,
			p->data[i].addr);
	}
}

①:我们首先先打印标题,方便查看。

②:我们只需用一个for循环,在用和结构体找到对应的值打印出来即可。

③:这里值得注意的是排版问题,一些缩进和排版是影响美观的,大家可自行设置,也可参考上诉源代码。

4.删除联系人信息:

我们创建DelContact函数来实现删除操作,源代码如下:

//删除指定联系人信息
void DelContact(Contact* p)
{
	if (p->sz == 0)
	{
		printf("通讯录为空!\n");
		return;
	}
	char name1[Max_name] = { 0 };
	printf("请输入你要删除的联系人姓名:>");
	scanf("%s", name1);
	int del = Findname(p, name1);
	if (del == -1)
	{
		printf("该通讯录不存在这个人!\n");
		return;
	}
	int i = 0;
	for (i = del; i < p->sz - 1; i++)
	{
		p->data[i] = p->data[i + 1];
	}
	p->sz--;
	printf("删除联系人成功!\n");
}

①:既然是删除,所以我们最开始应该判断一下通讯录是否为空;

②:然后创建一个临时数组char name1[],用于用户输入要删除的联系人的姓名;

③:接着我们需要判断通讯录是否存在这个人,所以这里又创建Findname函数,用于查找指定联系人,源代码如下:
 

//查找联系人
int Findname(Contact* p, char name1[])
{
	int i = 0;
	for (i = 0; i < p->sz; i++)
	{
		if (strcmp(p->data[i].name, name1))
		{
			return i;
		}
	}
	//没找到
	return -1;
}

这里值得注意的是循环里面的if语句,很多人在判断条件里面喜欢用“==”,但我们要注意,姓名是字符串,这里是两个字符串相比较,所以不能直接用“==”,所以这里用到字符串函数strcmp,具体用法参考:http://t.csdn.cn/qD0LQ

④:当没找到时,提示后直接返回;若找到了,就进行删除操作;

因为我们使用的是数组,所以删除操作简单,只需要先找到该联系人的位置del,然后将该位置后面的内容依次向前进行覆盖,最后现有人数sz自减一即可,所以这里用到一个for循环。

5.查看指定联系人信息:

我们创建SearchContact函数实现此操作,源代码如下:

//查找指定联系人
void SearchContact(const Contact* p)
{
	char name[Max_name] = { 0 };
	printf("请输入你要查看的联系人的姓名:>");
	while (getchar()!= '\n');
	scanf("%s", name);
	int i = Findname(p, name);
	if (i == -1)
	{
		printf("该通讯录不存在该联系人\n");
	}
	else
	{
		//显示标题
		printf("%-5s\t%-5s\t%-12s\t%-10s\n", "姓名", "性别", "电话号码", "地址");
		printf("%-5s\t%-5s\t%-12s\t%-10s\n",
				p->data[i].name,
				p->data[i].sex,
				p->data[i].tala,
				p->data[i].addr);
	}
}

①:首先创建一个临时数组便于用户输入指定联系人姓名,然后用一个while循环去掉缓冲区多余内容,以便scanf正常读入;

②:接着调用Findname函数,根据返回值进行操作

若返回-1,则该联系人不存在,直接返回;

若不是-1,说明找到了,然后我们打印出该联系人各个信息即可。

6.修改联系人信息:

我们创建ModifyContact函数来实现该操作,源代码如下:

//修改联系人信息
void ModifyContact(Contact* p)
{
	char name[Max_name] = { 0 };
	printf("请输入你要修改的联系人的姓名:>");
	while (getchar() != '\n');
	scanf("%s", name);
	int i = Findname(p, name);
	if (i == -1)
	{
		printf("该通讯录不存在该联系人\n");
	}
	else
	{
		printf("请重新输入该联系人的姓名:>");
		scanf("%s", p->data[i].name);
		printf("请重新输入该联系人的性别:>");
		scanf("%s", p->data[i].sex);
		printf("请重新输入该联系人的电话号码:>");
		scanf("%s", p->data[i].tala);
		printf("请重新输入该联系人的地址:>");
		scanf("%s", p->data[i].addr);
	}
	printf("修改成功!\n");
}

①:前面和查找联系人相同,需要用户先输入要修改的联系人的姓名,然后判断是否存在;

②:若存在的话只需返回该下标,然后对该下标的信息重新输入数据即可,比较简单。

总结

本次小编只是简单实现一个通讯录,方便大家寻找思路和入手方法,有很多漏洞以及改进大家可以自行实现,本次知识到此为止,希望对大家有所帮助!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1040117.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

多维时序 | MATLAB实现PSO-BP多变量时间序列预测(粒子群优化BP神经网络)

多维时序 | MATLAB实现PSO-BP多变量时间序列预测(粒子群优化BP神经网络) 目录 多维时序 | MATLAB实现PSO-BP多变量时间序列预测(粒子群优化BP神经网络)效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现PSO-BP粒子群优化BP神经网络多变量时间序列预测&#xff…

初学vue.js

准备Vue.js环境 ① 下载环境&#xff1a; javaScript语言的程序包&#xff1a;外部js文件 对于Vue来说&#xff0c;导入Vue的外部js文件就能够使用Vue框架了。 Vue框架的js文件获取: 官网提供的下载地址&#xff1a;https://cdn.jsdelivr.net/npm/vue/dist/vue.js ②导入环境…

Kotlin中使用Java数据类时引发的一个Bug

文章目录 基础复习&#xff1a;Kotlin语言中的对象比较背景问题出现解决方式方式一方式二 基础复习&#xff1a;Kotlin语言中的对象比较 比较对象的内容是否相等 ( 或者 equals )&#xff1a;Kotlin 中的操作符 和 equals效果相同 &#xff0c;都用于比较对象的内容是否相等,…

Wespeaker框架数据集准备(1)

1. 数据集准备(Data preparation) 进入wespeaker目录文件/home/username/wespeaker/examples/voxceleb/v2 对run.sh文件进行编辑 vim run.sh 可以看到run.sh里面的配置内容 #数据集下载&#xff0c;解压 stage1 #插入噪音&#xff0c;制作音频文件 stop_stage2 #数据集放置…

递归算法讲解,深度理解递归

首先最重要的就是要说明递归思想的作用&#xff0c;在后面学习的高级数据接口&#xff0c;树和图中&#xff0c;都需要用到递归&#xff0c;即深度优先搜索&#xff0c;如果递归掌握的不好&#xff0c;后面的数据结构将举步为艰。 加油 首先看下如何下面两个方法有什么区别&a…

基于Java+SpringBoot+Vue3+Uniapp前后端分离考试学习一体机设计与实现2.0版本(视频讲解,已发布上线)

博主介绍&#xff1a;✌全网粉丝4W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

Allegro如何将丝印文字Change到任意层面操作指导

Allegro如何将丝印文字Change到任意层面操作指导 在用Allegro进行PCB设计的时候,有时需要将丝印文字change到其它层面,如下图 可以看到丝印文字是属于REFDES这个Class的 如果需要把丝印文字change层面,只支持REFDES中以下的层面中来change

【深入浅出设计模式--命令模式】

深入浅出设计模式--命令模式 一、背景二、问题三、解决方案四、试用场景总结五、后记 一、背景 命令模式是一种行为设计模式&#xff0c;它可以将用户的命令请求转化为一个包含有相关参数信息的对象&#xff0c;命令的发送者不需要知道接收者是如何处理这条命令&#xff0c;多个…

Qt Chats(一)绘制折线图

1、一个简单的QChart绘图程序 Qt Charts基于Qt的Graphics View架构&#xff0c;其核心组件是QChartView 和 QChart QChartView是显示图标的视图&#xff0c;基类为QGraphicsViewQChart的基类是QGraphicsltem QChart类继承关系 QPolarChart 用于绘制 极坐标图的图表类 1.项目…

(自学)黑客技术——网络安全

如果你想自学网络安全&#xff0c;首先你必须了解什么是网络安全&#xff01;&#xff0c;什么是黑客&#xff01;&#xff01; 1.无论网络、Web、移动、桌面、云等哪个领域&#xff0c;都有攻与防两面性&#xff0c;例如 Web 安全技术&#xff0c;既有 Web 渗透2.也有 Web 防…

基于微信小程序的婚庆婚纱摄影预约平台(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…

彩色文本进度条

动态加色打印&#xff0c;\033控制&#xff0c;显示进行到的百分比&#xff0c;实时更新总共用时。 (本笔记适合能熟练应用字符串和循环技能的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程…

开发者必备!如何将闲置iPad Pro打造为编程工具,使用VS Code编写代码

文章目录 前言1. 本地环境配置2. 内网穿透2.1 安装cpolar内网穿透(支持一键自动安装脚本)2.2 创建HTTP隧道 3. 测试远程访问4. 配置固定二级子域名4.1 保留二级子域名4.2 配置二级子域名 5. 测试使用固定二级子域名远程访问6. ipad pro通过软件远程vscode6.1 创建TCP隧道 7. ip…

数据结构 | 队列

队列&#xff08;First In First Out&#xff09; 顺序队列 #include <iostream>class MyQueue {private:// store elementsvector<int> data; // a pointer to indicate the start positionint p_start; public:MyQueue() {p_start 0;}/** In…

爬虫怎么批量采集完成任务

目录 一、了解网络爬虫 二、Python与网络爬虫 三、批量采集任务的实现 1.确定采集网站及关键词 2.安装相关库 3.发送请求并获取响应 4.解析HTML文档 5.提取文章内容 6.保存文章内容 7.循环采集多篇文章 8.增加异常处理机制 9.优化代码性能 四、注意事项 总结 在当…

UNet网络模型学习总结

github&#xff1a;Machine_Learning/网络模型/UNet at main golitter/Machine_Learning (github.com) 因为VOC数据集太大&#xff0c;上传github很慢&#xff0c;所以就没有上传VOC数据&#xff0c;只有参考的目录位置。 数据集自行下载&#xff1a;https://host.robots.ox.…

顾曼宁(顾曼):漂流伞创始人与杭州高层次人才的杰出代表

杭州&#xff0c;这座以创新与活力为标签的城市&#xff0c;吸引了无数优秀的人才。在这座城市中&#xff0c;一位杰出的女性企业家以其独特的创业智慧和卓越的领导力&#xff0c;成为了杭州高层次人才的杰出代表之一&#xff0c;她的名字叫顾曼宁&#xff08;顾曼&#xff09;…

21天学会C++:Day14----模板

CSDN的uu们&#xff0c;大家好。这里是C入门的第十四讲。 座右铭&#xff1a;前路坎坷&#xff0c;披荆斩棘&#xff0c;扶摇直上。 博客主页&#xff1a; 姬如祎 收录专栏&#xff1a;C专题 目录 1. 知识引入 2. 模板的使用 2.1 函数模板 2.2 类模板 3. 模板声明和定义…

7实体与值对象 #

本系列包含以下文章&#xff1a; DDD入门DDD概念大白话战略设计代码工程结构请求处理流程聚合根与资源库实体与值对象&#xff08;本文&#xff09;应用服务与领域服务领域事件CQRS 案例项目介绍 # 既然DDD是“领域”驱动&#xff0c;那么我们便不能抛开业务而只讲技术&…

Kotlin异常处理runCatching,getOrNull,onFailure,onSuccess(1)

Kotlin异常处理runCatching&#xff0c;getOrNull&#xff0c;onFailure&#xff0c;onSuccess&#xff08;1&#xff09; fun main(args: Array<String>) {var s1 runCatching {1 / 1}.getOrNull()println(s1) //s11&#xff0c;打印1println("-")var s2 ru…