C语言/动态通讯录

简介: C语言/动态通讯录

本文使用了malloc、realloc、calloc等和内存开辟有关的函数。


文章目录

前言

二、头文件

三、主界面

四、通讯录功能函数

1.全代码

2.增加联系人
3.删除联系人

4.查找联系人

5.修改联系人

6.展示联系人

7.清空联系人

8.退出通讯录

总结


前言

为了使用通讯录时,可以随时调整大小,所以使用动态开辟内存函数写通讯录,可增加联系人容量。

动态开辟函数,即在内存的栈区开辟空间,所以使用完毕后,需要释放内存空间


一、通讯录运行图




二、头文件

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#include<stdlib.h>
#define Max 10
enum function
{
    quit,//退出  默认值为0
    increase,//增加  默认值为1
    delete,//删除  默认值为2
    find,//查找   默认值为3
    revise,//修改   默认值为4
    show,//展示   默认值为5
    empty,//清空   默认值为6
    sort//排序   默认值为7
};
//创建人
typedef struct Person
{
    char name[20];//姓名
    size_t age;//年龄
    char sex[8];//性别
    char address[15];//地址
    char phone[12];//电话
}person;
//动态
//创建通讯录
typedef struct contact
{
    person *per;//指向人这个结构体类型
    size_t sz;//通讯录已有人员个数
    size_t ContactMax;//通讯录当前最大容量
}contact;
//初始化
void init_contact(contact* con);
//增容
void tune(contact* con);
//增加
void increase_contact(contact* con);
//删除
void delete_contact(contact* con);
//查找
//return -1(no) / address(yes)
int find1(const contact** con);
void find_contact(const contact* con);
//修改
void revise_contact(contact* con);
//展示
void show_contact(const contact* con);
//排序通讯录
void sort_contact(contact* con);
//销毁通讯录
void destroy_contact(contact* con);
//保存文件
void save_contact(contact* con);
//将文件信息保存到通讯录中
void load_contact(contact* con);

三、主界面

#include "contact.h"
void menu1()
{
    printf("**************************************\n");
    printf("******* Simplified address book ******\n");
    printf("*******   1> increase contact   ******\n");
    printf("*******   2> delete contact     ******\n");
    printf("*******   3> find contact       ******\n");
    printf("*******   4> revise contact     ******\n");
    printf("*******   5> Show all contacts  ******\n");
    printf("*******   6> Empty all contacts ******\n");
    printf("*******   7> Sort by name       ******\n");
    printf("*******   0> Quit Contacts      ******\n");
    printf("**************************************\n");
}
void test()
{
    //创建通讯录
    contact con;
    //初始化通讯录
    init_contact(&con);
    //将文件信息保存到通讯录中
    load_contact(&con);
    size_t choice = 0;
    do
    {
        menu1();
        printf("请输入您的选择性:");
        scanf("%u", &choice);
        switch (choice)
        {
        case increase:
            //增加
            increase_contact(&con);
            break;
        case delete:
            //删除
            delete_contact( &con );
            break;
        case find:
            //查找
            find_contact(&con);
            break;
        case revise:
            //修改
            revise_contact(&con);
            break;
        case show:
            //展示
            show_contact(&con);
            break;
        case empty:
            //清空
            init_contact(&con);
            break;
        case sort:
            //排序
            sort_contact(&con);
            break;
        case quit:
            //保存
            save_contact(&con);
            //销毁
            destroy_contact(&con);
            printf("Exiting Contacts...\n");
            break;
        default:
            printf("You entered the wrong number, please re-enter it.\n");
            break;
        }
    } while (choice);
    printf("Exited Contacts.\n");
}
int main()
{
    test();
    return 0;
}

四、通讯录功能函数

1.全代码

