联系人通讯录(静态+动态版本)

前言

该通讯录可以用来存储1000个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址

提供方法:

  1. 添加联系人信息

  1. 删除指定联系人信息

  1. 查找指定联系人信息

  1. 修改指定联系人信息

  1. 显示所有联系人信息

  1. 清空所有联系人

  1. 以名字排序所有联系人

实现

在这里实现通讯录用三个模块

test.c--------------------测试通讯录的功能

contact.h---------------通讯录的实现(头文件和函数的声明)

contact.c---------------通讯录的实现(各个功能的实现)

一、通讯录菜单

首先建立一个菜单,菜单立马应该包括通讯录立马该有的功能,以便于用户的操作。

void menu()
{
    printf("*************************************\n");
    printf("******  1. add    2. del       ******\n");
    printf("******  3. search 4. modify    ******\n");
    printf("******  5. show   6. sort_name ******\n");
    printf("******  7.clcall  0. exit      ******\n");
    printf("*************************************\n");
}

二、主函数框架

主函数包含了创建通讯录,初始化,还使用了do while函数和switch函数,通过input读取用户输入的数字,利用switch函数进行调用各个函数的功能。

int main()
{
    int input = 0;
    //初始化通讯录
    Contact con;
    Init_contact(&con);
    do {
        menu();
        printf("请选择:");
        scanf("%d", &input);
        switch (input)
        {
            case 1:
                Addcontact(&con);
                break;
            case 2:
                delcontact(&con);
                break;
            case 3:
                search(&con);
                break;
            case 4:
                modify(&con);
                break;
            case 5:
                showcontact(&con);
                break;
            case 6:
                sort_name(&con);
                break;
            case 7:
                clcall(&con);
                break;
            case 0:
                printf("退出通讯录\n");
                break;
            default:
                printf("输入错误,请重新输入");
                break;
        }


    } while (input);
    return 0;
}

主函数首先使用Contact结构体创建了一个通讯录,然后再使用Init_contact(&con);进行了通讯录的初始化。该部分结构体和函数代码如下。

结构体:为了方便后期的处理数组大小,所以我们可以利用define来定义数组的大小。

#define date_MAX 1000

#define name_MAX 20
#define sex_MAX 4
#define tele_MAX 12
#define addr_MAX 10

typedef struct PeoInfo
{
    char name[name_MAX];
    int age;
    char sex[sex_MAX];
    char tele[tele_MAX];
    char addr[addr_MAX];
} PeoInfo;
//创建通讯录结构体(静态版本)
//typedef struct Contact
//{
//    PeoInfo date[date_MAX];//存放联系人数组
//    int sz = 0;//存放联系人的个数
//}Contact;
//创建通讯录结构体(动态版本)
typedef struct Contact
{
    PeoInfo *date;//存放联系人数组
    int sz = 0;//存放联系人的个数
    int capacity = 0;//当前联系人的最大容量
}Contact;

三、通讯录的功能实现

1.初始化函数:

使用了memset将通讯录初始化为0。

//初始化联系人(静态版本)
//void Init_contact(Contact* pc)
//{
//    assert(pc);
//    pc -> sz = { 0 };
//    memset(pc->date, 0, sizeof(pc->date));
//}
//动态版本
void Init_contact(Contact* pc)
{
    assert(pc);
    pc->sz = 0 ;
    PeoInfo * ptr =( PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo));
    if (ptr == NULL)
    {
        perror("Init_contact::calloc");
        return ;
    }
    else
    {
        pc->date = ptr;
        pc->capacity = DEFAULT_SZ;
    }
}

2.增加联系人

