前言
最近跟着b站的c++视频做了一个通讯录管理系统的程序,本文会简单分析这种程序代码的结构、设计思路以及涉及其中的一些c++语言知识和用法。 在此附上相关视频链接:https://www.bilibili.com/video/BV1et411b73Z?p=83&spm_id_from=pageDriver 如若涉及侵权,请告知作者删改
一、程序设计思路
先来看看这个程序的需要的功能 从这张图片我们可以看到,这样的一个通讯录管理系统的功能上就有7个选项,除开最后的“退出通讯录”,共有6个功能。从功能导向的思路来看,我们至少需要6个相应的函数去实现。 除此之外,我们还需要显示该菜单,除了0选项之外,每个功能使用后还可再次使用,或者选择其他功能,而菜单提供的功能又这么多,说明我们在main函数中需要循环结构和分支选择结构。
二、代码结构(附相关源码)
1、菜单栏显示
要显示上面的菜单,而且会出现多次使用该菜单的情况,不妨将其定义成函数。(当然,宏定义也是可以,读者不妨可以试试)
void showMenu()
{
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;
}
2、功能选择
前面提到了这一块的思路:循环+分支选择
int main()
{
int select = 0;
Address_List adl;
adl.m_size = 0;
while (1)
{
showMenu();
cin >> select;
switch (select)
{
case 1:
addPerson(&adl);
break;
case 2:
showPerson(&adl);
break;
case 3:
deletePerson(&adl);
break;
case 4:
findPerson(&adl);
break;
case 5:
modifyPerson(&adl);
break;
case 6:
cleanPerson(&adl);
break;
case 0:
cout << "欢迎下次使用" << endl;
system("pause");
return 0;
default:
break;
}
}
system("pause");
return 0;
}
其中的一些自定义的结构体变量,在此有相关代码
struct Person
{
string m_name;
int m_gender;
int m_age;
string m_phone_number;
string m_address;
};
struct Address_List
{
Person personArr[MAX];
int m_size;
};
结构体变量有“联系人”结构体和“通讯录”结构体。前者用来记录联系人的信息,后者用于存储联系人结构体。
3、添加联系人
联系人的添加涉及到了数据的输入,存储。 而存储是有限的,对通讯录数组的最大容量有限制。因此在添加联系人时要先判断通讯录是否满了。
void addPerson(Address_List* adl)
{
if (adl->m_size == MAX)
{
cout << "通讯录已满,无法添加!" << endl;
}
else
{
string name;
cout << "请输入姓名: " << endl;
cin >> name;
adl->personArr[adl->m_size].m_name = name;
int gender;
cout << "请输入性别: " << endl;
cout << "1——男" << endl;
cout << "2——女" << endl;
while (1)
{
cin >> gender;
if (gender == 1 || gender == 2)
{
adl->personArr[adl->m_size].m_gender = gender;
break;
}
cout << "错误输入,请重新输入!" << endl;
}
int age;
cout << "请输入年龄: " << endl;
while (1)
{
cin >> age;
if (age >= 0 && age <= 150)
{
adl->personArr[adl->m_size].m_age = age;
break;
}
cout << "错误输入,请重新输入!" << endl;
}
string phonenum;
cout << "请输入手机号码: " << endl;
while (1)
{
cin >> phonenum;
int b = 0;
int len = phonenum.length();
for (int i = 0; i < len; i++)
{
if (phonenum[i] >= 48 && phonenum[i] <= 57)
{
continue;
}
b = 1;
break;
}
if (b)
{
cout << "手机号码输入错误,请重新输入: " << endl;
}
else
{
adl->personArr[adl->m_size].m_phone_number = phonenum;
break;
}
}
string address;
cout << "请输入联系人地址: " << endl;
cin >> address;
adl->personArr[adl->m_size].m_address = address;
cout << "添加成功!" << endl;
adl->m_size++;
system("pause");
system("cls");
}
}
这其中在输入上有一些考量与限制,比如性别,手机号码。
4、显示联系人
思路:先判断通讯录是否为空,不空才输出联系人信息。
void showPerson(Address_List* adl)
{
if (adl->m_size == 0)
{
cout << "当前通讯录记录为空" << endl;
}
else
{
for (int i = 0; i < adl->m_size; i++)
{
cout << "姓名: " << adl->personArr[i].m_name << "\t"
<< "性别: " << (adl->personArr[i].m_gender == 1 ? "男" : "女") << "\t"
<< "年龄: " << adl->personArr[i].m_age << "\t"
<< "手机号码: " << adl->personArr[i].m_phone_number << "\t"
<< "地址: " << adl->personArr[i].m_address << endl;
}
}
system("pause");
system("cls");
}
5、删除联系人
思路类似,需要先判断联系人是否在通讯录中。 然后,对删除操作的思路其实就是做循环让后面的联系人信息覆盖要删除的信息,这种思路在作者的上一篇blog即编程题总结中的第一题数组原地去重的思路类似。 删除后,会更新通讯录中联系人人数。
int isExist(Address_List* adl, string name)
{
for (int i = 0; i < adl->m_size; i++)
{
if (adl->personArr[i].m_name == name)
{
return i;
}
}
return -1;
}
void deletePerson(Address_List* adl)
{
cout << "请输入你要删除的联系人: " << endl;
string name;
cin >> name;
int ret = isExist(adl, name);
if (ret == -1)
{
cout << "查无此人" << endl;
}
else
{
for (int i = ret; i < adl->m_size; i++)
{
adl->personArr[i] = adl->personArr[i + 1];
}
adl->m_size--;
cout << "删除成功!" << endl;
}
system("pause");
system("cls");
}
6、查找联系人
与删除类似,判断联系人是否在通讯录,同时利用判断函数返回的联系人在通讯录数组的索引。
void findPerson(Address_List* adl)
{
cout << "请输入你要查找的联系人: " << endl;
string name;
cin >> name;
int ret = isExist(adl, name);
if (ret != -1)
{
cout << "姓名: " << adl->personArr[ret].m_name << "\t"
<< "性别: " << (adl->personArr[ret].m_gender == 1 ? "男" : "女") << "\t"
<< "年龄: " << adl->personArr[ret].m_age << "\t"
<< "手机号码: " << adl->personArr[ret].m_phone_number << "\t"
<< "地址: " << adl->personArr[ret].m_address << endl;
}
else
{
cout << "查无此人!" << endl;
}
system("pause");
system("cls");
}
7、修改联系人
思路类似,同时由于涉及到信息的输入,所以也要考虑前面的添加联系人需要考虑的因素。
void modifyPerson(Address_List* adl)
{
cout << "请输入你要修改的联系人" << endl;
string name;
cin >> name;
int ret = isExist(adl, name);
if (ret == -1)
{
cout << "查无此人" << endl;
}
else
{
cout << "请输入姓名: " << endl;
cin >> name;
adl->personArr[ret].m_name = name;
cout << "请输入性别: " << endl;
cout << "1——男" << endl
<< "2——女" << endl;
int gender;
while (1)
{
cin >> gender;
if (gender == 1 || gender == 2)
{
adl->personArr[ret].m_gender = gender;
break;
}
cout << "性别输入错误,请重新输入" << endl;
}
cout << "请输入年龄: " << endl;
int age;
while (1)
{
cin >> age;
if (age >= 0 && age <= 150)
{
adl->personArr[ret].m_age = age;
break;
}
cout << "年龄输入错误,请重新输入" << endl;
}
cout << "请输入联系人号码: " << endl;
string phonenum;
while (1)
{
cin >> phonenum;
int b = 0;
int len = phonenum.length();
for (int i = 0; i < len; i++)
{
if (phonenum[i] >= 48 && phonenum[i] <= 57)
{
continue;
}
b = 1;
break;
}
if (b)
{
cout << "手机号码输入错误,请重新输入: " << endl;
}
else
{
adl->personArr[adl->m_size].m_phone_number = phonenum;
break;
}
}
cout << "请输入地址: " << endl;
string address;
cin >> address;
adl->personArr[ret].m_address = address;
}
system("pause");
system("cls");
}
8、清空联系人
就是清空通讯录,前面提到的用来记录的通讯录中联系人数量的变量此时做赋值为0的操作,而不是真的一个个去把这些信息去除掉,思路和删除联系人类似。
void cleanPerson(Address_List* adl)
{
cout << "是否需要清空通讯录" << endl
<< "1——是\t2——否" << endl;
int n = 0;
while (true)
{
cin >> n;
if (n == 1)
{
adl->m_size = 0;
cout << "通讯录已清空" << endl;
break;
}
else if (n == 2)
{
break;
}
else
{
cout << "错误输入,请重新输入" << endl;
}
}
system("pause");
system("cls");
}
二、小知识
1、数据结构数组和数据结构的嵌套 如图,这种在一个数据结构的定义中提到另一个数据结构就是数据结构的嵌套,同时personArr也是一种数据结构数组。 2、指针使用 在本文中的大量代码,尤其是函数的参数都使用了数据结构指针,为什么不适用值传递,而是选择指针传递呢? 原因有二:其一,指针传递可以直接对通讯录联系人等信息的修改;其二,当通讯录中联系人太多的时候会导致函数在调用的时候使用内存太大。这无疑会导致函数的栈帧空间过大,会使得这个程序的空间复杂度过大。而指针的好处在于,c++对于指针,其内存被定义为4个字节。无论这个指针的类型是什么。在函数调用,内存可以有极大的节省。
3、清屏操作
system(“pause”) 用于任意键继续 system(“cls”) 用于清屏操作 使用清屏主要是因为,在每次使用一次功能菜单后的信息显示过多,而且当使用次数过多时会显得很不美观。清屏配合循环结构在显示上会很棒。
三、程序源码
#include <iostream>
#include<string>
using namespace std;
#define MAX 1000
struct Person
{
string m_name;
int m_gender;
int m_age;
string m_phone_number;
string m_address;
};
struct Address_List
{
Person personArr[MAX];
int m_size;
};
void showMenu()
{
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;
}
void addPerson(Address_List* adl)
{
if (adl->m_size == MAX)
{
cout << "通讯录已满,无法添加!" << endl;
}
else
{
string name;
cout << "请输入姓名: " << endl;
cin >> name;
adl->personArr[adl->m_size].m_name = name;
int gender;
cout << "请输入性别: " << endl;
cout << "1——男" << endl;
cout << "2——女" << endl;
while (1)
{
cin >> gender;
if (gender == 1 || gender == 2)
{
adl->personArr[adl->m_size].m_gender = gender;
break;
}
cout << "错误输入,请重新输入!" << endl;
}
int age;
cout << "请输入年龄: " << endl;
while (1)
{
cin >> age;
if (age >= 0 && age <= 150)
{
adl->personArr[adl->m_size].m_age = age;
break;
}
cout << "错误输入,请重新输入!" << endl;
}
string phonenum;
cout << "请输入手机号码: " << endl;
while (1)
{
cin >> phonenum;
int b = 0;
int len = phonenum.length();
for (int i = 0; i < len; i++)
{
if (phonenum[i] >= 48 && phonenum[i] <= 57)
{
continue;
}
b = 1;
break;
}
if (b)
{
cout << "手机号码输入错误,请重新输入: " << endl;
}
else
{
adl->personArr[adl->m_size].m_phone_number = phonenum;
break;
}
}
string address;
cout << "请输入联系人地址: " << endl;
cin >> address;
adl->personArr[adl->m_size].m_address = address;
cout << "添加成功!" << endl;
adl->m_size++;
system("pause");
system("cls");
}
}
void showPerson(Address_List* adl)
{
if (adl->m_size == 0)
{
cout << "当前通讯录记录为空" << endl;
}
else
{
for (int i = 0; i < adl->m_size; i++)
{
cout << "姓名: " << adl->personArr[i].m_name << "\t"
<< "性别: " << (adl->personArr[i].m_gender == 1 ? "男" : "女") << "\t"
<< "年龄: " << adl->personArr[i].m_age << "\t"
<< "手机号码: " << adl->personArr[i].m_phone_number << "\t"
<< "地址: " << adl->personArr[i].m_address << endl;
}
}
system("pause");
system("cls");
}
int isExist(Address_List* adl, string name)
{
for (int i = 0; i < adl->m_size; i++)
{
if (adl->personArr[i].m_name == name)
{
return i;
}
}
return -1;
}
void deletePerson(Address_List* adl)
{
cout << "请输入你要删除的联系人: " << endl;
string name;
cin >> name;
int ret = isExist(adl, name);
if (ret == -1)
{
cout << "查无此人" << endl;
}
else
{
for (int i = ret; i < adl->m_size; i++)
{
adl->personArr[i] = adl->personArr[i + 1];
}
adl->m_size--;
cout << "删除成功!" << endl;
}
system("pause");
system("cls");
}
void findPerson(Address_List* adl)
{
cout << "请输入你要查找的联系人: " << endl;
string name;
cin >> name;
int ret = isExist(adl, name);
if (ret != -1)
{
cout << "姓名: " << adl->personArr[ret].m_name << "\t"
<< "性别: " << (adl->personArr[ret].m_gender == 1 ? "男" : "女") << "\t"
<< "年龄: " << adl->personArr[ret].m_age << "\t"
<< "手机号码: " << adl->personArr[ret].m_phone_number << "\t"
<< "地址: " << adl->personArr[ret].m_address << endl;
}
else
{
cout << "查无此人!" << endl;
}
system("pause");
system("cls");
}
void modifyPerson(Address_List* adl)
{
cout << "请输入你要修改的联系人" << endl;
string name;
cin >> name;
int ret = isExist(adl, name);
if (ret == -1)
{
cout << "查无此人" << endl;
}
else
{
cout << "请输入姓名: " << endl;
cin >> name;
adl->personArr[ret].m_name = name;
cout << "请输入性别: " << endl;
cout << "1——男" << endl
<< "2——女" << endl;
int gender;
while (1)
{
cin >> gender;
if (gender == 1 || gender == 2)
{
adl->personArr[ret].m_gender = gender;
break;
}
cout << "性别输入错误,请重新输入" << endl;
}
cout << "请输入年龄: " << endl;
int age;
while (1)
{
cin >> age;
if (age >= 0 && age <= 150)
{
adl->personArr[ret].m_age = age;
break;
}
cout << "年龄输入错误,请重新输入" << endl;
}
cout << "请输入联系人号码: " << endl;
string phonenum;
while (1)
{
cin >> phonenum;
int b = 0;
int len = phonenum.length();
for (int i = 0; i < len; i++)
{
if (phonenum[i] >= 48 && phonenum[i] <= 57)
{
continue;
}
b = 1;
break;
}
if (b)
{
cout << "手机号码输入错误,请重新输入: " << endl;
}
else
{
adl->personArr[adl->m_size].m_phone_number = phonenum;
break;
}
}
cout << "请输入地址: " << endl;
string address;
cin >> address;
adl->personArr[ret].m_address = address;
}
system("pause");
system("cls");
}
void cleanPerson(Address_List* adl)
{
cout << "是否需要清空通讯录" << endl
<< "1——是\t2——否" << endl;
int n = 0;
while (true)
{
cin >> n;
if (n == 1)
{
adl->m_size = 0;
cout << "通讯录已清空" << endl;
break;
}
else if (n == 2)
{
break;
}
else
{
cout << "错误输入,请重新输入" << endl;
}
}
system("pause");
system("cls");
}
int main()
{
int select = 0;
Address_List adl;
adl.m_size = 0;
while (1)
{
showMenu();
cin >> select;
switch (select)
{
case 1:
addPerson(&adl);
break;
case 2:
showPerson(&adl);
break;
case 3:
deletePerson(&adl);
break;
case 4:
findPerson(&adl);
break;
case 5:
modifyPerson(&adl);
break;
case 6:
cleanPerson(&adl);
break;
case 0:
cout << "欢迎下次使用" << endl;
system("pause");
return 0;
default:
break;
}
}
system("pause");
return 0;
}
附上一句,这次使用了数组,读者有兴趣的话不妨使用链表来存储。
|