C语言实现通讯录--静态版

这篇具有很好参考价值的文章主要介绍了C语言实现通讯录--静态版。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、题目要求

实现一个通讯录 ,里面存放100个人的信息,完成通讯录的基本操作功能:增删查改联系人

二、解题思路

(1)通讯录存放100个人的信息?
创建一个数组作为通讯录,100个元素,每个元素里面存放每个人的信息,所以数组里面的每个元素应该是结构体类型。
(2)每个人的信息应该包括哪些?
结构体里面应包含名字,性别,年龄,电话,地址
(3)通讯录应该具备哪些功能?
a.增加联系人
b.删除联系人
c.查找联系人
d.修改联系人
e.显示联系人
f.排序联系人信息(按照年龄或者名字)

三、模块划分

建立三个文件:
test.c 用于测试通讯录的相关功能
contsct.c 通讯录的实现模块(用函数实现功能)
contact.h 声明(函数的声明)

四、代码实现

test.c文件

#define _CRT_SECURE_NO_WARNINGS 1
//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");
}
//通讯录功能用枚举方法列举出来,提高代码的可读性
/*
在主函数中的switch...case...语句中选择功能时,case 1,2,3...这样的选项不能让代码阅读者清晰地联想到各个数字代表实现什么功能
但是使用枚举,在case语句中用case 1代表增加联系人的时候就可写成case add
当枚举中的选项和菜单上的数字匹配上之后,在case语句中想实现哪个功能,写哪个选项就可以了
这样的话,case里面的选项和我们想实现的功能的意思就关联起来了
*/
enum Option {
	Exit,
	add,
	del,
	search,
	modify,
	show,
	sort
};
int main() {
	int input = 0;
	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:
		{
			SortContact(&con);
			break;
		}
		case Exit:
		{
			printf("退出通讯录\n");
			break;
		}
		default:
		{
			printf("选择错误\n");
			break;
		}
		}
	} while (input);

	return 0;
}

contact.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"


//以后涉及到变化,就在这里修改就可以
//这里不能写成枚举,因为枚举常量必须是同一类型的枚举的可能取值,而这里定义的是变量的长度,枚举选项的取值是递增往下走的,对于这里是自己指定的长度,没必要定义成枚举类型
 

