C语言实现进阶通讯录2.0

C语言实现通讯录(进阶版 - 动态内存管理)

上次我们实现了一个可以存储1000个人信息的静态版本的通讯录,那就会衍生出两个情况。
1.如果联系人信息很少的话,会造成很大的内存浪费
2.如果联系人超过1000个人,就无法进行存储

所以,我们需要把通讯录改成动态版本
提供方法:
1.添加联系人信息
2.删除指定联系人信息
3.查找指定联系人信息
4.修改指定联系人信息
5.显示所有联系人信息
6.清空所有联系人
7.以名字排序所有联系人
0.退出通讯录
在这里插入图片描述


前言

这次写的会比较简略,可以对通讯录1.0版本进行参考
通讯录1.0


正文开始

一、通讯录菜单的实现

程序与用户的交互,需要一个菜单来进行引导,所以我们第一步先实现菜单
需要把菜单的功能列举出来让用户可以进行下一步操作

void mean()//菜单的实现
{
    
    
    printf("*****************************************************************\n");
    printf("*********           1.add              2.del          ***********\n");
    printf("*********           3.seek             4.mod          ***********\n");
    printf("*********           5.show             6.empty        ***********\n");
    printf("*********           7.sort             0.exit         ***********\n");
    printf("*****************************************************************\n");
}

二、main函数实现

第二步我们对主函数进行实现

int main()
{
    
    
    int input = 0;
    content ab;                                        //定义通讯录变量ab
    Initcontact(&ab);                                //初始化通讯录函数
    do
    {
    
    
        mean();
        printf("请选择->");
        scanf("%d",&input);
        switch (input)
        {
    
    
        case EXIT:
            printf("退出通讯录\n");
            break;
        case ADD:
            addcontact(&ab);                        //增加联系人信息函数
            break;
        case DEL:
            delcontact(&ab);                        //删除联系人信息函数
            break;
        case SEEK:
            seekcontact(&ab);                        //寻找联系人信息函数
            break;
        case MOD:
            modcontact(&ab);                        //修改联系人信息函数
            break;
        case SHOW:
            showcontact(&ab);                        //展示联系人信息函数
            break;
        case EMPTY:
            emptycontact(&ab);                        //清空联系人信息函数
        case SORT:
            sortcontact(&ab);                        //排序联系人信息函数
            break;
        }
    } while (input);
    return 0;

}
 

将所有需要实现的情况都放在main,方便自己可以逻辑清晰的编写代码

三、枚举选项

一开始我们就用数字来编辑了菜单的选项,在这里需要用到枚举来实现菜单的选项,与主函数中的case进行对应

enum mean
{
    
    
    EXIT,//0
    ADD,//1
    DEL,//2
    SEEK,//3
    MOD,//4
    SHOW,//5
    EMPTY,//6
    SORT//7
};

运用枚举是为了让代码逻辑更加简洁易懂,提高代码的可维护性

扫描二维码关注公众号,回复: 14495034 查看本文章

四、定义通讯录内容以及联系人内容

这是个动态增长的版本,需要记录存放的数据,有效数据个数,默认数据个数

typedef struct message
{
    
    
    char name[MIN_NAME];
    char sex[MIN_SEX];
    int age;
    char number[MIN_NUMBER];
    char address[MIN_ADDRESS];
}message;
typedef struct data
{
    
    
    message* data;                                //用来保存通讯录存放的数据
    int sz;                                        //用来记录通讯录中有效数据的个数
    int capcity;                                //用来记录通讯录默认数据个数
}content;

五、对全局变量进行声明

我们需要对通讯录内的数据做一定的限制,这里需要对全局变量做一些声明

#define MIN_NAME 15                                //设置姓名数组中字符的个数
#define MIN_SEX 5                                //设置性别数组中字符的个数
#define MIN_NUMBER 20                            //设置号码数组中字符的个数
#define MIN_ADDRESS 18                            //设置地址数组中字符的个数
#define FRINUM 3                                //设置通讯录默认起始数据

六、通讯录功能的实现

我们已经拥有一个简易的通讯录了,现在需要对前文列举的功能进行一一实现

1.初始化通讯录

