当前位置: 首页 > news >正文

【C语言】动态通讯录(超详细)

通讯录是一个可以很好锻炼我们对结构体的使用,加深对结构体的理解,在为以后学习数据结构打下结实的基础

这里我们想设计一个有添加联系人,删除联系人,查找联系人,修改联系人,展示联系人,排序这几种功能的通讯录

目录

  • 整体框架:
  • 菜单:
  • 创建通讯录:
  • 初始化:
  • 实现功能:
    • 添加联系人:
    • 删除联系人:
      • find()的定义:
    • 查找联系人:
    • 修改联系人:
    • 展示联系人:
    • 排序:
    • free空间:
  • 源代码:

注意:我们按照三个区域划分

在这里插入图片描述

上图所示进行区域划分

  • con.c用来放实现功能的函数
  • con.h用来放头文件的声明
  • test.c用来放整体框架

整体框架:

使用do...while循环创建整体框架

整体框架在test.c中,这部分我们用来测试代码

int main()
{int input = 0;InitContact(&Con);do{menu();printf("请输入你的选项\n");scanf("%d", &input);switch (input){case Add:break;case Del:break;case Search:break;case Modify:break;case Show:break;case Sort:break;case Exit:printf("你已成功退出\n");break;default:printf("输入错误,请重新输入\n");break;}} while (input);return 0;
}
注意
我在使用case语句时没有用数字1,2,3…
而是使用了枚举常量,因为枚举常量会更方便程序员查看与操作要与菜单的数字相匹配,不然就会弄巧成拙
enum option
{Exit,Add,Del,Search,Modify,Show,Sort,
};

菜单:

菜单的设计随心所欲,但要与枚举相匹配

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

创建通讯录:

此部分我们在Contact.h中创建,在另外两个里include就可以

创建通讯录之前要先创建一个联系人的结构体:
假设我们的结构体包含了一个人的姓名,年龄,性别,电话,住址
那么久可以很好的进行创建:

typedef struct PeoInfo
{char name[NAME_MAX];int age;char sex[SEX_MAX];char tele[TELE_MAX];char addr[ADDR_MAX];
}PeoInfo;

其中的常量用define按需求进行定义,避免牵一发而动全身的情况

#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30

因为要动态通讯录
故设计通讯录时不能使用PeoInfo创建数组的方式进行
可以创建结构体指针,指向动态内存分配的空间

typedef struct Contact
{PeoInfo* Data;int sz;int capacity;
}Contact;

最后在test.c文件中创建通讯录 Contact Con;

初始化:

con.c中进行设计,不要忘记在test.c中调用,在con.h中声明
实现功能皆是如此设计,将不在赘述

	void InitContact(Contact* pc)
{assert(pc);pc->sz = 0;pc->capacity = START;PeoInfo* p = (PeoInfo*)malloc(sizeof(PeoInfo) * START);//start为初始化大小,define定义为3if (p != NULL){pc->Data = p;}else{perror("InitContact->malloc");}
}

实现功能:

添加联系人:

