项目要实现的内容:能够存放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, //退出信息管理系统 0
add, //增加信息管理系统 1
deal, //删除信息管理系统 2
search, //搜索信息管理系统 3
modify, //修改信息管理系统 4
show, //展示信息管理系统 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++的相关课程。
感谢你的观看