数组的顺序存储表示(C语言数据结构)

数组的顺序存储表示(C语言数据结构)

简单介绍一下<stdarg.h>的作用

stdarg.h是C语言标准库头文件之一,用于支持变长参数函数。stdarg.h中定义了三个宏:va_startva_argva_end,这些宏可以帮助我们在变长参数函数中访问传递给函数的参数列表。以下是三个宏的详细解释:
1.va_start(ap, param):该宏用于初始化一个指向参数列表的指针ap,以便后续使用a_arg宏访问参数。ap是一个va_list类型的变量,param是传递给函数的最后一个固定参数的参数名。va_start宏必须在使用va_arg宏之前调用。
2.va_arg(ap, type):该宏用于访问参数列表中的下一个参数。ap是指向参数列表的指针,type是要访问的参数的类型。va_arg宏返回一个值,该值表示参数列表中的下一个参数,并将指针ap移动到下一个参数的位置。在使用va_arg宏之前,必须调用va_start宏初始化ap指针。
3.va_end(ap):该宏用于结束对参数列表的访问。ap是指向参数列表的指针,该指针必须是通过调用va_start宏初始化的。调用va_end宏后,指针ap将无效,不能再用于访问参数列表。
下面是一个示例程序,演示如何使用stdarg.h中的宏:3

#include <stdarg.h>
#include <stdio.h>

void print_ints(int num, ...) {
    va_list args;
    va_start(args, num); // 初始化指向参数列表的指针

    for (int i = 0; i < num; i++) {
        int val = va_arg(args, int); // 获取下一个整数参数
        printf("%d ", val);
    }

    va_end(args); // 结束对参数列表的访问
}

int main() {
    print_ints(3, 1, 2, 3); // 输出:1 2 3
    return 0;
}

数组的顺序存储表示和实现

由于数组一般不作插入和删除操作,也就是说,一旦建立了数组,则结构中的数据元素个数和元素之间的关系就不再发生改变。因此,采用顺序存储结构表示数组是自然的。
对于数组,一旦规定了它的维数和各维的长度,便可以为它分配存储空间。反之,只要给出一组下标,便可求得相应数组元素的存储位置。
假设每个数据元素占L个存储单元,则二维数组A中任意元素 a i j a_{ij} aij的存储位置就可由下式确定: L O C ( i , j ) = L O C ( 0 , 0 ) + ( b 2 ∗ i + j ) L LOC(i, j) = LOC(0, 0) + (b_2*i+j)L LOC(i,j)=LOC(0,0)+(b2i+j)L其中, a ( 0 , 0 ) a(0, 0) a(0,0)就是二维数组A的起始存储位置,也称为基地址或基址。
推广到一般情况,可得到n维数组的数据元素存储位置的计算公式: L ( j 1 , j 2 , . . . , j n ) = L O C ( 0 , 0 , . . . , 0 ) + ( b 2 ∗ b 3 ∗ . . . ∗ b n ∗ j 2 + . . . + b n ∗ j n − 1 + j n ) L(j_1, j_2,...,j_n) = LOC(0, 0,...,0)+(b_2*b_3*...*b_n*j_2+...+b_n*j_{n-1} + j_n) L(j1,j2,...,jn)=LOC(0,0,...,0)+(b2b3...bnj2+...+bnjn1+jn) = L O C ( 0 , 0 , . . . 0 , ) + ( ∑ i = 1 n − 1 j i ∏ k = i + 1 n b k + j n ) L = LOC(0,0,...0,) + (\sum^{n-1}_{i=1}j_i\prod^{n}_{k=i+1}b_k+j_n)L =LOC(0,0,...0,)+(i=1n1jik=i+1nbk+jn)L上式称为n维数组的映像函数。可以看出,一旦确定了数组的各维的长度,就可以很方便的确定元素的位置。由于计算各个元素的存储位置的时间相等,所以存取数组中任意元素的时间也相等。我们称具有这一特点的存储结构为随机存储结构。
在这里插入图片描述

/*
本文件完成数组的顺序存储表示
*/

#include<stdarg.h>
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>

