• 【项目】通讯录1(C语言)


    【项目】—— 通讯录1(C语言)

    通讯录是存储和管理我们的个人信息的程序应用。这里我们实现一个静态的通讯录(固定容量,无法扩容)

    通讯录的功能

    1. 存储100个联系人的信息(姓名、性别、年龄、电话、地址)
    2. 添加联系人
    3. 删除联系人
    4. 修改联系人
    5. 根据姓名查寻联系人
    6. 根据姓名将联系人升序排序
    7. 展示所有联系人

    一、通讯录的结构

    ​ 通讯录由C语言实现,实现环境是VS2019编译程序,结构如下

    1. 头文件contact.h:引入头文件,并声明通讯录的数据类型和函数声明
    2. 源文件contact.c:实现通讯录各个功能的函数
    3. 测试文件test.c:写有main函数,启动程序并实现业务逻辑

    二、头文件

    1. 头文件引用

    #pragma once			//防止头文件重复引用
    #include 		//标准输入输出,具体作用懂得都懂
    #include 		//我们会对每个函数内部的一些变量进行断言,方便我们调试
    #include 		//我们会对字符串进行操作
    #include 	//我们会执行一些命令行
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2. 结构体声明

    //定义变量最大数量
    #define MAX_INFO 100	//100个联系人
    #define MAX_NAME 20		//姓名占20字符
    #define MAX_SEX 10		//性别占10字符
    #define MAX_TEL 20		//电话占20字符
    #define MAX_ADDR 50		//地址占50字符
    
    //个人信息
    typedef struct PeoInfo
    {
    	char name[MAX_NAME];	 //姓名
    	char sex[MAX_SEX];		 //性别
    	int age;				//年龄
    	char tel[MAX_TEL];		 //电话
    	char addr[MAX_ADDR];	 //地址
    } PeoInfo;
    
    //通讯录
    typedef struct Contact
    {
    	PeoInfo data[MAX_INFO];	 //联系人
    	int count;				//联系人数量
    } Contact;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    3. 函数声明

    void menu();					// 菜单
    void init(Contact* pc);			 // 初始化
    void add(Contact* pc);			 // 添加
    void del(Contact* pc);			 // 删除
    void search(const Contact* pc);	  // 查寻
    void alter(Contact* pc);		 // 修改
    void sort(Contact* pc);			 // 排序
    void show(const Contact* pc);	 // 展示
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    三、测试文件

    当我们声明完变量和函数时,不要着急去实现函数,而是先构思好逻辑业务,构思好后再实现函数,边实现边调试,才能将BUG消灭到最初的时候

    int main()
    {
    	Contact con;
    	init(&con);
    
    	menu();
    
    	int chose = 0;
    	do
    	{
    		printf("请输入您要进行的操作序号>");
    
    		scanf("%d", &chose);
    
    		system("cls");		//此时有一个清屏,让黑乎乎的界面更加美观,清完之后打印菜单,方便用户操作
    		menu();
    
    		switch (chose)
    		{
    		case 0:
    			printf("欢迎下次光临!\n");
    			return 0;
    			break;
    
    		case 1:
    			add(&con);	//添加联系人
    			break;
    
    		case 2:
    			del(&con);	//删除联系人
    			break;
    
    		case 3:
    			search(&con);	//查找联系人
    			break;
    
    		case 4:
    			alter(&con);	//修改联系人
    			break;
    
    		case 5:
    			show(&con);		//展示所有联系人
    			break;
    
    		case 6:
    			sort(&con);		//对联系人排序
    			break;
    
    		default:
    			printf("输入错误,请重新输入\n");
    			break;
    		}
    		
    	} while (0 != chose);
    	
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    四、源文件

    1. 菜单

    用于提示用户操作信息,一套printf输出行云流水直接操作。

    void menu()
    {
    	printf("========================================\n");
    	printf("==------------------------------------==\n");
    	printf("==------  1.add       2.del     ------==\n");
    	printf("==------  3.search    4.alter   ------==\n");
    	printf("==------  5.show      6.sort    ------==\n");
    	printf("==------        0.exst          ------==\n");
    	printf("==------------------------------------==\n");
    	printf("========================================\n");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2. 初始化

    初始化通讯录,将数据内存内容全置为0,联系人数量置为0

    //初始化
    void init(Contact* pc)
    {
    	assert(pc != NULL);
    
    	pc->count = 0;
    	memset(pc, 0, sizeof(pc));	//将Contact内存设置为0
        
        //以下操作千万不要解除封印,不然会被开除的[狗头]
    	/* 
    	* //假装加载数据,显得有逼格
    	* printf("正在加载通讯录......\n");
    	* Sleep(5000);
    	* printf("加载完毕,开始使用吧!!!\n");
    	*/
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3. 获取指定姓名的联系人下标

    该函数会在查找、删除、修改联系人中使用,所以封装在一个函数,减少代码冗余

    遍历查找联系人,并返回其下标,若是联系人不存在则返回-1

    int getIndexByName(Contact* pc, const char* name)
    {
    	int i = 0;
    	for (i = 0; i < pc->count; i++)
    	{
    		if (strcmp(pc->data[i].name, name) == 0)
    		{
    			return i;
    		}
    	}
    	return -1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4. 添加联系人

    先判断通讯录满了,则不进行操作,提示“通讯录已满”,否则依次录入联系人信息

    void add(Contact* pc)
    {
    	assert(pc != NULL);
    	if (pc->count >= MAX_INFO)
    	{
    		printf("通讯录已满\n");
    		return;
    	}
    
    	printf("请输入姓名>");
    	scanf("%s", pc->data[pc->count].name);
    
    	printf("请输入性别>");
    	scanf("%s", pc->data[pc->count].sex);
    
    	printf("请输入年龄>");
    	scanf("%d", &(pc->data[pc->count].age));
    
    	printf("请输入电话>");
    	scanf("%s", pc->data[pc->count].tel);
    
    	printf("请输入地址>");
    	scanf("%s", pc->data[pc->count].addr);
    
    	pc->count++;
    
    	printf("添加成功\n");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    5. 删除联系人

    判断联系人是否为空,若是不为空,则查找指定姓名的联系人下标,并用后面的联系人覆盖掉他的信息,联系人的数量减一,若是该联系人不存在,则给出提示。

    void del(Contact* pc)
    {
    	assert(pc != NULL);
    
    	if (pc->count == 0)
    	{
    		printf("通讯录为空\n");
    		return;
    	}
    
    	char name[20] = { 0 };
    
    	printf("请输入删除信息的姓名>");
    	scanf("%s", name);
    
    	int i = getIndexByName(pc, name);
    
    	if (i != -1)
    	{
    		for (i; i < pc->count - 1; i++)
    		{
    			memcpy(&(pc->data[i]), &(pc->data[i + 1]), sizeof(PeoInfo));
    		}
    		pc->count--;
    		printf("删除成功\n");
    	}
    	else
    	{
    		printf("查无此人\n");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    6. 修改联系人

    void alter(Contact* pc)
    {
    	assert(pc != NULL);
    	if (pc->count == 0)
    	{
    		printf("通讯录为空\n");
    		return;
    	}
    
    	char name[20] = { 0 };
    	printf("请输入被修改联系人的姓名>");
    	scanf("%s", name);
    
    	int i = getIndexByName(pc, name);
    
    	if (i != -1)
    	{
    		printf("请输入姓名>");
    		scanf("%s", pc->data[i].name);
    
    		printf("请输入性别>");
    		scanf("%s", pc->data[i].sex);
    
    		printf("请输入年龄>");
    		scanf("%d", &(pc->data[i].age));
    
    		printf("请输入电话>");
    		scanf("%s", pc->data[i].tel);
    
    		printf("请输入地址>");
    		scanf("%s", pc->data[i].addr);
    
    		printf("修改成功\n");
    	}
    	else
    	{
    		printf("查无此人\n");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    7. 查询联系人

    根据姓名查询该联系人的所有信息

    void search(const Contact* pc)
    {
    	assert(pc != NULL);
    
    	if (pc->count == 0)
    	{
    		printf("通讯录为空\n");
    		return;
    	}
    
    	char name[20] = { 0 };
    	printf("请输入姓名>");
    	scanf("%s", name);
    
    	int i = getIndexByName(pc, name);
    	if (i != -1)
    	{
    		printf("%-20s\t%-10s\t%-10s\t%-20s\t%-20s\n",
    			"姓名", "性别", "年龄", "电话", "地址");
    		printf("%-20s\t%-10s\t%-10d\t%-20s\t%-20s\n",
    			pc->data[i].name, pc->data[i].sex, pc->data[i].age, pc->data[i].tel, pc->data[i].addr);
    	}
    	else
    	{
    		printf("查无此人\n");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    8. 联系人排序

    我们调用库函数qsort帮助我们完成排序,在使用前我们先要实现两个联系人的比较规则,我们使用联系人姓名的升序作为排序规则

    //比较规则
    int cmp_info(const void* e1, const void* e2)
    {
    	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
    }
     
    // 排序
    void sort(Contact* pc)
    {
    	assert(pc != NULL);
    
    	if (pc->count == 0)
    	{
    		printf("通讯录为空\n");
    		return;
    	}
    
    	qsort(pc->data, pc->count, sizeof(PeoInfo), cmp_info);
    	printf("排序成功\n");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    9. 展示所有联系人

    利用printf函数中的字宽限制展示的字符串长度,并使其左对齐,每个字段用制表符隔开,每个联系人信息占一行

    void show(const Contact* pc)
    {
    	assert(pc != NULL);
    
    	printf("%-20s\t%-10s\t%-10s\t%-20s\t%-20s\n",
    		"姓名", "性别", "年龄", "电话", "地址");
    	int i = 0;
    	for (i = 0; i < pc->count; i++)
    	{
    		printf("%-20s\t%-10s\t%-10d\t%-20s\t%-20s\n",
    			pc->data[i].name, pc->data[i].sex, pc->data[i].age, pc->data[i].tel, pc->data[i].addr);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    五、程序演示

    1. 启动程序时我们需要输入操作

    1

    1. 增加联系人时,我们输入操作1,再依次输入信息即可

    2

    1. 删除联系人时,我们输入操作2,再输入要删除的联系人姓名,若是联系人存在,则删除成功

    3

    1. 查找联系人时,我们输入操作3,再输入查找联系人的姓名,若是联系人存在,则显示他的所有信息

    4

    1. 修改联系人时,输入操作4,再输入修改联系人的姓名,依次输入联系人信息,则修改成功

    5

    1. 展示所有联系人时,输入操作5即可

    6

    1. 将联系人排序时,输入操作6,然后我们再输入5查看排序结果

    7

    8

    1. 退出时我们输入操作0即可

    9

    六、完整代码

    代码存储于gitee中:点击查看完整代码

  • 相关阅读:
    PCL点云处理之基于强度特征的SIFT关键点提取法 (二百一十五)
    java面向对象
    安装visual studio报错“无法安装msodbcsql“
    comsol如何建立平面坐标系
    SpringBoot入门到精通-基于阿里云短信服务-定义Starter封装通用组件
    PostgreSQL高级
    [附源码]计算机毕业设计springboot学分制环境下本科生学业预警帮扶系统
    MyBatis:自定义分页插件
    2023-05-20:go语言的slice和rust语言的Vec的扩容流程是什么?
    现在面试都不问八股文了吗
  • 原文地址:https://blog.csdn.net/weixin_52811588/article/details/126652938