首先我们需要实现通讯录的保存功能,我们需要实现通讯录的初始化功能

//初始化通讯录函数
void Initcontact(content* ab)
{
    
    
    assert(ab);
    ab->sz = 0;
    ab->capcity = FRINUM;
    message* tmp = (message*)malloc(FRINUM*sizeof(message));
    //判断tmp是否为空指针
    if (tmp == NULL)
    {
    
    
        printf("Initcontact::%s\n",strerror(errno));
        return;
    }
    ab->data = tmp;                                                                            //动态的为指针ab开辟内存
    return;
}

2.实现新增联系人(1.add)

//增加联系人函数
void addcontact(content* ab)
{
    
    
    assert(ab);
    capcityadd(ab);                                                                                //增加通讯录的容量
    printf("请输入联系人的姓名->");
    scanf("%s",ab->data[ab->sz].name);
    printf("请输入联系人的性别->");
    scanf("%s",ab->data[ab->sz].sex);
    printf("请输入联系人的年龄->");
    scanf("%d",&(ab->data[ab->sz].age));
    printf("请输入联系人的电话->");
    scanf("%s",ab->data[ab->sz].number);
    printf("请输入联系人的住址->");
    scanf("%s",ab->data[ab->sz].address);
    printf("增加联系人成功\n");
    ab->sz++;
}

3.实现删除联系人(2.del)

//删除联系人函数
void delcontact(content* ab)
{
    
    
    assert(ab);
    char name[MIN_NAME] = {
    
    0};
    printf("请输入要删除联系人的姓名->");
    scanf("%s", name);
    int ret = seekname(name,ab);             //查找姓名函数
    if (ret == -1)
        printf("没有该联系人\n");
    else
    {
    
    
        for (i = ret; i < ab->sz; i++)
        {
    
    
            ab->data[i] = ab->data[i + 1];
        }
        printf("删除指定联系人成功\n");
        ab->sz--;                            //注意这一一定要执行这一步,删除一个联系人以后通讯录中有效个数就应该减少1
    }
    return;
}

4.实现查找联系人(3.seek)

4.1.编写一个查找函数

为了使代码的可读性更高,功能更加齐全,我们需要编写一个通过姓名可以查找的功能

//查找姓名函数
int seekname(char* name, content* ab)
{
    
    
    for (i = 0; i < ab->sz; i++)
    {
    
    
        if ((strcmp(name, ab->data[i].name)) == 0)
            return i;
    }
    return -1;
}

4.2实现查找联系人

//寻找联系人函数
void seekcontact(content* ab)
{
    
    
    assert(ab);
    char name[MIN_NAME] = {
    
     0 };
    printf("请输入要查找联系人的姓名->");
    scanf("%s", name);
    int ret = seekname(name, ab);                        //查找姓名函数
    if (ret == -1)
    {
    
    
        printf("没有该联系人\n");
        return;
    }
    else
    {
    
    
        printf("%-7s\t%-5s\t%-5s\t%-15s\t%-20s\n", "姓名", "性别", "年龄", "电话", "住址");
        printf("%-7s\t%-5s\t%-5d\t%-15s\t%-20s\n",
            ab->data[ret].name, ab->data[ret].sex, ab->data[ret].age, ab->data[ret].number, ab->data[ret].address);
    }
    return;
}

5.实现修改联系人(4.mod)

//修改联系人信息函数
void modcontact(content* ab)
{
    
    
    assert(ab);
    char name[MIN_NAME] = {
    
     0 };
    printf("请输入要查找联系人的姓名->");
    scanf("%s", name);
    int ret = seekname(name, ab);                        //查找姓名函数
    if (ret == -1)
    {
    
    
        printf("没有该联系人\n");
        return;
    }
    else
    {
    
    
        printf("%-7s\t%-5s\t%-5s\t%-15s\t%-20s\n", "姓名", "性别", "年龄", "电话", "住址");
        printf("%-7s\t%-5s\t%-5d\t%-15s\t%-20s\n",
            ab->data[ret].name, ab->data[ret].sex, ab->data[ret].age, ab->data[ret].number, ab->data[ret].address);
    }
    printf("请输入修改信息\n");
    printf("请输入联系人的姓名->");
    scanf("%s", ab->data[ret].name);
    printf("请输入联系人的性别->");
    scanf("%s", ab->data[ret].sex);
    printf("请输入联系人的年龄->");
    scanf("%d", &(ab->data[ret].age));
    printf("请输入联系人的电话->");
    scanf("%s", ab->data[ret].number);
    printf("请输入联系人的住址->");
    scanf("%s", ab->data[ret].address);
    printf("修改成功\n");
    return;
}
 


