用 C++ 写通信录管理系统:我的学习记录与思考C语言-通信录管理系统
本文最后更新于22 天前,其中的信息可能已经过时,如有错误请发送邮件到3496667827@qq.com
AI智能摘要
本文是关于C++通信录管理系统的学习记录,作者在C++编程过程中开发了一个简单的联系人管理工具。系统实现了添加、删除、查找和修改联系人信息的基本功能,并采用了冒泡排序算法对联系人数据进行排序,以提高查找效率。尽管代码中存在一些小bug,但整体开发过程让作者对C++有了更深入的理解,并决定将此项目作为学习成果的总结。

最近在 C++ 的学习旅程里,捣鼓出了一个通信录管理系统。虽说还有些小 bug 没解决,但整个开发过程让我对 C++ 编程有了不少新感悟,决定好好记录下来,也算是给自己这段学习时光的一个小总结。

一、成品展示

这个通信录管理系统,能实现最基础的联系人管理功能。可以添加联系人,录入姓名、号码、地址;能删除联系人,根据姓名精准查找并移除;还能查找联系人信息,修改联系人号码 ,最后也能把所有联系人信息展示出来。虽然界面不算花哨,但核心功能都跑通了,对于还在学习基础阶段的我来说,算是一个小小的里程碑。

二、代码解析与思路

(一)结构体与常量定义

先定义了 Contact 结构体,把联系人的姓名、电话、地址信息封装起来,方便管理。用 #define N 100 设定联系人列表最大容量,这样后续数组创建就有了明确边界。

#define  _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>
#include <string.h>
#include <locale.h>
#define N 100  // 定义联系人列表的最大容量
typedef struct {
    char name[20];
    char phone[20];
    char addr[100];
}Contact;

(二)菜单与功能函数

show_menu 函数很简单,就是打印系统操作菜单,让用户清楚有哪些功能可以用。

