首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

高阶C语言|通讯录管理系统(详解+完整代码)

  • 25-02-16 17:20
  • 3742
  • 7157
blog.csdn.net

文章目录

    • @[toc]
      • 引言
      • 系统设计
      • 功能实现
        • 1. 初始化联系人列表
        • 2. 添加联系人
        • 3. 查找联系人
        • 4. 删除联系人
        • 5. 修改联系人
        • 6. 显示所有联系人
        • 7. 清空所有联系人
        • 8. 按名字排序联系人
      • 易错点与建议
      • 完整代码
        • `contact.h` — 头文件
        • `contact.c` — 主要功能实现
        • `test.c` — 主程序与测试

引言

功能:

  • 添加联系人
  • 删除联系人
  • 查找联系人
  • 修改联系人信息
  • 显示所有联系人
  • 清空所有联系人
  • 按名字排序联系人

系统设计

为了实现通讯录的功能,我们首先定义了一个 contact 结构体,包含了一个存储联系人信息的数组和当前已经存储的联系人个数。每个联系人信息是一个 info 结构体,包含姓名、年龄、性别、电话和地址。

typedef struct info {
    char name[MAX_NAME];
    int age;
    char gender[MAX_GENDER];
    char tele[MAX_TELE];
    char addr[MAX_ADDR];
} info;

typedef struct contact {
    info data[MAX_NUM];  // 存储联系人的信息
    int sz;  // 当前已存放联系人的个数
} contact;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

功能实现

1. 初始化联系人列表

首先,我们需要一个初始化函数来清空通讯录,并将联系人数量设置为 0。这个功能由 InitContact 函数实现:

void InitContact(contact* pc) {
    assert(pc);
    pc->sz = 0;
    memset(pc->data, 0, sizeof(pc->data));
}
  • 1
  • 2
  • 3
  • 4
  • 5
2. 添加联系人

通过 AddNewContact 函数,我们可以添加新的联系人信息。每次添加一个联系人,我们都会提示用户输入联系人姓名、年龄、性别、电话和地址,并将其存储到 data 数组中:

