目录
头文件(将常用的头文件、函数的声明、结构体类型的声明、枚举、枚举类型的声明放入其中,放在contact.h文件中)
主函数(单单实现菜单打印及菜单选择功能,放在test.cpp文件中)
函数的定义 (所有函数的定义,都放在contact.cpp文件中)
首先需要定义个人信息类型,存放联系人的各种信息,同时为了方便后续使用,我们将struct perinf重命名为perinf。
这里我们设定的基础信息是姓名、性别、电话号码、家庭住址、年龄,都用数组存放,为了方便后续修改这些数组的大小,我们定义常变量来实现想法。
利用个人信息的结构体数组来实现联系人信息的添加、删除等操作。
将sz变量设置为零,表示通讯录目前是零个联系人 。用memmset将个人信息结构体数组arr初始化成零。
在这里是实现用户所选择的功能,为了增加代码阅读性,用了枚举类型来替换case后面的数字。
在删除前,先进行判断,一是有没有联系人,二是要删除的联系人存不存在。对于第二条,我们首先得找出要删除的人再进行删除操作。
找到了就返回找到的元素下标,没找到就返回负一(因为数组中没有元素的下标是负一),判断是否找到我们利用strcmp函数
同样需要用到遍历查找函数,在删除函数那里已经给出定义。先打印题头然后再打印信息。
前言
上一次我们介绍了自定义类型,是不是想做点小项目来实践实践?这次的通讯录满足你的愿望。这次的通讯录不算是完全体,因为内存的开辟是通过大数组来完成的,后面一版才是动态开辟内存,请各位同志耐性等待~。
问题分析
通讯录要实现的基础功能有“增、删、查、改”,可根据自身需求加入“排序、显示整个通讯录”的功能。
工程的模块
头文件(将常用的头文件、函数的声明、结构体类型的声明、枚举、枚举类型的声明放入其中,放在contact.h文件中)
#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include<stdio.h>
#include<string.h>
//重定义最大名字,最大性别,最大电话,最大通讯录名额,最大地址
#define MAX_NAME 100
#define MAX_SEX 100
#define MAX_TELE 100
#define MAX_PERSON 1000
#define MAX_ADDRESS 100
//定以个人信息结构体
typedef struct perinf
{
char name[MAX_NAME];
char sex[MAX_SEX];
char tele[MAX_TELE];
char address[MAX_ADDRESS];
int age;
}perinf;
//定义通讯录类型
typedef struct contact
{
perinf arr[MAX_PERSON];
int sz;
}contact;
//定义菜单枚举类型
enum menu
{
EXIT,
ADD,
DEL,
SEEK,
MODIFY,
SORT,
DISPLAY
};
//定义查找内的菜单枚举类型
enum menu_seek
{
EXIT1,
NAME,
SEX,
TELE,
ADDRESS,
AGE
};
//定义排序菜单枚举类型
enum menu_sort
{
EXIT2,
SORTBYNAME,
SORTBYAGE
};
//声明打印菜单函数
void menu_print();
//声明菜单选择函数
void menu_option(int input, contact* p1);
//声明初始化通讯录函数
void Init_contact(contact* p1);
//声明添加联系人函数
void perinf_add(contact* p1);
//声明删除联系人函数
void perinf_del(contact* p1);
//声明遍历对比函数
int perinf_seek(contact* p1);
//声明查询函数
void perinf_SEEK(contact* p1);
//声明查找内的菜单函数
void menu_seek();
//声明查找内的菜单选择函数
void seekmenu_option(int a, int ret, contact* p1);
//声明修改函数
void perinf_MODIFY(contact* p1);
//声明显示通讯录函数
void perinf_dispay(contact* p1);
//声明排序菜单选择函数
void sortmenu_option(int a, contact* p1);
//声明排序菜单函数
void menu_sort();
//声明排序函数
void perinf_sort(contact* p1);
主函数(单单实现菜单打印及菜单选择功能,放在test.cpp文件中)
#define _CRT_SECURE_NO_WARNINGS
#include"contact.h"
int main()
{
contact con;
Init_contact(&con);
int input = 0;
do
{
//打印菜单
menu_print();
printf("请选择您需要的功能:>\n");
scanf("%d", &input);
menu_option(input,&con);
} while (input);
return 0;
}
函数的定义 (所有函数的定义,都放在contact.cpp文件中)
#include"contact.h"
//打印菜单函数
void Init_contact(contact* p1)
{
p1->sz = 0;
memset(p1->arr, 0, sizeof(p1->arr));
}
void menu_print()
{
printf("-------------------------------------\n");
printf("=====================================\n");
printf("=========1.添加 2.删除==========\n");
printf("=========3.查询 4.修改==========\n");
printf("=========5.排序 6.显示通讯录====\n");
printf("========= 0.退出 ==========\n");
printf("=====================================\n");
printf("-------------------------------------\n");
}
//查找内的菜单函数
void menu_seek()
{
printf("请选择要修改的内容\n");
printf("-------------------------------------\n");
printf("=====================================\n");
printf("=========1.姓名 2.性别==========\n");
printf("=========3.电话号码 4.家庭住址======\n");
printf("=========5.年龄 0.退出修改======\n");
printf("=====================================\n");
printf("-------------------------------------\n");
}
//查找内的菜单选择函数
void seekmenu_option(int a,int ret,contact* p1)
{
switch (a)
{
case NAME:
printf("请输入新姓名\n");
scanf("%s", p1->arr[ret].name);
printf("修改成功\n");
break;
case SEX:
printf("请输入新性别\n");
scanf("%s", p1->arr[ret].sex);
printf("修改成功\n");
break;
case TELE:
printf("请输入新电话号码\n");
scanf("%s", p1->arr[ret].tele);
printf("修改成功\n");
break;
case ADDRESS:
printf("请输入新家庭住址\n");
scanf("%s", p1->arr[ret].address);
printf("修改成功\n");
break;
case AGE:
printf("请输入新年龄\n");
scanf("%d", &p1->arr[ret].age);
printf("修改成功\n");
break;
case EXIT1:
printf("退出修改\n");
break;
default:
printf("请选择正确的选项\n");
break;
}
}
//菜单选择函数
void menu_option(int input,contact* p1)
{
switch (input)
{
case ADD:
perinf_add(p1);
break;
case DEL:
perinf_del(p1);
break;
case SEEK:
perinf_SEEK(p1);
break;
case MODIFY:
perinf_MODIFY(p1);
break;
case SORT:
perinf_sort(p1);
break;
case DISPLAY:
perinf_dispay(p1);
break;
case EXIT:
printf("退出成功,感谢使用。\n祝您生活美满,家庭幸福,身体健康\n");
break;
default:
printf("请重新选择正确的选项");
break;
}
}
//用户添加函数
void perinf_add(contact* p1)
{
if (p1->sz == MAX_PERSON)
{
printf("通讯录已满,添加失败\n");
return;
}
else
{
printf("请输入姓名:>\n");
scanf("%s", p1->arr[p1->sz].name);
printf("请输入性别:>\n");
scanf("%s", p1->arr[p1->sz].sex);
printf("请输入电话号码:>\n");
scanf("%s", p1->arr[p1->sz].tele);
printf("请输入年龄:>\n");
scanf("%d",&(p1->arr[p1->sz].age));
printf("请输入家庭住址:>\n");
scanf("%s", p1->arr[p1->sz].address);
}
p1->sz++;
printf("添加成功QvQ\n");
return;
}
//查找函数
int perinf_seek(contact* p1)
{
int i = 0;
char brr[MAX_NAME] = { 0 };
printf("请输入要操作的人名:>\n");
scanf("%s", brr);
//遍历查找人名
for (i = 0; i < p1->sz; i++)
{
if ((strcmp(p1->arr[i].name, brr) == 0))
{
return i;
}
}
return -1;
}
//删除函数
void perinf_del(contact* p1)
{
if (p1->sz == 0)
{
printf("当前通讯录尚未存入联系人,无法删除\n");
return;
}
int ret=perinf_seek(p1);
if (ret == -1)
{
printf("查无此人,无法删除\n");
return;
}
else
{
memmove(&(p1->arr[ret]), &(p1->arr[ret + 1]), (long long)(p1->sz - ret) * sizeof(p1->arr[0]));
printf("删除成功\n");
p1->sz--;
return;
}
}
//查询函数
void perinf_SEEK(contact* p1)
{
int ret=perinf_seek(p1);
if (ret == -1)
{
printf("查无此人\n");
return;
}
else
{
printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20s\n", "姓名", "性别", "电话号码", "家庭住址", "年龄");
printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20d\n", p1->arr[ret].name, p1->arr[ret].sex, p1->arr[ret].tele, p1->arr[ret].address, p1->arr[ret].age);
return;
}
}
//修改函数
void perinf_MODIFY(contact* p1)
{
int ret = perinf_seek(p1);
if (ret == -1)
{
printf("查无此人\n");
return;
}
else
{
int a = 0;
do
{
menu_seek();
scanf("%d", &a);
seekmenu_option(a, ret, p1);
} while (a);
}
}
//显示整个通讯录函数
void perinf_dispay(contact* p1)
{
int i = 0;
printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20s\n", "姓名", "性别", "电话号码", "家庭住址", "年龄");
for (i = 0; i < p1->sz; i++)
{
printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20d\n", p1->arr[i].name, p1->arr[i].sex, p1->arr[i].tele, p1->arr[i].address, p1->arr[i].age);
}
}
//排序函数
void perinf_sort(contact* p1)
{
int a = 0;
menu_sort();
printf("请选择排序方式\n");
scanf("%d", &a);
sortmenu_option(a, p1);
printf("排序完成\n");
}
//排序菜单函数
void menu_sort()
{
printf("请选择要修改的内容\n");
printf("-------------------------------------\n");
printf("=====================================\n");
printf("===1.按名字排序 2.按年龄排序===\n");
printf("=== 0.退出排序 ===\n");
printf("-------------------------------------\n");
}
//排序菜单选择函数
void sortmenu_option(int a,contact* p1)
{
int i = 0; int j = 0;
perinf tmp;
switch (a)
{
case SORTBYNAME:
for (i = 0; i < p1->sz; i++)
{
for (j = 0; j < p1->sz - 1; j++)
{
if (strcmp(p1->arr[j].name, p1->arr[j + 1].name) > 0)
{
tmp = p1->arr[j + 1];
p1->arr[j + 1] = p1->arr[j];
p1->arr[j] = tmp;
}
}
}
break;
case SORTBYAGE:
for (i = 0; i < p1->sz; i++)
{
for (j = 0; j < p1->sz - 1; j++)
{
if (p1->arr[j].age>p1->arr[j+1].age)
{
tmp = p1->arr[j + 1];
p1->arr[j + 1] = p1->arr[j];
p1->arr[j] = tmp;
}
}
}
break;
case EXIT2:
{
printf("退出排序\n");
}
break;
default:
printf("请选择正确的选项\n");
break;
}
}
具体实现步骤
搭建整体框架
#define _CRT_SECURE_NO_WARNINGS
#include"contact.h"
int main()
{
contact con;
Init_contact(&con);
int input = 0;
do
{
//打印菜单
menu_print();
printf("请选择您需要的功能:>\n");
scanf("%d", &input);
menu_option(input,&con);
} while (input);
return 0;
}
先定义一个contact 变量con,再利用通讯录初始化函数对con进行初始化。定义一个操作数input,用来接收用户的选择,用do...while循环实现多次操作(不然添加只能操作一次),do...while循环里面先用菜单打印函数,将选项呈现在用户面前,scanf接收用户的操作,后用菜单选项选择函数实现用户所选择的功能。
定义个人信息结构体类型
首先需要定义个人信息类型,存放联系人的各种信息,同时为了方便后续使用,我们将struct perinf重命名为perinf。
//定以个人信息结构体
typedef struct perinf
{
char name[MAX_NAME];
char sex[MAX_SEX];
char tele[MAX_TELE];
char address[MAX_ADDRESS];
int age;
}perinf;
这里我们设定的基础信息是姓名、性别、电话号码、家庭住址、年龄,都用数组存放,为了方便后续修改这些数组的大小,我们定义常变量来实现想法。
定义常变量
这里用不同的名字做区分
/重定义最大名字,最大性别,最大电话,最大通讯录名额,最大地址
#define MAX_NAME 100
#define MAX_SEX 100
#define MAX_TELE 100
#define MAX_PERSON 1000
#define MAX_ADDRESS 100
定义通讯录结构体类型
//定义通讯录类型
typedef struct contact
{
perinf arr[MAX_PERSON];
int sz;
}contact;
sz变量用作计数器,来表示通讯录当前的联系人数量有多少。
利用个人信息的结构体数组来实现联系人信息的添加、删除等操作。
定义初始化通讯录函数
void Init_contact(contact* p1)
{
p1->sz = 0;
memset(p1->arr, 0, sizeof(p1->arr));
}
将sz变量设置为零,表示通讯录目前是零个联系人 。用memmset将个人信息结构体数组arr初始化成零。
定义打印菜单函数
void menu_print()
{
printf("-------------------------------------\n");
printf("=====================================\n");
printf("=========1.添加 2.删除==========\n");
printf("=========3.查询 4.修改==========\n");
printf("=========5.排序 6.显示通讯录====\n");
printf("========= 0.退出 ==========\n");
printf("=====================================\n");
printf("-------------------------------------\n");
}
定义菜单选择函数
定义枚举类型
enum menu
{
EXIT,
ADD,
DEL,
SEEK,
MODIFY,
SORT,
DISPLAY
};
在这里是实现用户所选择的功能,为了增加代码阅读性,用了枚举类型来替换case后面的数字。
void menu_option(int input,contact* p1)
{
switch (input)
{
case ADD:
perinf_add(p1);
break;
case DEL:
perinf_del(p1);
break;
case SEEK:
perinf_SEEK(p1);
break;
case MODIFY:
perinf_MODIFY(p1);
break;
case SORT:
perinf_sort(p1);
break;
case DISPLAY:
perinf_dispay(p1);
break;
case EXIT:
printf("退出成功,感谢使用。\n祝您生活美满,家庭幸福,身体健康\n");
break;
default:
printf("请重新选择正确的选项");
break;
}
}
定义添加功能函数
我们这里先进行一个判断,判断通讯录是不是满了,没满就执行用户的录入,sz++来表示通讯录增加了一个函数,再用printf反馈添加成功。
//用户添加函数
void perinf_add(contact* p1)
{
if (p1->sz == MAX_PERSON)
{
printf("通讯录已满,添加失败\n");
return;
}
else
{
printf("请输入姓名:>\n");
scanf("%s", p1->arr[p1->sz].name);
printf("请输入性别:>\n");
scanf("%s", p1->arr[p1->sz].sex);
printf("请输入电话号码:>\n");
scanf("%s", p1->arr[p1->sz].tele);
printf("请输入年龄:>\n");
scanf("%d",&(p1->arr[p1->sz].age));
printf("请输入家庭住址:>\n");
scanf("%s", p1->arr[p1->sz].address);
}
p1->sz++;
printf("添加成功QvQ\n");
return;
}
定义删除函数
在删除前,先进行判断,一是有没有联系人,二是要删除的联系人存不存在。对于第二条,我们首先得找出要删除的人再进行删除操作。
//删除函数
void perinf_del(contact* p1)
{
if (p1->sz == 0)
{
printf("当前通讯录尚未存入联系人,无法删除\n");
return;
}
int ret=perinf_seek(p1);
if (ret == -1)
{
printf("查无此人,无法删除\n");
return;
}
else
{
memmove(&(p1->arr[ret]), &(p1->arr[ret + 1]), (long long)(p1->sz - ret) * sizeof(p1->arr[0]));
printf("删除成功\n");
p1->sz--;
return;
}
}
所以需要定义一个遍历查找函数
找到了就返回找到的元素下标,没找到就返回负一(因为数组中没有元素的下标是负一),判断是否找到我们利用strcmp函数
int perinf_seek(contact* p1)
{
int i = 0;
char brr[MAX_NAME] = { 0 };
printf("请输入要操作的人名:>\n");
scanf("%s", brr);
//遍历查找人名
for (i = 0; i < p1->sz; i++)
{
if ((strcmp(p1->arr[i].name, brr) == 0))
{
return i;
}
}
return -1;
}
定义查询函数
同样需要用到遍历查找函数,在删除函数那里已经给出定义。先打印题头然后再打印信息。
void perinf_SEEK(contact* p1)
{
int ret=perinf_seek(p1);
if (ret == -1)
{
printf("查无此人\n");
return;
}
else
{
printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20s\n", "姓名", "性别", "电话号码", "家庭住址", "年龄");
printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20d\n", p1->arr[ret].name, p1->arr[ret].sex, p1->arr[ret].tele, p1->arr[ret].address, p1->arr[ret].age);
return;
}
}
定义修改函数
同样是先遍历查找,找到了再开始修改。
//修改函数
void perinf_MODIFY(contact* p1)
{
int ret = perinf_seek(p1);
if (ret == -1)
{
printf("查无此人\n");
return;
}
else
{
int a = 0;
do
{
menu_seek();
scanf("%d", &a);
seekmenu_option(a, ret, p1);
} while (a);
}
}
修改菜单函数
void menu_seek()
{
printf("请选择要修改的内容\n");
printf("-------------------------------------\n");
printf("=====================================\n");
printf("=========1.姓名 2.性别==========\n");
printf("=========3.电话号码 4.家庭住址======\n");
printf("=========5.年龄 0.退出修改======\n");
printf("=====================================\n");
printf("-------------------------------------\n");
}
修改菜单选项实现函数
void seekmenu_option(int a,int ret,contact* p1)
{
switch (a)
{
case NAME:
printf("请输入新姓名\n");
scanf("%s", p1->arr[ret].name);
printf("修改成功\n");
break;
case SEX:
printf("请输入新性别\n");
scanf("%s", p1->arr[ret].sex);
printf("修改成功\n");
break;
case TELE:
printf("请输入新电话号码\n");
scanf("%s", p1->arr[ret].tele);
printf("修改成功\n");
break;
case ADDRESS:
printf("请输入新家庭住址\n");
scanf("%s", p1->arr[ret].address);
printf("修改成功\n");
break;
case AGE:
printf("请输入新年龄\n");
scanf("%d", &p1->arr[ret].age);
printf("修改成功\n");
break;
case EXIT1:
printf("退出修改\n");
break;
default:
printf("请选择正确的选项\n");
break;
}
}
定义上面使用到的枚举类型
enum menu_seek
{
EXIT1,
NAME,
SEX,
TELE,
ADDRESS,
AGE
};
定义排序函数
打印排序菜单,进入排序菜单选项实现函数
void perinf_sort(contact* p1)
{
int a = 0;
menu_sort();
printf("请选择排序方式\n");
scanf("%d", &a);
sortmenu_option(a, p1);
printf("排序完成\n");
}
定义排序菜单打印函数
//排序菜单函数
void menu_sort()
{
printf("请选择要修改的内容\n");
printf("-------------------------------------\n");
printf("=====================================\n");
printf("===1.按名字排序 2.按年龄排序===\n");
printf("=== 0.退出排序 ===\n");
printf("-------------------------------------\n");
}
定义排序菜单选项实现函数
使用的是冒泡排序,提供了两种排序方式,一种是按照名字排序,一种是按照年龄排序(敲这个函数的时候已经了凌晨一点了,偷懒只做了升序)
//排序菜单选择函数
void sortmenu_option(int a,contact* p1)
{
int i = 0; int j = 0;
perinf tmp;
switch (a)
{
case SORTBYNAME:
for (i = 0; i < p1->sz; i++)
{
for (j = 0; j < p1->sz - 1; j++)
{
if (strcmp(p1->arr[j].name, p1->arr[j + 1].name) > 0)
{
tmp = p1->arr[j + 1];
p1->arr[j + 1] = p1->arr[j];
p1->arr[j] = tmp;
}
}
}
break;
case SORTBYAGE:
for (i = 0; i < p1->sz; i++)
{
for (j = 0; j < p1->sz - 1; j++)
{
if (p1->arr[j].age>p1->arr[j+1].age)
{
tmp = p1->arr[j + 1];
p1->arr[j + 1] = p1->arr[j];
p1->arr[j] = tmp;
}
}
}
break;
case EXIT2:
{
printf("退出排序\n");
}
break;
default:
printf("请选择正确的选项\n");
break;
}
}
定义上面用到的枚举类型
enum menu_sort
{
EXIT2,
SORTBYNAME,
SORTBYAGE
};
定义显示整个通讯录函数
//显示整个通讯录函数
void perinf_dispay(contact* p1)
{
int i = 0;
printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20s\n", "姓名", "性别", "电话号码", "家庭住址", "年龄");
for (i = 0; i < p1->sz; i++)
{
printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20d\n", p1->arr[i].name, p1->arr[i].sex, p1->arr[i].tele, p1->arr[i].address, p1->arr[i].age);
}
}
总结
仅仅是初级版,后续会有升级,提供了实现增删查改的思路,希望能帮助同志们嘎嘎乱杀学校大作业!