void show_menu() {
    printf("\n * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
    printf("* 通信录管理系统    *\n");
    printf("* a - 添加联系人    *\n");
    printf("* d - 删除联系人    *\n");
    printf("* f - 查找联系人    *\n");
    printf("* m - 修改联系人    *\n");
    printf("* p - 显示联系人    *\n");
    printf("* q - 退出系统      *\n");
    printf("\n * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
}

排序函数 sort_data 用冒泡排序,按联系人姓名对列表排序,这样查找和展示时,数据更规整,也方便后续处理。

void sort_data(Contact contact_list[], int count) {
    int i, j, flag;
    Contact temp;
    for (i = 1; i < count; i++) {
        flag = 0;
        for (j = count - 1; j >= i; j--) {
            if (strcmp(contact_list[j - 1].name, contact_list[j].name) > 0) {
                flag = 1;
                temp = contact_list[j];
                contact_list[j] = contact_list[j - 1];
                contact_list[j - 1] = temp;
            }
        }
        if (flag == 0) {
            break;
        }
    }
}

load_data 函数负责从文件 data.txt 加载数据,用二进制读的方式,把数据读到 contact_list 数组里,加载完还调用 sort_data 排序,保证数据有序。

int load_data(Contact contact_list[]) {
    int count = 0;
    FILE* fp;
    if ((fp = fopen("data.txt", "rb")) == NULL) {
        printf("载入数据失败!\n");
        return -1;
    }
    while (!feof(fp)) {
        if (fread(&contact_list[count], sizeof(Contact), 1, fp) == 1) {
            count++;
        }
    }
    fclose(fp);
    sort_data(contact_list, count);
    printf("当前有 %d 个联系人\n", count);
    return count;
}

添加联系人的 add_new_contact 函数,先让用户输入信息,再以二进制追加写的方式,把新联系人数据存到 data.txt 里,实现数据持久化。

void add_new_contact() {
    Contact contact;
    printf("请输入添加的联系人信息:\n");
    printf("姓名:");
    getchar();
    scanf("%19s", contact.name);
    printf("号码:");
    getchar();
    scanf("%19s", contact.phone);
    printf("地址:");
    scanf(" %99s", contact.addr);
    FILE* fp;
    if ((fp = fopen("data.txt", "ab+")) == NULL) {
        printf("添加联系人失败!\n");
        return;
    }
    fwrite(&contact, sizeof(Contact), 1, fp);
    fclose(fp);
    printf("添加联系人成功!\n");
}

print_contact 函数用来展示联系人列表,遍历数组,把每个联系人的姓名、电话、地址打印出来,方便用户查看。

void print_contact(Contact contact_list[],int count) {
    int i;
    if (count == 0) {
        printf("当前没有联系人!\n");
        return;
    }
    printf("姓名\t 号码\t 地址\n");
    for(i = 0;i <count ;i++) {
        printf("%s\t%s\t%s \n",contact_list[i].name,contact_list[i].phone,contact_list[i].addr);
    }
}

删除联系人的 delete_contact 函数,先根据姓名找到要删除的联系人位置,然后把后面的联系人数据往前移,覆盖要删除的,最后重新把数组数据写入文件,实现删除效果。

void delete_contact(Contact contact_list[], int count) {
    int i, j;
    char name[20];
    getchar();
    printf("输入需要删除的联系人姓名:\n");
    scanf("%19s", name);
    for (i = 0;i < count;i++) {
        if (strcmp(contact_list[i].name, name) == 0) {
            break;
        }
    }
    if (i == count) {
        printf("没有该联系人的信息!\n");
        return;
    }
    for (j = i;j < count - 1;j++) {
        contact_list[j] = contact_list[j + 1];
    }
    FILE* fp;
    if ((fp = fopen("data.txt", "wb")) == NULL) {
        printf("打开文件错误,删除失败!\n");
        return;
    }
    fwrite(&contact_list[0], sizeof(Contact), count - 1, fp);
    fclose(fp);
}

find_contact 函数根据姓名查找联系人,遍历数组对比姓名,找到就打印信息,没找到提示用户。

void find_contact(Contact contact_list[], int count) {
    int i;
    char name[20];
    printf("输入需要查找的联系人姓名:\n");
    getchar();
    scanf("%19s",name);
    for (i = 0;i < count;i++) {
        if (strcmp(contact_list[i].name, name) == 0) {
            printf("姓名:%s,号码:%s,地址:%s\n", contact_list[i].name, contact_list[i].phone, contact_list[i].addr);
            break;
        }
    }
    if (i == count) {
        printf("没有该联系人信息!\n");
    }
}

modify_contact 函数先找到要修改的联系人,修改其号码后,把整个联系人数组重新写入文件,完成修改。

void modify_contact(Contact contact_list[],int count) {
    int i;
    char name[20];
    printf("请输入需要修改的联系人姓名");
    getchar();
    scanf("%19s",name);
    for (i = 0;i < count;i++) {
        if (strcmp(contact_list[i].name, name) == 0) {
            break;
        }
    }
    if (i == count) {
        printf("没有该联系人信息!\n");
        return;
    }
    printf("请输入%s的新号码:",name);
    getchar();
    scanf("%99s",&contact_list[i].phone);
    FILE* fp;
    if ((fp = fopen("data.txt","wb"))== NULL) {
        printf("修改联系人失败!\n");
        return;
    }
    fwrite(&contact_list[0],sizeof(Contact),count,fp);
    fclose(fp);
    printf("修改成功!\n");
}

(三)主函数流程

主函数 main 里,先调用 load_data 加载数据,然后展示菜单,通过循环和 switch 语句,根据用户输入的指令,调用对应的功能函数,实现交互。

int main() {
    int count = 0;
    Contact contact_list[N];
    count = load_data(contact_list);
    if (count == -1) {
        return 0;
    }
    show_menu();
    char ch;
    printf("数据加载成功,请输入你需要的操作: \n");
    while ((ch = getchar()) != EOF) {
        if (ch == '\n') continue; // 忽略换行符
        if (ch == 'q') break;
        switch (ch) {
        case 'a':
            add_new_contact();
            count = load_data(contact_list);
            break;
        case 'p':
            print_contact(contact_list,count);
            break;
        case 'd':
            delete_contact(contact_list, count);
            break;
        case 'f':
            find_contact(contact_list, count);
            break;
        case 'm':
            modify_contact(contact_list, count);
            break;
        default:
            printf("输入的命令有误! \n");
            break;
        }
        printf("请输入你需要的操作: \n");
        fflush(stdin);
        scanf("%c", &ch);
    }
    printf("退出系统! \n");
    return 0;
}

三、遇到的问题与不足

(一)输入的小麻烦

在 add_new_contact 这类函数里,用 getchar 处理输入缓冲区的换行符,还是偶尔会出问题。比如连续输入时,可能会跳过某些输入步骤,用户体验不太好。后来了解到,其实可以用 scanf(" %c", &ch); 这种带空格的格式控制,或者用 fgets 处理字符串输入,能更稳定解决缓冲区问题,后续优化打算试试这些方法。

(二)数据处理的隐患

删除和修改联系人时,是把整个联系人数组重新写入文件。如果联系人数量多了,这样操作效率低,而且一旦写入过程中出错,数据可能丢失。之后想优化的话,可以研究下文件的局部修改,比如用索引标记数据位置,精准修改,不用每次都重写整个文件。

(三)功能的局限性

目前系统功能比较基础,只能按姓名查找、删除、修改,要是有用户想按号码查找,就实现不了。而且联系人信息也只有姓名、电话、地址,实际使用中,可能还需要邮箱、备注等更多字段,后续可以考虑拓展结构体,丰富功能。

四、收获与成长

通过写这个通信录管理系统,我对 C++ 的结构体、文件操作、函数封装这些知识,从书本上的概念,真正变成了能动手用的技能。遇到 bug 时,学会了一步步调试,看程序执行流程,找变量的值变化,这种排错能力太重要了。

同时,也意识到编程不只是写代码,还要考虑用户体验、数据安全这些实际问题。一个小小的通信录系统,想要做好,也得不断优化细节。这也让我对后续深入学习 C++ 更有期待,想看看能把这样的小项目,迭代成多完善的工具。

虽然现在的通信录管理系统还有不少瑕疵,但它就像一个成长的标记,记录着我学 C++ 过程中的思考和实践。我会带着这些问题和收获,继续在编程路上折腾,把这个系统越改越好,也让自己的技术越来越扎实~

觉得有帮助可以投喂下博主哦~感谢!
作者:Hueil
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 协议
转载请注明 文章地址 及 作者 哦~
暂无评论

发送评论 编辑评论


                
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