void AddNewContact(contact* pc) {
    assert(pc);
    if (pc->sz == MAX_NUM) {
        printf("联系人已满,无法添加!\n");
        return;
    }
    printf("请输入姓名>");
    scanf("%19s", pc->data[pc->sz].name);
    printf("请输入年龄>");
    scanf("%d", &(pc->data[pc->sz].age));
    printf("请输入性别>");
    scanf("%9s", pc->data[pc->sz].gender);
    printf("请输入电话号码>");
    scanf("%12s", pc->data[pc->sz].tele);
    printf("请输入地址>");
    scanf("%29s", pc->data[pc->sz].addr);

    pc->sz++;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
3. 查找联系人

通过姓名查找联系人,我们可以使用 FindName 函数在通讯录中查找对应的联系人。如果找到了,就打印出该联系人的详细信息:

int FindName(const char* str, const contact* pc) {
    assert(str);
    for (int i = 0; i < pc->sz; i++) {
        if (strcmp(str, pc->data[i].name) == 0) {
            return i;  // 找到联系人,返回其位置
        }
    }
    return -1;  // 未找到联系人
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
4. 删除联系人

通过 DeleContact 函数,我们可以删除指定的联系人。删除的过程是将该联系人的后续联系人前移一位,并减少联系人数量:

void DeleContact(contact* pc) {
    assert(pc);
    char name[MAX_NAME] = { 0 };
    printf("请输入要删除联系人的姓名>");
    scanf("%s", name);
    int pos = FindName(name, pc);
    if (pos == -1) {
        printf("没有该联系人!\n");
        return;
    }
    for (int i = pos; i < pc->sz - 1; i++) {
        pc->data[i] = pc->data[i + 1];
    }
    pc->sz--;
    printf("删除成功!\n");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
5. 修改联系人

通过 ModifyContact 函数,我们可以修改联系人的信息。用户选择修改的字段后,程序会提示用户输入新的值并进行更新:

void ModifyContact(contact* pc) {
    assert(pc);
    char name[MAX_NAME] = { 0 };
    printf("请输入要修改联系人的姓名>");
    scanf("%s", name);
    int pos = FindName(name, pc);
    if (pos == -1) {
        printf("没有该联系人!\n");
        return;
    }
    int input = 0;
    do {
        menu2();  // 显示修改选项
        printf("请选择你要修改的项>");
        scanf("%d", &input);
        switch (input) {
            case 0: {
                printf("修改成功!\n");
                break;
            }
            case 1: {
                printf("请输入姓名>");
                scanf("%s", pc->data[pos].name);
                break;
            }
            case 2: {
                printf("请输入年龄>");
                scanf("%d", &(pc->data[pos].age));
                break;
            }
            case 3: {
                printf("请输入性别>");
                scanf("%s", pc->data[pos].gender);
                break;
            }
            case 4: {
                printf("请输入电话号码>");
                scanf("%s", pc->data[pos].tele);
                break;
            }
            case 5: {
                printf("请输入地址>");
                scanf("%s", pc->data[pos].addr);
                break;
            }
            default: {
                printf("数据错误,请重新输入!\n");
                break;
            }
        }
    } while (input);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
6. 显示所有联系人

通过 DisplayContact 函数,我们可以显示当前所有联系人的信息:

void DisplayContact(const contact* pc) {
    printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "名字", "年龄", "性别", "地址", "电话");
    for (int i = 0; i < pc->sz; i++) {
        printf("%-20s\t%-4S\t%-5d\t%-20s\t%-12s\n", pc->data[i].name,
               pc->data[i].gender,
               pc->data[i].age,
               pc->data[i].addr,
               pc->data[i].tele);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
7. 清空所有联系人

如果我们想要清空通讯录中的所有联系人,可以通过 ClearContact 函数实现:

void ClearContact(contact* pc) {
    assert(pc);
    InitContact(pc);  // 重置通讯录,清空所有联系人
    printf("所有联系人已清空!\n");
}
  • 1
  • 2
  • 3
  • 4
  • 5
8. 按名字排序联系人

最后,我们通过 qsort 函数按姓名排序所有联系人:

int CmpByName(const void* e1, const void* e2) {
    return strcmp(((info*)e1)->name, ((info*)e2)->name);
}

void SortContact(contact* pc) {
    assert(pc);
    qsort(pc->data, pc->sz, sizeof(pc->data[0]), CmpByName);
    printf("排序成功!\n");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

易错点与建议

  1. 输入安全性:使用 scanf 时没有限制输入长度,可能会导致缓冲区溢出。可以在读取字符串时限制输入长度,比如 scanf("%19s", name)。
  2. 内存越界检查:在访问数组和指针时,应该时刻注意数组越界的问题,避免读取非法内存。
  3. 模块化设计:目前我们将所有功能集中在一个文件中,可以考虑将各个功能拆分成多个文件,提高代码的可维护性。

完整代码

我将该项目拆分为了3个文件:

  • test.c
  • contact.h
  • contact.c
contact.h — 头文件

头文件通常包含全局变量、宏定义、结构体声明、函数原型等。在这个文件中,我们将声明通讯录相关的所有结构体和函数原型。

#pragma once
#include 
#include 
#include 
#include 

// 常量定义
#define MAX_NAME 20
#define MAX_GENDER 10
#define MAX_TELE 13
#define MAX_NUM 1000
#define MAX_ADDR 30

// 联系人信息结构体
typedef struct info {
    char name[MAX_NAME];
    int age;
    char gender[MAX_GENDER];
    char tele[MAX_TELE];
    char addr[MAX_ADDR];
} info;

// 通讯录结构体
typedef struct contact {
    info data[MAX_NUM];  // 存储联系人的信息
    int sz;  // 当前已存放联系人的个数
} contact;

// 函数声明
void InitContact(contact* pc);
void AddNewContact(contact* pc);
void FindContact(const contact* pc);
void DisplayContact(const contact* pc);
void DeleContact(contact* pc);
void ModifyContact(contact* pc);
void ClearContact(contact* pc);
void SortContact(contact* pc);
int FindName(const char* str, const contact* pc);
int CmpByName(const void* e1, const void* e2);
void menu();
void menu2();
void test();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
contact.c — 主要功能实现

在这个文件中,我们实现了通讯录的具体功能,包括联系人信息的增删改查、排序等。

#include "contact.h"

// 初始化联系人
void InitContact(contact* pc) {
    assert(pc);
    pc->sz = 0;
    memset(pc->data, 0, sizeof(pc->data));
}

// 添加联系人
void AddNewContact(contact* pc) {
    assert(pc);
    if (pc->sz == MAX_NUM) {
        printf("联系人已满,无法添加!\n");
        return;
    }
    printf("请输入姓名>");
    scanf("%s", pc->data[pc->sz].name);
    printf("请输入年龄>");
    scanf("%d", &(pc->data[pc->sz].age));
    printf("请输入性别>");
    scanf("%s", pc->data[pc->sz].gender);
    printf("请输入电话号码>");
    scanf("%s", pc->data[pc->sz].tele);
    printf("请输入地址>");
    scanf("%s", pc->data[pc->sz].addr);
    pc->sz++;
}

// 查找联系人
int FindName(const char* str, const contact* pc) {
    assert(str);
    for (int i = 0; i < pc->sz; i++) {
        if (strcmp(str, pc->data[i].name) == 0) {
            return i;
        }
    }
    return -1;
}

void FindContact(const contact* pc) {
    assert(pc);
    char name[MAX_NAME] = { 0 };
    printf("请输入要查找联系人的姓名>");
    scanf("%s", name);
    int pos = FindName(name, pc);
    if (pos == -1) {
        printf("没有该联系人!\n");
        return;
    }
    printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "名字", "年龄", "性别", "地址", "电话");
    printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", pc->data[pos].name,
           pc->data[pos].age,
           pc->data[pos].gender,
           pc->data[pos].addr,
           pc->data[pos].tele);
}

// 显示联系人
void DisplayContact(const contact* pc) {
    assert(pc);
    printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "名字", "年龄", "性别", "地址", "电话");
    for (int i = 0; i < pc->sz; i++) {
        printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", pc->data[i].name,
               pc->data[i].age,
               pc->data[i].gender,
               pc->data[i].addr,
               pc->data[i].tele);
    }
}

// 删除联系人
void DeleContact(contact* pc) {
    assert(pc);
    char name[MAX_NAME] = { 0 };
    printf("请输入要删除联系人的姓名>");
    scanf("%s", name);
    int pos = FindName(name, pc);
    if (pos == -1) {
        printf("没有该联系人!\n");
        return;
    }
    for (int i = pos; i < pc->sz - 1; i++) {
        pc->data[i] = pc->data[i + 1];
    }
    pc->sz--;
    printf("删除成功!\n");
}

// 修改联系人
void ModifyContact(contact* pc) {
    assert(pc);
    char name[MAX_NAME] = { 0 };
    printf("请输入要修改联系人的姓名>");
    scanf("%s", name);
    int pos = FindName(name, pc);
    if (pos == -1) {
        printf("没有该联系人!\n");
        return;
    }
    int input = 0;
    do {
        menu2();  // 显示修改选项
        printf("请选择你要修改的项>");
        scanf("%d", &input);
        switch (input) {
            case 1:
                printf("请输入姓名>");
                scanf("%s", pc->data[pos].name);
                break;
            case 2:
                printf("请输入年龄>");
                scanf("%d", &(pc->data[pos].age));
                break;
            case 3:
                printf("请输入性别>");
                scanf("%s", pc->data[pos].gender);
                break;
            case 4:
                printf("请输入电话号码>");
                scanf("%s", pc->data[pos].tele);
                break;
            case 5:
                printf("请输入地址>");
                scanf("%s", pc->data[pos].addr);
                break;
            case 0:
                printf("修改完成!\n");
                break;
            default:
                printf("无效选项,请重新选择!\n");
        }
    } while (input != 0);
}

// 清空所有联系人
void ClearContact(contact* pc) {
    assert(pc);
    InitContact(pc);  // 重置通讯录
    printf("所有联系人已清空!\n");
}

// 排序联系人(按姓名)
int CmpByName(const void* e1, const void* e2) {
    return strcmp(((info*)e1)->name, ((info*)e2)->name);
}

void SortContact(contact* pc) {
    assert(pc);
    qsort(pc->data, pc->sz, sizeof(pc->data[0]), CmpByName);
    printf("排序成功!\n");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
test.c — 主程序与测试

在这个文件中,我们将测试所有功能,用户可以选择相应的操作,程序会根据用户输入调用不同的函数。

#include "contact.h"

void menu() {
    printf("**************************************\n");
    printf("***** 0.退出        1.添加联系人 *****\n");
    printf("***** 2.查找联系人  3.显示联系人 *****\n");
    printf("***** 4.删除联系人  5.修改联系人 *****\n");
    printf("***** 6.清空联系人  7.排序联系人 *****\n");
    printf("**************************************\n");
}

void test() {
    int input = 0;
    contact con;
    InitContact(&con);  // 初始化通讯录
    do {
        menu();
        printf("请输入数字>");
        scanf("%d", &input);
        switch (input) {
            case 1:
                AddNewContact(&con);
                break;
            case 2:
                FindContact(&con);
                break;
            case 3:
                DisplayContact(&con);
                break;
            case 4:
                DeleContact(&con);
                break;
            case 5:
                ModifyContact(&con);
                break;
            case 6:
                ClearContact(&con);
                break;
            case 7:
                SortContact(&con);
                break;
            case 0:
                printf("退出成功!\n");
                break;
            default:
                printf("数据错误,请重新输入!\n");
                break;
        }
    } while (input != 0);
}

int main() {
    test();
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

通过这种方式,我们将项目分成了多个文件,使得代码更加模块化,便于维护和扩展。在实际开发中,将不同功能封装到不同的源文件中是很常见的做法,可以有效提高代码的可读性和可维护性。

注:本文转载自blog.csdn.net的我想吃余的文章"https://blog.csdn.net/Surplus886/article/details/145432271"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

106
编程语言
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top