C语言 可变长度的数组 -2

1、前言

在笔者的上一篇blog中,使用了“链表”这样一种数据结构来实现C语言版的可变数组;虽然它的功能强大,但是缺点也是很多的。例如,在释放内存的时候需要循环释放。假如链表中元素比较多,则释放内存就比较耗费时间;且其数据在内存中存放的位置不连续。

在此,笔者介绍另外一种方式,来实现可变数组:


2、基本思想

对于数组,想必大家应该是比较了解的。数组的在内存中是连续存放的,且其存放在内存的“栈”中。

最开始的时候,笔者想通过调用realloc()函数来扩展一个数组的存储区域。但是发现,执行报错。后来才知道,程序的栈是由系统维护的,能供给用户动态分配的内存区域只有“堆”。

既然“堆”可以让用户自己来分配,那么当我们发现有数据输入的时候,就向系统申请一段内存空间,吧数据保存进去。当发现还有数据要输入的时候,我们就扩充这个内存空间,然后把数据保存进去。这样的数据保存完毕之后,就能保证所存储的数据都是连续存放的,由一个指针(首地址)引用。这很类似于数组。


3、代码实现

既然基本思路有了,那么就以上一篇blog中的功能要求为例,继续改写代码。

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Student struct stu
#define Volume sizeof(struct stu)

//声明结构类型
struct stu{
    char name[16];
    int age;
};

int main()
{
    int len = 0;
    char identify[15] = {0};
    int old = 0;

    //创建指向Student类型存储区域的首地址的指针,以及存储区内部指针
    Student *head =NULL;
    Student *innerp = NULL;

    do{
        printf("please enter student's name: ---->less than 15 bytes  ----> press Enter to quit\n");
        gets(identify);

        //判断输入的姓名是否正常,如果输入的是enter键,则退出
        if(identify[0] == '\0'){
            break;
        }else{
            printf("please enter student's age:\n");
            scanf("%d%*c",&old);

            len++;
            if(len ==1){
                head = malloc(Volume);
            }else{
                head = realloc(head,(Volume*len));
            }

            innerp = head+(len-1);         //确定存储区域内部指针位置
            strcpy(innerp->name,identify);
            innerp->age = old;
        }
    }while(1);
    printf("input done. you have ended %d students.\n",len);
    printf("start reading informations\n");

    //如何head为NULL,则表示存储区域没有数据;
    if(head != NULL){
        innerp = head;   //存储区域内部指针重置
        for(int i =0; i<len; i++){
            innerp = head+i;                       //存储区域内部指针移动
            printf("No:%-5d\tName:%-15s\tAge:%-5d\n",i,innerp->name,innerp->age);
        }
        printf("All informations have been displayed\n");
    }else{
        printf("this is no data in memory\n");
    }
    printf("program is ending...\n");
    printf("program has ended.\n");
    return 0;
}

对于这两段代码会发现,使用这种方式,代码量少了很多,而且思路清晰,实现比较简单。相比上一段代码,它还具有几个优点:

  1. 结构体数据量少,比较节省内存空间;
  2. 数据是规则的连续存放的,这样可以很方便使用指针来查询;
  3. 指针变量少:上一个代码段中,结构体使用了一个指针,还使用了一个head指针和一个位置指针;而本段代码中,只使用了一个头指针和位置指针。事实上,位置指针都可以不用,可以像数组语言,用头指针加上一个偏移量,就是存储区域内的位置指针了。
  4. 内存的释放非常方便,只需要一句代码:free(head);即可。而上一段代码,却需要使用循环来释放空间。


5、写在最后

虽然笔者刚刚接触C语言才不过十几天而已,但是发现C语言太难了。它的难点在于直接操作内存,而不像.net 那样,有clr维护内存;它的难点还在于,知识体系的简单,没有过大的框架,全部由底层的数据类型,函数来构建程序。这因为如此,C语言给了程序员非常宽松的思想空间。只要你有想法,就可以(几乎是)任意操作计算机。

以上所写,纯属个人实践。如有错误,还请各位不吝赐教。

  • 2
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

raynadofan

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值