//增加联系人(静态版本)
//void Addcontact(Contact* pc)
//{
//    assert(pc);
//    if (pc->sz == date_MAX)
//    {
//        printf("通讯录已满\n");
//        return;
//    }
//    printf("请输入姓名:");
//    scanf("%s", pc->date[pc->sz].name);
//    printf("请输入年龄:");
//    scanf("%d", &(pc->date[pc->sz].age));
//    printf("请输入性别:");
//    scanf("%s", pc->date[pc->sz].sex);
//    printf("请输入电话:");
//    scanf("%s", pc->date[pc->sz].tele);
//    printf("请输入地址:");
//    scanf("%s", pc->date[pc->sz].addr);
//
//    pc->sz++;
//}
//动态版本
void check_capacity(Contact* pc)
{
    if (pc->sz == pc->capacity)
    {
        PeoInfo* ptr =(PeoInfo*)realloc(pc->date, (pc->capacity+INC_SZ)*sizeof(PeoInfo));
        if (ptr == NULL)
        {
            perror("check_capacity::realloc");
            return;
        }

        pc->date = ptr;
        pc->capacity += INC_SZ;
        printf("增容成功\n");
    }
}

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

    printf("请输入姓名:");
    scanf("%s", pc->date[pc->sz].name);
    printf("请输入年龄:");
    scanf("%d", &(pc->date[pc->sz].age));
    printf("请输入性别:");
    scanf("%s", pc->date[pc->sz].sex);
    printf("请输入电话:");
    scanf("%s", pc->date[pc->sz].tele);
    printf("请输入地址:");
    scanf("%s", pc->date[pc->sz].addr);

    pc->sz++;
}

当用户按下1,进入Addcontact函数,首先判断通讯录是否已满足最大容量,若没有满,对通讯录进行赋值,用户只需要根据提示的信息进行输入数据就可以了。添加完成后,就让sz++;记录当前通讯录实际有效人数。

静态版本:

联系人通讯录(静态+动态版本)_第1张图片

动态版本:

联系人通讯录(静态+动态版本)_第2张图片

3.显示联系人信息

void showcontact(const Contact* pc)
{
    assert(pc);
    if (pc->sz == 0)
    {
        printf("联系人为空\n");
        return;
    }
    else
    {
        printf("%-20s\t%-4s\t%-4s\t%-12s\t%-10s\n","姓名","年龄","性别","电话","地址");    
    }
    int i = 0;
    for ( i = 0; i < pc->sz; i++)
    {
        printf("%-20s\t%d\t%-4s\t%-12s\t%-10s\n", pc->date[i].name, 
                                        (pc->date[i].age), 
                                        pc->date[i].sex, 
                                        pc->date[i].tele, 
                                        pc->date[i].addr);
    }
}

首先判断联系人是否为空再进行是否打印,打印时,先打印出对应的联系人数据名称;便于用户阅读。

利用for循环遍历打印联系人信息。

打印时,为了使得打印出来的数据整齐,再数据中加入了前面的数字,还有\t,数字代表域宽:比如-20就代表域宽是20(长度不够20用空格填充),负号代表左对齐,默认是右对齐的。\t表示tab键,相当于一个分隔符。

联系人通讯录(静态+动态版本)_第3张图片

4.删除联系人函数

删除联系人首先需要进行查找,这里定义了一个查找函数,查看联系人是否存在。

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

函数联系人函数,首先判断联系人是否为空,然后根据用户输入的联系人,利用Findname函数查看要删除的联系人是否存在,如果存在,进行删除,然后将sz减1,确定有效联系人的个数。

void delcontact(Contact* pc)
{
    assert(pc);
    char name[name_MAX];
    if (pc->sz == 0)
    {
        printf("联系人为空,无法删除\n");
        return;
    }
    printf("请输入要删除的联系人:");
    scanf("%s", name);
    //查找
    int pos = Findname(pc, name);
    if (pos == -1)
    {
        printf("该通讯录没有存在这个名字\n");
        return;
    }
    //删除
    int i = 0;
    for (i = pos; i < pc->sz; i++)
    {
        pc->date[i] = pc->date[i + 1];
    }
    pc->sz--;
    printf("删除成功\n");
}
联系人通讯录(静态+动态版本)_第4张图片

5.查找联系人

void search(const Contact* pc)
{
    assert(pc);
    printf("%-20s\t%-4s\t%-4s\t%-12s\t%-10s\n", "姓名", "年龄", "性别", "电话", "地址");
    char name[name_MAX];
    printf("请输入你要查找的联系人:");
    scanf("%s", name);
    int pos = Findname(pc, name);
    if (pos == -1)
    {
        printf("查无此人\n");
        return;
    }
    else
    {
        printf("%-20s\t%d\t%-4s\t%-12s\t%-10s\n", pc->date[pos].name,
            (pc->date[pos].age),
            pc->date[pos].sex,
            pc->date[pos].tele,
            pc->date[pos].addr);
    }
}

根据用户输入的联系人姓名,利用Findname查找该联系人是否存在,如果存在,打印出该联系人的信息。

联系人通讯录(静态+动态版本)_第5张图片

6.修改联系人