6.实现展示联系人(5.show)

//展示联系人函数
void showcontact(content* ab)
{
    
    
    //姓名、性别、年龄、电话、住址
    assert(ab);
    printf("%-7s\t%-5s\t%-5s\t%-15s\t%-20s\n","姓名","性别", "年龄", "电话", "住址");
    for (i = 0; i < ab->sz; i++)
    {
    
    
        printf("%-7s\t%-5s\t%-5d\t%-15s\t%-20s\n",
            ab->data[i].name, ab->data[i].sex, ab->data[i].age, ab->data[i].number, ab->data[i].address);
    }
    return;
}

7.实现清空联系人(6.empty)

//清空联系人信息函数
void emptycontact(content* ab)
{
    
    
    assert(ab);
    printf("请确认是否要清空通讯录(Y/N):");
    char str = 0;
    while ((str = getchar()) != '\n')
    {
    
    
        ;
    }
    scanf("%c", &str);
    if (str == 'Y')
    {
    
    
        ab->data = 0;
        ab->capcity = 0;
        ab->sz = 0;
        printf("全部清除成功\n");
    }
    return;
}

8.实现排序联系人信息(7.sort)

//排序联系人信息函数
void sortcontact(content* ab)
{
    
    
    assert(ab);
    qsort(ab->data,ab->sz,sizeof(ab->data[0]),compare);
    printf("%-7s\t%-5s\t%-5s\t%-15s\t%-20s\n", "姓名", "性别", "年龄", "电话", "住址");
    for (i = 0; i < ab->sz; i++)
    {
    
    
        printf("%-7s\t%-5s\t%-5d\t%-15s\t%-20s\n",
            ab->data[i].name, ab->data[i].sex, ab->data[i].age, ab->data[i].number, ab->data[i].address);
    }
    return;
}


9.代码总览

到这里进阶通讯录2.0已经全部完成了,下面就是程序的源代码

9.1 function.h

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

#define _CRT_SECURE_NO_WARNINGS
#define MIN_NAME 15                                //设置姓名数组中字符的个数
#define MIN_SEX 5                                //设置性别数组中字符的个数
#define MIN_NUMBER 20                            //设置号码数组中字符的个数
#define MIN_ADDRESS 18                            //设置地址数组中字符的个数
#define FRINUM 3                                //设置通讯录默认起始数据

 
typedef struct message
{
    
    
    char name[MIN_NAME];
    char sex[MIN_SEX];
    int age;
    char number[MIN_NUMBER];
    char address[MIN_ADDRESS];
}message;
typedef struct data
{
    
    
    message* data;                                //用来保存通讯录存放的数据
    int sz;                                        //用来记录通讯录中有效数据的个数
    int capcity;                                //用来记录通讯录默认数据个数
}content;
 
void Initcontact(content* ab);                    //初始化通讯录函数声明
void addcontact(content* ab);                    //增加联系人信息函数声明
void delcontact(content* ab);                    //删除联系人信息函数声明
void seekcontact(content* ab);                    //寻找联系人信息函数声明
void modcontact(content* ab);                    //修改联系人信息函数声明
void emptycontact(content* ab);                    //清空联系人信息函数声明
void showcontact(content* ab);                    //展示联系人信息函数声明
void sortcontact(content* ab);                    //排序联系人信息函数声明

9.2 main.c

