iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言代码实现通讯录管理系统
  • 746
分享到

C语言代码实现通讯录管理系统

2024-04-02 19:04:59 746人浏览 独家记忆
摘要

目录一、需求分析二、程序结构三、头文件内容的介绍四、模块化实现各个功能(1)主函数实现(2)初始化通讯录(3)添加联系人信息(4)删除联系人信息(5)查找联系人信息(6)更改联系人信

本文实例为大家分享了C语言实现通讯录管理系统,供大家参考,具体内容如下

一、需求分析

运用C语言实现一个简单的通讯录管理系统,要求对数据有 增删改查清排显 等功能的实现(这里由于还没学到文件,所以下面所有的存储都是在内存中,也就是当程序结束的时候添加的信息都会清空掉 - 后续会加以改进的)

二、程序结构

在基本的程序设计中,都会将项目分为三个文件:

1、test.c - 主函数(负责调用各个功能的接口)
2、contact.c - 实现各个模块的功能
3、contact.h - 用于存放头文件、宏定义、函数声明等

三、头文件内容的介绍

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>

#define MAX 1000
#define NAME_MAX 20
#define SEX_MAX 5
#define ADDR_MAX 50
#define TELE_MAX 12

#define DEFAULT_SZ 3

// 数组版本
//typedef struct PeoInfo
//{
//    char name[NAME_MAX];
//    int age;
//    char sex[SEX_MAX];
//    char addr[ADDR_MAX];
//    char tele[TELE_MAX];
//}PeoInfo;
//
//typedef struct Contact
//{
//    //PeoInfo data[MAX];  // 存放信息
//    PeoInfo data[MAX];
//    int sz; // 存放通讯录有几个人的信息
//}Contact;

// 每个人的基本信息
typedef struct PeoInfo
{
    char name[NAME_MAX];
    int age;
    char sex[SEX_MAX];
    char addr[ADDR_MAX];
    char tele[TELE_MAX];
}PeoInfo;

typedef struct Contact
{
    //PeoInfo data[MAX];  // 存放信息
    PeoInfo* data;
    int sz; // 存放通讯录有几个人的信息
    int capacity; // 记录当前通讯录的最大容量
}Contact;


void DestoryContact(Contact* pc);
void InitContact(Contact* pc);
void AddContact(Contact* pc);
void ShowContact(const Contact* pc);
void DeleteContact(Contact* pc);
void SearchContact(const Contact* pc);
void ModifyContact(Contact* pc);
void SortContact(Contact* pc);

里面被注释的代码则是之前的数组版本,规定死了通讯录大小;而下面我们会用动态增容来进行实现。头文件里面用宏定义主要为了之后我们更改对应的大小的时候更加的方便;结构体主要存放的就是三大部分:

1. 一个指向每个人基本信息的结构体指针;2. sz记录着通讯录的记录条数;3. capacity 存放通讯录的容量

四、模块化实现各个功能

(1)主函数实现

int main()
{
    int input = 0;
    Contact con; // 创建通讯录

    InitContact(&con);

    do
    {
        menu();
        printf("请选择:->");
        scanf("%d", &input);

        switch (input)
        {
        case ADD:
            AddContact(&con);
            break;
        case DEL:
            DeleteContact(&con);
            break;
        case SEARCH:
            SearchContact(&con);
            break;
        case MODIFY:
            ModifyContact(&con);
            break;
        case SORT:
            SortContact(&con);
            break;
        case SHOW:
            ShowContact(&con);
            break;
        case EXIT:
            DestoryContact(&con);
            printf("退出\n");
            break;
        default:
            printf("输入错误,请重新输入\n");
            break;
        }
    } while (input);

    return 0;
}

一般函数的主函数里面都可以用do ……while结构来控制程序的执行顺序,在case后面用的则是 枚举常量 ,这样能做到更好的见名知意。

(2)初始化通讯录

void InitContact(Contact* pc)
{
    assert(pc);
    pc->sz = 0;
    PeoInfo* tmp = (PeoInfo*)malloc(DEFAULT_SZ * sizeof(PeoInfo));
    if (tmp != NULL)
    {
        pc->data = tmp;
    }
    else
    {
        printf("InitContact()::%s\n", strerror(errno));
    }

    pc->capacity = DEFAULT_SZ;
}

这里设定了通讯录的起始大小,后面可以通过动态增容来扩大(而数组版本的话就没有这么灵活了)

