如果要源码,直接拉到最底
首先声明,该系统的要求是按照我之前所看的“黑马程序员”的c++教学视频里的那个要求来写的,前期的几段代码有仿照的作法,还请见谅,但基本上是有本人亲手所写,所以,在逻辑思路上能比较的清晰。
之所以写这篇博客也不完全是因为想要开源代码,毕竟写得很烂嘛。但是,为了所谓的费曼学习法,假比看我博客的人就是所谓的我要去教授的人,那我通过写博客的方式理清思路,去更好得加深记忆点,以此来帮助我更好的学习c++程序设计。
好了,说了这么多,现在就来说说,我是如何“操纵”这篇代码的。
void setMenu() {
cout << "*********************" << endl;
cout << "****1、添加联系人****" << endl;
cout << "****2、显示联系人****" << endl;
cout << "****3、删除联系人****" << endl;
cout << "****4、查找联系人****" << endl;
cout << "****5、修改联系人****" << endl;
cout << "****6、清空联系人****" << endl;
cout << "****0、退出通讯录****" << endl;
cout << "*********************" << endl;
}
接着,你得在主函数中调用它,所以,你得有#include包含进头文件:
#include
using namespace std;
#include
#include"stdio.h"
其实这里的stdio.h可以不用包含进去,因为上面已经声明了c++的头文件形式,之所以在这加是为了防止某些操作的不合法。然后提前包含进string头文件,以免待会用到string类型时程序报错。
接着,我们就可以看到该有的效果啦,如下:
#include
using namespace std;
#include
#include"stdio.h"
void setMenu() {
cout << "*********************" << endl;
cout << "****1、添加联系人****" << endl;
cout << "****2、显示联系人****" << endl;
cout << "****3、删除联系人****" << endl;
cout << "****4、查找联系人****" << endl;
cout << "****5、修改联系人****" << endl;
cout << "****6、清空联系人****" << endl;
cout << "****0、退出通讯录****" << endl;
cout << "*********************" << endl;
}
int main() {
setMenu();
system("pause");
return 0;
}
但是,要求里既然说这是个菜单,那么菜单就得有选项吧,不能就光光一个菜单,没有输入操作来选择这些菜单里的功能吧。
所以,我们还得在主函数(main)里写一个选择函数,这里我们依照习惯,用的是switch()函数。如下:
int main() {
int select = 0;
while (true)
{
setMenu();
cin >> select;
switch (select)
{
case 1://添加联系人
break;
case 2://显示联系人
break;
case 3://删除联系人
break;
case 4://查找联系人
break;
case 5://修改联系人
break;
case 6://清空通讯录
break;
case 0://退出通讯录
break;
default:
break;
}
}
system("pause");
return 0;
}
从上面我们可以看出,我们把“输入(cin)”,“选择函数(switch)”,“菜单函数(menu)”,都放在了while循环的里面。之所以这样,是因为我们需要在进行了某个选项的操作之后,还能继续进行选择。
好啦,一个要求我们就已经做好了,接下来看第二要求。
case 0://退出通讯录
cout << "欢迎下次使用" << endl;
system("pause");
return 0;
break;
这就完成了,我们所需要的退出操作啦。
struct Person
{
string name; //1、姓名
int sex; //2、性别
int age; //3、年龄
int telephone;//4、手机号
string add; //5、地址
}; //创建联系人结构体
接着我们还得创建一个通讯录结构体,并且在通讯录结构体中创建联系人结构体的数组,为了使开辟的数组空间方便后期调试和修改,所以我们在声明头文件的代码下架了一条:
#include
using namespace std;
#include
#include"stdio.h"
int const MAX =1000;
这样创造一个全局的常变量MAX,使得MAX的值等于1000,以此来说明一会儿要在空间上开辟的数组的个数为1000个。如下:
struct ADDressbooks
{
Person personArray[MAX];//通讯录保存联系人数组
int size;//通讯录中人员个数
}; //创建通讯录结构体
这样就创造了一个还算合格的通讯录结构体和联系人结构体。
之后,按照他的要求,我们得在main()函数中创建一个通讯录对象:
//声明通讯录结构体变量
ADDressbooks ads;
//初始化联系人数量
ads.size = 0;
并且,我们为了能在switch()的选项里使用这个通讯录的对象,我们就把该结构体对象创建在while()函数的前面。
接下来就是封装添加联系人函数。其实到这我就和“黑马程序员”里的那个代码有所不同了,因为再黑马那的代码是在主函数中创建的时联系人结构体变量的指针,ADDressbooks *ads
,然后在函数调用的时候,传递的实参是结构体的首地址——&ads,并且在形参那同样用指针作为函数形参,所以整个代码看上去比较繁琐。
而我用的是c++特有的引用,所以在创建通讯录结构体变量时,就只是普通的创建变量的方式。好,让我们来看看代码是如何写的吧
首先是主函数里的调用:
case 1://添加联系人
AddPerson(ads);
break;
这里就直接是把结构体变量ads写入到函数实参中去,但是因为我们的函数形参所用的是引用接收变量,所以得到的是一个变量ads的首地址。
添加联系人的函数如下:
//添加联系人函数
void AddPerson(ADDressbooks &ads) {
if (ads.size == MAX) {
cout << "通讯录已满,请删除后重试" << endl;
return;
}
else {
//添加具体联系人
//姓名
string name;
cout << "请输入姓名" << endl;
cin >> name;
ads.personArray[ads.size].name = name;
//性别
int sex=0;
cout << "请输入性别" << endl;
cout << "1---男" << endl;
cout << "2---女" << endl;
while (sex != 1 || sex != 2) {
cin >> sex;
if (sex == 1 || sex == 2) {
ads.personArray[ads.size].sex = sex;
break;
}
else {
cout << "输入错误,请重新输入" << endl;
}
}
//年龄
int age;
cout << "请输入年龄" << endl;
cin >> age;
ads.personArray[ads.size].age = age;
//手机号
int telephone;
cout << "请输入手机号" << endl;
cin >> telephone;
ads.personArray[ads.size].telephone = telephone;
//地址
string addr;
cout << "请输入地址" << endl;
cin >> addr;
ads.personArray[ads.size].add = addr;
}
//更新通讯录联系人
ads.size++;
cout << "成功添加联系人" << endl;
system("pause");
system("cls");//清屏操作
}
因为至少先得判断通讯录是不是已经满了,所以我们用if-else的分支选择操作来判断,如果满了就返回“通讯录已满”,如果没满,就继续执行添加操作。然后,我们可以看到在输入性别那多出了一步循环的操作,是因为我们没有采用输入字符串的方式来添加性别,而是用数字代码代替字符串的操作来执行添加性别的操作,这样也方便了我们不用再多执行一步判断字符串是否相等的操作。只需要使在循环条件为真(true)时,我们可以通过判断来执行所要添加的联系人的性别,并且在输入错误时通过循环改正,知道输入的只时男/女(1/2)为止。但是,我为了保护while循环的安全性,把里面的循环条件——true,改成了sex != 1 || sex != 2,防止出现死循环的情况。
还有就是,因为该函数是放在主函数里的while循环里——为了重复出现菜单选项,所以,就有可能造成菜单选项在一个界面上出现过多的情况,为了看起来美观,我在接下来的每个被调用的函数末尾,包括现在的这个添加联系人函数末尾,添加了一个 system(“pause”);
system(“cls”); 这样的代码来执行清屏操作。
并且在函数的最后我们也同时写了一个ads.size++的代码,以此来更新通讯录联系人的数量(联系人+1)
好啦,添加联系人的操作到目前为止就结束了。现在我们得继续我们的题目要求了。
case 2://显示联系人
showPerson(ads);
break;
//显示联系人
void showPerson(ADDressbooks &ads) {
//cout << ads.size << endl;
if (ads.size == 0) {
cout << "通讯录联系人为空" << endl;
}
else {
//显示联系人操作
for (int i = 0;i < ads.size;i++) {
cout << "姓名:" << ads.personArray[i].name << '\t';
cout << "性别:" << (ads.personArray[i].sex ==1 ? "男":"女" )<< '\t';
cout << "年龄:" << ads.personArray[i].age << '\t';
cout << "电话:" << ads.personArray[i].telephone << '\t';
cout << "地址:" << ads.personArray[i].add << '\t';
cout << endl;
}
}
system("pause");
system("cls");
}
这样,就写好了。我们可以从上面的代码中看到,我们同样对上面的代码做了一个判断的操作。之所使用这样的操作的目的是使代码看上去更加得健壮性,在遇到执行代码时的未知的情况的时候,我们可以对它采取相应的措施,这样的习惯也应该在未来无论你写的哪一种代码下都适用。
还有,同样是在性别那,在输出的时候,因为,我们录入的性别是数字代码代替的,所以输出的时候,我们希望是中文字符串——男/女,因此我们直接使用了布尔函数,也就是在该条件为真时输出分号(:)左边的值(字符串),为假时输出右边的。
并且为了使输出看上去更加啊有概括性,在输出(cout)最后用了制表符(’/t’)来控制输出时各成员之间的间隔。
接下来是删除联系人的功能,要完成此功能呢,我们首先得先知道该联系人是否存在,也就是查找该联系人。如果存在返回该联系人的位置,如果不存在就返回-1。由于这里没有要求我们去判断如果联系人姓名相同的情况下该如何处理,所以就不加条件了。当然如果你要判断两个联系人相等的情况下该如何处理,应该不难想到,那就是在添加联系人操作的时候,先判断该联系人是否已经存在,如果存在,那就强制在所要添加得相同联系人的姓名后面加上一个编号即可。
回归正题,我们现在首先得解决的是判断是否存在。但是,由于写了上面的代码之后,就没有再继续模仿着黑马那边的代码写,所以,会有一些偏差。我的代码是先创建了一个删除联系人的函数,如下:
//删除联系人
void deletePerson(ADDressbooks &ads) {
string name;
cout << "请输入您要删除的联系人姓名" << endl;
cin >> name;
int value=isExist(ads, name);
if (value == -1) {
cout << "该联系人为空" << endl;
}
else {
//进行删除操作
if(value!=MAX){
for (int i = value;i < ads.size;i++) {
ads.personArray[i] = ads.personArray[i + 1];
}
}
else {
ads.personArray[value] = { "XXX",0,0,00000000000,"XXX XXX XXX" };
}
cout << "删除成功" << endl;
}
ads.size--;
system("pause");
system("cls");
}
case 3://删除联系人
deletePerson(ads);
break;
因为是删除联系人操作,所以我们先用输入一个姓名,然后用函数来进行查找是否存在,并用该函数的返回值来进行分支操作。判断函数如下:
//判断联系人是否存在函数
int isExist(ADDressbooks &ads,string name) {
int m=0;
for (int i = 0;i < ads.size;i++) {
if (ads.personArray[i].name != name) {
m = m + 1;
}
else { return i; }
}
if (m == ads.size) { return -1; }
}
可以看到,该函数的形参,一个是结构体的引用,用来接收该结构体的首地址,到了这里其实就可以发现引用的好处了,因为引用是地址传递,实参输入的是变量,但是传过去的是变量的地址,并且,在这里还可以看到,用引用的话,在函数中调用另一个函数的话,两个函数他就没必要反复得去创建指针变量gai。因为该变量是在主函数中创建的,然后用它传一个实参给一个函数,并且在该函数中又把所接收的该实参的地址传递给另一个函数,有点像无限套娃的操作哈,不过,用一个通俗点的语言来说,就是,我在不断传这个变量的时候,传的只是我的地址,包括这个变量在进入了这个函数之后,继续通过引用传递给下一个函数的时候,传的仍然还是该变量的地址,并没有说我当前接收的是该变量的地址,那么我再用该变量的地址作实参继续传递给下一个函数的时候,就是该变量地址的地址。(之所以写那么多,我就来备注下说说,其实这才是我最想写的内容,因为他很逻辑化,考察的不是代码技术的问题,而是逻辑的问题,所以,这也是我在写这篇代码的时候和黑马那边的不一样,那边的代码比较得通俗易懂,他没有函数套函数,俄罗斯套娃,这样恶心的东西,老师教起来也好教,但是他不够深。还有,他用的是指针,并不是说指针不好,但他就是太繁琐了一点,如果用指针的话:就像这样
//声明通讯录结构体变量
ADDressbooks *ads;
//初始化联系人数量
(*ads).size = 0;
case 3://删除联系人
deletePerson(&ads);
break;
//判断联系人是否存在函数
int isExist(ADDressbooks *ads,string name) {
int m=0;
for (int i = 0;i < (*ads).size;i++) {
if ((*ads).personArray[i].name != name) {
m = m + 1;
}
else { return i; }
}
if (m == (*ads).size) { return -1; }
}
//删除联系人
void deletePerson(ADDressbooks *ads) {
string name;
cout << "请输入您要删除的联系人姓名" << endl;
cin >> name;
int value=isExist(&(*ads), name);
if (value == -1) {
cout << "该联系人为空" << endl;
}
else {
//进行删除操作
if(value!=MAX){
for (int i = value;i < (*ads).size;i++) {
(*ads).personArray[i] = (*ads).personArray[i + 1];
}
}
else {
(*ads).personArray[value] = { "XXX",0,0,00000000000,"XXX XXX XXX" };
}
cout << "删除成功" << endl;
}
system("pause");
system("cls");
}
这样看上去也没有我之前用引用写得那么直观)
还有,用因为引用的话,在函数中你可以直接用变量名(别名)来调用结构体内的成员。(这个应该还算好懂)
其次是字符串变量name用来接收所要查找的联系人姓名(这段话如果看不懂的话,连着上面第一段的第一句话就懂了)。
接着,我们来说该“判断是否删除了联系人函数”的事。由于上面已经说明了该函数的型参数和形参类型,接下来就来解释一下,该函数为啥创建了一个局部变量m。因为我们想得到的是一个该联系人是否存在的结果,存在就返回该联系人所在的位置,不存在就返回-1。因此,为了使得该函数更加得有健壮性,多创造了一个变量m,用如果m等于现在所有的联系人的人数来判断该如何返回,如果m等于现在所有的联系人的人数,在循环遍历整个结构体数组时没有找到该联系人,所以判断他不存在,接着,如果,判断结果是找到了该联系人,则直接返回当前循环中的“i”的值,来表示该联系人现在所在的位置。
然后,在删除联系人函数里面,我们通过创建一个value变量来接收是否存在函数的返回值。然后,再对他进行操作。由于这里删除函数的操作是一个顺序表删除函数的操作(如果看过本人上篇博客的人,应该都知道,我现在还没有去学数据结构,当然,也包括现在),所以就直接是前面的数据等于后面的数据就可以了。
case 4://查找联系人
foundPerson(ads);
break;
//查找联系人
void foundPerson(ADDressbooks &ads) {
string name;
cout << "请输入您要查找的联系人姓名:" << endl;
cin >> name;
int value = isExist(ads, name);
if (value == -1) {
cout << "您要查找的联系人未在通讯录" << endl;
}
else {
cout << "姓名:" << ads.personArray[value].name << '\t';
cout << "性别:" << (ads.personArray[value].sex == 1 ? "男" : "女") << '\t';
cout << "年龄:" << ads.personArray[value].age << '\t';
cout << "电话:" << ads.personArray[value].telephone << '\t';
cout << "地址:" << ads.personArray[value].add << '\t';
cout << endl;
}
system("pause");
system("cls");
}
延用显示联系人时输出的格式,然后延用判断是否练习人是否存在的函数,继续俄罗斯套娃。
所以同样时延用判断是否存在该联系人函数,和延用添加联系人那的输入格式:
case 5://修改联系人
chancePerson(ads);
break;
//修改联系人
void chancePerson(ADDressbooks &ads) {
string name;
cout << "请输入你要修改的联系人姓名:" << endl;
cin >> name;
//修改方案
int value = isExist(ads, name);
if (value == -1) {
cout << "您所要修改的联系人方式不存在" << endl;
}
else {
//姓名
string name;
cout << "请输入姓名" << endl;
cin >> name;
ads.personArray[value].name = name;
//性别
int sex = 0;
cout << "请输入性别" << endl;
cout << "1---男" << endl;
cout << "2---女" << endl;
while (sex != 1 || sex != 2) {
cin >> sex;
if (sex == 1 || sex == 2) {
ads.personArray[value].sex = sex;
break;
}
else {
cout << "输入错误,请重新输入" << endl;
}
}
//年龄
int age;
cout << "请输入年龄" << endl;
cin >> age;
ads.personArray[value].age = age;
//手机号
int telephone;
cout << "请输入手机号" << endl;
cin >> telephone;
ads.personArray[value].telephone = telephone;
//地址
string addr;
cout << "请输入地址" << endl;
cin >> addr;
ads.personArray[value].add = addr;
}
system("pause");
system("cls");
}
该操作,也可以直接从黑马那看到的是,他用了一个逻辑删除的操作。
case 6://清空通讯录
clearPerson(ads);
break;
//清空通讯录
void clearPerson(ADDressbooks &ads) {
ads.size = 0;//只执行逻辑清空,size的值变为0说明在添加操作那的size++所操作的size值全变为0
cout << "联系人已清空" << endl;
system("pause");
system("cls");
}
逻辑删除是直接把记录所加联系人数量的结构体的成员变量size变来等于0,但是结构体数组里面的成员各个成员都还在,但是我未对此做多余的功能和操作,所以用户在清空了通讯录之后也无法查看到结构体数组里面的成员。
好啦,写到结尾,其实我有点疲了,如果各位看官不满意,我余下再改即可,还有这是你们要的源码
#include
using namespace std;
#include
#include"stdio.h"
int const MAX =1000;
void setMenu() {
cout << "*********************" << endl;
cout << "****1、添加联系人****" << endl;
cout << "****2、显示联系人****" << endl;
cout << "****3、删除联系人****" << endl;
cout << "****4、查找联系人****" << endl;
cout << "****5、修改联系人****" << endl;
cout << "****6、清空联系人****" << endl;
cout << "****0、退出通讯录****" << endl;
cout << "*********************" << endl;
}
struct Person
{
string name; //1、姓名
int sex; //2、性别
int age; //3、年龄
int telephone;//4、手机号
string add; //5、地址
}; //创建联系人结构体
struct ADDressbooks
{
Person personArray[MAX];//通讯录保存联系人数组
int size;//通讯录中人员个数
}; //创建通讯录结构体
//添加联系人函数
void AddPerson(ADDressbooks &ads) {
if (ads.size == MAX) {
cout << "通讯录已满,请删除后重试" << endl;
return;
}
else {
//添加具体联系人
//姓名
string name;
cout << "请输入姓名" << endl;
cin >> name;
ads.personArray[ads.size].name = name;
//性别
int sex=0;
cout << "请输入性别" << endl;
cout << "1---男" << endl;
cout << "2---女" << endl;
while (sex != 1 || sex != 2) {
cin >> sex;
if (sex == 1 || sex == 2) {
ads.personArray[ads.size].sex = sex;
break;
}
else {
cout << "输入错误,请重新输入" << endl;
}
}
//年龄
int age;
cout << "请输入年龄" << endl;
cin >> age;
ads.personArray[ads.size].age = age;
//手机号
int telephone;
cout << "请输入手机号" << endl;
cin >> telephone;
ads.personArray[ads.size].telephone = telephone;
//地址
string addr;
cout << "请输入地址" << endl;
cin >> addr;
ads.personArray[ads.size].add = addr;
}
//更新通讯录联系人
ads.size++;
cout << "成功添加联系人" << endl;
system("pause");
system("cls");//清屏操作
}
//显示联系人
void showPerson(ADDressbooks &ads) {
//cout << ads.size << endl;
if (ads.size == 0) {
cout << "通讯录联系人为空" << endl;
}
else {
//显示联系人操作
for (int i = 0;i < ads.size;i++) {
cout << "姓名:" << ads.personArray[i].name << '\t';
cout << "性别:" << (ads.personArray[i].sex ==1 ? "男":"女" )<< '\t';
cout << "年龄:" << ads.personArray[i].age << '\t';
cout << "电话:" << ads.personArray[i].telephone << '\t';
cout << "地址:" << ads.personArray[i].add << '\t';
cout << endl;
}
}
system("pause");
system("cls");
}
//判断联系人是否存在函数
int isExist(ADDressbooks &ads,string name) {
int m=0;
for (int i = 0;i < ads.size;i++) {
if (ads.personArray[i].name != name) {
m = m + 1;
}
else { return i; }
}
if (m == ads.size) { return -1; }
}
//删除联系人
void deletePerson(ADDressbooks &ads) {
string name;
cout << "请输入您要删除的联系人姓名" << endl;
cin >> name;
int value=isExist(ads, name);
if (value == -1) {
cout << "该联系人为空" << endl;
}
else {
//进行删除操作
if(value!=MAX){
for (int i = value;i < ads.size;i++) {
ads.personArray[i] = ads.personArray[i + 1];
}
}
else {
ads.personArray[value] = { "XXX",0,0,00000000000,"XXX XXX XXX" };
}
cout << "删除成功" << endl;
}
ads.size--;
system("pause");
system("cls");
}
//查找联系人
void foundPerson(ADDressbooks &ads) {
string name;
cout << "请输入您要查找的联系人姓名:" << endl;
cin >> name;
int value = isExist(ads, name);
if (value == -1) {
cout << "您要查找的联系人未在通讯录" << endl;
}
else {
cout << "姓名:" << ads.personArray[value].name << '\t';
cout << "性别:" << (ads.personArray[value].sex == 1 ? "男" : "女") << '\t';
cout << "年龄:" << ads.personArray[value].age << '\t';
cout << "电话:" << ads.personArray[value].telephone << '\t';
cout << "地址:" << ads.personArray[value].add << '\t';
cout << endl;
}
system("pause");
system("cls");
}
//修改联系人
void chancePerson(ADDressbooks &ads) {
string name;
cout << "请输入你要修改的联系人姓名:" << endl;
cin >> name;
//修改方案
int value = isExist(ads, name);
if (value == -1) {
cout << "您所要修改的联系人方式不存在" << endl;
}
else {
//姓名
string name;
cout << "请输入姓名" << endl;
cin >> name;
ads.personArray[value].name = name;
//性别
int sex = 0;
cout << "请输入性别" << endl;
cout << "1---男" << endl;
cout << "2---女" << endl;
while (sex != 1 || sex != 2) {
cin >> sex;
if (sex == 1 || sex == 2) {
ads.personArray[value].sex = sex;
break;
}
else {
cout << "输入错误,请重新输入" << endl;
}
}
//年龄
int age;
cout << "请输入年龄" << endl;
cin >> age;
ads.personArray[value].age = age;
//手机号
int telephone;
cout << "请输入手机号" << endl;
cin >> telephone;
ads.personArray[value].telephone = telephone;
//地址
string addr;
cout << "请输入地址" << endl;
cin >> addr;
ads.personArray[value].add = addr;
}
system("pause");
system("cls");
}
//清空通讯录
void clearPerson(ADDressbooks &ads) {
ads.size = 0;//只执行逻辑清空,size的值变为0说明在添加操作那的size++所操作的size值全变为0
cout << "联系人已清空" << endl;
system("pause");
system("cls");
}
int main(){
//声明通讯录结构体变量
ADDressbooks ads;
//初始化联系人数量
ads.size = 0;
int select=0;
while (true)
{
setMenu();
cin >> select;
switch (select)
{
case 1://添加联系人
AddPerson(ads);
break;
case 2://显示联系人
showPerson(ads);
break;
case 3://删除联系人
deletePerson(ads);
break;
case 4://查找联系人
foundPerson(ads);
break;
case 5://修改联系人
chancePerson(ads);
break;
case 6://清空通讯录
clearPerson(ads);
break;
case 0://退出通讯录
cout << "欢迎下次使用" << endl;
system("pause");
return 0;
break;
default:
cout << "输入有误,请重新输入" << endl;
system("pause");
system("cls");
continue;
}
}
system("pause");
return 0;
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200719165102402.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1l3ZWlL,size_16,color_FFFFFF,t_70