【C语言进阶】通讯录不好用?进来,零基础带你写出自己的通讯录

news2025/2/1 0:40:38

目录

🤩前言🤩:

😎正文:编写通讯录😎:

        1.文件建立:

        ①.头文件Contact.h:

        ②.函数定义文件Contact.c:

        ③.工程测试文件test.c:

        2.通讯录整体执行思路:

        3. menu 菜单函数实现:

        4. Contact 通讯录函数逻辑:

        5. Contact 函数中各功能的实现:

        ①.头文件 Contact.h:

        ②.初始化通讯录:

        ③.“打印联系人信息”PrintContact:

        ④.“打印全部联系人信息”PrintAllContact:

        ⑤.“增加联系人信息” AddContact:

        ⑥.“删除联系人信息”DelContact:

        ⑦.“查找联系人”SearchContact:

        ⑧.“修改联系人信息”ModifyContact:

🤠全部源码🤠:

        1.头文件Contact.h:

        2.函数实现Contact.c:

        3.程序主体test.c:

🥳总结🥳:


🛰️博客主页:✈️銮同学的干货分享基地

🛰️欢迎关注:👍点赞🙌收藏✍️留言

🛰️系列专栏:💐【进阶】C语言学习

🛰️代码仓库:🎉VS2022_C语言仓库

        家人们更新不易,你们的👍点赞👍和👉关注👈真的对我真重要,各位路过的友友麻烦多多点赞关注,欢迎你们的私信提问,感谢你们的转发!

        关注我,关注我,关注我,你们将会看到更多的优质内容!!


🏡🏡本文重点 🏡🏡:

🚅  编写静态通讯录(源码在结尾) 🚏🚏

🤩前言🤩:

        在前面的三节课中,我们学习了三种类型结构体:结构、枚举和联合,以及它们的作用原理、定义方式与大小计算等等相关知识。为了更好的帮助各位小伙伴们理解和学会使用结构体,今天我们就来尝试通过使用结构体, 零基础 编写出我们自己的通讯录

😎正文:编写通讯录😎:

        今天我们的目标是,要写出我们自己满意的通讯录,我们目标期望的通讯录主要包含五个基础功能:增、删、查、改、印,即增加新联系人删除联系人查找联系人修改联系人信息对联系人信息进行打印五个功能,

        1.文件建立:

        我们还是按照标准工程格式,分别建立三个文件:

        ①.头文件Contact.h:

        该文件是用于包含其它头文件,并存放功能实现函数的函数声明。好处是可以整合整个程序中所用到的全部头文件和函数声明,一目了然。并在引用时只需引用头文件game.h,其它被包含的头文件与函数声明均生效

        ②.函数定义文件Contact.c:

        这个文件主要是用于书写所有的程序功能实现的函数定义。一来将所有定义书写在一起便于我们进行阅读、修改;二来大大提升了程序的可移植性,当他人想要使用我们定义的函数时,只需将整个game.c文件发送给对方即可;第三点最重要,我们可以将其设置为静态库从而实现对我们函数代码的隐藏

        ③.工程测试文件test.c:

        我们在这个文件里去书写我们的程序主体部分,并对程序进行执行逻辑的编辑和检查。结合前两个文件的使用,可以使得我们的程序逻辑变得清晰,极有利于我们进行程序的运行逻辑检查

        2.通讯录整体执行思路:

        与之前写过的小游戏项目整体执行思路相同,首先我们自定义两个函数,menu 为菜单函数,负责向玩家打印游戏菜单Contact 为通讯录功能函数,负责实现整个通讯录功能的逻辑实现。当程序开始编译运行后,将会按照顺序,先执行 menu 函数打印出通讯录功能选项菜单,接着执行 Contact 函数为使用者提供相关功能服务

#include<stdio.h>

void menu()
{
	...
}

void Contact()
{
    ...
}

int main()
{
	Contact();

	return 0;
}

        同时,我们在使用通讯录时,往往会出现一次性添加、删除或修改多个联系人信息的场景,于是我们就需要让我们的程序多次循环的执行

