【c语言】通讯录(静态)

小张刚学习完结构体,枚举,联合相关的知识,实践实践,写一个通讯录呗!


通讯录的功能

1.通讯录可存放100的信息
2.信息的内容姓名,性别,年龄,电话,地址
3.支持增加联系人
4.支持删除联系人
5.支持查找联系人
6.支持修改联系人
7.支持排序联系人
8.打印数据

文件类型

test.c(测试通讯录相关功能)
contanct.c(通讯录功能的实现)
contanct.h(声明)

一个人信息在结构体中定义

struct peoinfo {
char name[20];姓名
char sex[5];性别
int age;年龄
char tel[12];电话
char addr[20];};地址

为了方便代码的可读性,我们在宏里面定义每个字符串数组的长度,修改如下

struct peoinfo {
char name[MAX_NAME];姓名
char sex[MAX_SEX];性别
int age;年龄
char tel[MAX_TEL];电话
char addr[MAX_ADDR];地址};

宏定义如下

#define MAX_NAME 20
#define MAX_SEX 6
#define MAX_TEL 12
#define MAX_ADDR 20
#define MAX 1000

通讯录用结构体

typedef struct pp{
struct peoinfo arr[MAX];
int sz;}pp;
用typedef将通讯录结构体类型重命名为pp,方便操作
在这里插入图片描述

菜单函数menu

void menu()
{printf("#######################################\n");printf("#*********    1.add    ***************#\n");printf("#*********    2.del    ***************#\n");printf("#*********    3.search ***************#\n");printf("#*********    4.modify ***************#\n");printf("#*********    5.sort   ***************#\n");printf("#*********    6.print  ****************#\n");printf("##########    0.exit   ################\n");}

选择功能函数test()

void test()
{pp pro;//定义一个通讯录
Initcontanct(&pro);//通讯录初始化,具体在下面
int input;do {menu();scanf_s("%d", &input);switch (input){case 1:Addcontanct(&pro);break;case 2:Delcontanct(&pro);break;case 3:findcontanct(&pro);break;case 4:modifycontanct(&pro);break;case 5:Sortcontanct(&pro);break;case 6:Printcontanct(&pro);break;case 7:break;case 0:printf("退出通讯录\n");break;default:printf("输入错误,请重新输入\n");break;}} while (input);
}

switch语句中的case1,2,3,4不好对应功能,为了提高代码可读性,我们可以定义一个枚举类型
enum opion
{
EXIT,//他的值为0,下面依次1,2,3,4,5,6
ADD,
DEL,
SEARCH,
MODIFY,
SORT,
PRINT
};

test()函数修改

void test()
{pp pro;
Initcontanct(&pro);
int input;do {menu();scanf_s("%d", &input);switch (input){case  ADD:Addcontanct(&pro);break;case DEL:Delcontanct(&pro);break;case SEARCH:findcontanct(&pro);break;case MODIFY:modifycontanct(&pro);break;case SORT:Sortcontanct(&pro);break;case PRINT:Printcontanct(&pro);break;case EXIT:printf("退出通讯录\n");break;default:printf("输入错误,请重新输入\n");break;}} while (input);
}

初始化通讯录函数

作用:将sz初始化为0,将struct peoinfo arr[]初始化为0,防止初始化为随机值,memset函数可以将从哪个地址开始多少个字节置为你想置的数,第一个参数是从哪个地址开始重置,第二个参数是置为什么,第三个参数是置多少个字节,memset头文件stdlib.h

void Initcontanct(pp*p)
{p->sz = 0;memset(p->arr, 0, sizeof(p->arr));
}

结构体指针p接收通讯录的地址&pro

添加联系人