//初始化通讯录--应传址
void InitContact(Contact* pc) {//修改结构体里面的内容,传址
	pc->sz = 0;
	memset(pc->data, 0, sizeof(pc->data));//pc所指向的data数组这块空间全改为0,1个字节1个字节地改变,数组总共有sizeof(pc-data)个字节
	/*
	注意初始化pc所指向的data数组时,不能写成pc->data=0;
	因为pc里放的数组是连续的空间,data数组名是地址,是个常量的值,不能这样直接改成0,这样修改的是地址而不是里面的值
	明确目的:想把pc所指向通讯录的data数组所有元素改为0,改的是一片空间,应该用memset函数
	*/
}
/*
memset(内存块的指针,内存块后面num个字节要设置的内容,num)
memset 内存设置函数
*/
/*
错误的初始化通讯录--传值
void InitContact(Contact c){
	pc.sz=0;
	//...
}
这里的结构体传参,传的是结构体变量时,
函数内部的修改不会影响到通讯录结构体con,因为con作为结构体对象,当进行值传递的时候,c是con的一份临时拷贝,修改不会影响con
*/
//增加指定联系人
void AddContact(Contact* pc) {
	if (pc->sz == MAX) {
		printf("通讯录已满,无法添加\n");
		return;//如果通讯录已满,直接返回,不返回的话继续指向下面代码会造成bug
	}
	//添加个人信息时是在通讯录的结构体数组data中添加,数组的每个元素都是PeoInfo类型
	printf("请输入名字:");
	scanf("%s", pc->data[pc->sz].name);//注意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);

	pc->sz++;
	printf("添加成功\n");
}
删除指定联系人
//void DelContact(Contact* pc) {
//	if (pc->sz == 0) {
//		printf("通讯录为空,无法删除\n");
//		return;
//	}
//	//1.根据要删除的人的名字找到在通讯录中的下标
//	char name[MAX_NAME] = { 0 };
//	printf("请输入要删除的人的名字:");
//	scanf("%s", name);
//	int i = 0; //i用来遍历通讯录中个人信息的数组
//	int pos = 0;//使用pos指向要删除的人的下标
//	for (i = 0; i < pc->sz; i++) {
//		if (0 == strcmp(pc->data[i].name, name)) {
//			pos = i;
//			break;
//			//这里考虑的是不重名的情况,找到了就直接把要删除下标给pos
//		}
//	}
//	if (i == pc -> sz) {//说明全部遍历完数组没找到退出来的
//		printf("要删除的人不存在\n");
//		return;
//	}
//	/*
//	如果用pos下标来怎么说明全部遍历完数组没找到退出来的情况呢?
//	应该在函数最开始将pos=-1;
//	注意不能将pos初始值置为0,因为可能要删除的人的下标是0
//	if(pos==-1){//如果pos为-1,说明刚刚遍历的过程没有将pos的值改变,即全部遍历完数组没找到退出来的情况
//		printf("要删除的人不存在\n");
//		return;
//	}
//	*/
//	//2.删除pos下标的数据
//	for (i = 0; i < pc->sz - 1; i++) {
//		pc->data[i] = pc->data[i + 1];
//		//这里采用的是覆盖删除,后一个数据赋值到前一个数据,覆盖数组的长度为pc->sz-1
//	}
//	pc->sz--; //删除完数组元素的个数-1
//	printf("删除成功\n");
//}
//显示联系人信息
void ShowContact(Contact* pc) {
	int i = 0;
	//打印标题
	//在%后面加上负号表示左对齐的方式,在%s的s前面加上数字可以限制打印出来最多几个字节
	printf("%-10s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
	for (i = 0; i < pc->sz; i++) {
		printf("%-10s %-4d %-5s %-12s %-30s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
	}
}
//实际上,删查改联系人都需要先在通讯录中查找
//为了减少代码的冗余度,可以封装一个查找的函数FindByName
//封装的这个函数前面加static,这个函数只能在自己所在的.c文件中使用,其他的源文件看不见该函数,对它加以保护
//根据名字在通讯录中查找下标的函数
static int FindByName(const 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
	/*
	不要写成
	if(i==pc->sz){
		return -1;
	}
	因为写成这样,if进去,条件成立才有返回,不成立无返回
	编译器在编译时发现这样的代码考虑不周全,有些情况是存在返回值的,就会发出警告
	所以,严谨的情况下,直接返回既清晰又严谨
	*/
}
//改进后的删除联系人函数
void DelContact(Contact* pc) {
	if (pc->sz == 0) {
		printf("通讯录为空,无法删除\n");
		return;
	}
	//1.根据要删除的人的名字找到在通讯录中的下标
	char name[MAX_NAME] = { 0 };
	printf("请输入要删除的人的名字:");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if (pos == -1) {
		printf("要删除的人不存在\n");
		return;
	}
	//2.删除pos位置上的数据
	int i = 0;
	for (i = pos; i < pc->sz; i++) {
		pc->data[i] = pc->data[i + 1];//从pos下标处开始覆盖
	}
	pc->sz--;
	printf("删除成功\n");
}
//查找联系人 
void SearchContact(const Contact* pc) {//查找不需要修改通讯录,使用const加以保护,防止被修改
	char name[MAX_NAME] = { 0 };
	printf("请输入要查找的人的名字:");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if (pos == -1) {
		printf("要查找的人不存在\n");
		return;
	}
	//找到的话直接打印这个联系人的信息
	printf("%-10s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
	printf("%-10s %-4d %-5s %-12s %-30s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr);
}
//修改联系人
void ModifyContact(Contact* pc) {
	char name[MAX_NAME] = { 0 };
	printf("请输入要修改的人的名字:");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if(pos == -1){
		printf("要修改的人不存在\n");
		return;
	}
	//修改:把要修改人下标为pos的信息全都再录入一遍
	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);

	printf("修改成功\n");
}
//排序联系人
//使用qsort进行排序,要自定义一个排序方法
int cmp_by_name(const void* e1, const void* e2) {//e1,e2指针各自指向一个人的信息
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc) {
	//按照名字来排序
	qsort(pc->data, pc->sz, sizeof(PeoInfo), cmp_by_name);
	printf("排序成功\n");
	//调用显示联系人函数ShowContact,自动打印一下排序后的结果
	ShowContact(pc);
}

contact.h文件

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30

//结构体存放每个联系人的信息
typedef struct PeoInfo { //typedef:给已定义的变量类型起个别名,这里的作用是给struct Peoinfo起个别名PeoInfo
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tele[MAX_TELE];
	char addr[MAX_ADDR];
}PeoInfo;
//结构体存放通讯录
typedef struct Contact {
	PeoInfo data[MAX]; //结构体数组存放每个联系人的信息
	int sz;  //记录通讯录中的有效信息
}Contact, * pContact;//*pContact意思是将结构体指针struct Contact*重命名为pContact

//初始化通讯录--传址
void InitContact(Contact* pc);
//增加指定联系人
void AddContact(Contact* pc);
//删除指定联系人
void DelContact(Contact* pc);
/*
传址可以写成void ...Contact(pContact pc);
这里通过pContact定义出来的指针也是结构体指针
*/
//显示联系人信息
void ShowContact(Contact* pc);
//查找联系人 
void SearchContact(const Contact* pc);
//修改联系人
void ModifyContact(Contact* pc);
//排序联系人
void SortContact(Contact* pc);

五、运行结果

C语言实现通讯录--静态版,C语言,c语言,算法,开发语言

六、总结

静态版本的通讯录:
缺点1 通讯录的大小是固定的—>100个元素,空间大小不够灵活

✨解决办法:动态内存分配

缺点2 数据不能永久保存
之前通讯录中的信息都是保存在内存中的,程序退出,内存就回收了,下一次重新运行程序,内存重新分配,之前的数据就不见了。

✨解决办法:存入文件中–>文件操作文章来源地址https://www.toymoban.com/news/detail-603622.html

到了这里,关于C语言实现通讯录--静态版的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 【进阶C语言】静态版通讯录的实现(详细讲解+全部源码)

    前言 📕作者简介: 热爱跑步的恒川 ,正在学习C/C++、Java、Python等。 📗本文收录于 C语言进阶 系列,本专栏主要内容为数据的存储、指针的进阶、字符串和内存函数的介绍、自定义类型结构、动态内存管理、文件操作等,持续更新! 📘相关专栏Python,Java等正在发展,拭目

    2023年04月25日
    浏览(29)
  • C语言之通讯录的实现(静态版,动态版,文件版)

    个人主页(找往期文章包括但不限于本期文章中不懂的知识点): 我要学编程(ಥ_ಥ)-CSDN博客 目录 静态通讯录的实现逻辑  test.c:通讯录的逻辑实现 Contact.h:函数的声明与头文件的包含 Contact.c:函数的实现  通讯录源码:  test.c: Contact.c: Contect.h: 动态版通讯录  test.c: Co

    2024年04月13日
    浏览(27)
  • 【c语言】通讯录(静态)

    小张刚学习完结构体,枚举,联合相关的知识,实践实践,写一个通讯录呗! 通讯录的功能 1.通讯录可存放100的信息 2.信息的内容姓名,性别,年龄,电话,地址 3.支持增加联系人 4.支持删除联系人 5.支持查找联系人 6.支持修改联系人 7.支持排序联系人 8.打印数据 文件类型

    2024年02月13日
    浏览(23)
  • C语言进阶——静态通讯录

    作者: 敲代码の流川枫 博客主页:流川枫的博客 专栏:C语言从入门到进阶 语录: Stay hungry stay foolish 工欲善其事必先利其器,给大家介绍一款超牛的斩获大厂offer利器——牛客网 点击免费注册和我一起刷题吧 目录 1.contact.h——通讯录相关的声明 2.contact.c——通讯录相关的

    2024年02月16日
    浏览(28)
  • C语言——通讯录详解(静态版)

    今天我们做一个简单的通讯录,同时也能加深对C语言的理解。 实现一个通讯录,我们要在通讯录中保存人的信息: 名字、年龄、性别、电话、地址。 我们也要知道编写通讯录的流程: 通讯录中存放100个人的信息 增加联系人 删除联系人 修改联系人 查找联系人 显示所有联系

    2024年02月12日
    浏览(26)
  • c语言实践——通讯录(1)(静态版)

    目录 前言 一、确定思路和框架 1.联系人的信息存储 2.通讯录的菜单设置 3.初始化通讯录 4.模块的实现 (1)传参问题 (2)实现查找函数  (3)新增联系人 (4)删除联系人 (5)查找联系人 (6)修改联系人 (7)展示通讯录 (8)对联系人进行排序 二、代码实操 1.创建文件

    2023年04月24日
    浏览(21)
  • 【C语言】——通讯录(静态-动态增长-文件储存)

      目录 前言: 一:整体框架 关于通讯录结构体的创建  二:通讯录的功能实现(静态) 2.1初始化通讯录 2.2增加联系人 2.3打印通讯录 2.4删除联系人  2.5 查找联系人 2.6修改联系人  2.7排序联系人 三:通讯录优化——动态内存  3.1通讯录的创建 3.2初始化通讯录  3.3增加联系

    2024年02月07日
    浏览(30)
  • 静态版通讯录——C语言【详解+全部码源】

    前言: 我们用C语言实现一个可以存放100个人信息的通讯录 每个人的信息包括: 姓名、性别、年龄、住址、电话 通讯录的功能包括: 增加联系人 删除指定联系人 查找指定联系人 修改指定联系人 显示联系人信息 排序联系人(按照年龄/名字) 与我们之前的扫雷和三子棋项目

    2023年04月20日
    浏览(24)
  • 通讯录的实现(静态入手版)

    🍉博客主页:阿博历练记 📖文章专栏:c语言(初阶与进阶) 🎁代码仓库:阿博编程日记 🌹欢迎关注:欢迎友友们点赞收藏+关注哦 在生活中,我们可以通过通讯录快速实现对一位好友的查找,便捷了我们的日常生活,今天阿博就带领友友们一起探索通讯录的实现🙈🙈🙈

    2024年02月02日
    浏览(28)
  • 通讯录的实现(静态版本,动态版本,文件版本)(后附完整源代码)

    对于通讯录来说,我们需要它实现以下几个功能。 1.人的信息:姓名+年龄+性别+电话+地址。 2.可以存放100个人的信息。 功能: 1增加联系人。 2删除联系人。 3查找指定联系人信息。 4修改指定联系人信息。 5显示所有联系人信息。 6按名字排序。 接下来分为三个模块,test.c

    2024年01月19日
    浏览(34)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包