void Contact()
{
	int input = 0;
	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:
			printf("正在退出!\n");
			break;
		default:
			printf("您的选择有误,请重新选择!\n");
		}
	} while (input);
}

        我们通过使用 do...while 循环语句,保证了我们程序的多次执行。并且我们通过将输入值 input 作为循环判断条件,既减少了变量的创建从而节省了空间,也避免了因输入错误导致直接跳出执行。同时,通过借助 switch 分支语句,我们也实现了对通讯录不同功能的调用和对输入选择的合法性检测

        通过编译运行验证主体功能实现情况:

        可以看到,整个程序的多次循环及功能选择模块已经成功实现,至此程序主体部分就已经书写完毕,接下来只需完成各个功能模块的逻辑实现即可。

        3. menu 菜单函数实现:

        在上面我们已经确定好了函数的主体实现逻辑,接下来就是实现各个功能模块。首当其冲的便是向用户反馈通讯录程序功能的 menu 菜单函数,该模块的功能仅仅是将通讯录程序的各项功能在屏幕上进行打印以向玩家进行功能说明,并没有进行实质上的代码逻辑处理,我们直接进行打印即可

void menu()
{
	printf("**********************************\n");
	printf("**********************************\n");
	printf("******** 欢迎使用本通讯录 ********\n");
	printf("**********************************\n");
	printf("***** 本通讯录现提供以下功能 *****\n");
	printf("************ 1.Add  **************\n");
	printf("************ 2.Del  **************\n");
	printf("************ 3.Search ************\n");
	printf("************ 4.Modify ************\n");
	printf("************ 5.Print *************\n");
	printf("************ 0.Exit  *************\n");
	printf("**********************************\n");
	printf("**********************************\n");
}

        我们很容易就能实现,将其编译运行起来查看反馈效果

        时至今日,这一模块的编写对各位小伙伴们来说应该已经是驾轻就熟了,我们不再作过多强调,直接进入下一部分功能模块的编写

        4. Contact 通讯录函数逻辑:

        (注:此处我们只关心实现逻辑,而具体功能的实现会在后面逐一进行讲解

        菜单成功打印,程序的主体实现逻辑也已经确定好了,接下来便是对我们通讯录的功能实现方式进行设计与编写了。

        首先我们要搞清楚我们的操作对象究竟是谁,我们可以想一想,我们平常在使用通讯录时,我们的操作对象应当是一个一个的联系人,以及每一个联系人的相关信息,于是我们可以想见,我们需要一种 “ 包 ” 来实现对每一个联系人信息的封装,于是在这里,我们使用结构体来进行实现:

typedef struct PeoInfo
{
	char name[MAX_NAME];
    //联系人信息:姓名
	char sex[MAX_SEX];
    //联系人信息:性别
	int age;
    //联系人信息:年龄
	char tele[MAX_TELE];
    //联系人信息:联系方式
	char addr[MAX_ADDR];
    //联系人信息:住址
}PeoInfo;

        我们可以在头文件中(全局的)定义一个名为 PeoInfo (译:个人信息,可自定义)的结构体类型 struct PeoInfo,并使用 typedef 关键字将该类型重命名为 PeoInfo ,接着我们在结构体内部创建了姓名、性别、年龄、联系方式与住址五个结构体成员,以用于存储结构体变量的信息。

        于是在我们想要执行功能之前,应当首先创建出一个用于储存联系人信息的结构体数组,并创建变量 sz 用于记录已存入的联系人数量

void Contact()
{
	int input = 0;
    
    //创建能够容纳1000个联系人相关信息的结构体数组:
	PeoInfo data[1000];
    //创建变量 sz 用于记录联系人数量
    int sz = 0;

	do
	{
		...
		switch (input)
		{
		    ...
		}
	} while (input);
}

        但是我认为这样的方式在进行传参时既要传递数组,又要传递变量的地址,还是有些繁琐,并且既然今天我们是针对结构体进行的实例练习,我们大可以再创建一个结构体用来封装这两个需要进行传参的数据

typedef struct contact
{
	PeoInfo data[MAX];
	int sz;
}contact;

        并且为了以后便于对通讯录大小进行修改和维护,我们使用宏定义来确定来联系人各项信息的最大值

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

        并且我们还知道,枚举类型中各成员的值为从零开始依次递增,于是我们可以再使用一个枚举类型来使我们的选项对应用户的选择

enum Option
{
	Exit,//值为0
	Add,//值为1
	Del,//值为2
	Search,//值为3
	Modify,//值为4
    Print//值为5
};

        接着按照上面我们已经确定的执行思路,根据用户的不同选择通过分支语句实现各实功能

        (注:这里不考虑增删查改功能的具体实现,后面会逐一进行讲解)

void Contact()
{
	int input = 0;
	contact con;
	do
	{
		menu();
		printf("请您进行选择:> ");
		scanf("%d", &input);
		switch (input)
		{
		case Add:
			AddContact();
			break;
		case Del:
			DelContact();
			break;
		case Search:
			SearchContact();
			break;
		case Modify:
			ModifyContact();
			break;
			break;
        case Print:
            PrintAllContact();
            break;
		case 0:
			printf("正在退出!\n");
			break;
		default:
			printf("您的选择有误,请重新选择!\n");
		}
	} while (input);
}

        这样,通讯录的大致逻辑就编辑完成了,而接下来各项功能的实现才是重头戏。

        5. Contact 函数中各功能的实现:

        ①.头文件 Contact.h:

        头文件中的内容存放的是其它头文件宏定义函数声明

        (注:这里只需要大致知道里面存放的内容即可,各内容在后面会逐一讲解)

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

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

enum Option
{
	Exit,//值为0
	Add,//值为1
	Del,//值为2
	Search,//值为3
	Modify,//值为4
	Print//值为5
};

typedef struct PeoInfo
{
	char name[MAX_NAME];
	char sex[MAX_SEX];
	int age;
	char tele[MAX_TELE];
	char addr[MAX_ADDR];
}PeoInfo;

typedef struct contact
{
	PeoInfo data[MAX];
	int sz;
}contact;

void InitContact(contact* p);
void PrintContact(const contact* p, int x);
void PrintAllContact(const contact* p);
void AddContact(contact* p);
void DelContact(contact* p);
void SearchContact(const contact* p);
void ModifyContact(const contact* p);

        ②.初始化通讯录:

        我们在创建好通讯录后,需要对创建好的初始通讯录进行初始化,否则内部的数据将为随机值而无法预测,导致程序的不合法:

//创建通讯录:
contact con;
//将其初始化:
InitContact(&con);

       我们对通讯录的初始化是通过函数调用实现的,所以在对通讯录结构体成员进行修改时是需要通过结构体指针进行访问的。

        首先我们将统计变量 sz 初始化为0,即表示最初的通讯录中的联系人信息数量为0:

void InitContact(contact* p)
{
	p->sz = 0;
}

        接着,既然没有联系人信息,为了避免随机值对程序造成影响,我们就通过使用之前讲过的 memset 函数将联系人信息 data 内数据全部初始化为0

void InitContact(contact* p)
{
	p->sz = 0;
	memset(p->data, 0, sizeof(p->data));
	//使用memeset函数将p->data所指向的空间中的数据初始化为0
	//操作的空间大小为sizeof函数所计算出的p->data所指向空间的大小,即整个无联系人数据的结构体数组data所占的空间的大小
}

        ③.“打印联系人信息”PrintContact:

        打印单个联系人信息很好处理,直接打印即可,因为这里我们不需要对传入地址内的数据进行修改,所以在数组传参时,我们可以使用 const 对其进行修饰,并实现打印:

void PrintContact(const contact* p, int x)
{
	assert(p);
	printf(" 联系人 :%04d\n", x + 1);
	printf(" 姓  名 :%s\n", p->data[x].name);
	printf(" 性  别 :%s\n", p->data[x].sex);
	printf(" 年  龄 :%d\n", p->data[x].age);
	printf("联系方式:%s\n", p->data[x].tele);
	printf("当前住址:%s\n", p->data[x].addr);
}

        ④.“打印全部联系人信息”PrintAllContact:

        首先这个函数可以作为单个功能,用于方便我们查看当前通讯录内的联系人存储信息,再者我们在删除联系人时,需要了解联系人的储存情况,进而准确的删除我们想要删除的特定联系人信息

        同时,这个函数的作用为打印全部的联系人信息,因此不需要对特定的下标进行处理,直接在函数内部定义变量 i 作为下标即可(可以自己根据情况调整打印格式):

void PrintAllContact(const contact* p)
{
	assert(p);
	printf("联系人 姓名                性别  年龄   联系方式      住址\n");
	int i = 0;
	for (i = 0; i < p->sz; i++)
	{
		printf(" %04d  %-20s %-5s %-4d %-12s %-30s\n", i + 1, p->data[i].name, p->data[i].sex, p->data[i].age, p->data[i].tele, p->data[i].addr);
	}
}

        ⑤.“增加联系人信息” AddContact:

        首先我们在函数调用时,因为我们要对内存中的数据进行实际的修改,故使用传址调用,应当向函数传入存放着结构体数组地址(数组名为首元素地址)与计数变量 sz 的 contact 类型结构体变量 con 的地址

AddContact(&con);

        接着便对 AddContact 函数功能实现进行设计。函数功能部分很简单,每次询问一项联系人信息,然后由用户输入该项信息,并向该联系人保存地址处存入该信息。但是在这个期间仍有很多的细节需要我们去注意。

        要注意的第一个要点是信息存入的地址,我们对于通讯录的访问是通过指针进行的,所以信息的存入地址一定是对应的存入地址,数组应当使用指针进行访问,变量则应当使用取地址操作符进行访问

void AddContact(contact* p)
{
	printf("请输入联系人姓名:>");
	scanf("%s", p->data[p->sz].name);
	printf("请输入联系人性别:>");
	scanf("%s", p->data[p->sz].sex);
	printf("请输入联系人年龄:>");
	scanf("%d", &(p->data[p->sz].age));
	printf("请输入联系人联系方式:>");
	scanf("%s", p->data[p->sz].tele);
	printf("请输入联系人住址:>");
	scanf("%s", p->data[p->sz].addr);
	PrintContact(p, p->sz);
	printf("联系人信息添加成功!\n");
	p->sz++;
}

        并且而我们还注意到这里有一个很巧妙的设计,那就是我们在进行访问时,数组的下标恰好与我们初始化的统计变量 sz 相同,并且在每次存储完联系人信息后,我们对会将用于统计联系人数量的统计变量sz 加上一,这时它又变成了下一次需要访问时的结构体数组的下标了

        并且我们在进行存储前还应当进行一次判断,即判断通讯簿内是否已经存满了联系人信息,如果已经存满了联系人信息,则应当提示用户没有足够的空间;若没有存满则将用户输入的联系人信息存入位置并打印反馈存入的联系人信息

void AddContact(contact* p)
{
	if (p->sz == MAX)
	{
		printf("通讯录空间不足,无法添加新成员!\n");
	}
	else
	{
		printf("请输入联系人姓名:>");
		scanf("%s", p->data[p->sz].name);
		printf("请输入联系人性别:>");
		scanf("%s", p->data[p->sz].sex);
		printf("请输入联系人年龄:>");
		scanf("%d", &(p->data[p->sz].age));
		printf("请输入联系人联系方式:>");
		scanf("%s", p->data[p->sz].tele);
		printf("请输入联系人住址:>");
		scanf("%s", p->data[p->sz].addr);
		PrintContact(p, p->sz);
		printf("联系人信息添加成功!\n");
		p->sz++;
	}
}

        ⑥.“删除联系人信息”DelContact:

        在想要删除联系人信息时,我们首先应当对通讯录中的内容进行判断,如果此时通讯录中没有存储任何联系人的信息,则应当提示用户没有联系人信息

if (p->sz == 0)
{
    printf("对不起,当前通讯录中没有联系人信息!\n");
}

        否则,即通讯录中保存有联系人信息时,则首先将当前通讯录中的所有联系人信息进行打印供用户确认,当用户希望删除某一联系人信息时,允许用户通过输入联系人的编号来删除该联系人

        删除时,我们的实现方式是,让选中联系人的后一个联系人将其覆盖,并以此类推至后面的所有联系人,并在完成后,将统计变量减一,即缩短联系人信息数组

        并在删除后将删除后的通讯录打印出来反馈给用户

void DelContact(contact* p)
{
	assert(p);
	int num = 0;
	if (p->sz == 0)
	{
		printf("对不起,当前通讯录中没有联系人信息!\n");
	}
	else
	{
		PrintAllContact(p);
		printf("请输入您想删除的联系人编号:>");
		scanf("%d", &num);
		int x = num - 1;
		if (0 < x && x < p->sz)
		{
			int j = 0;
			for (j = x; j < p->sz; j++)
			{
				p->data[j] = p->data[j + 1];
				p->sz--;
			}
			PrintAllContact(p);
		}
	}
}

        ⑦.“查找联系人”SearchContact:

        查找联系人的逻辑很简单,我们只需要定义一个字符串,然后让用户输入想要查找的联系人的姓名,接着我们就可以将通讯录中的联系人姓名与用户输入的姓名,使用遍历与 strcmp 函数进行比较,若相同,则将下标传递给 PrintContact 函数进行打印并跳出循环,若遍历结束全部找完仍没有找到相同的字符串,则提示用户联系人不存在

void SearchContact(const contact* p)
{
	assert(p);
	char name[MAX_NAME] = { 0 };
	printf("请输入您想要查询的联系人姓名:>");
	scanf("%s", &name);
	int i = 0;
	int ret = 1;
	for (i = 0; i < p->data; i++)
	{
		if (0 == strcmp(p->data[i].name, name))
		{
			PrintContact(p, i);
			ret = 0;
			break;
		}
	}
	if (ret)
	{
		printf("未找到该联系人!\n");
	}
}

        ⑧.“修改联系人信息”ModifyContact:

        修改的原理也很简单,首先我们同样对通讯录中的内容进行判断,内容为空则提示通讯录中没有联系人信息,否则提示进行修改

        在修改时,首先打印当前通讯录内全部信息供用户进行选择,用户可以通过联系人编号选择修改目标(获取下标),并选择想要修改的内容,再通过 switch 语句实现对目标内容的修改,最后将修改后的信息打印反馈给用户:

void ModifyContact(contact* p)
{
	assert(p);
	int x = 0;
	int input = 0;
	if (p->sz == 0)
	{
		printf("对不起,当前通讯录中没有联系人信息!\n");
	}
	else
	{
		PrintAllContact(p);
		printf("请输入您想要修改的联系人编号:>");
		scanf("%d", &x);
		PrintContact(p, x - 1);
		printf("当前支持修改的信息:\n");
		printf("1.Name\n");
		printf("2.Sex\n");
		printf("3.Age\n");
		printf("4.Tele\n");
		printf("5.Addr\n");
		printf("请选择您想要修改的信息:>");
		scanf("%d", &input);
		while (input)
		{
			switch (input)
			{
			case 1:
				printf("请输入联系人姓名:");
				scanf("%s", p->data[x - 1].name);
				printf("修改成功!\n");
				PrintContact(p, x - 1);
				input = 0;
				break;
			case 2:
				printf("请输入联系人性别:");
				scanf("%s", p->data[x - 1].sex);
				printf("修改成功!\n");
				PrintContact(p, x - 1);
				input = 0;
				break;
			case 3:
				printf("请输入联系人年龄:");
				scanf("%d", &(p->data[x - 1].age));
				printf("修改成功!\n");
				PrintContact(p, x - 1);
				input = 0;
				break;
			case 4:
				printf("请输入联系人联系方式:");
				scanf("%s", p->data[x - 1].tele);
				printf("修改成功!\n");
				PrintContact(p, x - 1);
				input = 0;
				break;
			case 5:
				printf("请输入联系人住址:");
				scanf("%s", p->data[x - 1].addr);
				printf("修改成功!\n");
				PrintContact(p, x - 1);
				input = 0;
				break;
			default:
				printf("您的选择有误,请重新选择!\n");
				break;
			}
		}
	}
}

🤠全部源码🤠:

        1.头文件Contact.h:

#pragma once

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

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

enum Option
{
	Exit,//值为0
	Add,//值为1
	Del,//值为2
	Search,//值为3
	Modify,//值为4
	Print//值为5
};

typedef struct PeoInfo
{
	char name[MAX_NAME];
	char sex[MAX_SEX];
	int age;
	char tele[MAX_TELE];
	char addr[MAX_ADDR];
}PeoInfo;

typedef struct contact
{
	PeoInfo data[MAX];
	int sz;
}contact;

void InitContact(contact* p);
void PrintContact(const contact* p, int x);
void PrintAllContact(const contact* p);
void AddContact(contact* p);
void DelContact(contact* p);
void SearchContact(const contact* p);
void ModifyContact(const contact* p);

        2.函数实现Contact.c:

#define _CRT_SECURE_NO_WARNINGS 1

#include"Contact.h"

void InitContact(contact* p)
{
	assert(p);
	p->sz = 0;
	memset(p->data, 0, sizeof(p->data));
	//使用memeset函数将p->data所指向的空间中的数据初始化为0
	//操作的空间大小为sizeof函数所计算出的p->data所指向空间的大小,即整个无联系人数据的结构体数组data所占的空间的大小
}

void PrintContact(const contact* p, int x)
{
	assert(p);
	printf(" 联系人 :%04d\n", x + 1);
	printf(" 姓  名 :%s\n", p->data[x].name);
	printf(" 性  别 :%s\n", p->data[x].sex);
	printf(" 年  龄 :%d\n", p->data[x].age);
	printf("联系方式:%s\n", p->data[x].tele);
	printf("当前住址:%s\n", p->data[x].addr);
}

void PrintAllContact(const contact* p)
{
	assert(p);
	printf("联系人 姓名                性别  年龄   联系方式      住址\n");
	int i = 0;
	for (i = 0; i < p->sz; i++)
	{
		printf(" %04d  %-20s %-5s %-4d %-12s %-30s\n", i + 1, p->data[i].name, p->data[i].sex, p->data[i].age, p->data[i].tele, p->data[i].addr);
	}
}

void AddContact(contact* p)
{
	assert(p);
	if (p->sz == MAX)
	{
		printf("通讯录空间不足,无法添加新成员!\n");
	}
	else
	{
		printf("请输入联系人姓名:>");
		scanf("%s", p->data[p->sz].name);
		printf("请输入联系人性别:>");
		scanf("%s", p->data[p->sz].sex);
		printf("请输入联系人年龄:>");
		scanf("%d", &(p->data[p->sz].age));
		printf("请输入联系人联系方式:>");
		scanf("%s", p->data[p->sz].tele);
		printf("请输入联系人住址:>");
		scanf("%s", p->data[p->sz].addr);
		PrintContact(p, p->sz);
		printf("联系人信息添加成功!\n");
		p->sz++;
	}
}

void DelContact(contact* p)
{
	assert(p);
	int num = 0;
	if (p->sz == 0)
	{
		printf("对不起,当前通讯录中没有联系人信息!\n");
	}
	else
	{
		PrintAllContact(p);
		printf("请输入您想删除的联系人编号:>");
		scanf("%d", &num);
		int x = num - 1;
		if (0 < x && x < p->sz)
		{
			int j = 0;
			for (j = x; j < p->sz; j++)
			{
				p->data[j] = p->data[j + 1];
				p->sz--;
			}
			PrintAllContact(p);
		}
	}
}

void SearchContact(const contact* p)
{
	assert(p);
	char name[MAX_NAME] = { 0 };
	printf("请输入您想要查询的联系人姓名:>");
	scanf("%s", &name);
	int i = 0;
	int ret = 1;
	for (i = 0; i < p->data; i++)
	{
		if (0 == strcmp(p->data[i].name, name))
		{
			PrintContact(p, i);
			ret = 0;
			break;
		}
	}
	if (ret)
	{
		printf("未找到该联系人!\n");
	}
}

void ModifyContact(contact* p)
{
	assert(p);
	int x = 0;
	int input = 0;
	if (p->sz == 0)
	{
		printf("对不起,当前通讯录中没有联系人信息!\n");
	}
	else
	{
		PrintAllContact(p);
		printf("请输入您想要修改的联系人编号:>");
		scanf("%d", &x);
		PrintContact(p, x - 1);
		printf("当前支持修改的信息:\n");
		printf("1.Name\n");
		printf("2.Sex\n");
		printf("3.Age\n");
		printf("4.Tele\n");
		printf("5.Addr\n");
		printf("请选择您想要修改的信息:>");
		scanf("%d", &input);
		while (input)
		{
			switch (input)
			{
			case 1:
				printf("请输入联系人姓名:");
				scanf("%s", p->data[x - 1].name);
				printf("修改成功!\n");
				PrintContact(p, x - 1);
				input = 0;
				break;
			case 2:
				printf("请输入联系人性别:");
				scanf("%s", p->data[x - 1].sex);
				printf("修改成功!\n");
				PrintContact(p, x - 1);
				input = 0;
				break;
			case 3:
				printf("请输入联系人年龄:");
				scanf("%d", &(p->data[x - 1].age));
				printf("修改成功!\n");
				PrintContact(p, x - 1);
				input = 0;
				break;
			case 4:
				printf("请输入联系人联系方式:");
				scanf("%s", p->data[x - 1].tele);
				printf("修改成功!\n");
				PrintContact(p, x - 1);
				input = 0;
				break;
			case 5:
				printf("请输入联系人住址:");
				scanf("%s", p->data[x - 1].addr);
				printf("修改成功!\n");
				PrintContact(p, x - 1);
				input = 0;
				break;
			default:
				printf("您的选择有误,请重新选择!\n");
				break;
			}
		}
	}
}

        3.程序主体test.c:

#define _CRT_SECURE_NO_WARNINGS 1

#include"Contact.h"

void menu()
{
	printf("**********************************\n");
	printf("**********************************\n");
	printf("******** 欢迎使用本通讯录 ********\n");
	printf("**********************************\n");
	printf("***** 本通讯录现提供以下功能 *****\n");
	printf("************ 1.Add ***************\n");
	printf("************ 2.Del ***************\n");
	printf("************ 3.Search ************\n");
	printf("************ 4.Modify ************\n");
	printf("************ 5.Print *************\n");
	printf("************ 0.Exit **************\n");
	printf("**********************************\n");
	printf("**********************************\n");
}

void Contact()
{
	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 Print:
			PrintAllContact(&con);
			break;
		case 0:
			printf("正在退出!\n");
			break;
		default:
			printf("您的选择有误,请重新选择!\n");
			break;
		}
	} while (input);
}

