先用person和addressbooks两个结构体管理联系人,person存单条数据(姓名、电话等用std::string),addressbooks存personarray[max]数组和m_size;所有函数传addressbooks*指针,避免传值失效;共用isexist()查重;删除用覆盖法;菜单用while(true)+switch,每case后加break;输入前清缓冲区。

用结构体 + 数组管理联系人,别一上来就写类
新手直接上 Contact 类容易卡在构造、析构、拷贝语义上,反而忽略核心逻辑。先用两个结构体打底:Person 存单条数据,AddressBooks 存数组和当前人数——这是所有教程里最稳的起点。
常见错误是把姓名、电话全声明成 char[20],结果输入带空格的名字就崩;必须用 std::string。另外 MAX 宏定义要放在头文件顶部,比如 #define MAX 1000,别写死在函数里,否则扩容时要改七八处。
-
Person里性别字段用int(1/2)比char或bool更直观,也方便后续扩展(比如加 3=未知) - 年龄别用
unsigned int:负数输入会绕成极大正数,int配输入校验更安全 - 通讯录结构体里存的是
Person personArray[MAX],不是Person* personArray——动态分配对新手属于干扰项
所有修改操作都传结构体指针,别传值
比如添加联系人函数写成 void addPerson(AddressBooks* abs),不是 void addPerson(AddressBooks abs)。传值会导致函数内修改不生效,main 里看到的还是旧数据——这是新手最常踩的坑,报错不明显,但删完人还在、改完名没变。
原因很简单:abs->m_Size++ 是在改原始内存里的值;而传值时,abs.m_Size++ 只是改了副本,函数退出就丢了。
- 显示、查找、删除、修改、清空,全部函数参数都用
AddressBooks*类型 - 调用时统一写
addPerson(&book),注意取地址符不能漏 - 如果编译报
cannot convert 'AddressBooks' to 'AddressBooks*',八成就是忘了&
查找和删除必须先实现 isExist() 函数
直接在 deletePerson() 里遍历找名字,会导致代码重复、逻辑混乱。单独抽一个 int isExist(AddressBooks* abs, string name),找到返回下标,没找到返回 -1——这个函数会被查找、删除、修改共用,少写一半 bug。
注意字符串比较必须用 ==,别用 strcmp():前者对 std::string 安全,后者只认 const char*,强制转 c_str() 容易空指针崩溃。
- 循环里用
for (int i = 0; i m_Size; i++),别写i m_Size——越界访问可能读到脏数据 - 找到后立刻
return i,别等循环跑完;没找到最后统一return -1 - 删除时用「覆盖法」:找到位置后,把最后一个元素挪过来,再
m_Size--,比整体前移高效
菜单循环别用 system("pause") 收尾
每次操作完停住看效果,用 system("pause") 看似省事,但 Windows 以外系统直接报错,而且会残留 cmd 窗口。正确做法是主循环用 while (true) 包住菜单和 switch,选项选 0 就 break。
更关键的是:每个 case 后必须加 break,漏掉就会“穿透”执行下一个功能——比如选 1 添加后,自动又执行了显示、删除……这种 bug 极难定位。
- 输入数字前先
cin.clear()和cin.ignore()清缓冲区,否则连续操作时可能把上次的回车当输入 - 性别、年龄等整数输入后,加个
if (cin.fail())判断是否输成了字母,失败就重置流并提示 - 清空功能不是把数组 memset,而是直接
abs->m_Size = 0——数组内容不用管,数量归零就行
真正卡住新手的,从来不是语法,而是「改了代码却看不到效果」——往往是因为传参方式错了、缓冲区没清、或者 break 漏写了。把这些点盯死,比堆功能重要得多。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