void Addcontanct(pp* p)
{if (p->sz == 1000){printf("通讯录已经存满\n");return;}printf("请输入姓名\n");scanf("%s",p->arr[p->sz].name);printf("请输入性别\n");scanf("%s",p->arr[p->sz].sex);printf("请输入年龄\n");scanf("%d",&(p->arr[p->sz].age));printf("请输入电话\n");scanf("%s",p->arr[p->sz].tel);printf("请输入地址\n");scanf("%s",p->arr[p->sz].addr);p->sz++;printf("录入成功\n");}

注意年龄不是数组,scanf的时候必须加&取地址符,每次添加1个,p->sz+1;如果==1000,表示已经存满,return直接跳出,不再进行添加过程

打印数据函数

void Printcontanct(pp* p)
{int i = 0;printf("******************************************************\n");printf("%-10s %-5s %-5s %-12s %-20s\n", "姓名","性别","年龄","电话","地址");printf("******************************************************\n");for (i = 0; i < p->sz; i++){printf("%-10s %-5s %-5d %-12s %-20s\n", p->arr[i].name, p->arr[i].sex, p->arr[i].age, p->arr[i].tel, p->arr[i].addr);printf("******************************************************\n");}
}

注意:为了能打印更加美观,打印采用左对齐,打印*的每行为了将用户分开,更好看一点,循环遍历通讯录每个成员,将其打印,每个用户打印完了,记得换行

删除联系人

void Delcontanct(pp* p)
{char name[MAX_NAME];printf("请输入要删除朋友的名字\n");scanf("%s",name);if (find(p, name) == -1){printf("查无此人\n");}else{int k = find(p, name);for (int j = k; j < p->sz - 1; j++){p->arr[j] = p->arr[j + 1];}p->sz--;printf("删除成功\n");}
}

查找函数find()

int find(pp* p, char name[])
{int i = 0;for (int i = 0; i < p->sz; i++){if (!strcmp(p->arr[i].name, name))return i;}return -1;
}

注意查找函数的功能是遍历通讯录,如果有此人,返回这个人数组的下标,如果没有此人,返回-1;使用strcmp比较函数记得头文件string.h,删除一个人,输入要删除的那个人的名字,将输入名字的数组地址和通讯录的地址传给find()函数,调用find()函数遍历通讯录,如果没有此人,find()函数返回-1;打印查无此人,否则用k接收其要删除用户的下标,将k下标的用户删除,然后将后面的依次向前挪,删除一个,对应的p->sz- -
在这里插入图片描述

查找联系人

void findcontanct(pp* p)
{char name[MAX_NAME];if (p->sz == 0){printf("通讯录为空\n");return;}printf("请输入要查找朋友的名字\n");scanf("%s", name);if (find(p, name) == -1){printf("查无此人\n");}else{int k = find(p, name);printf("******************************************************\n");printf("%-10s %-5s %-5s %-12s %-20s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%-10s %-5s %-5d %-12s %-20s\n", p->arr[k].name, p->arr[k].sex, p->arr[k].age, p->arr[k].tel, p->arr[k].addr);printf("******************************************************\n");}
}

注意:查找基本和删除类似,输入名字后,需要调用find函数查找对应名字的下标,返回-1;表示没找到,如果返回了下标将这个下标对应的信息打印出来

修改联系人信息

void modifycontanct(pp* p)
{char name[MAX_NAME];printf("请输入修改朋友的名字\n");scanf("%s", name);if (find(p, name) == -1){printf("查无此人\n");}else{int k = find(p, name);printf("请输入要修改朋友的信息\n");printf("修改性别->");scanf("%s", p->arr[k].sex);printf("修改年龄->");scanf("%d", &(p->arr[k].age));printf("修改电话->");scanf("%s", p->arr[k].tel);printf("修改地址->");scanf("%s", p->arr[k].addr);printf("修改成功\n");}
}

注意修改联系人信息还是需要find()函数查找联系人名字,find()函数返回其下标,修改的时候,直接对下标对应的用户进行操作,年龄不是数组,scanf需要加&取地址符

排序联系人(年龄排序)

