动态内存通讯录(C语言)

实现代码

contact.h

#define DEFAULT_SZ 3//最初通讯录容量为3
#define INC_SZ 2//存储个数达到上限后,增容2
#define NAME_max 10
#define SEX_max 5
#define ADDR_max 30
#define TELE_max 12
#include <string.h>//memset的头文件
#include <stdio.h>
#include <assert.h>
#include <stdlib.h> //calloc头文件
//人的信息
typedef struct Peoinfor
{
    char name[NAME_max];
    int age;
    char sex[SEX_max];
    char addr[ADDR_max];
    char tele[TELE_max];
}Peo;


//通讯录:动态内存版
typedef struct Contact
{
    Peo* data;//用来存放人的信息
    int sz;//当前已存放的人信息个数
    int capacity;//当前通讯录的最大容量
}Contact;


void InitContact(Contact* pc);//声明:初始化通讯录函数
void AddContact(Contact* pc);//声明:添加联系人函数
void DelContact(Contact* pc);//声明:删除联系人函数
int FindBy_name(const Contact* pc, char* delname);//声明:查找联系人函数,删查改功能都需要用到此函数
void ShowContact(const Contact* pc);//声明:显示联系人函数,显示功能不需要修改东西,故加上const保证指针不被修改
void SearchContact(const Contact* pc);//声明:查找联系人函数,并显示信息
void ModifyConract(Contact* pc);//修改联系人信息
void chack_capacity(Contact* pc);//检查是否增/减容函数
void DestroyContact(Contact* pc); //释放开辟的动态内存

contact.c

#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"

//初始化通讯录
void InitContact(Contact* pc)//这里传过来的是地址
{
    assert(pc);
    pc->sz = 0;
    Peo* ptr=(Peo*)calloc( DEFAULT_SZ,sizeof(Peoinfor));//开辟动态内存,用ptr接收
    if (ptr == NULL)//判断是否开辟空间成功
    {
        perror("InitContact:calloc ");//打印错误信息
        return;
    }
    pc->data = ptr;//动态内存开辟成功就让pc指向那块内存
    pc->capacity = DEFAULT_SZ;//一开始创建通讯录最大容量为3
}

//增,减容函数
void chack_capacity(Contact* pc)
{
    if (pc->sz == pc->capacity)//存储人数达到最大值
    {
        Peo* ptr = (Peo*)realloc(pc->data,(pc->capacity + INC_SZ )* sizeof(Peoinfor));//扩容2个动态内存,用ptr接收
        if (ptr == NULL)//判断是否扩容空间成功
        {
            perror("chack_capacity:realloc ");//打印错误信息
            return;
        }
        pc->data = ptr;//动态内存开辟成功就让pc指向那块内存
        pc->capacity += INC_SZ;//通讯录最大容量值+2
        printf("增容\n");//测试用
    }
    else if ((pc->sz <= pc->capacity - INC_SZ) && (pc->sz >= DEFAULT_SZ))//当存储人数>=3且<=最大容量-2时,减容2个存储位
    {
        Peo* ptr = (Peo*)realloc(pc->data, (pc->capacity - INC_SZ) * sizeof(Peoinfor));//减容2个,用ptr接收
        if (ptr == NULL)//判断是否减容空间成功
        {
            perror("chack_capacity:realloc ");//打印错误信息
            return;
        }
        pc->data = ptr;//动态内存减容成功就让pc指向那块内存
        pc->capacity -= INC_SZ;//通讯录最大容量值-2
        printf("减容\n");//测试用
    }
}

//添加联系人
void AddContact(Contact* pc)
{
    assert(pc);
    chack_capacity(pc);//检查是否增容
    printf("请输入姓名 年龄 性别 地址 电话号码:");
    scanf("%s %d %s %s %s", pc->data[pc->sz].name, &(pc->data[pc->sz].age), pc->data[pc->sz].sex, pc->data[pc->sz].addr, pc->data[pc->sz].tele);
    //以上name,sex,addr,tele是char类型数组,数组名就是地址,故不需要&,但age是int变量,故需要加&
    printf("保存成功!\n");
    pc->sz++;

    //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);

}

//显示联系人
void ShowContact(const Contact* pc)
{
    assert(pc);
    if (pc->sz == 0)
    {
        printf("无可显示联系人\n");
        return;
    }
    else
    {
        int i = 0;
        //printf("%-10s\t%-4s\t%-4s\t%-30s\t%-20s\n", "姓名","年龄", "性别", "地址", "电话号码");//老师那可以,我这不行
        for (i = 0; i < pc->sz; i++)
        {
            printf("联系人%d:\n", i + 1);//联系人=下标+1
            printf("%-10s\t%-4d\t%-4s\t%-30s\t%-20s\n", pc->data[i].name,    /*数字用于对齐,-号表示左对齐*/
                pc->data[i].age,
                pc->data[i].sex,
                pc->data[i].addr,
                pc->data[i].tele);
        }
    }
}

//查找函数
int FindBy_name(const Contact* pc, char* delname)
{
    int ret = 0;//要查找的联系人的下标
    for (ret = 0; ret < pc->sz; ret++)
    {
        if (strcmp(pc->data[ret].name, delname) == 0)//判断联系人i与要查找联系人名字相等
        {
            return ret;//找到返回相应下标
        }
    }
    return ret = -1;//找不到返回-1
}


