基于单向链表的C语言通讯录实现分析

前言

在计算机编程中,数据结构的选择对程序的性能和功能实现有着至关重要的影响。今天我们来分析一个基于单向链表实现的C语言通讯录程序。这个程序展示了如何利用链表这种动态数据结构来管理联系人信息,实现了基本的增删改查功能。

目录

前言

正文

[1. 整体架构设计](#1. 整体架构设计)

[2. 核心数据结构](#2. 核心数据结构)

联系人信息结构

链表节点结构

[3. 链表核心功能实现](#3. 链表核心功能实现)

节点创建

尾插法实现

链表销毁

[4. 通讯录业务逻辑](#4. 通讯录业务逻辑)

添加联系人

查找功能辅助函数

删除联系人

[5. 用户界面设计](#5. 用户界面设计)

总结

优点

可改进之处

扩展建议


正文

1. 整体架构设计

该通讯录程序采用模块化设计,主要分为三个核心模块:

  • SList:通用单向链表实现

  • contact:通讯录业务逻辑

  • test:用户界面和测试代码

这种分层架构使得代码结构清晰,便于维护和扩展。

2. 核心数据结构

联系人信息结构
复制代码
typedef struct personInfo
{
    char name[NAME_MAX];
    char gender[GENDER_MAX];
    int age;
    char tel[TEL_MAX];
    char addr[ADDR_MAX];
}peoInfo;

这个结构体定义了联系人的完整信息,包含姓名、性别、年龄、电话和地址,字段设计合理,涵盖了通讯录的基本需求。

链表节点结构
复制代码
typedef struct SListNode
{
    SLTDataType data;
    struct SListNode* next;
}SLTNode;

经典的链表节点设计,使用typedefpeoInfo定义为SLTDataType,使得链表可以通用化。

3. 链表核心功能实现

节点创建
复制代码
SLTNode* SLTBuyNode(SLTDataType x)
{
    SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
    if (newnode == NULL)
    {
        perror("malloc fail!");
        exit(1);
    }
    newnode->data = x;
    newnode->next = NULL;
    return newnode;
}

这段代码实现了节点的动态内存分配,包含必要的错误检查,确保程序在内存不足时能够优雅退出。

尾插法实现
复制代码
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
    assert(pphead);
    SLTNode* newnode = SLTBuyNode(x);

    if (*pphead == NULL)
    {
        *pphead = newnode;
    }
    else
    {
        SLTNode* ptail = *pphead;
        while (ptail->next)
        {
            ptail = ptail->next;
        }
        ptail->next = newnode;
    }
}

尾插法的实现考虑了空链表和非空链表两种情况,逻辑清晰。不过这里有个小瑕疵:没有对传入的数据进行校验。

链表销毁
复制代码
void SListDestroy(SLTNode** pphead)
{
    assert(pphead && *pphead);
    SLTNode* pcur = *pphead;
    while (pcur)
    {
        SLTNode* next = pcur->next;
        free(pcur);
        pcur = next;
    }
    *pphead = NULL;
}

内存管理很完善,确保不会出现内存泄漏,这是很多初学者容易忽略的地方。

4. 通讯录业务逻辑

添加联系人
复制代码
void ContactAdd(contact** con)
{
    peoInfo info;
    printf("请输入要添加的联系人的姓名:\n");
    scanf("%s", info.name);
    // ... 其他字段输入
    SLTPushBack(con, info);
    printf("插入成功!\n");
}

用户交互设计友好,但缺乏输入验证,在实际使用中可能会因为非法输入导致问题。

查找功能辅助函数
复制代码
contact* FindByName(contact* con, char name[])
{
    contact* cur = con;
    while (cur)
    {
        if (strcmp(cur->data.name, name) == 0)
        { 
            return cur;
        }
        cur = cur->next;
    }
    return NULL;
}

这个函数被多个操作复用(删除、查找、修改),体现了良好的代码复用思想。使用strcmp进行字符串比较是正确的做法。

删除联系人
复制代码
void ContactDel(contact** con)
{
    char name[NAME_MAX];
    printf("请输入要删除的联系人姓名:\n");
    scanf("%s", name);
    contact* pos = FindByName(*con, name);
    if (pos == NULL)
    {
        printf("要删除的联系人数据不存在\n");
        return;
    }
    SLTErase(con, pos);
    printf("删除成功!\n");
}

先查找后删除的模式确保了操作的安全性,用户反馈也很明确。

5. 用户界面设计

复制代码
void menu()
{
    printf("******************************************\n");
    printf("*********         通讯录         *********\n");
    printf("********1.添加联系人    2.删除联系人******\n");
    printf("********3.修改联系人    4.查找联系人******\n");
    printf("********5.展示联系人    0.退出通讯录******\n");
    printf("******************************************\n");
}

菜单设计简洁明了,功能划分清晰。主循环使用switch-case结构,是控制台程序的典型做法。

测试代码提供了完整的用户交互流程:

复制代码
void SListTest02()
{
    contact* con = NULL;
    int n = 0;

    do
    {
        menu();
        printf("请输入你的选择:\n");
        scanf("%d", &n);
        switch (n)
        {
        case 1:
            ContactAdd(&con);
            break;
        // ... 其他case
        case 0:
            printf("退出通讯录!\n");
            break;
        default:
            printf("输入错误,请重新输入:\n");
            break;
        }
    } while (n);

    ContactDesTroy(&con);
}

总结

优点

  1. 架构清晰:模块化设计使得各功能职责明确

  2. 内存管理完善:动态内存分配和释放处理得当

  3. 代码复用性好:查找等功能被多个操作复用

  4. 用户交互友好:操作提示和反馈明确

可改进之处

  1. 输入验证缺失:没有对用户输入进行有效性检查

  2. 错误处理不足:部分边界情况处理不够完善

  3. 功能扩展性:目前仅支持按姓名查找,可以增加更多查找方式

  4. 数据持久化:缺少文件存储功能,数据无法保存

扩展建议

  • 添加文件读写功能,实现数据持久化

  • 增加按电话号码、地址等多条件查询

  • 实现联系人排序功能

  • 添加输入验证和错误恢复机制

这个通讯录程序作为一个教学示例,很好地展示了单向链表在实际情况中的应用,为学习数据结构和C语言编程提供了很好的参考。

相关推荐
老鱼说AI1 小时前
算法初级教学第四步:栈与队列
网络·数据结构·python·算法·链表
客梦1 小时前
数据结构核心内容
数据结构·笔记
忘记9261 小时前
什么是stream流
开发语言
FMRbpm1 小时前
栈练习--------有效的括号(LeetCode 20)
数据结构·c++·leetcode·新手入门
上78将1 小时前
JVM回收垃圾机制
java·开发语言·jvm
ReinaXue1 小时前
快速认识图像生成算法:VAE、GAN 和 Diffusion Models
图像处理·人工智能·神经网络·算法·生成对抗网络·计算机视觉·语言模型
张人玉1 小时前
C#Https协议相关知识点
开发语言·https·c#
獭.獭.1 小时前
C++ -- STL【list的模拟实现】
c++·stl·list
再睡一夏就好1 小时前
进程调度毫秒之争:详解Linux O(1)调度与进程切换
linux·运维·服务器·c++·算法·哈希算法