#include"contact.h"
void menu2()
{
    system("cls");
    printf("1> name \t 2> age\n");
    printf("3> sex \t 4> address\n");
    printf("5> phone\n");
    printf("Please select:");
}
//动态
void init_contact(contact* con)
{
    assert(con);
    // per    sz ContactMax
    con->sz = 0;
    person* p = (person*)calloc(Max, sizeof(person));
    if (p == NULL)
    {
        perror("init_contact::calloc");
        return;
    }
    con->per = p;
    con->ContactMax = Max;
}
//将文件信息保存到通讯录中
void load_contact(contact* con)
{
   //打开文件
    FILE* p = fopen("contact.txt", "rb");
    if (p == NULL)
    {
        perror("load_contact::fopen");
        return;
    }
    person tmp = { 0 };
    size_t i = 0;
    while(fread(&tmp, sizeof(person), 1, p))
    {
        //考虑增容
        tune(con);
        con->per[i] = tmp;
        con->sz++;
        i++;
    }
    //关闭文件
    fclose(p);
    p = NULL;
}
void tune(contact* con)
{
    if (con->sz == con->ContactMax)
    {
        person *p = (person *)realloc(con->per, (con->ContactMax + Max) * sizeof(person));
        if (p == NULL)
        {
            perror("tune::realloc");
            return;
        }
        con->per = p;
        con->ContactMax += Max;
    }
}
//动态开辟
void increase_contact(contact* con)
{
    assert(con);
    //检测当前通讯录是否需要增容
    tune(con);
    printf("name:");
    scanf("%s", &(con->per[con->sz].name));
    printf("age:");
    scanf("%u", &(con->per[con->sz].age));
    printf("sex:");
    scanf("%s", &(con->per[con->sz].sex));
    printf("address:");
    scanf("%s", &(con->per[con->sz].address));
    printf("phone:");
    scanf("%s", &(con->per[con->sz].phone));
    (con->sz)++;
}
void delete_contact(contact* con)
{
    assert(con);
    int result = find1(&con);
    if (result != -1)
    {
        char true[5] = { 0 };
        printf("Are you sure you want to delete %s's information?", &con->per[result].name);
        printf("yes/no:");
        scanf("%s", true);
        if (!strcmp(true, "yes"))
        {
            if ( con->sz )
            {
                memmove(con->per[result].name, con->per[(con->sz) - 1].name, sizeof(con->per[0]));
            }
            else
            {
                memset(con->per[result].name, 0, sizeof(con->per[0]));
            }
            (con->sz)--;
            printf("The deletion was successful, thanks for using!\n");          
        }
        else
        {
            printf("Delete failed, please try again!\n");
        }
    }
    else
    {
        printf("Delete failed, please try again!\n");
    }
}
int find1(const contact** con)
{
    assert(*con);
    size_t i = 0;
    char sample1[20] = { 0 };
    printf("请输入你要查找的名字:");
    scanf("%s", sample1);
    while (i < (*con)->sz)
    {
        if (!strcmp(sample1, (*con)->per[i].name))
        {
            return i;
        }
        else
        {
            i++;
        }
    }
    return -1;
}
void find_contact(const contact* con)
{
    assert(con);
    int result = find1(&con);
    if (result != -1)
    {
        printf("Found, the basic information of the contact is:");
        printf("name:%-20s\tage:%-4d\tsex:%-5s\taddress:%-30s\tphone:%-12s\n",
            con->per[result].name,
            con->per[result].age,
            con->per[result].sex,
            con->per[result].address,
            con->per[result].phone);
    }
    else
    {
        printf("Didn't find it!\n");
    }
}
void revise_contact(contact* con)
{
    assert(con);
    int result = find1(&con);
    if (result != -1)
    {
        char choice1[5] = { 0 };
        printf("Are you sure you want to revise %s's information?", con->per[result].name);
        printf("yes/no:");
        scanf("%s", choice1);
        if (!strcmp(choice1, "yes"))
        {
            menu2();
            printf("Please enter the option you want to modify:");
            int choice2 = -1;
            scanf("%d", &choice2);
            char sample1[30] = { 0 };
            size_t sample2 = 0;
            printf("请输入:");
            switch ( choice2 )
            {
            case 1:
            case 3:
            case 4:
            case 5:
                scanf("%s", sample1);
                break;
            case 2:
                scanf("%d", sample2);
                break;
            }
            switch (choice2)
            {
            case 1:
                memmove(con->per[result].name, sample1, sizeof(sample1));
                break;
            case 3:
                memmove(con->per[result].sex, sample1, sizeof(sample1));
                break;
            case 4:
                memmove(con->per[result].address, sample1, sizeof(sample1));
                break;
            case 5:
                memmove(con->per[result].phone, sample1, sizeof(sample1));
                break;
            case 2:
                con->per[result].age = sample2;
                break;
            }
            printf("修改成功,感谢使用!!!\n");
        }
        else
        {
            printf("修改失败,请再次尝试!!!\n");
        }
    }
    else
    {
        printf("修改失败,请再次尝试!!!\n");
    }
}
void show_contact(const contact* con)
{
    assert(con);
    printf("\n\n================================================\n");
    printf("================================================\n\n");
    if ( con->sz )
    {
        size_t i = 0;
        for (; i < (con->sz); i++)
        {
            printf("name:%-20s\tage:%-4d\tsex:%-8s\taddress:%-15s\tphone:%-12s\n",
                con->per[i].name, con->per[i].age, con->per[i].sex,
                con->per[i].address, con->per[i].phone);
        }
        printf("\n\n");
    }
    else
    {
        printf("There is no contact information in the address book!\n");
    }
}
int cmp_char(const void* str1, const void* str2)
{
    return strcmp(((person*)str1)->name, ((person*)str2)->name);
}
void sort_contact(contact* con)
{
    qsort(con -> per[0].name, con -> sz, sizeof(con -> per[0]), cmp_char);
}
void destroy_contact(contact* con)
{
    free(con->per);
    con->per = NULL;
    con->ContactMax = 0;
    con->sz = 0;
    con = NULL;
}
void save_contact(contact* con)
{
    //写文件
    FILE* p = fopen("contact.txt", "wb");
    if (p == NULL)
    {
        perror("save_contact::fopen");
        return;
    }
    int i = 0;
    for (i = 0; i < con->sz; i++)
    {
        fwrite(con->per + i, sizeof(person), 1, p);
    }
    //关闭文件
    fclose(p);
    p = NULL;
    printf("保存成功\n");
}

