用C实现通讯录(详细讲解+源码)

 前言

📚作者简介:爱编程的小马,正在学习C/C++,Linux及MySQL..

📚以后会将数据结构收录为一个系列,敬请期待

● 本期内容会给大家带来通讯录的讲解,主要是利用结构体来实现通讯录,该通讯录可以存储几百人甚至是几千人的信息,每个信息包括:姓名,年龄,性别,电话以及地址。准备好了就跟着小马出发吧。


通讯录

 前言

1.通讯录环境及文件配置

2.通讯录的实现

2.1 通讯录的功能

2.2 通讯录的定义

2.3 录入人员信息的函数实现

2.4 定义检查人员是否存在函数

 2.5 删除通讯录中已经存在的信息函数实现

 2.6 查找通讯录成员函数

2.7 修改通讯录成员函数

2.8 显示通讯录

2.9 给通讯录排序

3.通讯录全部源码

3.1 test.c

3.2 contact.h

3.3 contact.c

总结


 

1. 通讯录环境及文件配置

本通讯录是在VS2019的环境下,需要创建三个文件,test.c ,contact.c ,contact.h

test.c //主函数,调用通讯录相关功能

contact.c //函数功能的实现

contact.h //函数头文件的包含及函数的声明

2. 通讯录的实现

2.1 通讯录的功能

2.2 通讯录的定义

首先需要一个菜单,可以提供给玩家选择:

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");printf("******************************\n");
}

 通讯录的定义:

1、封装一个结构体信息用来存储人员信息

2、再需要一个结构体数组来管理这个人员信息(暂时能存储100个人)


#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 20
#define ADDR_MAX 30
#define ADD_ONCE 2
#define MAX 100
typedef struct peoinfo
{char name[NAME_MAX];int age;char sex[SEX_MAX];char tele[TELE_MAX];char addr[ADDR_MAX];
}peoinfo;
typedef struct contact
{peoinfo data [MAX];int sz;
}contact;

2.3 录入人员信息的函数实现

1、判断:如果人员信息录入满了就不再录入了

2、挨个录入姓名,年龄,性别,电话以及住址,录入完成后打印增加成功,然后记录人员信息的sz往后走一步(sz++)