void AddContact(Contact* pc)
{assert(pc);if (pc->sz == pc->capacity){PeoInfo* str = (PeoInfo*)realloc(pc->Data, sizeof(PeoInfo) * (pc->capacity + START_ADD));//START_ADD为define定义,为一次扩容数量if (str != NULL){pc->Data = str;pc->capacity = pc->capacity + START_ADD;printf("增容成功\n");}else{perror("AddContact->realloc");return;}}printf("输入名字\n");scanf("%s", pc->Data[pc->sz].name);printf("输入年龄\n");scanf("%d", &pc->Data[pc->sz].age);printf("输入性别\n");scanf("%s", &pc->Data[pc->sz].sex);printf("输入电话\n");scanf("%s", &pc->Data[pc->sz].tele);printf("输入住址\n");scanf("%s", &pc->Data[pc->sz].addr);printf("输入成功\n");pc->sz++;
}

删除联系人:

void DelContact(Contact* pc)
{if (pc->sz == 0){printf("通讯录为空,无需删除\n");return;}char name[NAME_MAX];printf("输入你要删除人的姓名\n");scanf("%s", name);int ret = find(pc, name);//我们这里使用了find函数if (ret == -1){printf("查无此人\n");return;}for (int i = ret; i < pc->sz-1; i++){pc->Data[i] = pc->Data[i + 1];}pc->sz--;
}

我们在输入查找姓名后要进行查找,因此我们设计了一个find函数,方便别的函数的使用

find()的定义:

int find(Contact* pc, char name[])
{for (int i = 0; i < pc->sz; i++){if (strcmp(name, pc->Data[i].name) == 0){return i;}}return -1;
}

查找联系人:

void SearchContact(Contact* pc)
{if (pc->sz == 0){printf("通讯录为空\n");return;}char name[NAME_MAX];printf("输入你要查找人的姓名\n");scanf("%s", name);int ret = find(pc, name);if (ret == -1){printf("查无此人\n");return;}printf(" % -20s % -5s % -5s % -20s % -20s\n", "姓名", "年龄", "性别", "电话", "住址");printf(" % -20s % -5d % -5s % -20s % -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)
{if (pc->sz == 0){printf("通讯录为空\n");return;}char name[NAME_MAX];printf("输入你要修改人的姓名\n");scanf("%s", name);int ret = find(pc, name);if (ret == -1){printf("查无此人\n");return;}printf("输入名字\n");scanf("%s", pc->Data[ret].name);printf("输入年龄\n");scanf("%d", &pc->Data[ret].age);printf("输入性别\n");scanf("%s", &pc->Data[ret].sex);printf("输入电话\n");scanf("%s", &pc->Data[ret].tele);printf("输入住址\n");scanf("%s", &pc->Data[ret].addr);printf("输入成功\n");
}

展示联系人:

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

排序:

排序可以按照名字排,或是年龄,亦或是性别等等
这里我们只进行名字的排序,使用方法大同小异(快排)

int cmp_name(void* e1,void* e2)
{return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{qsort(pc->Data, pc->sz, sizeof(PeoInfo), cmp_name);
}

free空间:

最后一步就是释放空间有始有终

void DestoryContact(Contact* pc)
{free(pc);
}

源代码:

con.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"int find(Contact* pc, char name[])
{for (int i = 0; i < pc->sz; i++){if (strcmp(name, pc->Data[i].name) == 0){return i;}}return -1;
}//void InitContact(Contact* pc)
//{
//	assert(pc);
//	pc->sz = 0;
//	memset(pc->Data, 0, sizeof(pc->Data));
//}
void InitContact(Contact* pc)
{assert(pc);pc->sz = 0;pc->capacity = START;PeoInfo* p = (PeoInfo*)malloc(sizeof(PeoInfo) * START);if (p != NULL){pc->Data = p;}else{perror("InitContact->malloc");}
}void DestoryContact(Contact* pc)
{free(pc);
}void AddContact(Contact* pc)
{assert(pc);if (pc->sz == pc->capacity){PeoInfo* str = (PeoInfo*)realloc(pc->Data, sizeof(PeoInfo) * (pc->capacity + START_ADD));if (str != NULL){pc->Data = str;pc->capacity = pc->capacity + 2;printf("增容成功\n");}else{perror("AddContact->realloc");return;}}printf("输入名字\n");scanf("%s", pc->Data[pc->sz].name);printf("输入年龄\n");scanf("%d", &pc->Data[pc->sz].age);printf("输入性别\n");scanf("%s", &pc->Data[pc->sz].sex);printf("输入电话\n");scanf("%s", &pc->Data[pc->sz].tele);printf("输入住址\n");scanf("%s", &pc->Data[pc->sz].addr);printf("输入成功\n");pc->sz++;
}void ShowContact(Contact* pc)
{if (pc->sz == 0){printf("通讯录为空,无需打印\n");return;}printf(" % -20s % -5s % -5s % -20s % -20s\n", "姓名", "年龄", "性别", "电话", "住址");for (int i = 0; i < pc->sz; i++){printf(" % -20s % -5d % -5s % -20s % -20s\n",pc->Data[i].name, pc->Data[i].age, pc->Data[i].sex, pc->Data[i].tele, pc->Data[i].addr);}
}void DelContact(Contact* pc)
{if (pc->sz == 0){printf("通讯录为空,无需删除\n");return;}char name[NAME_MAX];printf("输入你要删除人的姓名\n");scanf("%s", name);int ret = find(pc, name);if (ret == -1){printf("查无此人\n");return;}for (int i = ret; i < pc->sz-1; i++){pc->Data[i] = pc->Data[i + 1];}pc->sz--;
}void SearchContact(Contact* pc)
{if (pc->sz == 0){printf("通讯录为空\n");return;}char name[NAME_MAX];printf("输入你要查找人的姓名\n");scanf("%s", name);int ret = find(pc, name);if (ret == -1){printf("查无此人\n");return;}printf(" % -20s % -5s % -5s % -20s % -20s\n", "姓名", "年龄", "性别", "电话", "住址");printf(" % -20s % -5d % -5s % -20s % -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)
{if (pc->sz == 0){printf("通讯录为空\n");return;}char name[NAME_MAX];printf("输入你要修改人的姓名\n");scanf("%s", name);int ret = find(pc, name);if (ret == -1){printf("查无此人\n");return;}printf("输入名字\n");scanf("%s", pc->Data[ret].name);printf("输入年龄\n");scanf("%d", &pc->Data[ret].age);printf("输入性别\n");scanf("%s", &pc->Data[ret].sex);printf("输入电话\n");scanf("%s", &pc->Data[ret].tele);printf("输入住址\n");scanf("%s", &pc->Data[ret].addr);printf("输入成功\n");
}int cmp_name(void* e1,void* e2)
{return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{qsort(pc->Data, pc->sz, sizeof(PeoInfo), cmp_name);
}

con.h

#pragma once
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30#define START 3
#define START_ADD 2typedef 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;int sz;int capacity;
}Contact;//init
void InitContact(Contact* pc);//add
void AddContact(Contact* pc);//show
void ShowContact(Contact* pc);//del
void DelContact(Contact* pc);//search
void SearchContact(Contact* pc);//modify
void ModifyContact(Contact* pc);//sort
void SortContact(Contact* pc);//destory
void DestoryContact(Contact* pc);

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"enum option
{Exit,Add,Del,Search,Modify,Show,Sort,
};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");printf("**************************\n");
}
int main()
{int input = 0;Contact Con;InitContact(&Con);do{menu();printf("请输入你的选项\n");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:DestoryContact(&Con);printf("你已成功退出\n");break;default:printf("输入错误,请重新输入\n");break;}} while (input);return 0;
}

欢迎纠错与讨论

相关文章:

【C语言】动态通讯录(超详细)

通讯录是一个可以很好锻炼我们对结构体的使用&#xff0c;加深对结构体的理解&#xff0c;在为以后学习数据结构打下结实的基础 这里我们想设计一个有添加联系人&#xff0c;删除联系人&#xff0c;查找联系人&#xff0c;修改联系人&#xff0c;展示联系人&#xff0c;排序这几…...

Mac下docker安装MySQL8.0.34

学习并记录一下如何用docker部署MySQL 在Docker中搜索并下载MySQL8.0.x的最新版本 下载好后&#xff0c;在Images中就可以看到MySQL的镜像了 通过下面的命令也可以查看docker images启动镜像&#xff0c;使用下面的命令就可以启动镜像了docker run -itd --name mysql8.0.34 -…...

基于python编写的excel表格数据标记的exe文件

目录 一、需求&#xff1a; 二、思路&#xff1a; 三、工具 四、设计过程 &#xff08;一&#xff09;根据需要导入相关的图形界面库 &#xff08;二&#xff09;创建图形窗口 &#xff08;三&#xff09;标签设计 &#xff08;四&#xff09;方法按钮设计 &#xff0…...

acwing算法基础之基础算法--高精度加法算法

目录 1 知识点2 模板 1 知识点 大整数 大整数&#xff0c;它们的长度都为 1 0 6 10^6 106。大整数是指长度为 1 0 6 10^6 106的整数。 大整数 - 大整数 大整数 * 小整数 大整数 / 小整数 把大整数存储到向量中&#xff0c;需要考虑高位在前还是低位在前&#xff0c;低位在前…...

openGauss学习笔记-84 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT部署服务器优化:x86

文章目录 openGauss学习笔记-84 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT部署服务器优化&#xff1a;x8684.1 BIOS84.2 操作系统环境设置84.3 网络 openGauss学习笔记-84 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT部署服务器优化&#xff1a;x86 …...

二分查找:34. 在排序数组中查找元素的第一个和最后一个位置

个人主页 &#xff1a; 个人主页 个人专栏 &#xff1a; 《数据结构》 《C语言》《C》《算法》 文章目录 前言一、题目解析二、解题思路1. 暴力查找2. 一次二分查找 部分遍历3. 两次二分查找分别查找左右端点1.查找区间左端点2. 查找区间右端点 三、代码实现总结 前言 本篇文…...

javaee ssm框架项目整合thymeleaf2.0 更多thymeleaf标签用法 项目结构图

创建ssmthymeleaf项目 创建ssmthymeleaf项目参考此文 thymeleaf更多常用标签 <!DOCTYPE html> <html lang"en" xmlns:th"http://www.thymeleaf.org"> <head><meta charset"UTF-8"><title>Title</title> …...

lv7 嵌入式开发-网络编程开发 11 TCP管理与UDP协议

目录 1 TCP管理 1.1 三次握手 1.2 四次挥手 1.3 保活计时器 2 wireshark安装及实验 3.1 icmp协议抓包演示 3.2 tcp协议抓包演示 3 UDP协议 3.1 UDP 的主要特点&#xff1a; 4 练习 1 TCP管理 1.1 三次握手 TCP 建立连接的过程叫做握手。 采用三报文握手&#xff1…...

overleaf在线编辑工具使用教程

文章目录 1 用 orcid注册overleaf获取模板2 使用模板 1 用 orcid注册overleaf获取模板 通常来说&#xff0c;在期刊投稿网站information for author中找template 。下载压缩包后上传到over leaf中。 加入找不到官方模板&#xff0c;用overleaf中的 2 使用模板 .bib文件&…...

Python基础复习【第一弹】【黑马】

本篇是观看b站黑马视频所做的笔记第一弹&#xff0c;为1-98节。 b站-黑马Python # 1.Hello World print("Hello World")# 2.字面量 在代码中&#xff0c;被写下来固定的值# 3.字符串 print("python")# 4.单行注释 # 多行注释""" "&q…...

【Word】公式编辑器中连字符/减号等显示偏长/过长

问题 当公式编辑器中出现连字符的时候&#xff0c;连字符显示偏长&#xff0c;如下图所示&#xff1a; 方法 在连字符的前后加上双引号后即可解决连字符显示偏长的问题。 最终效果对比如下&#xff1a; 结语 Word的公式编辑器中&#xff0c;双引号内部的内容被当做普通…...

架构设计系列4:如何设计高性能架构

在架构设计系列1&#xff1a;什么是架构设计中&#xff0c;我们讲了架构设计的主要目的&#xff0c;是为了解决软件系统复杂度带来的问题&#xff0c;今天我们来聊聊软件系统复杂度的来源之一高性能。 一、什么是高性能架构&#xff1f; 要搞清楚什么是高性能架构&#xff0c…...

1392. 最长快乐前缀

链接&#xff1a; 1392. 最长快乐前缀 题解&#xff1a; class Solution { public:string longestPrefix(string s) {if (s.size() < 0) {return "";}int MOD 1e9 7;// 构建26的n次方&#xff0c;预处理std::vector<long> pow26(s.size());pow26[0] 1…...

【C++设计模式之备忘录模式:行为型】分析及示例

简介 备忘录模式&#xff08;Memento Pattern&#xff09;是一种行为型设计模式&#xff0c;它用于保存和恢复对象的状态。备忘录模式通过将对象的状态封装成一个备忘录&#xff08;Memento&#xff09;&#xff0c;并将备忘录保存在一个管理者&#xff08;Caretaker&#xff…...

数据结构与算法(四):哈希表

参考引用 Hello 算法 Github&#xff1a;hello-algo 1. 哈希表 1.1 哈希表概述 哈希表&#xff08;hash table&#xff09;&#xff0c;又称散列表&#xff0c;其通过建立键 key 与值 value 之间的映射&#xff0c;实现高效的元素查询 具体而言&#xff0c;向哈希表输入一个键…...

FFmpeg 命令:从入门到精通 | ffplay 播放控制选项

FFmpeg 命令&#xff1a;从入门到精通 | ffplay 播放控制选项 FFmpeg 命令&#xff1a;从入门到精通 | ffplay 播放控制选项选项表格图片 FFmpeg 命令&#xff1a;从入门到精通 | ffplay 播放控制选项 选项表格 项目说明Q&#xff0c;Esc退出播放F&#xff0c;鼠标左键双击全…...

代码随想录day59

647. 回文子串 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具有不同开始位置或结束位置的子串&#xff0c;即使是由相同的字符组成&#…...

【小工具-生成合并文件】使用python实现2个excel文件根据主键合并生成csv文件

1 小工具说明 1.1 功能说明 一般来说&#xff0c;我们会先有一个老的文件&#xff0c;这个文件内容是定制好相关列的表格&#xff0c;作为每天的报告。 当下一天来的时候&#xff0c;需要根据新的报表文件和昨天的报表文件做一个合并&#xff0c;合并的时候就会出现有些事新增…...

【论文阅读】An Evaluation of Concurrency Control with One Thousand Cores

An Evaluation of Concurrency Control with One Thousand Cores Staring into the Abyss: An Evaluation of Concurrency Control with One Thousand Cores ABSTRACT 随着多核处理器的发展&#xff0c;一个芯片可能有几十乃至上百个core。在数百个线程并行运行的情况下&…...

网页版”高德地图“如何设置默认城市?

问题&#xff1a; 每次打开网页版高德地图时默认定位的都是“北京”&#xff0c;想设置起始点为目前本人所在城市&#xff0c;烦恼的是高德地图默认的初始位置是北京。 解决&#xff1a; 目前网页版高德地图暂不支持设置起始点&#xff0c;打开默认都是北京&#xff0c;只能将…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向

在人工智能技术呈指数级发展的当下&#xff0c;大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性&#xff0c;吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型&#xff0c;成为释放其巨大潜力的关键所在&…...

电脑桌面太单调,用Python写一个桌面小宠物应用。

下面是一个使用Python创建的简单桌面小宠物应用。这个小宠物会在桌面上游荡&#xff0c;可以响应鼠标点击&#xff0c;并且有简单的动画效果。 import tkinter as tk import random import time from PIL import Image, ImageTk import os import sysclass DesktopPet:def __i…...