简单通讯录2.0(利用动态内存开辟)

本文介绍了在通讯录1.0基础上利用动态内存开辟改进的空间利用率,详细说明了如何修改结构体,调整数据初始化和增加功能,以及添加内存释放和增容函数。在程序退出时调用内存释放函数,避免空间浪费。尽管如此,通讯录2.0仍存在数据丢失问题,将在后续的通讯录3.0中通过文件应用解决,以便持久化存储数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  在通讯录实现1.0中上利用了结构体与数组实现了基本要求,但其在空间利用率有很大不足,故此利用动态内存开辟对程序进行修改。
  首先要对结构体的设置进行修改(个人信息属性可不必修改),修改后结构体如下所示:

 typedef struct Contact
{
    PeoInfo *data;//放弃数组改为指针
    int sz;
    int capacity;
    //记录当前通讯录容量
}Contact,*pCon;

  测试部分代码基本不需要更改,只需在程序退出时调用内存释放函数(void DestroContact(pCon p);)
  功能实现部分也只需对数据初始化,数据增加函数进行更改,由于现在的空间是动态内存开辟的,所以需要增加内存释放函数(程序退出时调用)以及增容函数(当前通讯录容量已满时调用)
  相关函数实现如下:

#include "contact.h"

static int search(pCon p,char name[])
{
    int i = 0;
    assert(p);
    for(i=0;i<p->sz;i++)
    {
        if(strcmp(p->data[i].name,name) == 0)
        {
            return i;
        }
        return -1;
    }
}
int check_capacity(pCon p) //增容函数
{
    if(p->sz == p->capacity)
    {
        PeoInfo*tmp = realloc(p->data,(p->capacity+DEF_AD)*sizeof(PeoInfo));
        //创建临时指针接收地址,不能直接赋值给原本的地址避免增容失败时对原数据造成影响。
        if(tmp!=NULL)
        {
            p->data = tmp;
            p->capacity += DEF_AD;
            printf("增容成功!\n");
        }
        else
        {
            printf("增加失败\n");
            return 0;
        }
    }
    return 1;
}


 void InitContact(pCon p) //初始化
{
    assert(p);
    p->sz = 0;
    p->data = (PeoInfo*)malloc(DEF_SZ*sizeof(PeoInfo));
    p->capacity = 3;
    memset(p->data,0,DEF_SZ*sizeof(PeoInfo));
    p->capacity = DEF_SZ;
}

 void DestroContact(pCon p)  //新增内存释放函数,避免内存泄漏。
 {
     free(p->data);
     p->data = NULL;
     p->capacity = 0;
     p->sz = 0;
     printf("已销毁!\n");
 }

void AddContact(pCon p) //添加联系人
{
    assert(p);
    if(!check_capacity(p))
    {
        printf("增容失败\n");
        return;
    }
    else 
    {
        printf("请输入名字:");
        scanf("%s",p->data[p->sz].name);
        printf("请输入年龄:");
        scanf("%d",&(p->data[p->sz].age));
        printf("请输入性别:");
        scanf("%s",p->data[p->sz].sex);
        printf("请输入地址:");
        scanf("%s",p->data[p->sz].addr);
        printf("请输入电话:");
        scanf("%s",p->data[p->sz].tele);
        printf("添加成功!\n");
        p->sz++;
    }
}

void ShowContact(pCon p)
{
        int i= 0;
        printf("%8s\t%5s\t%5s\t%10s\t%15s\t\n","name","age","sex","tele","addr");
        for(i=0;i<p->sz;i++)
            PRINT(i);
}

void DelContact(pCon p)
{
    int i = 0;
    int j = 0;
    int pos = 0;
    char name[MAX_NAME];
    if(p->sz ==0)
    {
        printf("通讯录为空,无法删除\n");
        return;
    }
    printf("请输入待删除的名字:");
    scanf("%s",name);
    pos = search(p,name);
    if(pos = -1)
        printf("要删除的人不存在\n");
    else 
    {
        for(j=pos;j<(p->sz-1);j++)
            {
                p->data[j] = p->data[j+1];
            }
        p->sz--;
        printf("删除成功\n");
    }
}

void SearContact(pCon p)
{
    int pos = 0;
    char name[MAX_NAME];
    assert(p);
    if(p->sz ==0)
    {
        printf("通讯录为空,无法查找\n");
        return;
    }
    printf("请输入待查找的名字:");
    scanf("%s",name);
    pos = search(p,name);
    if(pos != (-1)){
        PRINT(pos);}
    else
        printf("要查找的人不存在\n");   
}