void AddContact(contact* pc)
{assert(pc);if (pc->sz == MAX){printf("通讯录已满,请删除后重试\n");return;}printf("请输入名字:>");scanf("%s", pc->data[pc->sz].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");
}

2.4 定义检查人员是否存在函数

为什么要定义这个函数呢?因为两点原因:1、后面的删除,查找,修改人员信息是不是都要先确定这个人是否存在我们再进行下一步操作。2、在前面定义,后面直接引用即可,不用反复定义


int FindName(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;
}

 2.5 删除通讯录中已经存在的信息函数实现

1、判断:如果通讯录为空,就不要删除了,直接返回

2、如果不为空,我们就调用检查人员是否存在这个函数,如果存在,则继续,如果不存在,就返回

3、如果有这个人,那应该从这个人的地址往后,依次向前覆盖,最后总数sz-1是不是就完成了删除

void DelContact(contact* pc)
{char name[NAME_MAX];printf("请输入要删除人的名字:>");scanf("%s", name);if (pc->sz == 0){printf("通讯录为空,无法删除\n");return;}int ret = FindName(pc, name);if (ret == -1){printf("查无此人,无法删除请重试\n");return;}int i = 0;for (i = ret; i < ret - 1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("删除成功\n");
}

 2.6 查找通讯录成员函数

1、判断:如果通讯录为空,不要查找了直接返回

2、调用检查人员存在函数,如果没有就直接返回,如果存在就直接打印人员信息

void SearchContact(contact* pc)
{char name[NAME_MAX];int i = 0;printf("请输入被查找人的名字:>");scanf("%s", name);int ret = FindName(pc, name);if (ret == -1){printf("查无此人\n");}else{printf("%-20s%-5s%-5s%-12s%-20s\n", "姓名", "年龄", "性别", "电话", "地址");printf("%-20s%-5d%-5s%-12s%-20s\n", pc->data[ret].name,pc->data[ret].age,pc->data[ret].sex,pc->data[ret].tele,pc->data[ret].addr);}
}

2.7 修改通讯录成员函数

1、判断:如果通讯录为空就不要修改了,直接返回

2、调用检查人员存在函数,如果没有就直接返回,如果存在就直接修改人员信息

void ModifyContact(contact* pc)
{char name[NAME_MAX];int i = 0;printf("请输入要修改人的名字:>");scanf("%s", name);int ret = FindName(pc, name);if (ret == -1)printf("要修改的人不存在\n");else{printf("请输入名字:>");scanf("%s", pc->data[ret].name);printf("请输入年龄:>");scanf("%d", &pc->data[ret].age);printf("请输入性别:>");scanf("%s", pc->data[ret].sex);printf("请输入电话:>");scanf("%s", pc->data[ret].tele);printf("请输入地址:>");scanf("%s", pc->data[ret].addr);printf("修改成功\n");}}

2.8 显示通讯录

void ShowContact(contact* pc)
{assert(pc);if (pc->sz == 0)printf("通讯录为空,无需打印\n");else{int i = 0;for (i = 0; i < pc->sz; i++){printf("%-20s%-5s%-5s%-12s%-20s\n", "姓名", "年龄", "性别", "电话", "地址");printf("%-20s%-5d%-5s%-12s%-20s\n", pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);}}
}

2.9 给通讯录排序

1、首先需要确定按什么排序

2、实现的思想是使用qsort函数

void menun()
{printf("******************************\n");printf("**** 1.按名字    2.按年龄 ****\n");printf("**** 3.按性别    4.按电话 ****\n");printf("**** 5.按地址             ****\n");printf("******************************\n");
}
int NAME(const void* p1, const void* p2)
{return strcmp(((peoinfo*)p1)->name, ((peoinfo*)p2)->name);
}int AGE(const void* p1, const void* p2)
{return (((peoinfo*)p1)->age- ((peoinfo*)p2)->age);
}
int SEX(const void* p1, const void* p2)
{return strcmp(((peoinfo*)p1)->sex, ((peoinfo*)p2)->sex);
}
int TELE(const void* p1, const void* p2)
{return strcmp(((peoinfo*)p1)->tele, ((peoinfo*)p2)->tele);
}
int ADDR(const void* p1, const void* p2)
{return strcmp(((peoinfo*)p1)->addr, ((peoinfo*)p2)->addr);
}
void SortContact(contact* pc)
{menun();int input = 0;printf("请输入排序的方式:>");scanf("%d", &input);int (*cmp[6])(const void* p1, const void* p2) = { NULL,NAME,AGE,SEX,TELE,ADDR};switch (input){case 1:qsort(pc->data, pc->sz, sizeof(peoinfo), cmp[input]);break;case 2:qsort(pc->data, pc->sz, sizeof(peoinfo), cmp[input]);break;case 3:qsort(pc->data, pc->sz, sizeof(peoinfo), cmp[input]);break;case 4:qsort(pc->data, pc->sz, sizeof(peoinfo), cmp[input]);break;case 5:qsort(pc->data, pc->sz, sizeof(peoinfo), cmp[input]);break;default:printf("输入非法\n");}printf("排序成功\n");
}

3. 通讯录全部源码

3.1 test.c

#define  _CRT_SECURE_NO_WARNINGS 1
#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");printf("******************************\n");}
enum Option
{EXIT,ADD,DEL,SEARCH,MODIFY,SHOW,SORT
};
int main()
{int input = 0;contact con;Init(&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");}} while (input);return 0;
}

3.2 contact.h

#pragma once
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 20
#define ADDR_MAX 30
#define ADD_ONCE 2
#define MAX 100
typedef struct peoinfo
{char name[NAME_MAX];int age;char sex[SEX_MAX];char tele[TELE_MAX];char addr[ADDR_MAX];
}peoinfo;
typedef struct contact
{peoinfo data [MAX];int sz;
}contact;void Init(contact * pc);
void  AddContact(contact* pc);void ShowContact(contact*pc);void DelContact(contact* pc);void SearchContact(contact *pc);void ModifyContact(contact* pc);void SortContact(contact* pc);void free_contact(contact *pc);

3.3 contact.c

#define  _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"void Init(contact* pc)
{//静态版assert(pc);pc->sz = 0;memset(pc->data, 0, sizeof(pc->data));
}
void AddContact(contact* pc)
{assert(pc);if (pc->sz == MAX){printf("通讯录已满,请删除后重试\n");return;}printf("请输入名字:>");scanf("%s", pc->data[pc->sz].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 ShowContact(contact* pc)
{assert(pc);if (pc->sz == 0)printf("通讯录为空,无需打印\n");else{int i = 0;for (i = 0; i < pc->sz; i++){printf("%-20s%-5s%-5s%-12s%-20s\n", "姓名", "年龄", "性别", "电话", "地址");printf("%-20s%-5d%-5s%-12s%-20s\n", pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);}}
}//从后往前覆盖就好了,总数删除完毕之后再减一个int FindName(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;
}
void DelContact(contact* pc)
{char name[NAME_MAX];printf("请输入要删除人的名字:>");scanf("%s", name);if (pc->sz == 0){printf("通讯录为空,无法删除\n");return;}int ret = FindName(pc, name);if (ret == -1){printf("查无此人,无法删除请重试\n");return;}int i = 0;for (i = ret; i < ret - 1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("删除成功\n");
}void SearchContact(contact* pc)
{char name[NAME_MAX];int i = 0;printf("请输入被查找人的名字:>");scanf("%s", name);int ret = FindName(pc, name);if (ret == -1){printf("查无此人\n");}else{printf("%-20s%-5s%-5s%-12s%-20s\n", "姓名", "年龄", "性别", "电话", "地址");printf("%-20s%-5d%-5s%-12s%-20s\n", pc->data[ret].name,pc->data[ret].age,pc->data[ret].sex,pc->data[ret].tele,pc->data[ret].addr);}
}void ModifyContact(contact* pc)
{char name[NAME_MAX];int i = 0;printf("请输入要修改人的名字:>");scanf("%s", name);int ret = FindName(pc, name);if (ret == -1)printf("要修改的人不存在\n");else{printf("请输入名字:>");scanf("%s", pc->data[ret].name);printf("请输入年龄:>");scanf("%d", &pc->data[ret].age);printf("请输入性别:>");scanf("%s", pc->data[ret].sex);printf("请输入电话:>");scanf("%s", pc->data[ret].tele);printf("请输入地址:>");scanf("%s", pc->data[ret].addr);printf("修改成功\n");}}void menun()
{printf("******************************\n");printf("**** 1.按名字    2.按年龄 ****\n");printf("**** 3.按性别    4.按电话 ****\n");printf("**** 5.按地址             ****\n");printf("******************************\n");
}
int NAME(const void* p1, const void* p2)
{return strcmp(((peoinfo*)p1)->name, ((peoinfo*)p2)->name);
}int AGE(const void* p1, const void* p2)
{return (((peoinfo*)p1)->age- ((peoinfo*)p2)->age);
}
int SEX(const void* p1, const void* p2)
{return strcmp(((peoinfo*)p1)->sex, ((peoinfo*)p2)->sex);
}
int TELE(const void* p1, const void* p2)
{return strcmp(((peoinfo*)p1)->tele, ((peoinfo*)p2)->tele);
}
int ADDR(const void* p1, const void* p2)
{return strcmp(((peoinfo*)p1)->addr, ((peoinfo*)p2)->addr);
}
void SortContact(contact* pc)
{menun();int input = 0;printf("请输入排序的方式:>");scanf("%d", &input);int (*cmp[6])(const void* p1, const void* p2) = { NULL,NAME,AGE,SEX,TELE,ADDR};switch (input){case 1:qsort(pc->data, pc->sz, sizeof(peoinfo), cmp[input]);break;case 2:qsort(pc->data, pc->sz, sizeof(peoinfo), cmp[input]);break;case 3:qsort(pc->data, pc->sz, sizeof(peoinfo), cmp[input]);break;case 4:qsort(pc->data, pc->sz, sizeof(peoinfo), cmp[input]);break;case 5:qsort(pc->data, pc->sz, sizeof(peoinfo), cmp[input]);break;default:printf("输入非法\n");}printf("排序成功\n");
}

总结

上文就是通讯录的详细讲解和全部源码,下一节会给大家更新动态内存存储相关的知识。

如果这份博客对大家有帮助,希望各位给小马一个大大的点赞鼓励一下,如果喜欢,请收藏一下,谢谢大家!!!
制作不易,如果大家有什么疑问或给小马的意见,欢迎评论区留言。

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

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

相关文章

[ESP32]:TFLite Micro推理CIFAR10模型

[ESP32]&#xff1a;TFLite Micro推理CIFAR10模型 模型训练 数据集处理 from keras.datasets import cifar10 from keras.preprocessing.image import ImageDataGenerator from keras.models import Sequential, load_model, Model from keras.layers import Input, Dense, …

目标检测(任务概述、机器学习时代的方法、深度学习时代的目标检测模型)

文章目录 目标检测任务概述机器学习时代的目标检测方法深度学习时代的目标检测模型基于提议的目标检测模型R-CNN 模型Fast RCNN 模型Faster RCNN 模型SSD 模型YOLO 模型 基于分割的目标检测模型FCN 模型U-Net 模型 目标检测任务概述 目标检测任务的概念&#xff1a;尝试从一张…

xLua详解

目录 环境准备xLua导入 C#调用LuaLua解析器Lua文件加载重定向Lua解析管理器全局变量的获取全局函数的获取List和Dictionary映射table类映射table接口映射tableLuaTable映射table Lua调用C#准备工作Lua使用C#类Lua调用C#枚举Lua使用C# 数组 List 字典数组List字典 Lua使用C#扩展…

解决NetworkManager覆盖/etc/resolv.conf的问题

发布时间&#xff1a;2024.4.27 问题 /etc/resolv.conf是Linux下DNS的配置文件。 但是NetworkManager会用覆盖它&#xff0c;导致我们每次都要重新配置。 解决办法 这是官方推荐的做法。或者你可以用resolveconf工具。 $ nm-connection-editor会调起一个界面&#xff0c;…

RabbitMQ通配符模式

RabbitMQ通配符模式 简介代码演示生产者消费者 简介 RabbitMQ是一个开源的消息中间件&#xff0c;在分布式系统中被广泛应用于消息的传递和处理。它支持多种工作模式&#xff0c;其中之一是通配符&#xff08;TOPIC&#xff09;模式。本文将对RabbitMQ的通配符模式进行详细的讲…

Python_AI库 matplotlib扩展知识

Python_AI库 matplotlib扩展知识 在数据分析和处理的领域里&#xff0c;可视化是一种不可或缺的手段。通过图形化的展示&#xff0c;我们可以更直观地理解数据的分布、趋势和关系。而matplotlib&#xff0c;作为Python中最为流行的数据可视化库之一&#xff0c;以其强大的功能…

【C++】简易二叉搜索树

目录 一、概念&#xff1a; 二、代码实现&#xff1a; 大致结构&#xff1a; 1、遍历&#xff1a; 2、insert 3、find 4、erase 三、总结&#xff1a; 一、概念&#xff1a; 二叉搜索树又称为二叉排序树&#xff0c;是一种具有特殊性质的二叉树&#xff0c;对于每一个节…

在虚拟环境中找到Qt Designer

Pyqt5中找到Qt Designer 安装Pyqt5和Qt Designer: pip install pyqt5-tools 假设Python的虚拟环境名为:d2l &#xff0c;虚拟环境在d2l文件夹中 D:\Software\d2l\Lib\site-packages\qt5_applications\Qt\bin 双击Qt designer启动 Pyside2中找到Qt Designer d2l是虚拟环境…

上位机图像处理和嵌入式模块部署(树莓派4b下使用sqlite3)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 嵌入式设备下面&#xff0c;有的时候也要对数据进行处理和保存。如果处理的数据不是很多&#xff0c;一般用json就可以。但是数据如果量比较大&…

rust前端web开发框架yew使用

构建完整基于 rust 的 web 应用,使用yew框架 trunk 构建、打包、发布 wasm web 应用 安装后会作为一个系统命令&#xff0c;默认有两个特性开启 rustls - 客户端与服务端通信的 tls 库update_check - 用于应用启动时启动更新检查&#xff0c;应用有更新时提示用户更新。nati…

Linux——终端

一、终端 1、终端是什么 终端最初是指终端设备&#xff08;Terminal&#xff09;&#xff0c;它是一种用户与计算机系统进行交互的硬件设备。在早期的计算机系统中&#xff0c;终端通常是一台带有键盘和显示器的电脑&#xff0c;用户通过它输入命令&#xff0c;计算机在执行命…

Swift中的单例

在Swift中实现单例模式可以通过使用静态常量或静态变量来实现。下面是一个示例&#xff1a; class Singleton {static let sharedInstance Singleton()private init() {// 这里是初始化代码}// 这里是其他实例方法和属性 }在上面的示例中&#xff0c;通过使用static let来创建…

SpringBoot引入Layui样式总是出现404

一般出现Layui样式文件如css&#xff0c;js404的错误 解决方案 &#xff08;1&#xff09;首先将其中的静态资源下载resources/static中 &#xff08;2&#xff09;在启动类中重写方法 package com.gq.booksystem;import org.mybatis.spring.annotation.MapperScan; import …

商城数据库(1-4)

1——商家认证项目表&#xff08;wang_accreds&#xff09; CREATE TABLE wang_accreds (accredId int(11) NOT NULL AUTO_INCREMENT COMMENT 自增ID,accredName varchar(50) NOT NULL COMMENT 名称,accredImg varchar(150) NOT NULL DEFAULT 0 COMMENT 图标,dataFlag tinyint…

centOS 7.9操作

名称日期版本作者centOS7.9操作2024.4.271.0lll 实验题目&#xff1a; 创建一个用户。 在创建的用户中再创建一个2024的目录。 在2024的下在创建一个 1---10的目录&#xff0c;再创建一个a--z.txt的文件。 在创建一个2024bak的目录。 再将当前用户的所有文件备份到2024ba…

【算法学习】线段树基础版

一 线段树 1.概念 线段树可以理解为一个二叉树&#xff0c;如果是利用线段树求区间的和&#xff0c;那么每个结点的权值维护的是结点所维护区间的和&#xff0c;再将该区间一分为二&#xff0c;分别交由左右儿子维护。 拿区间1 - 4的和来举例子&#xff0c; 根结点维护的是区…

开发管理导读

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言一、代码版本管理1、github代码版本管理2、gitlab代码版本管理3、SVN&#xff08;Subversion&#xff09;代码版本管理 二、代…

JavaEE——Spring Boot入门

目录 &#x1f4da; JavaEE——Spring Boot入门 &#x1f527; 1. 新建Spring Boot项目 &#x1f6e0; 2. 添加pom依赖 &#x1f4dd; 3. 添加application.yml文件 &#x1f4c2; 4. 创建Dao层 &#x1f527; 5. 创建Service层 &#x1f5a5;️ 6. 创建Controller层及HT…

【小浩算法cpp题解】合并两个有序链表(21)

目录 前言我的思路我的代码 前言 今天继续做链表相关的题目&#xff0c;考研期间练多了现在觉得这种题目真是简单。晚上如果有机会可以再做一个树的深度优先搜索。 我的思路 其实这道题的思路比较像排序中的二路归并&#xff0c;最核心的点是在归并的时候要防止断链,我的解决…

librosa 语音识别 学习笔记

目录 不错的功能介绍 librosa安装 语音识别 不错的功能介绍 librosa&#xff0c;一个很有趣的 Python 库&#xff01; - 简书 音频转特征向量 GitHub - librosa/librosa: Python library for audio and music analysis librosa安装 2024.04.27 测试ok Win11系统 pip in…