#define MAX_ARRAY_DIM  8 //数组维数的最大值为8
#define ElemType int
typedef struct {
    ElemType* base; //数组元素的基地址,由InitArray分配
    int dim;        //数组维数
    int* bounds;    //数组维界基址(简单说就是每一维所能存储的元素的个数),由InitArray分配
    int* constants; //数组映像函数常数基址,由InitArray分配
}Array;

bool InitArray(Array* A, int dim, ...);
bool DestroyArray(Array* A);
bool Value(Array* A, ElemType* e, ...);
bool Assign(Array* A, ElemType e, ...);

int main() {
    Array A;
    int dim = 3;
    int a = 3, b = 4, c = 5;
    if (InitArray(&A, dim, a, b, c)) {
        printf("初始化数组成功\n");
    } else {
        printf("初始化数组失败\n");
    }
    int e = 0;
    Assign(&A, 4, 1, 3, 3);
    Value(&A, &e, 1, 3, 3);
    printf("dim:%d\n",A.dim);
    printf("bounds:%d %d %d\n", A.bounds[0], A.bounds[1], A.bounds[2]);
    printf("constans:%d %d\n", A.constants[0], A.constants[1]);
    printf("%d", e);
    return 0;
}

/// @brief 初始化一个数组
/// @param A 即将被初始化的数组
/// @param dim 数组的维数
/// @param ... 各个维的所能存储的元素的个数
/// @return 如果初始化成功则返回true
bool InitArray(Array* A, int dim, ...) {
    //判断输入的维数是否合法
    if (dim < 1 || dim > MAX_ARRAY_DIM) { printf("你输入维数的有毛病吧"); return false; }
    A->dim = dim;
    int* bound = (int*)malloc(8 * sizeof(int));
    if (!bound) { printf("这次不是你的问题,是系统分配内存的问题"); return false; }
    A->bounds = bound;
    //输入每一维所能容纳的元素的个数
    va_list ap;
    va_start(ap, dim);
    int ElemTotal = 1;
    for (int i = 0; i < A->dim; i++) {
        A->bounds[i] = va_arg(ap, int);
        if (A->bounds[i] < 0) { printf("元素个数输入的有毛病"); return false; }
        ElemTotal *= A->bounds[i];
    }
    va_end(ap);
    A->base = (ElemType*)malloc(ElemTotal * sizeof(ElemType));
    if (!A->base) { printf("这次不是你的问题,是系统分配内存的问题"); return false; }
    //初始化数组映像函数常数基址
    A->constants = (int*)malloc((A->dim) * sizeof(int));
    if (!A->constants) { printf("这次不是你的问题,是系统分配内存的问题"); return false; }
    int total = 1;
    for (int j = 1; j < A->dim; j++) {
        total *= A->bounds[j];
    }
    A->constants[0] = total;
    for (int i = 1; i < A->dim; i++) {
        A->constants[i] = total / A->bounds[i];
    }
    return true;
}

/// @brief 销毁数组
/// @param A 即将被销毁的数组
/// @return 似乎只能返回true
bool DestroyArray(Array* A) {
    free(A->base);
    free(A->bounds);
    free(A->constants);
    return true;
}

/// @brief 将e赋值为所指定的A的元素值
/// @param A 指定的数组
/// @param e 将被赋值的变量
/// @param  ... 元素的下标
/// @return 如果各下标不越界,将e赋值成功后,返回true
bool Value(Array* A, ElemType* e, ...) {
    int total = 0;
    va_list ap;
    va_start(ap, e);
    for (int i = 0; i < A->dim; i++) {
        int index = va_arg(ap, int);
        if (index < 0 || index > A->bounds[i]) { printf("你怕是有点越界了"); return 0; }
        total += index * A->constants[i];
    }
    *e = *(A->base + total);
    return true;
}

/// @brief 若下标不越界,则将e赋值给所指定的A的元素
/// @param A 即将被赋值的Array
/// @param e 
/// @param  ... 下标
/// @return 如果赋值成功则返回true
bool Assign(Array* A, ElemType e, ...) {
    int total = 0;
    va_list ap;
    va_start(ap, e);
    for (int i = 0; i < A->dim; i++) {
        int index = va_arg(ap, int);
        if (index < 0 || index > A->bounds[i]) { printf("你怕是有点越界了"); return 0; }
        total += index * A->constants[i];
    }
    *(A->base + total) = e;
    return true;
}
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值