导言:“练习成就不了完美。多练习会产生髓磷脂,是髓磷脂让你做到完美。”——丹尼尔·科伊尔(Daniel Coyle)
目录
一:通讯录的思想
二:通讯录的实现
1.创建文件
2.打印菜单
3.创建联系人结构体
4.初始化菜单
5.实现菜单的功能
a.增加联系人
b.删除联系人
c.查找联系人
d.修改联系人
e.打印联系人
三:总结
一:通讯录的思想
我们将每一位联系人的姓名,性别,年龄,电话,地址来用一个结构体保存,用另一个结构体来保存通讯录的信息和通讯录已经保存的联系人的个数。
剩下通过函数依次实现通讯录各个功能:
1.增加联系人? 2.删除联系人? 3.查找联系人 4.修改联系人? 5.打印联系人信息
二:通讯录的实现
1.创建文件
首先我们创建三个文件,test.c用来测试,address.h用来声明结构体和函数,address.c用来实现各个功能函数的实现。
?2.打印菜单
打印菜单是十分有必要的,能够实现与用户的交互,菜单需要包含通讯录的各个功能,便于操作。
打印菜单如下:
void menu() {
printf("-------- 1.增加:-------- \n");
printf("-------- 2.删除:-------- \n");
printf("-------- 3.查询:-------- \n");
printf("-------- 4.修改:-------- \n");
printf("-------- 5.打印:-------- \n");
printf(" 0.退出通讯录: \n");
}
实际打印效果如下:
3.创建联系人结构体?
这里我们联系人的信息用结构体来保存,在头文件声明。
//类型的声明
//一位联系人的基本信息,我们都放在一个结构体里面
typedef struct People {
char name[NAME_MAX]; //名字
char sex[SEX_MAX]; //性别
int age; //年龄
char tele[TELE_MAX]; //电话号码
char addr[ADDR_MAX]; //地址
}People;
//通讯录
typedef struct Address {
People date[MAX];//可以存放1000位联系人
int sz;//记录通讯录已经保存的联系人个数
}Address;
这里我们设定存放1000位联系人。第二个结构体是我们的通讯录,sz是记录通讯录已经保存的联系人个数。
看到这儿,可能会有人好奇我定义的数组里面大写字母代表的是什么,这里我用的宏定义的变量,便于后期数值的修改。
#pragma once
//头文件这里用来类型的声明和函数的声明
#include<stdio.h>
#include<assert.h>
#include<string.h>
//这样是为了便于后续好修改大小和数据
#define MAX 1000
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
4.初始化菜单
刚开始的时候,在结构体Address中我们并没有给数组和sz赋值,不知道起始数值是多少,所以现在我们需要将他们全部赋值为0,是通讯录里面为空。
我们首先声明一个初始化函数。
//初始化通讯录函数
void InitAddress(Address* p);
由于结构体传参的数据所占内存可能过大,所以我们结构体传递用地址传递,后面都是如此。
函数的实现如下:
//初始化
void InitAddress(Address* p) {
assert(p);//断言,为了指针的有效性
p->sz = 0;
//利用库函数,将数组全部初始化为0
memset(p->date, 0, sizeof(p->date));
}
初始化函数这里我们用到了库函数memset,是将整个数组的字节大小全部修改为0.
5.实现菜单的功能
a.增加联系人
在初始化函数后,我们开始实现模拟菜单的功能。但是在实现功能之前,我们还要选择菜单选项,可以让用户选择几就执行几所对应的功能,并且能让用户可以一直输入下去,这里我们使用枚举变量来代表我们用户选择的数字,更加直接明了。
//利用枚举类型便于直观
enum Option {
EXIT,//0
ADD,//1
DEL,//2
FIND,//3
MODIFY,//4
PRINT//5
};
void test() {
printf("欢迎进入通讯录:\n");
int input = 0;
Address add;
//初始化通讯录
InitAddress(&add);
do {
menu();
scanf("%d", &input);
switch (input) {
case ADD:
//增加联系人
Add_Address(&add);
break;
case DEL:
//删除联系人
Del_Address(&add);
break;
case FIND:
//查询联系人
Find_Address(&add);
break;
case MODIFY:
//修改联系人
Modify_Address(&add);
break;
case PRINT:
Print_Address(&add);
break;
case EXIT:
printf("退出通讯录:\n");
break;
default:
printf("输入错误,请重新输入:\n");
break;
}
} while (input);
}
int main() {
test();
return 0;
}
现在我们来实现增加联系人的操作,首先我们要声明一个函数。
//增加联系人
void Add_Address(Address* p);
函数的实现:
//增加联系人
void Add_Address(Address* p) {
assert(p);
//先判断有没有空间添加联系人
if (p->sz == MAX) {
printf("通讯录已满,无法添加!\n");
}
//否则,添加联系人
//录入信息
printf("请输入联系人姓名:");
scanf("%s", p->date[p->sz].name);
printf("请输入联系人性别:");
scanf("%s", p->date[p->sz].sex);
printf("请输入联系人年龄:");
scanf("%d", &p->date[p->sz].age);
printf("请输入联系人电话:");
scanf("%s", p->date[p->sz].tele);
printf("请输入联系人地址:");
scanf("%s", p->date[p->sz].addr);
//记录完一次,我们sz保存的联系人就要加一次
p->sz++;
printf("联系人保存成功!\n");
}
只要依次输入对应数据,即可保存成功。
最终效果如下:
?
b.删除联系人
删除元素我们需要将sz作为下标来使用,具体实现如下,我们先声明一个函数。
//删除联系人
void Del_Address(Address* p);
函数的实现
//删除联系人
//这里我们设置,如果存在这个联系人,就返回下标sz
//如果不存在这个联系人,就返回-1。
int Find_name(const Address* p,char name[]) {
assert(p);
//采用循环遍历
int i = 0;
for (i = 0; i < p->sz; i++) {
if (0 == strcmp(p->date[i].name, name)) {
//等于0,表示存在这个联系人
return i;
}
}
//否则返回-1
return -1;
}
void Del_Address(Address* p) {
assert(p);
//判断是否为空
if (p->sz == 0) {
printf("通讯录已空,无法删除!\n");
}
char name[20] = { 0 };
printf("请输入你要删除的联系人姓名:\n");
scanf("%s", name);
int ret = Find_name(p,name);
if (ret == -1) {
printf("这个联系人不存在!\n");
return;
}
else {
int j = 0;
for (j = ret; j < p->sz - 1; j++) {
p->date[j] = p->date[j + 1];
}
p->sz--;
}
printf("删除成功.\n");
}
这里中间我们又定义了一个函数Find_name(),这个函数用来查找要删除的联系人是否在通讯录中,用库函数strcmp比较函数来判断是否存在。另外,在删除元素的时候要主要数组下标越界的问题。
最终效果如下:
c.查找联系人
查找联系人和删除很像,只要用Find_name()函数查找,再打印出来即可。首先我们再声明函数。
//查询联系人
void Find_Address(Address* p);
函数的实现
//查询联系人
void Find_Address(const Address* p) {
assert(p);
char name[20];
printf("请输入你要查询的联系人姓名:\n");
scanf("%s", name);
int ret = Find_name(p, name);
if (ret == -1) {
printf("查无此人\n");
}
else {
//打印当前查询联系人信息
printf("%-20s %-5s %-5s %-12s %-30s\n", "姓名", "性别", "年龄", "电话", "地址");
printf("%-20s %-5s %-5d %-12s %-30s\n", p->date[ret].name, p->date[ret].sex, p->date[ret].age, p->date[ret].tele, p->date[ret].addr);
}
}
最终效果如下:
?d.修改联系人
修改联系人我们这里让用户选择修改什么类容,通过信息查询来进行修改,跟实现菜单差不多,也是通过do? while?和switch来实现用户的选择,我们先声明一个函数。
//修改联系人
void Modify_Address(Address* p);
函数的实现
//修改联系人信息
void Modify_Address(Address* p) {
assert(p);
char name[20]={0};
printf("请选择你要修改的联系人姓名:\n");
scanf("%s", name);
int ret= Find_name(p, name);
if (ret == -1) {
printf("查无此人\n");
}
else {
int input = 0;
do {
printf("请选择你要修改的信息:\n");
printf("1.修改联系人名字:\n");
printf("2.修改联系人性别:\n");
printf("3.修改联系人年龄:\n");
printf("4.修改联系人电话:\n");
printf("5.修改联系人地址:\n");
printf(" 0.退出修改: \n");
scanf("%d", &input);
switch (input) {
case 1:
//修改名字:
printf("请输入你要修改的联系人名字:\n");
scanf("%s", p->date[ret].name);
break;
case 2:
printf("请输入你要修改的联系人性别:\n");
scanf("%s", p->date[ret].sex);
break;
case 3:
printf("请输入你要修改的联系人年龄:\n");
scanf("%s", &p->date[ret].age);
break;
case 4:
printf("请输入你要修改的联系人电话:\n");
scanf("%s", &p->date[ret].tele);
break;
case 5:
printf("请输入你要修改的联系人地址:\n");
scanf("%s", &p->date[ret].addr);
break;
case 0:
printf("退出修改\n");
break;
default:
printf("输入无效,请重新输入:\n");
break;
}
} while (input);
}
printf("修改成功!\n");
}
这里我们通过Find_name函数所返回的那个下标进行修改,那个下标就是我们要修改的联系人对象。
最终效果如下:
?
e.打印联系人
这里我们使用一个for循环和sz当作下标来依次打印出联系人的信息。
声明函数:
//打印通讯录
void Print_Address(Address* p);
函数的实现
//打印联系人
void Print_Address(Address* p) {
assert(p);
//前面-是左对齐的意思,不加-就是右对齐
printf("%-20s %-5s %-5s %-12s %-30s\n", "姓名", "性别", "年龄", "电话", "地址");
int i = 0;
for (i = 0; i < p->sz; i++) {
printf("%-20s %-5s %-5d %-12s %-30s\n", p->date[i].name, p->date[i].sex, p->date[i].age, p->date[i].tele, p->date[i].addr);
}
}
三.总结
写到这儿也结束了,通讯录是考察结构体的运用和创建,完整源码如下,供参考,欢迎提错误。
#pragma once
//头文件这里用来类型的声明和函数的声明
#include<stdio.h>
#include<assert.h>
#include<string.h>
//这样是为了便于后续好修改大小和数据
#define MAX 1000
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
//利用枚举类型便于直观
enum Option {
EXIT,//0
ADD,//1
DEL,//2
FIND,//3
MODIFY,//4
PRINT//5
};
//类型的声明
//一位联系人的基本信息,我们都放在一个结构体里面
typedef struct People {
char name[NAME_MAX]; //名字
char sex[SEX_MAX]; //性别
int age; //年龄
char tele[TELE_MAX]; //电话号码
char addr[ADDR_MAX]; //地址
}People;
//通讯录
typedef struct Address {
People date[MAX];//可以存放1000位联系人
int sz;//记录通讯录已经保存的联系人个数
}Address;
//函数的声明
//初始化通讯录函数
void InitAddress(Address* p);
//增加联系人
void Add_Address(Address* p);
//删除联系人
void Del_Address(Address* p);
//打印通讯录
void Print_Address(Address* p);
//查询联系人
void Find_Address(Address* p);
//修改联系人
void Modify_Address(Address* p);
#define _CRT_SECURE_NO_WARNINGS 1
#include"address.h"
//通讯录函数的实现
//初始化
void InitAddress(Address* p) {
assert(p);//断言,为了指针的有效性
p->sz = 0;
//利用库函数,将数组全部初始化为0
memset(p->date, 0, sizeof(p->date));
}
//增加联系人
void Add_Address(Address* p) {
assert(p);
//先判断有没有空间添加联系人
if (p->sz == MAX) {
printf("通讯录已满,无法添加!\n");
}
//否则,添加联系人
//录入信息
printf("请输入联系人姓名:");
scanf("%s", p->date[p->sz].name);
printf("请输入联系人性别:");
scanf("%s", p->date[p->sz].sex);
printf("请输入联系人年龄:");
scanf("%d", &p->date[p->sz].age);
printf("请输入联系人电话:");
scanf("%s", p->date[p->sz].tele);
printf("请输入联系人地址:");
scanf("%s", p->date[p->sz].addr);
//记录完一次,我们sz保存的联系人就要加一次
p->sz++;
printf("联系人保存成功!\n");
}
//删除联系人
//这里我们设置,如果存在这个联系人,就返回下标sz
//如果不存在这个联系人,就返回-1。
int Find_name(const Address* p,char name[]) {
assert(p);
//采用循环遍历
int i = 0;
for (i = 0; i < p->sz; i++) {
if (0 == strcmp(p->date[i].name, name)) {
//等于0,表示存在这个联系人
return i;
}
}
//否则返回-1
return -1;
}
void Del_Address(Address* p) {
assert(p);
//判断是否为空
if (p->sz == 0) {
printf("通讯录已空,无法删除!\n");
}
char name[20] = { 0 };
printf("请输入你要删除的联系人姓名:\n");
scanf("%s", name);
int ret = Find_name(p,name);
if (ret == -1) {
printf("这个联系人不存在!\n");
return;
}
else {
//删除
int j = 0;
for (j = ret; j < p->sz - 1; j++) {
p->date[j] = p->date[j + 1];
}
p->sz--;
}
printf("删除成功.\n");
}
//打印联系人
void Print_Address(Address* p) {
assert(p);
//前面-是左对齐的意思,不加-就是右对齐
printf("%-20s %-5s %-5s %-12s %-30s\n", "姓名", "性别", "年龄", "电话", "地址");
int i = 0;
for (i = 0; i < p->sz; i++) {
printf("%-20s %-5s %-5d %-12s %-30s\n", p->date[i].name, p->date[i].sex, p->date[i].age, p->date[i].tele, p->date[i].addr);
}
}
//查询联系人
void Find_Address(const Address* p) {
assert(p);
char name[20];
printf("请输入你要查询的联系人姓名:\n");
scanf("%s", name);
int ret = Find_name(p, name);
if (ret == -1) {
printf("查无此人\n");
}
else {
//打印当前查询联系人信息
printf("%-20s %-5s %-5s %-12s %-30s\n", "姓名", "性别", "年龄", "电话", "地址");
printf("%-20s %-5s %-5d %-12s %-30s\n", p->date[ret].name, p->date[ret].sex, p->date[ret].age, p->date[ret].tele, p->date[ret].addr);
}
}
//修改联系人信息
void Modify_Address(Address* p) {
assert(p);
char name[20]={0};
printf("请选择你要修改的联系人姓名:\n");
scanf("%s", name);
int ret= Find_name(p, name);
if (ret == -1) {
printf("查无此人\n");
}
else {
int input = 0;
do {
printf("请选择你要修改的信息:\n");
printf("1.修改联系人名字:\n");
printf("2.修改联系人性别:\n");
printf("3.修改联系人年龄:\n");
printf("4.修改联系人电话:\n");
printf("5.修改联系人地址:\n");
printf(" 0.退出修改: \n");
scanf("%d", &input);
switch (input) {
case 1:
//修改名字:
printf("请输入你要修改的联系人名字:\n");
scanf("%s", p->date[ret].name);
break;
case 2:
printf("请输入你要修改的联系人性别:\n");
scanf("%s", p->date[ret].sex);
break;
case 3:
printf("请输入你要修改的联系人年龄:\n");
scanf("%s", &p->date[ret].age);
break;
case 4:
printf("请输入你要修改的联系人电话:\n");
scanf("%s", &p->date[ret].tele);
break;
case 5:
printf("请输入你要修改的联系人地址:\n");
scanf("%s", &p->date[ret].addr);
break;
case 0:
printf("退出修改\n");
break;
default:
printf("输入无效,请重新输入:\n");
break;
}
} while (input);
}
printf("修改成功!\n");
}
#define _CRT_SECURE_NO_WARNINGS 1
//通讯录
//静态版本
//通讯录可以存储1000位联系人
#include"address.h"
void menu() {
printf("-------- 1.增加:-------- \n");
printf("-------- 2.删除:-------- \n");
printf("-------- 3.查询:-------- \n");
printf("-------- 4.修改:-------- \n");
printf("-------- 5.打印:-------- \n");
printf(" 0.退出通讯录: \n");
}
void test() {
printf("欢迎进入通讯录:\n");
int input = 0;
Address add;
//初始化通讯录
InitAddress(&add);
do {
menu();
scanf("%d", &input);
switch (input) {
case ADD:
//增加联系人
Add_Address(&add);
break;
case DEL:
//删除联系人
Del_Address(&add);
break;
case FIND:
//查询联系人
Find_Address(&add);
break;
case MODIFY:
//修改联系人
Modify_Address(&add);
break;
case PRINT:
Print_Address(&add);
break;
case EXIT:
printf("退出通讯录:\n");
break;
default:
printf("输入错误,请重新输入:\n");
break;
}
} while (input);
}
int main() {
test();
return 0;
}
|