void modify(Contact* pc)
{
    assert(pc);
    char name[name_MAX];
    printf("请输入你要修改的名字:");
    scanf("%s", name);
    int pos = Findname(pc, name);
    if (pos == -1)
    {
        printf("查无此人\n");
        return;
    }

    printf("请输入姓名:");
    scanf("%s", pc->date[pos].name);
    printf("请输入年龄:");
    scanf("%d", &(pc->date[pos].age));
    printf("请输入性别:");
    scanf("%s", pc->date[pos].sex);
    printf("请输入电话:");
    scanf("%s", pc->date[pos].tele);
    printf("请输入地址:");
    scanf("%s", pc->date[pos].addr);

    printf("修改完成\n");
}

根据用户输入的联系人姓名,利用Findname查找该联系人是否存在,如果存在,用户根据提示信息,将联系人的信息进行修改

联系人通讯录(静态+动态版本)_第6张图片

7.以名字进行排序

void sort_name(Contact* pc)
{
    assert(pc);
    if (pc->sz == 0)
    {
        printf("联系人为空,无需排序\n");
        return;
    }
    int i = 0;
    int j = 0;
    for (i = 0; i < pc->sz - 1; i++)
    {
        for (j = 0; j < pc->sz - i-1; j++)
        {
            if (strcmp( pc->date[j].name, pc->date[j + 1].name) > 0)
            {
                PeoInfo tmp; 
                tmp  = pc->date[j];
                pc->date[j] = pc->date[j + 1];
                pc->date[j + 1] = tmp;
            }
        }
    }
    printf("排序成功\n");
}

排序功能主要使用了冒泡排序,利用strcmp判断联系人的名字首字母大小,根据字母表的顺序,将联系人的信息进行排序。

联系人通讯录(静态+动态版本)_第7张图片

8.清空所有联系人

void clcall(Contact* pc)
{
    assert(pc);
    printf("你确定要清空所有联系人吗?(yes/no)\n");
    char str[5] = {0};
    scanf("%s", &str);
    if (strcmp(str, "yes") == 0)
    {
        pc->sz = 0;
        printf("清空所有联系人成功\n");
    }
    else if (strcmp(str, "yes") != 0)
    {
        printf("已取消清空联系人");
    }
    else
    {
        printf("输入错误,请重新输入");
    }
}

清空所有联系人,使用if语句进行确认用户是否确定清空,若用户输入yes,将sz置为0,清空所有联系人的数据。

联系人通讯录(静态+动态版本)_第8张图片

9.保存通讯录

当用户按下0退出通讯录,为了避免之前输入的联系人的数据丢失,所以先将之前的联系人信息保存起来。

void SaveContact(Contact* pc)
{
    //写数据
    //1、打开文件
    FILE* pf = fopen("contact.txt", "wb");
    if (NULL == pf)
    {
        perror("SaveContact");
    }
    else
    {
        //写数据
        int i = 0;
        for ( i = 0; i < pc->sz; i++)
        {
            fwrite(pc->date + i, sizeof(PeoInfo), 1, pf);
        }
        fclose(pf);
        pf = NULL;
        printf("保存成功\n");
    }
}

10.销毁通讯录

当用户按下0,销毁通讯录,使用free函数释放动态开辟的数组指针,同时对sz和capacity置0以及对通讯录指针置为空指针。

//销毁通讯录
void Destory_contact(Contact* pc)
{
    free(pc->date);
    pc->date = NULL;
    pc->capacity = 0;
    pc->sz = 0;
    pc = NULL;
}

11.加载文件信息到通讯录

该函数放在初始化函数,将之前保存的通讯录进行初始化。

//加载文件信息到通讯录
void LoadContact(Contact* pc)
{
    //读数据
    //1.打开文件
    FILE* pf = fopen("contact.txt", "rb");
    if (NULL == pf)
    {
        perror("LoadContact");
    }
    else
    {
;        //2.读数据
        PeoInfo tmp = { 0 };
        int i = 0;
        while ( fread(&tmp,sizeof(PeoInfo),1,pf) )
        {
            //增容
            check_capacity(pc);
            pc->date[i] = tmp;
            pc->sz++;
            i++;
        }
        fclose(pf);
        pf = NULL;
    }
}

四、完整代码

#include
#include
#include
#include

#define date_MAX 1000

#define DEFAULT_SZ 3
#define INC_SZ 2