(3)添加联系人信息

void check_capacity(Contact* pc)
{
    assert(pc);
    if (pc->sz == pc->capacity)
    {
        // 增容
        PeoInfo* tmp = (PeoInfo*)realloc(pc->data, (pc->capacity + 2)*sizeof(PeoInfo));
        if (tmp != NULL)
        {
            pc->data = tmp;
            pc->capacity += 2;
            printf("增容成功\n");
        }
        else
        {
            printf("InitContact()::%s\n", strerror(errno));
        }
    }
}

void AddContact(Contact* pc)
{
    assert(pc);
    check_capacity(pc);

    // 添加内容
    printf("名字:");
    scanf("%s", pc->data[pc->sz].name);
    printf("年龄:");
    scanf("%d", &(pc->data[pc->sz].age));
    printf("性别:");
    scanf("%s", pc->data[pc->sz].sex);
    printf("地址:");
    scanf("%s", pc->data[pc->sz].addr);
    printf("电话:");
    scanf("%s", pc->data[pc->sz].tele);
    
    pc->sz++;
    printf("添加成功\n");
}

这里实现了一个check_capacity 的接口,用来判断当前通讯录是否存满了;若满了则进行扩容(一般按2倍进行扩容),注意:添加成功后需要对 sz++

(4)删除联系人信息

int FindByName(const Contact* pc, char* name)
{
    int i = 0;
    for (i = 0; i < pc->sz; i++)
    {
        if (strcmp(pc->data[i].name, name) == 0)
        {
            return i;
        }
    }
    return -1;
}

void DeleteContact(Contact* pc)
{
    char name[NAME_MAX] = { 0 };
    assert(pc);

    if (pc->sz == 0)
    {
        printf("通讯录为空\n");
        return;
    }

    // 根据输入的人名进行删除
    printf("请输入要删除的人名:");
    scanf("%s", name);

    int pos = FindByName(pc, name);

    if (pos == -1)
    {
        printf("要删除的人不存在\n");
    }
    else
    {
        // 删除
        //int j = 0;
        //for (j = pos; j < pc->sz-1; j++)  // sz-1为了防止j+1非法访问
        //{
        //    pc->data[j] = pc->data[j + 1];
        //}

        //pc->sz--;
        //printf("删除成功\n");
        //if (pc->sz>1)
        memmove((pc->data) + pos, (pc->data) + pos + 1, (pc->sz - pos)*sizeof(PeoInfo));
        pc->sz--;
    }
}

这里我就只做了按照名字进行删除,你们也可以都尝试一下哟。下面写了两种删除方法(这里的按名字删除前需要进行查找,因此我们也可以直接使用我们下面要实现的查找函数,但如果查找里面进行了其他功能,那时不能直接使用的哟)

(5)查找联系人信息

void SearchContact(const Contact* pc)

{
    char name[NAME_MAX] = { 0 };
    assert(pc);

    if (pc->sz == 0)
    {
        printf("通讯录为空\n");
        return;
    }

    printf("请输入要查找的姓名:");
    scanf("%s", name);
    int i = FindByName(pc, name);

    if(-1 == i)
    {
        // 没有找到
        printf("你要查找的人不存在\n");
    }
    else
    {
        // 找到了
        printf("%-10s\t%-5s\t%-5s\t%-20s\t%-13s\n", 
                "姓名", "年龄", "性别", "地址", "电话");
        printf("%-10s\t%-5d\t%-5s\t%-20s\t%-13s\n",
            pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].addr, pc->data[i].tele);
    }
}

这里如果查找到了后,我打印显示了一下

(6)更改联系人信息

void ModifyContact(Contact* pc)
{
    char name[NAME_MAX] = { 0 };
    assert(pc);

    if (pc->sz == 0)
    {
        printf("通讯录为空\n");
        return;
    }

    printf("请输入要修改信息的姓名:");
    scanf("%s", name);

    int i = FindByName(pc, name);

    // 修改内容
    printf("新的名字:");
    scanf("%s", pc->data[i].name);
    printf("新的年龄:");
    scanf("%d", &(pc->data[i].age));
    printf("新的性别:");
    scanf("%s", pc->data[i].sex);
    printf("新的地址:");
    scanf("%s", pc->data[i].addr);
    printf("新的电话:");
    scanf("%s", pc->data[i].tele);

    printf("修改后的信息为:\n");

    printf("%-10s\t%-5s\t%-5s\t%-20s\t%-13s\n", "姓名", "年龄", "性别", "地址", "电话");
    printf("%-10s\t%-5d\t%-5s\t%-20s\t%-13s\n",
        pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].addr, pc->data[i].tele);
}