//删除联系人
void DelContact(Contact* pc)
{
    assert(pc);
    if (pc->sz == 0)
    {
        printf("无可删除联系人\n");
        return;
    }
    else
    {
        char delname[NAME_max] = { 0 };
        printf("请输入要删除联系人的名字:");
        scanf("%s", &delname);
        //1.找到相应联系人
        int ret = FindBy_name(pc, delname);
        if (ret == -1)
        {
            printf("找不到联系人\n");
            return;
        }
        //2.删除
        int i = 0;
        for (i = ret; i < pc->sz - 1; i++)//假设删除第3个联系人,则用第4个联系人覆盖第3个位置,5覆盖4,依此类推,直至最后一个联系人覆盖倒数第2个联系人的位置
            //若有5个联系人,则循环2次完成覆盖,故i< pc->sz - 1,最后一个联系人原本的位置不用管,后面pc->sz--就访问不到那了
        {
            pc->data[i] = pc->data[i + 1];//后一位覆盖前一位
        }
        pc->sz--;
        printf("删除成功!\n");
        chack_capacity(pc);//检查是否减容
    }

}

//查找联系人,并显示信息
void SearchContact(const Contact* pc)
{
    assert(pc);
    printf("请输入查找联系人姓名:");
    char sear_name[NAME_max] = { 0 };
    scanf("%s", &sear_name);
    int ret = FindBy_name(pc, sear_name);
    if (ret == -1)
    {
        printf("找不到联系人\n");
        return;
    }
    else
    {
        printf("找到联系人%d:\n", ret + 1);//联系人=下标+1
        printf("%-10s\t%-4d\t%-4s\t%-30s\t%-20s\n", pc->data[ret].name,    /*数字用于对齐,-号表示左对齐*/
            pc->data[ret].age,
            pc->data[ret].sex,
            pc->data[ret].addr,
            pc->data[ret].tele);
    }
}

//修改联系人信息
void ModifyConract(Contact* pc)
{
    assert(pc);
    printf("请输入修改的联系人姓名:");
    char mod_name[NAME_max] = { 0 };
    scanf("%s", &mod_name);
    int ret = FindBy_name(pc, mod_name);
    if (ret == -1)
    {
        printf("找不到联系人\n");
        return;
    }
    else
    {
        printf("请选择要修改的信息(0.退出 1.姓名 2.年龄 3.性别 4.地址 5.电话号码):");
        int mod = 0;
        scanf("%d", &mod);
        do
        {
            switch (mod)
            {
            case 0:
                printf("退出修改\n");
                goto end0;
                break;
            case 1:
                printf("请输入新的姓名:");
                scanf("%s", pc->data[ret].name);
                goto end;
                break;
            case 2:
                printf("请输入新的年龄:");
                scanf("%d", &(pc->data[ret].age));
                goto end;
                break;
            case 3:
                printf("请输入新的性别:");
                scanf("%s", pc->data[ret].sex);
                goto end;
                break;
            case 4:
                printf("请输入新的地址:");
                scanf("%s", pc->data[ret].addr);
                goto end;
                break;
            case 5:
                printf("请输入新的电话号码:");
                scanf("%s", pc->data[ret].tele);
                goto end;
                break;
            defult:
                printf("选择错误请重新选择\n");
                break;
            }
        } while (mod);
    end:
        printf("修改成功!\n");
    }
end0:
    return;
}


void DestroyContact(Contact* pc)//释放开辟的动态内存
{
    free(pc);
    pc = NULL;
}

test.c

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include "contact.h"//自己创建的头文件用“”

//通讯录要求:
//1.人的信息:姓名,年龄,性别,地址,电话
//2.通讯录可以存放100个人的信息
//3.功能:
//    (1)增加联系人
//    (2)删除指定联系人
//    (3)查找指定联系人信息
//    (4)修改指定联系人信息
//    (5)显示所有联系人信息
//    (6)排序(姓名)


void menu()
{
    printf("*****************MENU****************\n");
    printf("*******1.add            2.del********\n");
    printf("*******3.search         4.modify*****\n");
    printf("*******5.show           6.sort*******\n");
    printf("***************0.exit****************\n");
    printf("-------------------------------------\n");
}
enum Option
{
    EXIT,  //0
    ADD,   //1
    DEL,   //2
    SEARCH,//3
    MODIFY,//4
    SHOW,  //5
    SORT   //6
    //常量取值与目录序号一一对应
};
int main()
{

    Contact con;    //创建通讯录con
    InitContact(&con);//初始化通讯录

    int input = 0;

    do
    {
        menu();
        printf("请选择功能:");
        scanf("%d", &input);
        switch (input)
        {
        case EXIT:     //使用枚举后,这里的0就可以用EXIT代表,更直观的显示出0代表的功能
            DestroyContact(&con);//释放动态内存
            printf("退出通讯录!\n");
            break;
        case ADD:
            AddContact(&con);
            break;
        case DEL:
            DelContact(&con);
            break;
        case SEARCH:
            SearchContact(&con);
            break;
        case MODIFY:
            ModifyConract(&con);
            break;
        case SHOW:
            ShowContact(&con);
            break;
        case SORT:
            break;
        default:
            printf("选择错误,请重新选择:\n");
            break;
        }
    } while (input);


    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值