#include "function.h"
//实现通讯录:通讯录可以用来存储1000个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址
//1.添加联系人信息
//2.删除指定联系人信息
//3.查找指定联系人信息
//4.修改指定联系人信息
//5.显示所有联系人信息
//6.清空所有联系人
//7.以名字排序所有联系人
enum number
{
    
    
    EXIT,
    ADD,
    DEL,
    SEEK,
    MOD,
    SHOW,
    EMPTY,
    SORT
};
void mean()
{
    
    
    printf("*****************************************************************\n");
    printf("*********           1.add              2.del          ***********\n");
    printf("*********           3.seek             4.mod          ***********\n");
    printf("*********           5.show             6.empty        ***********\n");
    printf("*********           7.sort             0.exit         ***********\n");
    printf("*****************************************************************\n");
}
int main()
{
    
    
    int input = 0;
    content ab;                                        //定义通讯录变量ab
    Initcontact(&ab);                                //初始化通讯录函数
    do
    {
    
    
        mean();
        printf("请选择->");
        scanf("%d",&input);
        switch (input)
        {
    
    
        case EXIT:
            printf("退出通讯录\n");
            break;
        case ADD:
            addcontact(&ab);                        //增加联系人信息函数
            break;
        case DEL:
            delcontact(&ab);                        //删除联系人信息函数
            break;
        case SEEK:
            seekcontact(&ab);                        //寻找联系人信息函数
            break;
        case MOD:
            modcontact(&ab);                        //修改联系人信息函数
            break;
        case SHOW:
            showcontact(&ab);                        //展示联系人信息函数
            break;
        case EMPTY:
            emptycontact(&ab);                        //清空联系人信息函数
        case SORT:
            sortcontact(&ab);                        //排序联系人信息函数
            break;
        }
    } while (input);
    return 0;

}

9.3 function.c

#include "function.h"
 
int i = 0;                                                                                        //全局变量i
//排序里面的比较函数
int compare(const void* e1, const void* e2)
{
    
    
    return strcmp(((message*)e1)->name, ((message*)e2)->name);
}
 
//增加通讯录容量函数
void capcityadd(content* ab)
{
    
    
    if (ab->sz == ab->capcity)
    {
    
    
        message* tmp = (message*)realloc(ab->data, (ab->capcity + 2) * sizeof(message));            //注意这里的结构体,不要引错了
        if (tmp != NULL)
        {
    
    
            ab->data = tmp;
            ab->capcity += 2;
            printf("增加容量成功\n");
        }
        else
        {
    
    
            printf("addcontact::%s\n", strerror(errno));
        }
    }
}
 
//查找姓名函数
int seekname(char* name, content* ab)
{
    
    
    for (i = 0; i < ab->sz; i++)
    {
    
    
        if ((strcmp(name, ab->data[i].name)) == 0)
            return i;
    }
    return -1;
}
 
//初始化通讯录函数
void Initcontact(content* ab)
{
    
    
    assert(ab);
    ab->sz = 0;
    ab->capcity = FRINUM;
    message* tmp = (message*)malloc(FRINUM*sizeof(message));
    //判断tmp是否为空指针
    if (tmp == NULL)
    {
    
    
        printf("Initcontact::%s\n",strerror(errno));
        return;
    }
    ab->data = tmp;                                                                            //动态的为指针ab开辟内存
    return;
}
 
//增加联系人函数
void addcontact(content* ab)
{
    
    
    assert(ab);
    capcityadd(ab);                                                                                //增加通讯录的容量
    printf("请输入联系人的姓名->");
    scanf("%s",ab->data[ab->sz].name);
    printf("请输入联系人的性别->");
    scanf("%s",ab->data[ab->sz].sex);
    printf("请输入联系人的年龄->");
    scanf("%d",&(ab->data[ab->sz].age));
    printf("请输入联系人的电话->");
    scanf("%s",ab->data[ab->sz].number);
    printf("请输入联系人的住址->");
    scanf("%s",ab->data[ab->sz].address);
    printf("增加联系人成功\n");
    ab->sz++;
}
 
//删除联系人函数
void delcontact(content* ab)
{
    
    
    assert(ab);
    char name[MIN_NAME] = {
    
    0};
    printf("请输入要删除联系人的姓名->");
    scanf("%s", name);
    int ret = seekname(name,ab);                        //查找姓名函数
    if (ret == -1)
        printf("没有该联系人\n");
    else
    {
    
    
        for (i = ret; i < ab->sz; i++)
        {
    
    
            ab->data[i] = ab->data[i + 1];
        }
        printf("删除指定联系人成功\n");
        ab->sz--;                                        //注意这一一定要执行这一步,删除一个联系人以后通讯录中有效个数就应该减少1
    }
    return;
}
 