2.增加联系人

使用realloc()调整通讯录大小。

联系人信息图为:


void tune(contact* con)
{
    if (con->sz == con->ContactMax)
    {
        person *p = (person *)realloc(con->per, (con->ContactMax + Max) * sizeof(person));
        if (p == NULL)
        {
            perror("tune::realloc");
            return;
        }
        con->per = p;
        con->ContactMax += Max;
    }
}
//动态开辟
void increase_contact(contact* con)
{
    assert(con);
    //检测当前通讯录是否需要增容
    tune(con);
    printf("name:");
    scanf("%s", &(con->per[con->sz].name));
    printf("age:");
    scanf("%u", &(con->per[con->sz].age));
    printf("sex:");
    scanf("%s", &(con->per[con->sz].sex));
    printf("address:");
    scanf("%s", &(con->per[con->sz].address));
    printf("phone:");
    scanf("%s", &(con->per[con->sz].phone));
    (con->sz)++;
}

3.删除联系人

通过联系人的姓名来查找需要删除的联系人,找到之后确认删除该联系人。

例如:


int find1(const contact** con)
{
    assert(*con);
    size_t i = 0;
    char sample1[20] = { 0 };
    printf("请输入你要查找的名字:");
    scanf("%s", sample1);
    while (i < (*con)->sz)
    {
        if (!strcmp(sample1, (*con)->per[i].name))
        {
            return i;
        }
        else
        {
            i++;
        }
    }
    return -1;
}
void delete_contact(contact* con)
{
    assert(con);
    int result = find1(&con);
    if (result != -1)
    {
        char true[5] = { 0 };
        printf("Are you sure you want to delete %s's information?", &con->per[result].name);
        printf("yes/no:");
        scanf("%s", true);
        if (!strcmp(true, "yes"))
        {
            if ( con->sz )
            {
                memmove(con->per[result].name, con->per[(con->sz) - 1].name, sizeof(con->per[0]));
            }
            else
            {
                memset(con->per[result].name, 0, sizeof(con->per[0]));
            }
            (con->sz)--;
            printf("The deletion was successful, thanks for using!\n");          
        }
        else
        {
            printf("Delete failed, please try again!\n");
        }
    }
    else
    {
        printf("Delete failed, please try again!\n");
    }
}

4.查找联系人

通过联系人姓名查找联系人。

int find1(const contact** con)
{
    assert(*con);
    size_t i = 0;
    char sample1[20] = { 0 };
    printf("请输入你要查找的名字:");
    scanf("%s", sample1);
    while (i < (*con)->sz)
    {
        if (!strcmp(sample1, (*con)->per[i].name))
        {
            return i;
        }
        else
        {
            i++;
        }
    }
    return -1;
}
void find_contact(const contact* con)
{
    assert(con);
    int result = find1(&con);
    if (result != -1)
    {
        printf("Found, the basic information of the contact is:");
        printf("name:%-20s\tage:%-4d\tsex:%-5s\taddress:%-30s\tphone:%-12s\n",
            con->per[result].name,
            con->per[result].age,
            con->per[result].sex,
            con->per[result].address,
            con->per[result].phone);
    }
    else
    {
        printf("Didn't find it!\n");
    }
}

5.修改联系人

先查找,再修改。

可以修改联系人的任一信息。