int main()
{
	Contact();

	return 0;
}

🥳总结🥳:

        到这里,我们的基础通讯录功能就得以实现啦,不过作为基础版本的它仍然存在着许多缺陷,例如缺少了许多的合法性检测,很多地方的输入将不能保证其正确性。同时我们也仍可以再向其中添加更多例如字典排序等等实用的功能。而关于这些内容的讲解我也将在下一篇文章中带领大家一起完成

        🔥🔥有那么多人看着你等着你倒下,所以你你拼了命也不能输!!!🔥🔥

        更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~  你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

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

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

相关文章

A White Paper on Neural Network Quantization--阅读笔记1

A White Paper on Neural Network Quantization--阅读笔记1一、模型量化的意义二、量化主要做什么三、目前量化主要分类四、量化基本知识介绍0、基本知识1、误差来源2、量化范围的设定五、量化方法介绍1、均匀仿射量化(Uniform affine quantization)2、对称均匀量化(Symmetric …

热门技术中的应用:微服务相关协议-第35讲-二进制类RPC协议:还是叫NBA吧,总说全称多费劲

前面我们讲了两个常用文本类的RPC协议,对于陌生人之间的沟通,用NBA、CBA这样的缩略语,会使得协议约定非常不方便。 在讲CDN和DNS的时候,我们讲过接入层的设计,对于静态资源或者动态资源静态化的部分都可以做缓存。但是对于下单、支付等交易场景,还是需要调用API。 对于…

基于yolov5的智慧交通监测系统

本项目实现了智慧交通监测、红绿灯监测、行人监测、车辆识别、斑马线闯红灯监测等多种监测功能。 目录 背景 演示效果&#xff1a; 检测代码样例&#xff1a; 最后的检测效果如图所示 项目具体的工作流程为&#xff1a; 总结&#xff1a; 背景 针对城市交通拥堵问题&#x…

Effective C++条款33:避免遮掩继承而来的名称(Avoid hiding inherited names)

Effective C条款33&#xff1a;避免遮掩继承而来的名称&#xff08;Avoid hiding inherited names&#xff09;条款33&#xff1a;避免遮掩继承而来的名称1、同名全局变量在局部作用域中被隐藏2、继承中的隐藏3、进一步论证——继承中的函数的隐藏4、如何将隐藏的行为进行覆盖4…

vTESTstudio入门到精通 - 如何自动化控制Simulation节点_03

我们工作中经常会遇到需要仿真大量的CAN/CANFD报文的情况,通常我们只能通过人工去测试,因为很难实现仿真控制大量报文的发送和停止?那我们该如何去解决呢? 今天我们主要来解决这个问题,通过CAPL去控制simulation节点的仿真发送和停止,最大限度的在实验室仿真实车的报文数…

段错误产生原因

嵌入式C开发&#xff0c;或多或少都遇到段错误&#xff08;segmentation fault &#xff09;。 下面是一些典型的段错误产生的原因&#xff1a; 访问不存在的内存地址 访问只读的内存地址 栈溢出 内存越界 …… 实例 1. 访问不存在的内存地址 #include <stdio.h>in…

小学生C++编程基础 课程7(A)

897.a到b (课程7&#xff09; 难度&#xff1a;1 登录 898.2位偶数 &#xff08;课程7&#xff09; 难度&#xff1a;1 登录 899.从0开始&#xff08;课程7&#xff09; 登录 900.前面数 &#xff08;课程7&#xff09; 登录 901.奇数 (课程7) 登录 902.7的倍数 (课程7) …

第二证券|新冠药销售占比不到1.5%,三连板医药龙头跌停!

今天早盘&#xff0c;A股商场延续调整态势&#xff0c;沪指震动失守3100点整数关口&#xff0c;深证成指、创业板指跌幅在1%左右。 虽然指数体现不佳&#xff0c;但个股层面不乏亮点。从涨跌份额来看&#xff0c;早盘A股商场有2695只股票上涨&#xff0c;2017只股票跌落&#x…

计算机毕设Python+Vue学生在线请假管理系统(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

双向扩散模型

🍿*★,*:.☆欢迎您/$:*.★* 🍿 简单的描述是一个图先扩散为噪声而后 噪声扩散为另一个图 这样的思路类似如 当人类看到图之后 开始联想和脑补 不断的脑补 一步一步的 脑补出另一幅图 比如给定图的一部分 脑补出另一部分 与传统的扩散模型 不同的点在于 初始给定的是一个…

2022 UUCTF Web

目录 <1> Web (1) websign(禁用js绕过) (2) ez_rce(?>闭合 rce) (3) ez_unser(引用传递) (4) ez_upload(apache后缀解析漏洞) (5) ezsql(union注入) (6) funmd5(代码审计 %0a绕过preg_replace) (7) phonecode(伪随机数漏洞) (8) ezpop(反序列化字符串逃逸) …

Sharding-JDBC(三)按月分表

目录1.Maven 依赖2.创建表结构3.yml 配置4.TimeShardingAlgorithm.java 分片算法类5.ShardingAlgorithmTool.java 分片工具类6.ShardingTablesLoadRunner.java 初始化缓存类7.SpringUtil.java Spring工具类8.代码测试9.测试结果背景&#xff1a; 项目用户数据库表量太大&#x…

20221220英语学习

今日新词&#xff1a; hurt adj.&#xff08;身体上&#xff09;受伤的, &#xff08;感情上&#xff09;受伤的 blood n.血, 血统, 有…类型的血的, 家世 sister adj.姐妹的, 同类(型)的 humour n.&#xff08; humor&#xff09;幽默, 心情, 情绪, 脾气 holiness n.神圣…

UX设计师是做什么的,现在怎么样

对设计领域略知一点的学生都知道UX设计已经流行了很长一段时间&#xff0c;几年前它的平均工资甚至超过了程序员&#xff0c;那么它的未来会一如既往地保持它的热度吗&#xff1f;未来稳定增长的高薪会下降吗&#xff1f;UX可以称之为科技领域的新秀。根据去年的数据统计&#…

AnQICMS 安装步骤教程

AnQICMS 安装步骤教程 支持的系统 支持 Windows 7、Windows 8、Windows 10、Windows 11、Windows server 各个版本。 Windows XP 未测试 支持 Ubuntu、Centos、Red Hat、Debian 等 基于 X86 的 Linux 版本。 支持 MacOS。 Linux服务器上部署AnQiCMS 先从 https://www.anqic…

力扣(LeetCode)169. 多数元素(C++)

抵消法 多数元素的数量比其他所有元素的总数还多。那么从前往后遍历&#xff0c;遇到相同元素&#xff0c;计数 111 &#xff0c;遇到不同元素&#xff0c;计数 −1-1−1 &#xff0c;考虑边界&#xff0c;当旧数的出现次数减到 000 &#xff0c;那么新数就可以替换旧数&#…

携手华为,瑞金医院病理科为健康数字化保驾护航

作者 | 曾响铃 文 | 响铃说 人生在世&#xff0c;沧桑流转&#xff0c;到了晚年&#xff0c;各种疾病袭来&#xff0c;总是无法避免&#xff0c;总要坦然接受。 只是&#xff0c;这个时候&#xff0c;能够知道自己究竟得的是什么病&#xff0c;才好去积极面对、笑对苦难。 …

前端简单案例——扩展卡

效果展示 色块可以替换成图片&#xff0c;改变background-color为background-image即可。 html代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content&quo…

图片加载引入的内存溢出问题分析

Android ImageView进行图片加载时&#xff0c;经常会遇到内存溢出的问题&#xff0c;本文针对于这一问题出现的定义、原理、过程、解决方案做统一总结。 1.一些定义 在分析具体问题之前&#xff0c;我们先了解一些基本概念&#xff0c;这样可以帮助理解后面的原理部分。当然了…

实时通讯技术Ajax,WebSocket,SSE

实时通讯技术是一项基于web开发的重要技术&#xff0c;网站是需要前后端通讯的&#xff0c;因此数据刷新的时间就是获取信息的时间&#xff0c;为了能准确而有快速的获取信息需要尽可能的提高信息的刷新效率。 常见的实时通讯技术&#xff1a; 通讯方式AjaxCometWebSocketSSE…