void ModifyContact(pCon p)
{
    int pos;
    char name[MAX_NAME] = {0};
    assert(p);
    printf("请输入待查找的名字:");
    scanf("%s",name);
    pos = search(p,name);
    PRINT(pos);
    if(pos != (-1))
      {
            printf("请输入名字:");
            scanf("%s",p->data[pos].name);
            printf("请输入年龄:");
            scanf("%d",&(p->data[pos].age));
            printf("请输入性别:");
            scanf("%s",p->data[pos].sex);
            printf("请输入地址:");
            scanf("%s",p->data[pos].addr);
            printf("请输入电话:");
            scanf("%s",p->data[pos].tele);
       }
    else
        printf("要修正的人不存在\n");
    printf("修改成功!\n");
}

void EmptyContact(pCon p)
{
    assert(p);
    p->sz = 0;
}

void SortContact(pCon p)
{
    int i = 0;
    int j = 0;
    int flag = 0;
    PeoInfo tmp;
    assert(p);
    for(i=0;i<(p->sz-1);i++)
      {
        flag = 0;
        for(j=0;j<(p->sz-1-i);j++)
          {
              if(strcmp(p->data[j].name ,p->data[j+1].name)>0)
               {
                   PeoInfo tmp = p->data[j];
                   p->data[j] = p->data[j+1];
                   p->data[j+1] = tmp;
                   flag = 1;
               }
          }
        if(flag == 0)
        {
            return;
        }
      }
  }

  测试部分实现如下:

#include"contact.h"
#include<stdio.h>
#include<stdlib.h>


void menu()
{
    printf("***************************\n");
    printf("***  1.add      2.del   ***\n");
    printf("***  3.search   4.mod   ***\n");
    printf("***  5.sort     6.empty ***\n");
    printf("***  7.show     0.EXIT  ***\n");
    printf("***************************\n");

}

enum Option
{
    EXIT,
    ADD,
    DEL,
    SEARCH,
    MOD,
    SORT,
    EMPTY,
    SHOW
};

void test()
{
    int input;
    Contact con;
    InitContact(&con);
    menu();
    do
    {
        scanf("%d",&input);
        switch(input)
        {
            case EXIT:
                DestroContact(&con);
                return 0;
            case ADD:
                AddContact(&con);
                menu();
                break;
            case DEL:
                DelContact(&con);
                menu();
                break;
            case SEARCH:
                SearContact(&con);
                menu();
                break;
            case MOD:
                ModifyContact(&con);
                menu();
                break;
            case SORT:
                SortContact(&con);
                menu();
                break;
            case EMPTY:
                EmptyContact(&con);
                menu();
                break;
            case SHOW:
                ShowContact(&con);
                menu();
                break;
            default:
                printf("输入错误,请重新输入:");
       }
    }while(input);
}
int main()
{
    test();
    return 0;
}

  头文件部分如下:

#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#ifndef __CONTACT_H__
#define __CONTACT_H__
#define PRINT(x) printf("%8s\t%5d\t%5s\t%10s\t%15s\t\n",\
                p->data[x].name,\
                p->data[x].age,\
                p->data[x].sex,\
                p->data[x].tele,\
                p->data[x].addr);

#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_ADDR 25
#define MAX_TELE 12
#define MAX 100
#define DEF_SZ 3
#define DEF_AD 2

typedef struct PeoInfoInfo
{
    char name[MAX_NAME];
    char sex[MAX_SEX];
    char addr[MAX_ADDR];
    int age;
    char tele [MAX_TELE];
}PeoInfo;

 typedef struct Contact
{
    PeoInfo *data;//放弃数组改为指针
    int sz;
    int capacity;
    //记录当前通讯录容量
}Contact,*pCon;

 void InitContact(pCon p);
 void AddContact(pCon p);
 void ShowContact(pCon p);
 void SearContact(pCon p);
 void DelContact(pCon p);
 void ModifyContact(pCon p);
 void EmptyContact(pCon p);
 void SortContact(pCon p);
 void DestroContact(pCon p);
#endif 

  相较于通讯录1.0,代码虽然对空间利用率实现了改进,但是程序仍然有一个致命的缺点就是当程序退出时所有数据均会被销毁,所以在通讯录3.0中会加入文件应用,将输入数据保存到本地文件当中,可随时调用查看。
  以上内容均为学习练习所用,如有不足之处欢迎批评指正,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值