【C语言】通讯录的简单实现

通讯录的内容


contect.h 

#pragma once
// 包含头文件
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>// 使用枚举常量定义功能
enum Function
{quit, // 注意这是逗号,不是分号save,addition,delete,search,revise,sort,show // 最后一个没有逗号
};// 人的信息
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
typedef struct People_Information
{char name[NAME_MAX];int age;char sex[SEX_MAX];char tele[TELE_MAX];char addr[ADDR_MAX];
}People; // 通过typedef将struct People_Informtion定义为了People// 通讯录
#define DATA_MAX 1000
typedef struct Contact
{People data[DATA_MAX]; // data数组里面存放的是每个人的信息int sz; // 用于记录通讯录中有几个人的信息
}Contact; // 通过typedef将struct Contact定义为了Contact// 函数声明
// 初始化通讯录
void InitContact(Contact* contact);
// 增加个人信息
void AddContact(Contact* contact);
// 显示通讯录
void ShowContact(const Contact* contact);
// 删除指定信息
void DelContact(Contact* contact);
// 查找指定信息
void SeaContact(const Contact* contact);
// 修改指定联系人
void RevContact(Contact* contact);
// 排序通讯录
void SorContact(Contact* contact);

contact.c 

#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
void menu()
{printf("..............................\n");printf("....0:quit........1:save......\n");printf("....2:addition....3:delete....\n");printf("....4:search......5:revise....\n");printf("....6:sort........7:show......\n");printf("..............................\n");
}
int main()
{// 利用do{}while();循环和switch语句进行多次选择int input;// 进入main函数就要创建通讯录Contact contact; // contact就是一个通讯录// 初始化通讯录InitContact(&contact); // 将通讯录的地址传过去,不仅节省地址,而且可以通过形参改变实参do{// 有哪些功能// 通过菜单将功能展现出来menu();printf("请输入功能序号:");scanf("%d", &input);switch (input){// 通过枚举常量定义会更直观case quit:printf("退出通讯录!\n");break;case save:break;case addition:AddContact(&contact);break;case delete:DelContact(&contact);break;case search:SeaContact(&contact);break;case revise:RevContact(&contact);break;case sort:SorContact(&contact);break;case show:ShowContact(&contact);break;default:printf("无此序号,请重新输入。\n");}} while (input);return 0;
}

test.c 

