C语言小组通讯录如何用C语言实现?

99ANYc3cd6
预计阅读时长 33 分钟
位置: 首页 C语言 正文

我们将创建一个基于文件存储的命令行通讯录管理系统,这个程序可以实现以下核心功能:

  1. 添加联系人:可以输入姓名、电话、性别、邮箱等信息。
  2. 显示所有联系人:以表格形式列出通讯录中的所有人。
  3. 按姓名查找联系人:根据姓名精确查找并显示信息。
  4. 删除联系人:根据姓名删除指定的联系人。
  5. 修改联系人信息:根据姓名找到联系人并修改其信息。
  6. 数据持久化:所有联系人信息会自动保存在一个名为 contacts.dat 的文件中,程序关闭后重新打开,数据依然存在。
  7. 清空通讯录:一键清空所有联系人。
  8. 退出系统:安全退出系统,并保存数据。

项目结构

为了代码清晰,我们将代码分成三个文件:

  • main.c: 主程序文件,包含主菜单和函数调用逻辑。
  • contacts.h: 头文件,包含结构体定义、函数声明和常量。
  • contacts.c: 功能实现文件,包含所有核心功能的函数实现。

代码实现

1 头文件 contacts.h

这个文件定义了联系人的数据结构、程序用到的常量以及所有需要被其他文件调用的函数。

// contacts.h
#ifndef CONTACTS_H
#define CONTACTS_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义最大姓名长度和电话号码长度
#define MAX_NAME_LEN 50
#define MAX_PHONE_LEN 20
#define MAX_EMAIL_LEN 50
#define MAX_GENDER_LEN 10
// 定义联系人结构体
typedef struct {
    char name[MAX_NAME_LEN];
    char phone[MAX_PHONE_LEN];
    char gender[MAX_GENDER_LEN];
    char email[MAX_EMAIL_LEN];
} Contact;
// 定义通讯录结构体,可以存储多个联系人
typedef struct {
    Contact contacts[1000]; // 假设最多存储1000个联系人
    int count;              // 当前联系人数量
} AddressBook;
// 函数声明
void initAddressBook(AddressBook *book);
void saveToFile(AddressBook *book);
void loadFromFile(AddressBook *book);
void showMenu();
void addContact(AddressBook *book);
void displayContacts(AddressBook *book);
void findContact(AddressBook *book);
void deleteContact(AddressBook *book);
void modifyContact(AddressBook *book);
void clearContacts(AddressBook *book);
#endif // CONTACTS_H

2 功能实现文件 contacts.c

这个文件包含了所有核心功能的C语言代码实现。

// contacts.c
#include "contacts.h"
// 初始化通讯录
void initAddressBook(AddressBook *book) {
    book->count = 0;
    loadFromFile(book); // 启动时自动加载数据
}
// 将通讯录数据保存到文件
void saveToFile(AddressBook *book) {
    FILE *fp = fopen("contacts.dat", "wb");
    if (fp == NULL) {
        printf("错误:无法打开文件进行保存!\n");
        return;
    }
    fwrite(book, sizeof(AddressBook), 1, fp);
    fclose(fp);
}
// 从文件加载通讯录数据
void loadFromFile(AddressBook *book) {
    FILE *fp = fopen("contacts.dat", "rb");
    if (fp == NULL) {
        // 文件不存在是正常情况(第一次运行)
        return;
    }
    fread(book, sizeof(AddressBook), 1, fp);
    fclose(fp);
}
// 显示主菜单
void showMenu() {
    printf("\n\n");
    printf("========== 小组通讯录管理系统 ==========\n");
    printf("   1. 添加联系人\n");
    printf("   2. 显示所有联系人\n");
    printf("   3. 查找联系人\n");
    printf("   4. 删除联系人\n");
    printf("   5. 修改联系人\n");
    printf("   6. 清空通讯录\n");
    printf("   0. 退出系统\n");
    printf("========================================\n");
    printf("请输入您的选择 (0-6): ");
}
// 添加联系人
void addContact(AddressBook *book) {
    if (book->count >= 1000) {
        printf("通讯录已满,无法添加!\n");
        return;
    }
    Contact newContact;
    printf("请输入姓名: ");
    scanf("%s", newContact.name);
    printf("请输入电话: ");
    scanf("%s", newContact.phone);
    printf("请输入性别: ");
    scanf("%s", newContact.gender);
    printf("请输入邮箱: ");
    scanf("%s", newContact.email);
    book->contacts[book->count] = newContact;
    book->count++;
    printf("联系人添加成功!\n");
    saveToFile(book); // 保存到文件
}
// 显示所有联系人
void displayContacts(AddressBook *book) {
    if (book->count == 0) {
        printf("通讯录为空,没有联系人可显示,\n");
        return;
    }
    printf("\n%-20s %-15s %-10s %-30s\n", "姓名", "电话", "性别", "邮箱");
    printf("------------------------------------------------------------\n");
    for (int i = 0; i < book->count; i++) {
        printf("%-20s %-15s %-10s %-30s\n",
               book->contacts[i].name,
               book->contacts[i].phone,
               book->contacts[i].gender,
               book->contacts[i].email);
    }
}
// 按姓名查找联系人
void findContact(AddressBook *book) {
    char name[MAX_NAME_LEN];
    printf("请输入要查找的联系人姓名: ");
    scanf("%s", name);
    int found = 0;
    for (int i = 0; i < book->count; i++) {
        if (strcmp(book->contacts[i].name, name) == 0) {
            printf("\n找到联系人!\n");
            printf("姓名: %s\n", book->contacts[i].name);
            printf("电话: %s\n", book->contacts[i].phone);
            printf("性别: %s\n", book->contacts[i].gender);
            printf("邮箱: %s\n", book->contacts[i].email);
            found = 1;
            break; // 找到第一个后停止
        }
    }
    if (!found) {
        printf("未找到姓名为 '%s' 的联系人,\n", name);
    }
}
// 删除联系人
void deleteContact(AddressBook *book) {
    char name[MAX_NAME_LEN];
    printf("请输入要删除的联系人姓名: ");
    scanf("%s", name);
    int foundIndex = -1;
    for (int i = 0; i < book->count; i++) {
        if (strcmp(book->contacts[i].name, name) == 0) {
            foundIndex = i;
            break;
        }
    }
    if (foundIndex == -1) {
        printf("未找到姓名为 '%s' 的联系人,\n", name);
        return;
    }
    // 将后面的联系人前移,覆盖要删除的联系人
    for (int i = foundIndex; i < book->count - 1; i++) {
        book->contacts[i] = book->contacts[i + 1];
    }
    book->count--;
    printf("联系人 '%s' 删除成功!\n", name);
    saveToFile(book); // 保存到文件
}
// 修改联系人
void modifyContact(AddressBook *book) {
    char name[MAX_NAME_LEN];
    printf("请输入要修改的联系人姓名: ");
    scanf("%s", name);
    int foundIndex = -1;
    for (int i = 0; i < book->count; i++) {
        if (strcmp(book->contacts[i].name, name) == 0) {
            foundIndex = i;
            break;
        }
    }
    if (foundIndex == -1) {
        printf("未找到姓名为 '%s' 的联系人,\n", name);
        return;
    }
    printf("找到了联系人 '%s',请输入新的信息:\n", name);
    printf("请输入新电话 (原: %s): ", book->contacts[foundIndex].phone);
    scanf("%s", book->contacts[foundIndex].phone);
    printf("请输入新性别 (原: %s): ", book->contacts[foundIndex].gender);
    scanf("%s", book->contacts[foundIndex].gender);
    printf("请输入新邮箱 (原: %s): ", book->contacts[foundIndex].email);
    scanf("%s", book->contacts[foundIndex].email);
    printf("联系人信息修改成功!\n");
    saveToFile(book); // 保存到文件
}
// 清空通讯录
void clearContacts(AddressBook *book) {
    char confirm;
    printf("警告:此操作将清空所有联系人数据,且无法恢复!\n");
    printf("您确定要继续吗?(y/n): ");
    scanf(" %c", &confirm); // 注意前面的空格,用于吸收回车
    if (confirm == 'y' || confirm == 'Y') {
        book->count = 0;
        // 删除文件以清空数据
        remove("contacts.dat");
        printf("通讯录已清空,\n");
    } else {
        printf("操作已取消,\n");
    }
}