//寻找联系人函数
void seekcontact(content* ab)
{
    
    
    assert(ab);
    char name[MIN_NAME] = {
    
     0 };
    printf("请输入要查找联系人的姓名->");
    scanf("%s", name);
    int ret = seekname(name, ab);                        //查找姓名函数
    if (ret == -1)
    {
    
    
        printf("没有该联系人\n");
        return;
    }
    else
    {
    
    
        printf("%-7s\t%-5s\t%-5s\t%-15s\t%-20s\n", "姓名", "性别", "年龄", "电话", "住址");
        printf("%-7s\t%-5s\t%-5d\t%-15s\t%-20s\n",
            ab->data[ret].name, ab->data[ret].sex, ab->data[ret].age, ab->data[ret].number, ab->data[ret].address);
    }
    return;
}
 
//修改联系人信息函数
void modcontact(content* ab)
{
    
    
    assert(ab);
    char name[MIN_NAME] = {
    
     0 };
    printf("请输入要查找联系人的姓名->");
    scanf("%s", name);
    int ret = seekname(name, ab);                        //查找姓名函数
    if (ret == -1)
    {
    
    
        printf("没有该联系人\n");
        return;
    }
    else
    {
    
    
        printf("%-7s\t%-5s\t%-5s\t%-15s\t%-20s\n", "姓名", "性别", "年龄", "电话", "住址");
        printf("%-7s\t%-5s\t%-5d\t%-15s\t%-20s\n",
            ab->data[ret].name, ab->data[ret].sex, ab->data[ret].age, ab->data[ret].number, ab->data[ret].address);
    }
    printf("请输入修改信息\n");
    printf("请输入联系人的姓名->");
    scanf("%s", ab->data[ret].name);
    printf("请输入联系人的性别->");
    scanf("%s", ab->data[ret].sex);
    printf("请输入联系人的年龄->");
    scanf("%d", &(ab->data[ret].age));
    printf("请输入联系人的电话->");
    scanf("%s", ab->data[ret].number);
    printf("请输入联系人的住址->");
    scanf("%s", ab->data[ret].address);
    printf("修改成功\n");
    return;
}
 
//清空联系人信息函数
void emptycontact(content* ab)
{
    
    
    assert(ab);
    printf("请确认是否要清空通讯录(Y/N):");
    char str = 0;
    while ((str = getchar()) != '\n')
    {
    
    
        ;
    }
    scanf("%c", &str);
    if (str == 'Y')
    {
    
    
        ab->data = 0;
        ab->capcity = 0;
        ab->sz = 0;
        printf("全部清除成功\n");
    }
    return;
}
 
//展示联系人函数
void showcontact(content* ab)
{
    
    
    //姓名、性别、年龄、电话、住址
    assert(ab);
    printf("%-7s\t%-5s\t%-5s\t%-15s\t%-20s\n","姓名","性别", "年龄", "电话", "住址");
    for (i = 0; i < ab->sz; i++)
    {
    
    
        printf("%-7s\t%-5s\t%-5d\t%-15s\t%-20s\n",
            ab->data[i].name, ab->data[i].sex, ab->data[i].age, ab->data[i].number, ab->data[i].address);
    }
    return;
}
 
//排序联系人信息函数
void sortcontact(content* ab)
{
    
    
    assert(ab);
    qsort(ab->data,ab->sz,sizeof(ab->data[0]),compare);
    printf("%-7s\t%-5s\t%-5s\t%-15s\t%-20s\n", "姓名", "性别", "年龄", "电话", "住址");
    for (i = 0; i < ab->sz; i++)
    {
    
    
        printf("%-7s\t%-5s\t%-5d\t%-15s\t%-20s\n",
            ab->data[i].name, ab->data[i].sex, ab->data[i].age, ab->data[i].number, ab->data[i].address);
    }
    return;
}



猜你喜欢

转载自blog.csdn.net/m0_60338933/article/details/124360523