C语言实战项目---通讯录

项目要实现的内容:能够存放100个人的通讯录程序,能够实现联系人数据的存储,删除,修改,查找,展示联系人的信息。

所需知识:结构体,指针,函数.................

废话不多说,咱们直接开始

1.界面的打印

我们需要一个可以执行选择的界面提供用户选择不同的数字来执行不同的程序。

我们在这里提前声明一下:

1.add(增加联系人的信息)

2.deal(删除联系人的信息)

3.search(查找联系人的信息)

4.modify(修改联系人的信息)

5.show(展示联系人的信息)

那我们现在就开始

void menu()
{printf("************************************************\n");printf("***      1. add        2.deal                   *\n");printf("***      3.search      4.modify                 *\n");printf("***      5.show        6.exit                   *\n");printf("*************************************************\n");}

这个就是我们的菜单

菜单的打印很简单就使用一个 printf一个函数,我们接着继续把选择语句写出来 在我们写之前我们来思考一个问题(我们一共有六个可供选择的程序接口,那么我们该如何分辨我们选择执行的程序不会出错呢?)其实有个办法就是使用  枚举常量来实现。

大家来看不懂枚举的大家看我往期博客 我把地址放在这 CSDN

enum Option
{exit,       //退出信息管理系统   0add,        //增加信息管理系统   1deal,       //删除信息管理系统   2search,     //搜索信息管理系统   3 modify,     //修改信息管理系统   4show,       //展示信息管理系统   5};

这样我们就可以清楚的知道我们所选择的每个选项,所要执行的程序。

我们来实现选择,选择不同的数字来执行不同的程序。原理很简单,使用一个do while(循环)

嵌套一个Switch语句。

int main()
{int input = 0;do{menu();printf("请选择\n");scanf_s("%d", &input);switch (input){case exit:printf("退出信息管理系统");break;case add:ADDContact(&con);break;case deal:DEALContact(&con);break;case search:SearchContact(&con);break;case modify:ModifyCkontact(&con);break;case show:SHOWContact(&con);break;default:printf("请重新选择");break;}} while (input);return 0;
}

大家请看,当我们使用了枚举类型之后我们的选择都具象化了。

最基本的菜单和界面操作完成后我们来实现各种接口。

2.实现接口的预操作

2.1 创建结构体变量

我们创建的结构体是用来保存联系人的信息,其中包含联系人的“姓名”“性别”“地址”“年龄”“电话”

我们使用typedef 来将结构体命名为 peopleinform(people--人,inform--信息)

typedef struct peopleinform //设置人的信息
{char name[20];char sex[5];char adrs[30];int age;char tele[20];}peopleinform;

这是一个人的信息,但是我们的通讯录要实现的是100个人的信息,那么我们就需要再创建一个结构体来实现。

typedef struct Contact
{peopleinform date[100]; //用来存放数据int sz; //用来记录的是信息管理系统中存放信息的个数}Contact;

以上就是我们预处理,那么我们来实现接口。

 3.初始化联系人信息管理系统

再实现联系人数据增加的前提是我们要初始化date,sz,保证它们中没有任何的数据,以免对我们后续联系人数据的增加产生干扰。

我们初始化有两个办法,一个就是使用memset函数之间初始化

                                       二是使用循环来实现。

                                       由于C语言提供了函数,我们就使用这个。

//初始化信息管理系统
void IntiContact(Contact* pc);
void IntiContact(Contact* pc)
{assert(pc);pc->sz = 0;memset(pc->date, 0, sizeof(pc->date));/*memset是一个初始化函数,作用是将某一块内存中的全部设置为指定的值s指向要填充的内存块。c是要被设置的值。n是要被设置该值的字符数。返回类型是一个指向存储区s的指针*/}

关键点拨:我们使用指针类型的原因,大家都知道传参。一个是传值,一个是传地址。

为什么在这里我们选择传地址(完了使用指针访问地址)???

在此之前我还有一篇博客(函数栈帧的创建与销毁)地址放在这里--CSDN 感兴趣的可以去详细了解。

解释:形参是实参的一份临时拷贝,如果单纯的传值,我们访问的时候是不需要修改的。

传值-----(B是一个中间人我是C需要把一份东西给A,我把东西给B,B给A),但是当我要找到A时,我就需要A的地址了。

传地址----(B这个中间人直接把A的地址给了我,我直接去找A,对A里面的值进行修改)。

因为我们需要对   date 和 sz 的内部的值进行修改所以 我们使用的是传地址。

初始化完成之后我们就可以来实现各种各样的接口了。

4.联系人数据的增加

//增加学生信息的信息
void ADDContact(Contact* pc);

这个过程是相对比较简单的使用printf函数和scanf函数即可。

报错:scanf函数我们在使用的时候,如果我们在后面不加上具体的数量,大小会报错。

void ADDContact(Contact* pc)
{assert(pc);//先判断信息管理系统有没有空间支持增加if (pc->sz == 100){printf("信息管理系统已满无法增加\n");return;}//如果没有返回就增加一个人的信息printf("请输入名字");scanf_s("%s", pc->date[pc->sz].name, 20);printf("请输入年龄");scanf_s("%d", &(pc->date[pc->sz].age));printf("请输入性别");scanf_s("%s", pc->date[pc->sz].sex, 5);printf("请输入电话");scanf_s("%s", pc->date[pc->sz].tele, 20);printf("请输入地址");scanf_s("%s", pc->date[pc->sz].adrs, 30);//由于信息录入完成所以增加了一个人的信息pc->sz++;printf("增加成功\n");}

 程序跑起来效果就是这样。

5.联系人数据的查看

由于“删除”“修改”“查找”都需要使用遍历查找,所以我们把它们放在后面,我们先来实现查看接口。

//查看学生信息的信息
void SHOWContact(Contact* pc);

相较于后面几个接口这个接口比较好实现,使用循环来打印就是。

大家请看

void SHOWContact(Contact* pc)
{assert(pc);;	if (pc->sz == 0){printf("信息管理系统为空无法打印\n");return;}int i = 0;printf("%-20s%-5s%-5s%-12s%-30s\n", "姓名", "年龄", "性别", "电话", "地址");for (i = 0; i < pc->sz; i++){//打印每个人的信息printf("%-20s%-5d%-5s%-12s%-30s\n", //分别打印姓名,年龄,性别,电话,地址。pc->date[i].name, pc->date[i].age, pc->date[i].sex, pc->date[i].tele, pc->date[i].adrs);}
}

我来为大家解释一下代码:

printf("%-20s%-5s%-5s%-12s%-30s\n", "姓名", "年龄", "性别", "电话", "地址");

这一行代码:是打印我们的上面部分,采用的是左对齐的方式。(所以%20s,我们会加上“-”这个符号,其中%20s,是宽度)

printf("%-20s%-5d%-5s%-12s%-30s\n", //分别打印姓名,年龄,性别,电话,地址。
            pc->date[i].name, pc->date[i].age, pc->date[i].sex, pc->date[i].tele, pc->date[i].adrs);

这一行打印的是我们下面的部分。

那我们接着继续往下看

6.联系人数据的删除
 

6.1查找指定联系人

//删除指定学生信息的信息
void DEALContact(Contact* pc);

在我们实现删除的前提是找到指定的联系人,那么该如何操作呢?

思路如下:1.自定函数FindByName通过遍历来找到指定的姓名

                  2.再来删除

查找的代码:

int FIndByNmae(Contact* pc, char name[])
{assert(pc);int i = 0;for (i = 0; i < pc->sz; i++){if (strcmp(pc->date[i].name, name) == 0){return i;}}return -1; //找不到
}

分析如下:我们使用循环来遍历SZ(sz中存储的是有效联系人的信息,我们查找是否有名字相同的),我们使用了  strcmp 函数我们可以找到此人。找不到就会直接返回。

怕大家不理解Strcmp 我找来了资料大家可以看看。

 6.2删除指定联系人

oid DEALContact(Contact* pc)
{char name[20];assert(pc);if (pc->sz == 0){printf("没有学生信息的数据无法删除");return;}//找到学生信息printf("输入想要删除学生信息的名字:");scanf_s("%s", name, 20);//找到名字为name的人//分装一个新的函数FIndByName用来查找学生信息int ret = FIndByNmae(pc, name);if (ret == -1){printf("要删除的人不存在\n");return;}//删除这个人的信息 int i = 0;for (i = ret; i < pc->sz - 1; i++){pc->date[i] = pc->date[i + 1];}pc->sz--;printf("删除成功");}

我来给大家详细通过画图来解释一下删除的全过程(如何进行删除操作的)

 

假设我们要删除 ret那么如何删除呢?

我们通过覆盖,从后面到前面覆盖,就是使用ret后面的那一个来把ret覆盖起来。

以上就是删除联系人的信息

7.联系人数据的修改

 //修改指定学生信息的信息 
void  ModifyCkontact(Contact*pc);

当我们有了自定义函数来实现查找之后,修改操作便会简单很多。 我们之间把增加的后半段代码复制过来。

void  ModifyCkontact(Contact* pc)
{char name[20];assert(pc);printf("请输入你要修改的人的名字:");scanf_s("%s", name, 20);int ret = FIndByNmae(pc, name);if (ret == -1){printf("要修改的人不存在\n");return;}//修改printf("请输入名字");scanf_s("%s", pc->date[ret].name, 20);printf("请输入年龄");scanf_s("%d", &(pc->date[ret].age));printf("请输入性别");scanf_s("%s", pc->date[ret].sex, 5);printf("请输入电话");scanf_s("%s", pc->date[ret].tele, 20);printf("请输入地址");scanf_s("%s", pc->date[ret].adrs, 30);printf("修改成功");
}

8.联系人数据的查找

//查找指定学生信息的信息void SearchContact(Contact*pc);
void SearchContact(Contact*pc)
{char name[20];assert(pc);printf("请输入你要查找的人的名字:");scanf_s("%s", name, 20);int ret = FIndByNmae(pc, name);if (ret == -1){printf("要查找的人不存在\n");return;}//显示出来printf("%-20s%-5s%-5s%-12s%-30s\n", "姓名", "年龄", "性别", "电话", "地址");printf("%-20s%-5d%-5s%-12s%-30s\n", //分别打印姓名,年龄,性别,电话,地址。pc->date[ret].name, pc->date[ret].age, pc->date[ret].sex, pc->date[ret].tele, pc->date[ret].adrs);}

 相同的原理只要我们可以找到就可以实现。

9.通讯录的完整代码

text.c

#include"Contact.h"
void menu()
{ printf("************************************************\n" );printf("        基于动态链表实现的学生信息系统          *\n");printf("***      1. add        2.deal                   *\n");printf("***      3.search      4.modify                 *\n");printf("***      5.show        6.exit                   *\n");printf("*************************************************\n");printf("本系统提供了增加,删除,搜索,修改,展示 学生信息\n");
}
enum Option
{exit,       //退出信息管理系统add,        //增加信息管理系统deal,       //删除信息管理系统search,     //搜索信息管理系统modify,     //修改信息管理系统show,       //展示信息管理系统};
int main()
{int input = 0;Contact con;  //con就是创建的信息管理系统//初始化信息管理系统(因为在开始信息管理系统没有进行初始化内部存放的都是随机值)IntiContact(&con);do{menu();printf("请选择\n");scanf_s("%d", &input);switch (input){case exit:printf("退出信息管理系统");break;case add:ADDContact(&con);break;case deal:DEALContact(&con);break;case search:SearchContact(&con);break;case modify:ModifyCkontact(&con);break;case show:SHOWContact(&con);break;default:printf("请重新选择");break;}} while (input);return 0;
}

 Contact.c

#include"Contact.h"
void IntiContact(Contact* pc)
{assert(pc);pc->sz = 0;memset(pc->date, 0, sizeof(pc->date));/*memset是一个初始化函数,作用是将某一块内存中的全部设置为指定的值s指向要填充的内存块。c是要被设置的值。n是要被设置该值的字符数。返回类型是一个指向存储区s的指针*/}
void ADDContact(Contact* pc)
{assert(pc);//先判断信息管理系统有没有空间支持增加if (pc->sz == 100){printf("信息管理系统已满无法增加\n");return;}//如果没有返回就增加一个人的信息printf("请输入名字");scanf_s("%s", pc->date[pc->sz].name,20);printf("请输入年龄");scanf_s("%d", &(pc->date[pc->sz].age));printf("请输入性别");scanf_s("%s", pc->date[pc->sz].sex,5);printf("请输入电话");scanf_s("%s", pc->date[pc->sz].tele,20);printf("请输入地址");scanf_s("%s", pc->date[pc->sz].adrs,30);//由于信息录入完成所以增加了一个人的信息pc->sz++;printf("增加成功\n");}
void SHOWContact(Contact* pc)
{assert(pc);;	if (pc->sz == 0){printf("信息管理系统为空无法打印\n");return;}int i = 0;printf("%-20s%-5s%-5s%-12s%-30s\n", "姓名", "年龄", "性别", "电话", "地址");for (i = 0; i < pc->sz; i++){//打印每个人的信息printf("%-20s%-5d%-5s%-12s%-30s\n", //分别打印姓名,年龄,性别,电话,地址。pc->date[i].name, pc->date[i].age, pc->date[i].sex, pc->date[i].tele, pc->date[i].adrs);}
}int FIndByNmae(Contact* pc, char name[])
{assert(pc);int i = 0;for (i = 0; i < pc->sz; i++){if (strcmp(pc->date[i].name, name) == 0){return i;}}return -1; //找不到}void DEALContact(Contact* pc)
{char name[20];assert(pc);if (pc->sz == 0){printf("没有学生信息的数据无法删除");return;}//找到学生信息printf("输入想要删除学生信息的名字:");scanf_s("%s", name, 20);//找到名字为name的人//分装一个新的函数FIndByName用来查找学生信息int ret = FIndByNmae(pc, name);if (ret == -1){printf("要删除的人不存在\n");return;}//删除这个人的信息 int i = 0;for (i = ret; i < pc->sz-1; i++){pc->date[i] = pc->date[i + 1];}pc->sz--;printf("删除成功");}
void SearchContact(Contact*pc)
{char name[20];assert(pc);printf("请输入你要查找的人的名字:");scanf_s("%s", name, 20);int ret = FIndByNmae(pc, name);if (ret == -1){printf("要查找的人不存在\n");return;}//显示出来printf("%-20s%-5s%-5s%-12s%-30s\n", "姓名", "年龄", "性别", "电话", "地址");printf("%-20s%-5d%-5s%-12s%-30s\n", //分别打印姓名,年龄,性别,电话,地址。pc->date[ret].name, pc->date[ret].age, pc->date[ret].sex, pc->date[ret].tele, pc->date[ret].adrs);}void  ModifyCkontact(Contact* pc)
{char name[20];assert(pc);printf("请输入你要修改的人的名字:");scanf_s("%s", name, 20);int ret = FIndByNmae(pc, name);if (ret == -1){printf("要修改的人不存在\n");return;}//修改printf("请输入名字");scanf_s("%s", pc->date[ret].name, 20);printf("请输入年龄");scanf_s("%d", &(pc->date[ret].age));printf("请输入性别");scanf_s("%s", pc->date[ret].sex, 5);printf("请输入电话");scanf_s("%s", pc->date[ret].tele, 20);printf("请输入地址");scanf_s("%s", pc->date[ret].adrs, 30);printf("修改成功");
}

Contact.h

#pragma once
#include<string.h>
#include<assert.h>
#define NAME_MAX 20;
#define SEX_MAX 5;
#define ADRS_MAX 20;
#define TELE_MAX 15;
#include<stdio.h>
typedef struct peopleinform //设置人的信息
{char name[20];char sex[5];char adrs[30];int age;char tele[20];}peopleinform;
typedef struct Contact
{peopleinform date[100]; //用来存放数据int sz; //用来记录的是信息管理系统中存放信息的个数}Contact;
//初始化信息管理系统
void IntiContact(Contact* pc);
//增加学生信息的信息
void ADDContact(Contact* pc);
//查看学生信息的信息
void SHOWContact(Contact* pc);
//删除指定学生信息的信息
void DEALContact(Contact*pc);
//查找指定学生信息的信息void SearchContact(Contact*pc);//修改指定学生信息的信息 
void  ModifyCkontact(Contact*pc);

今天的博客就到这里了,后续为大家更新C++的相关课程。

感谢你的观看

                               

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

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

相关文章

2016-2021年全国范围的2.5m分辨率的建筑屋顶数据

一、论文介绍 摘要&#xff1a;大规模且多年的建筑屋顶面积&#xff08;BRA&#xff09;地图对于解决政策决策和可持续发展至关重要。此外&#xff0c;作为人类活动的细粒度指标&#xff0c;BRA可以为城市规划和能源模型提供帮助&#xff0c;为人类福祉带来好处。然而&#xf…

Qt之常用控件一

Widget常见属性及其作用 属性作用enabled 设置控件是否可使⽤. true 表⽰可⽤, false 表⽰禁⽤ geometry 位置和尺⼨. 包含 x, y, width, height 四个部分. 其中坐标是以⽗元素为参考进⾏设置的. windowTitle 设置 widget 标题 windowIcon 设置 widget 图标 windowOpa…

java日历类概述

Java中的Calendar类位于java.util包下&#xff0c;它是一个抽象类&#xff0c;用于表示和管理日期及时间。Calendar类并不是直接实例化的&#xff0c;而是通过其提供的静态方法来获取实例。通常情况下&#xff0c;当你尝试创建一个Calendar实例时&#xff0c;实际上你得到的是G…

The 2023 ICPC Asia Hefei Regional Contest

目录 B. Queue Sorting 应该还会再补几题 B. Queue Sorting 题解&#xff1a; Dilworth定理: 【偏序关系与偏序集、Hasse图、极大元、极小元、全序关系、最大元、良序集/三小时讲不完离散数学之集合论/考研复试/期末复习考前冲刺/近世代数/抽象代数】https://www.bilibili.c…

C++奇迹之旅:string类对象的容量操作

文章目录 &#x1f4dd; string类的常用接口&#x1f309; string类对象的容量操作&#x1f320;size&#x1f320;length&#x1f320;capacity&#x1f320;clear&#x1f320;empty&#x1f320;reserve&#x1f309;resize &#x1f6a9;总结 &#x1f4dd; string类的常用…

PMP有效期三年后,还有必要续证吗?

通常情况下是必要的&#xff0c;续证条件是在3年内累积60个PDU和支付150美元。如果到期后没有进行续证&#xff0c;但仍希望保持证书&#xff0c;就需要重新参加PMP考试。重新参加考试的费用包括3900元的报名费和数千元的培训费。因此&#xff0c;与重新考试相比&#xff0c;续…

通过 Java 操作 redis -- 基本通用命令

目录 使用 String 类型的 get 和 set 方法 使用通用命令 exists &#xff0c;del 使用通用命令 keys 使用通用命令 expire,ttl 使用通用命令 type 要想通过 Java 操作 redis&#xff0c;首先要连接上 redis 服务器&#xff0c;推荐看通过 Java 操作 redis -- 连接 redis 关…

思维导图在线怎么制作?推荐这些工具

思维导图在线怎么制作&#xff1f;在如今的快节奏时代中&#xff0c;思维导图作为一种高效的信息组织与思考工具&#xff0c;受到了广泛的应用。在线制作思维导图成打破了时间和空间的限制&#xff0c;使得团队协作变得更加便捷&#xff0c;个人创作也更为灵活。以下是四款备受…

建模电梯的状态图和学生选课ER图

第一题 尝试建模电梯的状态图&#xff08;选做&#xff09; 第二题 学校规定&#xff1a; 一个学生可选修多门课&#xff0c;一门课有若于学生选修。 一个教师可讲授多门课&#xff0c;一门课只有一个教师讲授。 一个学生选修一门课&#xff0c;仅有一个成绩。 学生的属性有学号…

JS中的arguments是什么?

arguments是当我们不确定有多少个参数传递时&#xff0c;就可以使用argument来获取。在js中&#xff0c;arguments实际上就是当前函数的一个内置对象&#xff0c;存储了我们传递的所有实参。arguents的展示形式就是一个伪数组&#xff0c;所以我们可以对它进行遍历。 我们先来…

基于Python的飞机大战游戏

学习目标 了解 飞机大战游戏的规则 理解 面向对象思想,会独立设计游戏的类与模块 掌握 pygame模块的使用 1.1 游戏介绍 飞机大战是一款由腾讯公司微信团队推出的软件内置的小游戏,这款游戏画面简洁有趣,规则简单易懂,操作简便易上手,在移动应用兴起之初曾风靡一时。 1.1.…

oracle 9i 行头带有scn的表

oracle 9i 行头带有scn的表 conn scott/tiger drop table t1; drop table t2; create table t1(c varchar2(5)); create table t2(c varchar2(6)) ROWDEPENDENCIES; --t2表每行都有scn,会增加六个字节的开销 alter table t1 pctfree 0; alter table t2 pctfree 0; insert in…

WordPress原创插件:超链接点击访问统计

WordPress原创插件&#xff1a;超链接点击访问统计 https://download.csdn.net/download/huayula/89296775

【Ajax零基础教程】-----第四课 简单实现

一、XMLHttpRequest对象 通过XMLHttpRequest对象来向服务器发送异步请求&#xff0c;从服务器获取数据。然后用JavaScript来操作DOM而更新页面。XMLHttpRequest是ajax的核心机制&#xff0c;它是IE5中首先引入的&#xff0c;是一种支持异步请求的技术。 简单的说&#xff0c;也…

第四百九十八回

文章目录 1. 概念介绍2. 使用方法2.1 固定样式2.2 自定义样式 3. 示例代码4. 内容总结 我们在上一章回中介绍了"GetMaterialApp组件"相关的内容&#xff0c;本章回中将介绍使用get显示SnackBar.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在介…

ppt通过修改幻灯片母版修改页脚

修改幻灯片母版 幻灯片母版就可以了&#xff0c;就可以修改页脚

1290.二进制链表转整数

给你一个单链表的引用结点 head。链表中每个结点的值不是 0 就是 1。已知此链表是一个整数数字的二进制表示形式。 请你返回该链表所表示数字的 十进制值 。 示例 1&#xff1a; 输入&#xff1a;head [1,0,1] 输出&#xff1a;5 解释&#xff1a;二进制数 (101) 转化为十进制…

即插即用篇 | YOLOv8 引入多光谱通道注意力 | 频率领域中的通道注意力网络

本改进已集成到 YOLOv8-Magic 框架。 注意力机制,尤其是通道注意力,在计算机视觉领域取得了巨大成功。许多工作聚焦于如何设计高效的通道注意力机制,同时忽略了一个基本问题,即通道注意力机制使用标量来表示通道,这很困难,因为会造成大量信息的丢失。在这项工作中,我们从…

05-10 周五 FastBuild 容器启动引起超时问题定位与解决

05-10 周五 FastBuild 容器启动超时问题 时间版本修改人描述2024年5月11日16:45:33V0.1宋全恒新建文档2024年5月11日22:37:21V1.0宋全恒完成解决方案的撰写&#xff0c;包括问题分析&#xff0c;docker命令 简介 关于FastBuild的优化&#xff0c;已经撰写了多个博客&#xff0…

搭建一个Xx431?

搭建一个Xx431? 嘿uu们!刚结束了一周六天班感觉如何? 我的状态倒还行,工作生活总能找到乐子,本周整活就是用纸巾和蛋糕托做的油灯,另外想制冷片做个温水冷水可调的杯托,但我还不会搞3d,希望今年能搞起来. 题外话就说到这,这个选题也是因为实际遇到的问题需要这玩意,下班路…