3 主程序文件 main.c

这个文件是程序的入口,负责调用其他函数,形成完整的交互流程。

// main.c
#include "contacts.h"
int main() {
    AddressBook book;
    initAddressBook(&book); // 初始化通讯录,加载文件数据
    int choice;
    do {
        showMenu();
        scanf("%d", &choice);
        switch (choice) {
            case 1:
                addContact(&book);
                break;
            case 2:
                displayContacts(&book);
                break;
            case 3:
                findContact(&book);
                break;
            case 4:
                deleteContact(&book);
                break;
            case 5:
                modifyContact(&book);
                break;
            case 6:
                clearContacts(&book);
                break;
            case 0:
                printf("感谢使用,再见!\n");
                break;
            default:
                printf("无效的输入,请重新输入 (0-6)!\n");
        }
    } while (choice != 0);
    return 0;
}

如何编译和运行

  1. 保存文件:将上面的三段代码分别保存为 main.ccontacts.ccontacts.h,并将它们放在同一个文件夹下。

  2. 编译:打开你的终端(Windows上是CMD或PowerShell,Linux或macOS上是Terminal),进入文件所在的目录,然后使用GCC编译器进行编译。

    # 编译 main.c 和 contacts.c,并生成一个名为 address_book 的可执行文件
    gcc main.c contacts.c -o address_book
  3. 运行

    • 在Windows上:
      address_book.exe
    • 在Linux或macOS上:
      ./address_book

程序启动后,你就可以通过输入数字来选择不同的功能了,当你添加或修改联系人后,一个名为 contacts.dat 的文件会自动创建或更新在同一个目录下,用于存储数据。


项目特点与改进方向

特点:

  • 模块化设计:代码结构清晰,职责分明,易于维护和扩展。
  • 数据持久化:使用文件保存数据,解决了程序关闭后数据丢失的问题。
  • 用户友好:提供清晰的菜单和提示信息。
  • 健壮性:处理了文件打开失败等基本错误情况。

可以进一步改进的方向(适合进阶学习):

  1. 输入验证:增加对电话号码(必须是数字)、邮箱格式的验证。
  2. 动态内存分配:目前使用固定大小的数组(1000人),可以改为动态分配内存,实现按需增长。
  3. 排序功能:增加按姓名或电话号码排序的功能。
  4. 模糊查找:实现不输入完整姓名即可查找的功能(输入“张”可以查到所有姓张的人)。
  5. 更美观的界面:使用一些简单的控制台库(如 ncurses)来美化界面。
  6. 加密存储:对存储的文件进行加密,保护隐私。

这个项目是一个非常好的C语言综合练习,涵盖了结构体、文件操作、函数、指针、循环和条件判断等核心知识点,希望对你有帮助!

-- 展开阅读全文 --
头像
织梦循环栏目下文章如何实现动态加载?
« 上一篇 04-23
明解C语言和啊哈C语言,哪本更适合新手?
下一篇 » 04-23

相关文章

取消
微信二维码
支付宝二维码

目录[+]