void Sortcontanct(pp* p)
{int i = 0;for (int i = 0; i < p->sz-1; i++){for (int j = 0; j < p->sz - i-1; j++){if (p->arr[j].age > p->arr[j + 1].age){int tmp = p->arr[j].age;p->arr[j].age = p->arr[j + 1].age;p->arr[j + 1].age = tmp;char name[MAX_NAME];strcpy(name, p->arr[j].name);strcpy(p->arr[j].name, p->arr[j+1].name);strcpy(p->arr[j + 1].name, name);char sex[MAX_SEX];strcpy(sex, p->arr[j].sex);strcpy(p->arr[j].sex, p->arr[j + 1].sex);strcpy(p->arr[j + 1].sex, sex);char tel[MAX_TEL];strcpy(tel, p->arr[j].tel);strcpy(p->arr[j].tel, p->arr[j + 1].tel);strcpy(p->arr[j + 1].tel, tel);char addr[MAX_ADDR];strcpy(addr, p->arr[j].addr);strcpy(p->arr[j].addr, p->arr[j + 1].addr);strcpy(p->arr[j + 1].addr, tel);}}
}printf("按年龄排序成功,快去打印吧\n");
}

注意利用冒泡排序按年龄从小到大排序,将年龄交换的同时,需要将两个人的名字,性别,电话,住址也进行交换,字符串数组,我们采用strcpy,strcpy头文件string.h,交换的思想也是用到了三个数交换的灵感

但是我的上一篇讲的是qsort排序,我们也可以用qsort进行排序,拒绝屎山代码

修改:排序联系人

int int_cmp_age(const void* p1, const void* p2)//按年龄比较
{return ((struct peoinfo*)p1)->age - ((struct peoinfo*)p2)->age;
}
void Sortcontanct(pp* p)
{qsort(p->arr, p->sz, sizeof(peoinfo), int_cmp_age);printf("按年龄排序成功,快去打印吧\n");
}

整体代码展示
contanct.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_NAME 20
#define MAX_SEX 6
#define MAX_TEL 12
#define MAX_ADDR 20
#define MAX 1000
enum opion
{EXIT,ADD,DEL,SEARCH,MODIFY,SORT,PRINT
};
typedef struct peoinfo {char name[MAX_NAME];char sex[MAX_SEX];int age;char tel[MAX_TEL];char addr[MAX_ADDR];}peoinfo;typedef struct pp{struct peoinfo arr[MAX];int sz;}pp;
void Initcontanct(pp*p);
void Addcontanct(pp* p);
void Printcontanct(pp* p);
void Delcontanct(pp* p);
void findcontanct(pp* p);
void modifycontanct(pp* p);
void Sortcontanct(pp* p);

contanct.c