#define name_MAX 20
#define sex_MAX 4
#define tele_MAX 12
#define addr_MAX 10
//创建联系人结构体
typedef struct PeoInfo
{
    char name[name_MAX];
    int age;
    char sex[sex_MAX];
    char tele[tele_MAX];
    char addr[addr_MAX];
} PeoInfo;
//创建通讯录结构体(静态版本)
//typedef struct Contact
//{
//    PeoInfo date[date_MAX];//存放联系人数组
//    int sz = 0;//存放联系人的个数
//}Contact;

typedef struct Contact
{
    PeoInfo *date;//存放联系人数组
    int sz = 0;//存放联系人的个数
    int capacity = 0;//当前联系人的最大容量
}Contact;
//初始化
void Init_contact(Contact* pc);
//增加联系人
void Addcontact(Contact* pc);
//显示联系人信息
void showcontact(const Contact* pc);
//删除联系人
void delcontact(Contact* pc);
//查找联系人
void search(const Contact* pc);
//修改联系人
void modify(Contact* pc);
//以名字进行排序
void sort_name(Contact* pc);
//清空所有联系人
void clcall(Contact* pc);

//初始化联系人(静态版本)
//void Init_contact(Contact* pc)
//{
//    assert(pc);
//    pc -> sz = { 0 };
//    memset(pc->date, 0, sizeof(pc->date));
//}

void Init_contact(Contact* pc)
{
    assert(pc);
    pc->sz = 0 ;
    PeoInfo * ptr =( PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo));
    if (ptr == NULL)
    {
        perror("Init_contact::calloc");
        return ;
    }
    else
    {
        pc->date = ptr;
        pc->capacity = DEFAULT_SZ;
    }
}
//销毁通讯录
void Destory_contact(Contact* pc)
{
    free(pc->date);
    pc->date = NULL;
    pc->capacity = 0;
    pc->sz = 0;
    pc = NULL;
}

//增加联系人(静态版本)
//void Addcontact(Contact* pc)
//{
//    assert(pc);
//    if (pc->sz == date_MAX)
//    {
//        printf("通讯录已满\n");
//        return;
//    }
//    printf("请输入姓名:");
//    scanf("%s", pc->date[pc->sz].name);
//    printf("请输入年龄:");
//    scanf("%d", &(pc->date[pc->sz].age));
//    printf("请输入性别:");
//    scanf("%s", pc->date[pc->sz].sex);
//    printf("请输入电话:");
//    scanf("%s", pc->date[pc->sz].tele);
//    printf("请输入地址:");
//    scanf("%s", pc->date[pc->sz].addr);
//
//    pc->sz++;
//}
void check_capacity(Contact* pc)
{
    if (pc->sz == pc->capacity)
    {
        PeoInfo* ptr =(PeoInfo*)realloc(pc->date, (pc->capacity+INC_SZ)*sizeof(PeoInfo));
        if (ptr == NULL)
        {
            perror("check_capacity::realloc");
            return;
        }

        pc->date = ptr;
        pc->capacity += INC_SZ;
        printf("增容成功\n");
    }
}
//动态版本
void Addcontact(Contact* pc)
{
    assert(pc);
    check_capacity(pc);

    printf("请输入姓名:");
    scanf("%s", pc->date[pc->sz].name);
    printf("请输入年龄:");
    scanf("%d", &(pc->date[pc->sz].age));
    printf("请输入性别:");
    scanf("%s", pc->date[pc->sz].sex);
    printf("请输入电话:");
    scanf("%s", pc->date[pc->sz].tele);
    printf("请输入地址:");
    scanf("%s", pc->date[pc->sz].addr);

    pc->sz++;
}
//显示联系人信息
void showcontact(const Contact* pc)
{
    assert(pc);
    if (pc->sz == 0)
    {
        printf("联系人为空\n");
        return;
    }
    else
    {
        printf("%-20s\t%-4s\t%-4s\t%-12s\t%-10s\n","姓名","年龄","性别","电话","地址");    
    }
    int i = 0;
    for ( i = 0; i < pc->sz; i++)
    {
        printf("%-20s\t%d\t%-4s\t%-12s\t%-10s\n", pc->date[i].name, 
                                        (pc->date[i].age), 
                                        pc->date[i].sex, 
                                        pc->date[i].tele, 
                                        pc->date[i].addr);
    }
    printf("添加联系人成功\n");
}
int Findname(const Contact* pc, char* name)
{
    assert(pc);
    int i = 0;
    for (i = 0; i < pc->sz; i++)
    {
        if (strcmp(pc->date[i].name,name)==0)
        {
            return i;
        }
    }
    return -1;
}
//删除联系人