#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"// 初始化通讯录
void InitContact(Contact* contact)
{assert(contact);// contact->data = 0; // contact->data表示的是首元素地址// 初始化一块连续的内存空间可以使用memsetmemset(contact->data, 0, sizeof(contact->data));contact->sz = 0;
}// 增加个人信息
void AddContact(Contact* contact)
{assert(contact);// 进入函数进行判断if (contact->sz == DATA_MAX){printf("通讯录已满,无法增加个人信息!\n");return;}// 没有满则进行增加个人信息printf("请输入姓名:");scanf("%s", &(contact->data[contact->sz].name));printf("请输入年龄:");scanf("%d", &(contact->data[contact->sz].age));printf("请输入性别:");scanf("%s", &(contact->data[contact->sz].sex));printf("请输入电话:");scanf("%s", &(contact->data[contact->sz].tele));printf("请输入地址:");scanf("%s", &(contact->data[contact->sz].addr));// 增加完一条信息后sz要加1contact->sz++;printf("增加成功!\n");
}// 显示通讯录
void ShowContact(const Contact* contact)
{assert(contact);// 进入函数进行判断if (contact->sz == 0){printf("通讯录为空!\n");return;}// 显示信息// 标题printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "住址");for (int i = 0; i < contact->sz; i++){printf("%-10s %-5d %-5s %-12s %-30s\n",contact->data[i].name,contact->data[i].age,contact->data[i].sex,contact->data[i].tele,contact->data[i].addr);}
}// 通过名字查找联系人下标
int FindByName(const Contact* contact, char* name)
{assert(contact);for (int i = 0; i < contact->sz; i++){if (strcmp(contact->data[i].name, name) == 0){// 找到返回数组下标return i;}}return -1;
}// 删除指定信息
void DelContact(Contact* contact)
{assert(contact);char name[NAME_MAX];if (contact->sz == 0){printf("通讯录为空!\n");return;}// 通过名字查找printf("请输入要删除人的姓名:");scanf("%s", name);int ret = FindByName(contact, name);// 没找到if (ret == -1){printf("要删除的人不存在!\n");}// 找到了// 删除这个人(其实是覆盖)for (int i = ret; i < contact->sz - 2; i++) // 减2这里不是很懂{contact->data[i] = contact->data[i + 1];}contact->sz--;printf("删除成功!\n");// 最后一个直接覆盖当前这个// 结构体类型相同可以直接赋值/*contact->data[ret] = contact->data[contact->sz];contact->sz--;*/
}// 查找指定信息
void SeaContact(const Contact* contact)
{assert(contact);char name[NAME_MAX];if (contact->sz == 0){printf("通讯录为空!\n");return;}// 通过名字查找printf("请输入要修改人的姓名:");scanf("%s", name);int ret = FindByName(contact, name);// 没找到if (ret == -1){printf("要查找的人不存在!\n");}// 找到了// 显示出来printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "住址");printf("%-10s %-5d %-5s %-12s %-30s\n",contact->data[ret].name,contact->data[ret].age,contact->data[ret].sex,contact->data[ret].tele,contact->data[ret].addr);
}// 修改指定联系人
void RevContact(Contact* contact)
{assert(contact);char name[NAME_MAX];if (contact->sz == 0){printf("通讯录为空!\n");return;}// 通过名字修改printf("请输入要修改人的姓名:");scanf("%s", name);int ret = FindByName(contact, name);// 没找到if (ret == -1){printf("要修改的人不存在!\n");}// 找到了// 修改printf("请输入姓名:");scanf("%s", &(contact->data[contact->sz].name));printf("请输入年龄:");scanf("%d", &(contact->data[contact->sz].age));printf("请输入性别:");scanf("%s", &(contact->data[contact->sz].sex));printf("请输入电话:");scanf("%s", &(contact->data[contact->sz].tele));printf("请输入地址:");scanf("%s", &(contact->data[contact->sz].addr));printf("修改成功!\n");
}int compare_name(const void* x, const void* y)
{return strcmp((char*)x, (char*)y);
}// 排序通讯录
void SorContact(Contact* contact)
{assert(contact);if (contact->sz == 0){printf("通讯录为空!\n");return;}// 排序通讯录qsort(contact, contact->sz, sizeof(contact->data[0]), compare_name);// 显示信息// 标题printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "住址");for (int i = 0; i < contact->sz; i++){printf("%-10s %-5d %-5s %-12s %-30s\n",contact->data[i].name,contact->data[i].age,contact->data[i].sex,contact->data[i].tele,contact->data[i].addr);}
}

  注意:

传址还是传值

通讯录初始化涉及到传递参数,那我们到底是传址还是传值呢?

InitContact(&contact);  // 传递的是地址

// 传址:因为更节省内存空间(地址只占4/8个字节),而且可以通过形参来改变实参;

// 传值:所需的内存空间更大,并且改变形参并不会影响实参;


memset初始化连续空间

// 这里使用的是memset初始化数组,也可以通过循环将数组一个一个制成0;

memset的用法

 


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

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

相关文章

C++项目:【负载均衡式在线OJ】

文章目录 一、项目介绍 二、技术栈与开发环境 1.所用技术: 2.开发环境&#xff1a; 三、项目演示 1.运行代码 2.进入项目首页 3.题目列表 4.点击具体一道题 5.编辑代码并提交 四、项目思维导图 五、项目宏观结构 六、Comm公共模块 1.日志工具log.hpp 2.其他工具…

Excel恢复科学技术法显示的数据

Excel中输入位数较大的数据时&#xff0c;软件会自动使用科学计数法显示。很多时候并不需要这样的计数格式&#xff0c;所以需要把它转变为普通的数字格式 操作方法 选中单元格/列/行》右键》设置单元格式 在打开的窗口中&#xff0c;切换到“数字”选项卡&#xff0c;点击“自…

Mybatis用Byte[]存图片,前端显示图片

前端页面 static下 也就是说byte[] 转成JSON字符串后,和用BASE64编码后是一摸一样的,那么SpringBoot会自动将实体类转JSON字符串,也就是说根本不需要Base64编码 注意:两个值并非一摸一样,一个多了个双引号 byte[]的值前后有个双引号 有一点点区别 一个有双引号,一个没有…

【LeetCode刷题(数据结构)】:对称二叉树

给你一个二叉树的根节点 root 检查它是否轴对称 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false 提示&#xff1a; 树中节点数目在范围 [1, 1000] 内 -100 < Node.val < 100 对称二叉…

nginx的location的优先级和匹配方式

nginx的location的优先级和匹配方式 在http模块中有server&#xff0c;server模块中有location&#xff0c;location匹配的是uri 在一个server中&#xff0c;会有多个location&#xff0c;如何来确定匹配哪个location niginx的正则表达式 ^ 字符串的起始位置 $ 字符串的…

Jenkins+Gitlab+Docker(Dockerfile)部署

Docker部署运行 ​ 上一篇内容中使用Jenkins(运行服务器)Gitlab(代码存储库)Webhook(网络钩子)的方式部署运行我们的项目。需要我们在服务器上做好很多相关的环境配置及依赖。 ​ 那么假如有这样一个场景&#xff1a;需要把不同技术栈的项目部署到同一台服务器上运行。比如PH…

7.定时器

定时器资源 CC2530有四个定时器TIM1~TIM4和休眠定时器 TIM1 定时器1 是一个独立的16 位定时器&#xff0c;支持典型的定时/计数功能&#xff0c;比如输入捕获&#xff0c;输出比较和PWM 功能。定时器有五个独立的捕获/比较通道。每个通道定时器使用一个I/O 引脚。定时器用于…

组件协作模式

二、组件协作模式 组件协作模式概念1、模板方法模式&#xff08;Template_Method&#xff09;模式定义动机(Motivation)具体代码举例实现要点总结 2、策略模式&#xff08;Strategy&#xff09;3、观察者模式&#xff08;Observer/Event&#xff09; 组件协作模式概念 现代软件…

智能警用装备管理系统-科技赋能警务

警用物资装备管理系统&#xff08;智装备DW-S304&#xff09;是依托互云计算、大数据、RFID技术、数据库技术、AI、视频分析技术对警用装备进行统一管理、分析的信息化、智能化、规范化的系统。 &#xff08;1&#xff09;感知智能化 装备感知是整个方案的基础&#xff0c;本方…

Python爬虫(二十三)_selenium案例:动态模拟页面点击

本篇主要介绍使用selenium模拟点击下一页&#xff0c;更多内容请参考:Python学习指南 #-*- coding:utf-8 -*-import unittest from selenium import webdriver from selenium.webdriver.common.keys import Keys from bs4 import BeautifulSoup import timeclass douyuSelenium…

Linemod算法研究

转载&#xff0c;这篇博客写的比较详细&#xff0c;分析也到位. https://www.cnblogs.com/aoru45/p/16810996.html

【Windows日志】记录系统事件的日志

文章目录 一、概要二、Windows日志介绍 2.1 应用程序日志2.2 系统日志2.3 安全日志 三、查看与分析日志四、常见事件ID 4.1 登录事件 4.1.1 4624登陆成功4.1.2 4625登陆失败 4.2 特权使用4.3 账户管理事件4.4 账户登录事件5.2 事件ID汇总 一、概要 Windows主要有以下三类日…

【Android知识笔记】图片专题(BitmapDrawable)

如何计算一张图片的占用内存大小? 注意是占用内存,不是文件大小可以运行时获取重要的是能直接掌握计算方法基础知识 Android 屏幕像素密度分类: (其实还有一种 ldpi = 120,不过这个已经绝种了,所以最低的只需关心mdpi即可) 上表中的比例为:m : h : xh : xxh: xxxh = …

自动驾驶学习笔记(四)——变道绕行仿真

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《2023星火培训【感知专项营】》免费课程—>传送门 文章目录 前言 仿真内容 启动Dreamview 开启Sim…

如何降低海康、大华等网络摄像头调用的高延迟问题(一):海康威视网络摄像头的python sdk使用(opencv读取sdk流)

目录 1.python sdk使用 1.海康SDK下载 2.opencv读取sdk流 先说效果&#xff0c;我是用的AI推理的实时流&#xff0c;延迟从高达7秒降到小于1秒 如果觉得这个延迟还不能接受&#xff0c;下一章&#xff0c;给大家介绍点上不得台面的小方法 SDK&#xff08;Software Developme…

《3D 数学基础》几何检测-最近点

目录 1. 直线上的最近点 2. 射线上的最近点 3. 点到平面的距离 4. 圆或球上的最近点 5. AABB上的最近点 1. 直线上的最近点 q是距离q的最近点&#xff0c;也就是q在直线上的投影。 其中p是直线上的点&#xff08;向量表示&#xff09;&#xff0c;n是直线的法向量&#x…

【苍穹外卖 | 项目日记】第四天

前言&#xff1a; 今天状态还可以&#xff0c;既有自己实战独立写接口&#xff0c;又听了课&#xff0c;学习了新的知识 目录 前言&#xff1a; 今日完结任务&#xff1a; 今日收获&#xff1a; 实现店铺状态接口 杂项知识点&#xff1a; 总结&#xff1a; 今日完结任务…

2023.10.14 培训总结

培训内容 数字模型联合仿真及集成测试技术 MBSE(Model-Based-System-Engiaeering&#xff09; 参数化建模参数化仿真 产生的疑问 支持面向对象支持CAE CFD工具优化工具 飞机的业务功能 开发分布式架构 新技术 WSDL协议DDS 发布/订阅SAOPCORBA 明显开发者 Chris Garrett 美…

【基于Kmeans、Kmeans++和二分K均值算法的图像分割】数据挖掘实验三

文章目录 Ⅰ、项目任务要求任务描述&#xff1a;主要任务要求&#xff1a; II、实现过程数据集描述实现描述具体实现过程 III、完整代码代码①代码② Ⅰ、项目任务要求 任务描述&#xff1a; 图像分割是图像处理和计算机视觉中重要的一环&#xff0c;在实际生活中得到了广泛的…

P1433 吃奶酪

#include <iostream> #include <cmath> using namespace std; #define M 15 #define S(n) ((n) * (n)) double indx[M 5], indy[M 5], ans 0, sum 0;//坐标数组&#xff0c;从下标为1开始记录 int n, vis[M 5] { 0 };//vis数组&#xff0c;选过的数字标记为1…