#include"contanct.h"
void Initcontanct(pp*p)
{p->sz = 0;memset(p->arr, 0, sizeof(p->arr));
}
void Addcontanct(pp* p)
{if (p->sz == 1000){printf("通讯录已经存满\n");return;}printf("请输入姓名\n");scanf("%s",p->arr[p->sz].name);printf("请输入性别\n");scanf("%s",p->arr[p->sz].sex);printf("请输入年龄\n");scanf("%d",&(p->arr[p->sz].age));printf("请输入电话\n");scanf("%s",p->arr[p->sz].tel);printf("请输入地址\n");scanf("%s",p->arr[p->sz].addr);p->sz++;printf("录入成功\n");}
void Printcontanct(pp* p)
{int i = 0;printf("******************************************************\n");printf("%-10s %-5s %-5s %-12s %-20s\n", "姓名","性别","年龄","电话","地址");printf("******************************************************\n");for (i = 0; i < p->sz; i++){printf("%-10s %-5s %-5d %-12s %-20s\n", p->arr[i].name, p->arr[i].sex, p->arr[i].age, p->arr[i].tel, p->arr[i].addr);printf("******************************************************\n");}
}
int find(pp* p, char name[])
{int i = 0;for (int i = 0; i < p->sz; i++){if (!strcmp(p->arr[i].name, name))return i;}return -1;
}
void Delcontanct(pp* p)
{char name[MAX_NAME];printf("请输入要删除朋友的名字\n");scanf("%s",name);if (find(p, name) == -1){printf("查无此人\n");}else{int k = find(p, name);for (int j = k; j < p->sz - 1; j++){p->arr[j] = p->arr[j + 1];}p->sz--;printf("删除成功\n");}
}
void findcontanct(pp* p)
{char name[MAX_NAME];if (p->sz == 0){printf("通讯录为空\n");return;}printf("请输入要查找朋友的名字\n");scanf("%s", name);if (find(p, name) == -1){printf("查无此人\n");}else{int k = find(p, name);printf("******************************************************\n");printf("%-10s %-5s %-5s %-12s %-20s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%-10s %-5s %-5d %-12s %-20s\n", p->arr[k].name, p->arr[k].sex, p->arr[k].age, p->arr[k].tel, p->arr[k].addr);printf("******************************************************\n");}
}
void modifycontanct(pp* p)
{char name[MAX_NAME];printf("请输入修改朋友的名字\n");scanf("%s", name);if (find(p, name) == -1){printf("查无此人\n");}else{int k = find(p, name);printf("请输入要修改朋友的信息\n");printf("修改性别->");scanf("%s", p->arr[k].sex);printf("修改年龄->");scanf("%d", &(p->arr[k].age));printf("修改电话->");scanf("%s", p->arr[k].tel);printf("修改地址->");scanf("%s", p->arr[k].addr);printf("修改成功\n");}
}
int int_cmp_age(const void* p1, const void* p2)//按年龄比较
{return ((struct peoinfo*)p1)->age - ((struct peoinfo*)p2)->age;
}
void Sortcontanct(pp* p)
{qsort(p->arr, p->sz, sizeof(peoinfo), int_cmp_age);printf("按年龄排序成功,快去打印吧\n");
}

test.c

#include"contanct.h"
void menu()
{printf("#######################################\n");printf("#*********    1.add    ***************#\n");printf("#*********    2.del    ***************#\n");printf("#*********    3.search ***************#\n");printf("#*********    4.modify ***************#\n");printf("#*********    5.sort   ***************#\n");printf("#*********    6.print  ****************#\n");printf("##########    0.exit   ################\n");}
void test()
{pp pro;
Initcontanct(&pro);
int input;do {menu();scanf_s("%d", &input);switch (input){case  ADD:Addcontanct(&pro);break;case DEL:Delcontanct(&pro);break;case SEARCH:findcontanct(&pro);break;case MODIFY:modifycontanct(&pro);break;case SORT:Sortcontanct(&pro);break;case PRINT:Printcontanct(&pro);break;case EXIT:printf("退出通讯录\n");break;default:printf("输入错误,请重新输入\n");break;}} while (input);
}void main()
{test();}

结果展示
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
存在的问题大家可以指出,后面会和大家分享动态通讯录,大家多多支持,还有就是我访问终于破2000了哈哈哈哈哈
彩蛋
在这里插入图片描述
今天分享就到这里,下一篇见

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

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

相关文章

【LeetCode】1572.矩阵对角线元素的和

题目 给你一个正方形矩阵 mat&#xff0c;请你返回矩阵对角线元素的和。 请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。 示例 1&#xff1a; 输入&#xff1a;mat [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;25 解释&#xff1a;对角线的和为&a…

零基础看懂免费开源的Stable Diffusion

文章目录 前言Diffusion模型推理过程训练过程 Stable Diffusion模型参考 前言 前面一篇文章主要讲了扩散模型的理论基础&#xff0c;还没看过上篇的小伙伴可以点击查看&#xff1a;DDPM理论基础。这篇我们主要讲一下一经推出&#xff0c;就火爆全网的Stable Diffusion模型。St…

SpringBoot 整合JDBC

