浅浅玩一下,通讯录管理系统,如何使用C++来做(低级C++,其实够高级了)
本帖最后由 C丁洞杀O 于 2023-1-9 18:44 编辑emmm,不是大佬的我却始终想要模仿大佬,嗯,这次非常简单所以我就不写注释了,很整齐的,对吧?
废话不多说!上代码 (随意抄,随意改,无版权)
// 代码可以改,高级版的话,我在做,大概实现的功能是导入通讯录,导出通讯录,可能在加个窗口,菜单啥的
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <strmif.h>
#include <algorithm>
#include <memory>
using namespace std;
#define MAXPATH 0xFFFFFFF
void update(short a=0) {
if (a == 1)
{
system("pause");
}
#ifdef_WIN32
system("cls");
#endif //_WIN32
system("claer");
}
class MailList {
protected:
structPerson
{
size_t _id;
string _name;
short _callP; // 电话
char _sex; // 性别
// Person(const Person&) = delete;
Person() {
_id = 0;
_name = "";
_sex = 0;
for (size_t i = 0; i < 11; i++)
{
_callP = 0;
}
}
void operator=(Person p) {
_id = p._id;
_name = p._name;
for (size_t i = 0; i < 11; i++)
{
_callP = p._callP;
}
_sex = p._sex;
}
};
void setCallP(Person& p, const char* callP) {
for (size_t i = 0; i < 11; i++)
{
p._callP = callP - '0';
}
}
public:
MailList(const MailList&) = delete;
MailList() {
me = new Person;
me->_id = 0;
me->_name = "自己";
setCallP(*me, "0000000000");
me->_sex = '_';
}
// 添加联系人
void addPerson(string _name,const char* _callP,char _sex) {
Person temp;
temp._id = getMailListLenth() + 1;
temp._name = _name;
setCallP(temp, _callP);
temp._sex = _sex;
callP.push_back(temp);
cout << temp._name <<" : 添加成功!\n";
update(1);
}
// 显示联系人
void showAllPerson() {
size_t i = 1;
for (auto it = callP.begin(); it < callP.end(); it++)
{
it->_id = i;
cout << it->_id << ":" << it->_name << "; ";
for (size_t i = 0; i < 11; i++)
{
cout << it->_callP;
}
cout <<"; "<< it->_sex << endl;
i++;
}
update(1);
}
// 获取联系人
size_t getPerson(string _name) {
bool isFind=false;
for (auto it = callP.begin(); it < callP.end(); it++)
{
if (it->_name == _name)
{
isFind = true;
cout << it->_id << ": " << it->_name << "; ";
for (size_t i = 0; i < 11; i++)
{
cout << it->_callP;
}
cout << "; " << it->_sex << endl;
/*update(1);
return it->_id;*/
}
}
if (!isFind)
{
cout << "未能找到, 请检查后再次输入!\n";
}
update(1);
return 0;
}
// 删除联系人
void deletePerson(size_t _id) {
bool rightFind = false;
// 别见外,我不会vector的消除,干脆这样吧
vector<Person> temp;
for (auto it = callP.begin(); it < callP.end(); it++)
{
if (!(it->_id == _id))
{
temp.push_back(*it);
}
else {
rightFind = true;
}
}
callP = temp;
if (rightFind)
{
cout << "删除成功!";
}
update(1);
}
// 清空联系人
void clearAllPerson() {
callP.clear();
cout << "清理成功!";
update(1);
}
// 修改联系人
void resetPerson(size_t _id) {
_id = _id - 1;
update(0);
while(1){
cout << "1 修改名称 2 修改电话 3 修改性别 E 退出 \n";
char command;
command = getchar();
switch (command)
{
case '1':
{
string name;
cin >> name;
callP._name = name;
}
break;
case '2':
{
cout << "输入电话号码\n01234567890\n";
char _callP;
cin >> _callP;
if (!(strlen(_callP) == 11))
{
cout << "电话输入错误!" << endl;
cin >> _callP;
}
setCallP(callP, _callP);
}
break;
case '3':
{
cout << "请输入性别\n";
char sex;
cin >> sex;
callP._sex = sex;
}
break;
case 'e':case 'E':
return;
default:
break;
}
}
update(0);
}
~MailList() {
delete me;
}
protected:
size_t getMailListLenth() const{
return callP.size();
}
private:
Person* me;
vector<Person> callP;
};
//class MailListVIP : MailList {
//
//};
class Command {
public:
Command(const Command&) = delete;
Command() {
cout << "-欢迎使用本通讯录管理系统-" << endl;
cout << "----- 作者:C丁洞杀O -----" << endl;
cout << "----- Made in China-----" << endl;
cout << "----- from Fishc.com -----" << endl;
cout << "--- It's free to study ---" << endl;
update(1);
PmailList = new MailList;
}
void showMenu() {
cout<<"$ 通讯录管理系统:菜单(Menu) $ \n";
cout<<"##############################\n";
cout<<"#######1、添加联系人#######\n";
cout<<"#######2、显示联系人#######\n";
cout<<"#######3、删除联系人#######\n";
cout<<"#######4、查找联系人#######\n";
cout<<"#######5、清空联系人#######\n";
cout<<"#######6、修改联系人#######\n";
cout<<"#######E、退出此程序#######\n";
cout<<"##############################\n";
getCommand();
update();
}
int run() {
while (1)
{
showMenu();
}
}
void getCommand() {
string command;
cin>>command;
switch (command)
{
case '1':// 添加联系人
{
cout << "功能:添加联系人\n";
string _name;
char callP;
char sex;
cin >> _name >> callP >> sex;
if (!(strlen(callP) == 11))
{
cout << "电话输入错误!" << endl;
cin >> callP;
}
PmailList->addPerson(_name, callP, sex);
}
break;
case '2':// 显示联系人
{
cout << "功能:显示联系人\n";
PmailList->showAllPerson();
}
break;
case '3': // 删除联系人
{
cout << "功能:删除联系人\n";
cout << "输入联系人id进行删除!";
size_t id;
cin >> id;
PmailList->deletePerson(id);
}
break;
case '4':// 查找联系人
{
cout << "功能:查找联系人\n";
cout << "输入名称查找联系人!";
string name;
cin >> name;
PmailList->getPerson(name);
}
break;
case '5':// 清空联系人
{
cout << "功能:清空联系人\n";
PmailList->clearAllPerson();
}
break;
case '6': // 修改联系人
{
cout << "功能:修改联系人\n";
cout << "输入id修改联系人 $";
size_t id;
cin >> id;
PmailList->resetPerson(id);
}
break;
case 'E':case 'e':
update();
cout << "欢迎下次光临,本系统,永远为您服务!\n";
update(1);
exit(0);
break;
default:
cout << "代码未能解析,请重新输入\n";
update(1);
break;
}
}
~Command() {
delete PmailList;
PmailList = nullptr; // 删除函数,防止野指针
}
MailList* PmailList;
// unique_ptr<MailList> pMailList; // 使用智能指针(其实不要担心)
// MailListVIP* ImailList;
};
int main() {
Command cmd;
return cmd.run();
}
有人反馈了一些问题,已改;
补充一下,保证编译环境为Vs2019;Debug;x86;多字节字符集;控制台程序;Windows11;其他环境不保证! 我把大部分的注释都删掉了,emmm,最后留下的只是功能实现代码,当然,我没有刻意追求效率,否则的话,这个代码可以上1000行了,查找,搜索,啥的都可以用算法,还有,其实,可以做网络版的,就是真的能通话的那种,完整版的话,我觉得要做个局域网聊天+通讯录管理+窗口+数据保存,然后在做点聊天室,当然,这不可能一个程序完成,分成多个,甚至是搭配dll, lib等等,完整的项目就出来了,对吧 编译报错了,请问有头绪吗?
test.cpp:28:22: error: definition of implicit copy constructor for 'Person' is deprecated because it has a user-provided copy assignment operator [-Werror,-Wdeprecated-copy-with-user-provided-copy]
void operator=(Person& p) {
^ dolly_yos2 发表于 2023-1-9 09:32
编译报错了,请问有头绪吗?
文件格式cpp, 编译标准C++14,Debug x86 Vs2019 C丁洞杀O 发表于 2023-1-9 10:27
文件格式cpp, 编译标准C++14,Debug x86 Vs2019
问题太多了,只是程序能解析出来的就画了满屏幕的波浪线。就这样吧。
可能离您理想的 C++ 应该有的样子和/或效率还有距离 dolly_yos2 发表于 2023-1-9 12:20
问题太多了,只是程序能解析出来的就画了满屏幕的波浪线。就这样吧。
可能离您理想的 C++ 应该有的样子 ...
我的编译器没有问题呀,无论是编译还是链接都没有问题,警告请无视,那个是版本问题 C丁洞杀O 发表于 2023-1-9 13:21
我的编译器没有问题呀,无论是编译还是链接都没有问题,警告请无视,那个是版本问题
In file included from /usr/include/c++/12.2.0/string:50,
from /usr/include/c++/12.2.0/bits/locale_classes.h:40,
from /usr/include/c++/12.2.0/bits/ios_base.h:41,
from /usr/include/c++/12.2.0/ios:42,
from /usr/include/c++/12.2.0/ostream:38,
from /usr/include/c++/12.2.0/iostream:39,
from main.cpp:2:
/usr/include/c++/12.2.0/bits/stl_algobase.h: In instantiation of ‘static constexpr _OI std::__copy_move<false, false, std::random_access_iterator_tag>::__copy_m(_II, _II, _OI) ’:
/usr/include/c++/12.2.0/bits/stl_algobase.h:492:12: required from ‘constexpr _OI std::__copy_move_a2(_II, _II, _OI) ’
/usr/include/c++/12.2.0/bits/stl_algobase.h:522:42: required from ‘constexpr _OI std::__copy_move_a1(_II, _II, _OI) ’
/usr/include/c++/12.2.0/bits/stl_algobase.h:530:31: required from ‘constexpr _OI std::__copy_move_a(_II, _II, _OI) ’
/usr/include/c++/12.2.0/bits/stl_algobase.h:620:7: required from ‘constexpr _OI std::copy(_II, _II, _OI) ’
/usr/include/c++/12.2.0/bits/vector.tcc:244:31: required from ‘constexpr std::vector<_Tp, _Alloc>& std::vector<_Tp, _Alloc>::operator=(const std::vector<_Tp, _Alloc>&) ’
main.cpp:106:17: required from here
/usr/include/c++/12.2.0/bits/stl_algobase.h:385:25: error: binding reference of type ‘MailList::Person&’ to ‘const MailList::Person’ discards qualifiers
385 | *__result = *__first;
| ~~~~~~~~~~^~~~~~~~~~
main.cpp:26:32: note: initializing argument 1 of ‘void MailList::Person::operator=(MailList::Person&)’
26 | void operator=(Person &p) {
| ~~~~~~~~^
C丁洞杀O 发表于 2023-1-9 13:21
我的编译器没有问题呀,无论是编译还是链接都没有问题,警告请无视,那个是版本问题
我理解,我们的编译器大不相同,不过这些问题我能轻松解决
问题的核心在于您的实现。恕我直言,您没能发挥您热爱的 C++ 的潜力,有很多能够用程序自动检测出的,有调优空间的地方,比如不必要的复制传递
一些警告也不是版本问题,而是代码编写的错误或者说至少是容易导致使用时出现问题的地方,比如复制赋值运算符的重载导致隐式声明的复制构造函数被弃用,C++ 的通常范式下如果重载了复制赋值运算符就应该同时自定义赋值构造函数和析构函数( Rule of Three )
new 申请的空间没有对应的 delete,不过也有看法认为固定申请常数次、保有到程序结束而未释放的内存不算内存泄漏,姑且不管了
一些设计上的问题更是见仁见智,这里就更不多说了 // 代码可以改,高级版的话,我在做,大概实现的功能是导入通讯录,导出通讯录,可能在加个窗口,菜单啥的
#include <iostream>
#include <map>
#include <vector>
//#include <strmif.h>
#include <string.h>
#include <algorithm>
#include <string>
using namespace std;
#define MAXPATH 0xFFFFFFF
void update(short a = 0) {
if(a == 1) system("pause");
//system("cls");
system("clear");
}
class MailList {
protected:
struct Person {
size_t _id;
string _name;
short _callP; // 电话
char _sex; // 性别
//void operator=(Person &p) {
void operator=(const Person &p) {
_id = p._id;
_name = p._name;
for(size_t i = 0; i < 11; i++) {
_callP = p._callP;
}
_sex = p._sex;
}
};
void setCallP(Person &p, const char *callP) {
for(size_t i = 0; i < 11; i++) {
p._callP = callP - '0';
}
}
public:
MailList() {
me._id = 0;
me._name = "自己";
setCallP(me, "0000000000");
me._sex = '_';
}
// 添加联系人
void addPerson(string _name, const char *_callP, char _sex) {
Person temp;
temp._id = getMailListLenth() + 1;
temp._name = _name;
setCallP(temp, _callP);
temp._sex = _sex;
callP.push_back(temp);
cout << temp._name << " : 添加成功!\n";
update(1);
}
// 显示联系人
void showAllPerson() {
size_t i = 1;
for(auto it = callP.begin(); it < callP.end(); it++) {
it->_id = i;
cout << it->_id << ":" << it->_name << "; ";
for(size_t i = 0; i < 11; i++) {
cout << it->_callP;
}
cout << "; " << it->_sex << endl;
i++;
}
update(1);
}
// 获取联系人
size_t getPerson(string _name) {
bool isFind = false;
for(auto it = callP.begin(); it < callP.end(); it++) {
if(it->_name == _name) {
isFind = true;
cout << it->_id << ": " << it->_name << "; ";
for(size_t i = 0; i < 11; i++) {
cout << it->_callP;
}
cout << "; " << it->_sex << endl;
/*update(1);
return it->_id;*/
}
}
if(!isFind) {
cout << "未能找到, 请检查后再次输入!\n";
}
update(1);
return 0;
}
// 删除联系人
void deletePerson(size_t _id) {
bool rightFind = false;
// 别见外,我不会vector的消除,干脆这样吧
vector<Person> temp;
for(auto it = callP.begin(); it < callP.end(); it++) {
if(!(it->_id == _id)) {
temp.push_back(*it);
} else {
rightFind = true;
}
}
callP = temp;
if(rightFind) {
cout << "删除成功!";
}
update(1);
}
// 清空联系人
void clearAllPerson() {
callP.clear();
cout << "清理成功!";
update(1);
}
// 修改联系人
void resetPerson(size_t _id) {
_id = _id - 1;
update(0);
while(1) {
cout << "1 修改名称 2 修改电话 3 修改性别 E 退出 \n";
char command;
command = getchar();
switch(command) {
case '1': {
string name;
cin >> name;
callP._name = name;
} break;
case '2': {
cout << "输入电话号码\n01234567890\n";
char _callP;
cin >> _callP;
if(!(strlen(_callP) == 11)) {
cout << "电话输入错误!" << endl;
cin >> _callP;
}
setCallP(callP, _callP);
} break;
case '3': {
cout << "请输入性别\n";
char sex;
cin >> sex;
callP._sex = sex;
} break;
case 'e':
case 'E':
return;
default:
break;
}
}
update(0);
}
protected:
size_t getMailListLenth() const { return callP.size(); }
private:
Person me;
vector<Person> callP;
};
// class MailListVIP : MailList {
//
// };
class Command {
public:
Command() {
cout << "-欢迎使用本通讯录管理系统-" << endl;
cout << "----- 作者:C丁洞杀O -----" << endl;
cout << "----- Made in China-----" << endl;
cout << "----- from Fishc.com -----" << endl;
cout << "--- It's free to study ---" << endl;
update(1);
PmailList = new MailList;
}
// 不需要释放内存吗?
~Command() {delete PmailList;}
void showMenu() {
cout << "$ 通讯录管理系统:菜单(Menu) $ \n";
cout << "##############################\n";
cout << "#######1、添加联系人#######\n";
cout << "#######2、显示联系人#######\n";
cout << "#######3、删除联系人#######\n";
cout << "#######4、查找联系人#######\n";
cout << "#######5、清空联系人#######\n";
cout << "#######6、修改联系人#######\n";
cout << "#######E、退出此程序#######\n";
cout << "##############################\n";
getCommand();
update();
}
int run() {
while(1) {
showMenu();
}
}
void getCommand() {
string command;
cin >> command;
switch(command) {
case '1': // 添加联系人
{
cout << "功能:添加联系人\n";
string _name;
char callP;
char sex;
cin >> _name >> callP >> sex;
if(!(strlen(callP) == 11)) {
cout << "电话输入错误!" << endl;
cin >> callP;
}
PmailList->addPerson(_name, callP, sex);
} break;
case '2': // 显示联系人
{
cout << "功能:显示联系人\n";
PmailList->showAllPerson();
} break;
case '3': // 删除联系人
{
cout << "功能:删除联系人\n";
cout << "输入联系人id进行删除!";
size_t id;
cin >> id;
PmailList->deletePerson(id);
} break;
case '4': // 查找联系人
{
cout << "功能:查找联系人\n";
cout << "输入名称查找联系人!";
string name;
cin >> name;
PmailList->getPerson(name);
} break;
case '5': // 清空联系人
{
cout << "功能:清空联系人\n";
PmailList->clearAllPerson();
} break;
case '6': // 修改联系人
{
cout << "功能:修改联系人\n";
cout << "输入id修改联系人 $";
size_t id;
cin >> id;
PmailList->resetPerson(id);
} break;
case 'E':
case 'e':
update();
cout << "欢迎下次光临,本系统,永远为您服务!\n";
update(1);
exit(0);
break;
default:
cout << "代码未能解析,请重新输入\n";
update(1);
break;
}
}
MailList *PmailList;
// MailListVIP* ImailList;
};
int main() {
Command cmd;
return cmd.run();
}
dolly_yos2 发表于 2023-1-9 13:50
我理解,我们的编译器大不相同,不过这些问题我能轻松解决
问题的核心在于您的实现。恕我直言,您没能发 ...
我这编译器一般默认会提供构造函数和解析函数啊?这不是正常的吗?而且我也说了这是低级C++,有些地方我也没有用C++提供的算法库,是直接写的,其实我还能更加简单,但这不是怕不能用吗? 人造人 发表于 2023-1-9 13:53
Liunx版的?我是Windows上用的,可能会有差异吧 C丁洞杀O 发表于 2023-1-9 15:45
Liunx版的?我是Windows上用的,可能会有差异吧
嗯,所以操作系统/编译器特定的东西还是尽量不要用
因为你不知道 你的代码会运行在什么机器上
我这编译器一般默认会提供构造函数和解析函数
那个默认的析构函数会帮你 delete PmailList; 吗?
本帖最后由 C丁洞杀O 于 2023-1-9 15:57 编辑
人造人 发表于 2023-1-9 15:50
嗯,所以操作系统/编译器特定的东西还是尽量不要用
因为你不知道 你的代码会运行在什么机器上
return的时候,系统帮你回收,这个不用担心,进程结束的时候,内存自动释放,当然,感谢您的提醒,我已把析构和构造函数补上的 dolly_yos2 发表于 2023-1-9 13:50
我理解,我们的编译器大不相同,不过这些问题我能轻松解决
问题的核心在于您的实现。恕我直言,您没能发 ...
设计这方面,这是阉割版,我可能在删的时候没有删干净,不好意思,而且原来我是分文件编写的,有什么错误欢迎指出,目前已改,有没有达到您满意的需求呢 C丁洞杀O 发表于 2023-1-9 15:52
return的时候,系统帮你回收,这个不用担心,进程结束的时候,内存自动释放,当然,感谢您的提醒,我已 ...
这是有系统的时候,你不释放,系统会帮你释放
如果没有系统的时候,你不释放,谁帮你释放?
你以为C/C++就能写些操作系统上面运行的应用程序?
还是上面那句话,不要假设你的代码会在什么环境下运行
C丁洞杀O 发表于 2023-1-9 15:44
我这编译器一般默认会提供构造函数和解析函数啊?这不是正常的吗?而且我也说了这是低级C++,有些地方我 ...
是正常的,但是自定义的复制赋值操作符会阻止隐式提供的复制构造函数()
语义上,自定义的复制赋值操作符意味着默认的无法满足需求,这通常也意味着复制构造函数同样需要自定义,析构也需要额外的(或特殊的)操作,比如保证所有权唯一性。这也就是 Rule of Three 背后的逻辑 C丁洞杀O 发表于 2023-1-9 15:59
设计这方面,这是阉割版,我可能在删的时候没有删干净,不好意思,而且原来我是分文件编写的,有什么错误 ...
哪有什么“要求”,就像我说的,设计上见仁见智,把模型设计的“显然没有问题”是极其困难的 dolly_yos2 发表于 2023-1-9 16:05
是正常的,但是自定义的复制赋值操作符会阻止隐式提供的复制构造函数()
语义上,自 ...
已经将复制构造函数禁止了,多谢提醒!
页:
[1]