void delcontact(Contact* pc)
{
    assert(pc);
    char name[name_MAX];
    if (pc->sz == 0)
    {
        printf("联系人为空,无法删除\n");
        return;
    }
    printf("请输入要删除的联系人:");
    scanf("%s", name);
    //查找
    int pos = Findname(pc, name);
    if (pos == -1)
    {
        printf("该通讯录没有存在这个名字\n");
        return;
    }
    //删除
    int i = 0;
    for (i = pos; i < pc->sz; i++)
    {
        pc->date[i] = pc->date[i + 1];
    }
    pc->sz--;
    printf("删除成功\n");
}

//查找联系人
void search(const Contact* pc)
{
    assert(pc);
    printf("%-20s\t%-4s\t%-4s\t%-12s\t%-10s\n", "姓名", "年龄", "性别", "电话", "地址");
    char name[name_MAX];
    printf("请输入你要查找的联系人:");
    scanf("%s", name);
    int pos = Findname(pc, name);
    if (pos == -1)
    {
        printf("查无此人\n");
        return;
    }
    else
    {
        printf("%-20s\t%d\t%-4s\t%-12s\t%-10s\n", pc->date[pos].name,
            (pc->date[pos].age),
            pc->date[pos].sex,
            pc->date[pos].tele,
            pc->date[pos].addr);
    }
}

//修改联系人
void modify(Contact* pc)
{
    assert(pc);
    char name[name_MAX];
    printf("请输入你要修改的名字:");
    scanf("%s", name);
    int pos = Findname(pc, name);
    if (pos == -1)
    {
        printf("查无此人\n");
        return;
    }

    printf("请输入姓名:");
    scanf("%s", pc->date[pos].name);
    printf("请输入年龄:");
    scanf("%d", &(pc->date[pos].age));
    printf("请输入性别:");
    scanf("%s", pc->date[pos].sex);
    printf("请输入电话:");
    scanf("%s", pc->date[pos].tele);
    printf("请输入地址:");
    scanf("%s", pc->date[pos].addr);

    printf("修改完成\n");
}

//以名字进行排序
void sort_name(Contact* pc)
{
    assert(pc);
    if (pc->sz == 0)
    {
        printf("联系人为空,无需排序\n");
        return;
    }
    int i = 0;
    int j = 0;
    for (i = 0; i < pc->sz - 1; i++)
    {
        for (j = 0; j < pc->sz - i-1; j++)
        {
            if (strcmp( pc->date[j].name, pc->date[j + 1].name) > 0)
            {
                PeoInfo tmp; 
                tmp  = pc->date[j];
                pc->date[j] = pc->date[j + 1];
                pc->date[j + 1] = tmp;
            }
        }
    }
    printf("排序成功\n");
}

//清空所有联系人
void clcall(Contact* pc)
{
    assert(pc);
    printf("你确定要清空所有联系人吗?(yes/no)\n");
    char str[5] = {0};
    scanf("%s", &str);
    if (strcmp(str, "yes") == 0)
    {
        pc->sz = 0;
        printf("清空所有联系人成功\n");
    }
    else if (strcmp(str, "yes") != 0)
    {
        printf("已取消清空联系人");
    }
    else
    {
        printf("输入错误,请重新输入");
    }
}
void menu()
{
    printf("*************************************\n");
    printf("******  1. add    2. del       ******\n");
    printf("******  3. search 4. modify    ******\n");
    printf("******  5. show   6. sort_name ******\n");
    printf("******  7.clcall  0. exit      ******\n");
    printf("*************************************\n");
}

int main()
{
    int input = 0;
    Contact con;
    Init_contact(&con);
    do {
        menu();
        printf("请选择:");
        scanf("%d", &input);
        switch (input)
        {
            case 1:
                Addcontact(&con);
                break;
            case 2:
                delcontact(&con);
                break;
            case 3:
                search(&con);
                break;
            case 4:
                modify(&con);
                break;
            case 5:
                showcontact(&con);
                break;
            case 6:
                sort_name(&con);
                break;
            case 7:
                clcall(&con);
                break;
            case 0:
                printf("退出通讯录\n");
                break;
            default:
                printf("输入错误,请重新输入");
                break;
        }


    } while (input);
    return 0;
}

你可能感兴趣的:(C语言,算法,c语言)