SpringData简介 Sping Data 官网&#xff1a;https://spring.io/projects/spring-data数据库相关的启动器 &#xff1a;可以参考官方文档&#xff1a;https://docs.spring.io/spring-boot/docs/2.6.5/reference/htmlsingle/#using-boot-starter 整合JDBC 创建测试项目测试数据…

Vue [Day7] 综合案例

核心概念回顾 state&#xff1a;提供数据 getters&#xff1a;提供与state相关的计算属性 mutations&#xff1a;提供方法&#xff0c;用于修改state actions&#xff1a;存放异步操作 modules&#xff1a;存模块 功能分析 https://www.npmjs.com/package/json-server#ge…

BGP实验

题目 IP地址配置 172.16.X.0/24为模拟用户环回接口接口 172.16.7.X/32为BGP邻居关系建立的环回接口 R1&#xff1a; R2&#xff1a; R3&#xff1a; R4&#xff1a; R5&#xff1a; R6&#xff1a; R7&#xff1a; R8&#xff1a; BGP邻居关系建立、宣告和反射器、联邦配置 R…

使用阿里云服务器部署和使用GitLab

本文阿里云百科分享使用阿里云服务器部署和使用GitLab&#xff0c;GitLab是Ruby开发的自托管的Git项目仓库&#xff0c;可通过Web界面访问公开的或者私人的项目。本教程介绍如何部署和使用GitLab。 目录 准备工作 部署GitLab环境 使用GitLab 登录GitLab 生成密钥对文件并…

Tomcat部署与优化

目录 一、Tomcat介绍 二、Tomcat核心组件 1、web容器&#xff1a;完成web服务器的功能&#xff0c;web应用 2、servlet容器&#xff1a;名字&#xff1a;catalina&#xff0c;处理servlet代码 servlet的功能 3、jsp&#xff1a;jsp动态页面翻译成servlet代码&#xff0c;用…

20.5 HTML 媒体

1. video视频标签 video视频标签: 是HTML中用于在网页上嵌入视频的元素.常用的视频标签属性: - src属性: 指定视频文件的URL地址. - controls属性: 用于显示视频播放控件(如播放按钮, 进度条等), 使用户能够控制视频的播放. - width和height: 指定视频的宽度和高度. - autopla…

CMake语法中的PUBLIC、PRIVATE、INTERFACE关键字含义

在CMake语法中&#xff0c;经常见到PUBLIC、PRIVATE、INTERFACE关键字&#xff0c;它们是什么意思呢&#xff1f;下面举例说明。 如上图,说明如下&#xff1a; RIVATE&#xff1a;私有的。生成 libhello-world.so时&#xff0c;只在 hello_world.c 中包含了 hello.h&#xff0…

音视频研发分享:关键帧截图+wasm快照--我又做了一件有益于社会的事情

音视频研发分享&#xff1a;关键帧截图wasm快照--我又做了一件有益于社会的事情 简单的一个视频设备快照功能到底有多费事多费电&#xff1f;新的方法有方法&#xff01; 省了多少电&#xff1f; 简单的一个视频设备快照功能到底有多费事多费电&#xff1f; 以前&#xff0c;我…

【C# 基础精讲】构造函数和析构函数

构造函数&#xff08;Constructor&#xff09;和析构函数&#xff08;Destructor&#xff09;是面向对象编程中的两个重要概念&#xff0c;它们分别用于在对象创建和销毁的时候执行特定的操作。这两个函数在C#以及其他面向对象编程语言中都具有重要的作用&#xff0c;用于初始化…

Ajax-AJAX请求的不同发送方式

&#x1f954;&#xff1a;你一定能成为想要成为的人 发送AJAX请求不同方式 发送AJAX请求不同方式1、jQuery发送AJAX请求2、axios发送AJAX请求&#xff08;重点&#xff09;3、fetch发送AJAX请求 发送AJAX请求不同方式 1、jQuery发送AJAX请求 首先需要jquery的js文件&#xf…