(7)显示所有联系人信息

void ShowContact(const Contact* pc)
{
    assert(pc);
    // 打印标题
    printf("%-10s\t%-5s\t%-5s\t%-20s\t%-13s\n", "姓名", "年龄", "性别", "地址", "电话");
    int i = 0;
    for (i = 0; i < pc->sz; i++)
    {
        printf("%-10s\t%-5d\t%-5s\t%-20s\t%-13s\n",
            pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].addr, pc->data[i].tele);
    }
}

直接遍历打印即可

(8)对联系人信息进行排序

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

int cmp_by_age(const void* e1, const void* e2)
{
    return ((PeoInfo*)e1)->age - ((PeoInfo*)e2)->age;
    // return strcmp(, ((PeoInfo*)e2)->name);
}

void SortContact(Contact* pc)
{
    int choice = 0;
    printf("请选择:(1、按姓名;2、按年龄)");
    scanf("%d", &choice);

    if (1 == choice)
    {
        qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_by_name);

        printf("排序后的数据:\n");
        ShowContact(pc);
    }
    else if (2 == choice)
    {
        qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_by_age);
        printf("排序后的数据:\n");
        ShowContact(pc);
    }
    else
    {
        printf("输入有误\n");
    }
}

这里使用qsort实现的排序,可以对 姓名 或 年龄进行排序的

(9)退出时销毁通讯录

void DestoryContact(Contact* pc)
{
    assert(pc);
    free(pc->data);
    pc->data = NULL;
}

直接将里面指向有效内容的 pc->data 进行free释放就行,因为它本来就是动态开辟的,后面要有个好习惯,free之后将其置为NULL,不然就为野指针了。

总结:

以上就是动态增容版本通讯录的全部代码,尽管用了动态增容,里面仍然会存在很多的空间浪费,后面等博主学了链表后,在进行改进。

希望这篇文章对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: C语言代码实现通讯录管理系统

本文链接: https://www.lsjlt.com/news/151533.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • c语言怎么计算字符串长度
    在C语言中,可以使用内置的strlen()函数来计算字符串的长度。该函数位于string.h头文件中。以下是一个示例代码: #inc...
    99+
    2024-05-14
    c语言
  • c语言怎么判断三个数的大小
    可以通过比较三个数之间的大小关系来判断它们的大小。以下是一个示例代码: #include <stdio.h> int ...
    99+
    2024-05-14
    c语言
  • c++排序函数sort怎么使用
    在C++中,使用sort函数对容器中的元素进行排序,可以按照默认的升序排列,也可以自定义排序规则。 下面是一个简单的例子,对一个ve...
    99+
    2024-05-14
    c++
  • c++中string的compare函数怎么使用
    在C++中,可以使用string的compare函数来比较两个string对象的大小。该函数的原型如下: int compare(c...
    99+
    2024-05-14
    c++
  • c++中string的compare函数有什么用
    c++中string的compare函数用于比较两个字符串的大小关系。该函数返回一个整数值,表示两个字符串的比较结果。 具体来说,如...
    99+
    2024-05-14
    c++
  • c++中print函数的功能有哪些
    在C++中,通常使用std::cout来进行输出操作,而不是使用print函数。std::cout是C++标准库中的一个输出流对象,...
    99+
    2024-05-14
    c++
  • c语言数据结构怎么使用
    在C语言中,数据结构可以通过定义结构体来实现。以下是一些常见的数据结构的使用方法示例: 链表: #include <std...
    99+
    2024-05-14
    c语言
  • c++中print函数的用法是什么
    在C++中没有内置的print函数,但可以使用cout来输出内容到控制台。cout是C++标准库中的一个输出流对象,可以使用<...
    99+
    2024-05-14
    c++
  • c++中concept的用法是什么
    在C++20中,Concept是一种新的语言特性,用于定义类型要求和约束。Concept可以被用来约束函数模板、类模板和普通函数的参...
    99+
    2024-05-14
    c++
  • c++中concept的作用是什么
    在C++中,concept的作用是定义一种通用的约束,用于限制模板参数的类型范围。通过使用concept,可以在编译时对模板参数进行...
    99+
    2024-05-14
    c++
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作