int find1(const contact** con)
{
    assert(*con);
    size_t i = 0;
    char sample1[20] = { 0 };
    printf("请输入你要查找的名字:");
    scanf("%s", sample1);
    while (i < (*con)->sz)
    {
        if (!strcmp(sample1, (*con)->per[i].name))
        {
            return i;
        }
        else
        {
            i++;
        }
    }
    return -1;
}
void revise_contact(contact* con)
{
    assert(con);
    int result = find1(&con);
    if (result != -1)
    {
        char choice1[5] = { 0 };
        printf("Are you sure you want to revise %s's information?", con->per[result].name);
        printf("yes/no:");
        scanf("%s", choice1);
        if (!strcmp(choice1, "yes"))
        {
            menu2();
            printf("Please enter the option you want to modify:");
            int choice2 = -1;
            scanf("%d", &choice2);
            char sample1[30] = { 0 };
            size_t sample2 = 0;
            printf("请输入:");
            switch ( choice2 )
            {
            case 1:
            case 3:
            case 4:
            case 5:
                scanf("%s", sample1);
                break;
            case 2:
                scanf("%d", sample2);
                break;
            }
            switch (choice2)
            {
            case 1:
                memmove(con->per[result].name, sample1, sizeof(sample1));
                break;
            case 3:
                memmove(con->per[result].sex, sample1, sizeof(sample1));
                break;
            case 4:
                memmove(con->per[result].address, sample1, sizeof(sample1));
                break;
            case 5:
                memmove(con->per[result].phone, sample1, sizeof(sample1));
                break;
            case 2:
                con->per[result].age = sample2;
                break;
            }
            printf("修改成功,感谢使用!!!\n");
        }
        else
        {
            printf("修改失败,请再次尝试!!!\n");
        }
    }
    else
    {
        printf("修改失败,请再次尝试!!!\n");
    }
}

6.展示联系人

展示所有联系人及其所有信息。

void show_contact(const contact* con)
{
    assert(con);
    printf("\n\n================================================\n");
    printf("================================================\n\n");
    if ( con->sz )
    {
        size_t i = 0;
        for (; i < (con->sz); i++)
        {
            printf("name:%-20s\tage:%-4d\tsex:%-8s\taddress:%-15s\tphone:%-12s\n",
                con->per[i].name, con->per[i].age, con->per[i].sex,
                con->per[i].address, con->per[i].phone);
        }
        printf("\n\n");
    }
    else
    {
        printf("There is no contact information in the address book!\n");
    }
}

7.清空联系人

又名初始化通讯录。

重新向内存申请一片空间,存储联系人信息。

void init_contact(contact* con)
{
    assert(con);
    // per    sz ContactMax
    con->sz = 0;
    person* p = (person*)calloc(Max, sizeof(person));
    if (p == NULL)
    {
        perror("init_contact::calloc");
        return;
    }
    con->per = p;
    con->ContactMax = Max;
}

8.退出通讯录

通过free()释放内存栈区的空间,避免内存泄露。

void destroy_contact(contact* con)
{
    free(con->per);
    con->per = NULL;
    con->ContactMax = 0;
    con->sz = 0;
    con = NULL;
}

总结

在使用完内存函数之后,一定一定要记得释放空间哦~

上述代码展示就是整个动态通讯录的全部啦,如果你有兴趣想要了解,可以通过C_Ccpp/C_study/contact at main · Yjun6/C_Ccpp (github.com)找到它们。

相关文章
|
2月前
|
存储 C语言
探索C语言数据结构:利用顺序表完成通讯录的实现
本文介绍了如何使用C语言中的顺序表数据结构实现一个简单的通讯录,包括初始化、添加、删除、查找和保存联系人信息的操作,以及自定义结构体用于存储联系人详细信息。
34 2
|
2月前
|
存储 C语言
手把手教你用C语言实现通讯录管理系统
手把手教你用C语言实现通讯录管理系统
|
4月前
|
存储 搜索推荐 算法
【C语言】C语言—通讯录管理系统(源码)【独一无二】
【C语言】C语言—通讯录管理系统(源码)【独一无二】
|
4月前
|
存储 数据可视化 C语言
【C语言】C语言 手机通讯录系统的设计 (源码+数据+论文)【独一无二】
【C语言】C语言 手机通讯录系统的设计 (源码+数据+论文)【独一无二】
|
6月前
|
机器学习/深度学习 搜索推荐 程序员
C语言实现个人通讯录(功能优化)-2
C语言实现个人通讯录(功能优化)
C语言实现个人通讯录(功能优化)-2
|
6月前
|
存储 C语言 索引
C语言实现个人通讯录(功能优化)-1
C语言实现个人通讯录(功能优化)
C语言实现个人通讯录(功能优化)-1
|
6月前
|
C语言
C语言学习记录——通讯录(静态内存)
C语言学习记录——通讯录(静态内存)
36 2
|
7月前
|
C语言
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(二)
我们可以通过创建并定义符号常量NUMBER,来作为判断是否胜利的标准。如三子棋中,令NUMBER为3,则这八个方向中有任意一个方向达成3子连珠,则连珠的这个棋子所代表的玩家获胜。
82 1
|
7月前
|
算法 C语言 C++
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(一)
三子棋游戏设计的核心是对二维数组的把握和运用。
98 1
|
6月前
|
存储 人机交互 C语言
【C语言项目实战】使用单链表实现通讯录
【C语言项目实战】使用单链表实现通讯录