(二十九)第 5 章 数组和广义表(数组的顺序存储)

本文介绍了数组的顺序存储结构,强调数组定义后其维数和维界不可变。主要内容包括数组元素的存取和修改。文章通过C语言实现相关操作,提供了`errorRecord.h`, `sqArray.h`, `sqArray.c`, `main.c`四个代码文件作为示例。" 106367549,8698905,Java实现:三天打鱼两天晒网算法,"['Java', '日期与时间', '算法实现', '编程问题']

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

1. 背景说明

数组一旦被定义,它的维数和维界就不再改变。因此,除了结构的初始化和销毁之外,数组只有存取元素和修改元素值的操作。

2. 示例代码

1) errorRecord.h

// 记录错误宏定义头文件

#ifndef ERROR_RECORD_H
#define ERROR_RECORD_H

#include <stdio.h>
#include <string.h>
#include <stdint.h>

// Extracts the file name from the file path
#define FILE_NAME(X) strrchr(X, '\\') ? strrchr(X, '\\') + 1 : X

// Define DEBUG macro for enabling debug mode
#define DEBUG

// Print error message
#ifdef DEBUG
#define ERR_RECORD(ERR_CODE, ...) do { \
    printf(ANSI_COLOR_BRIGHT_CYAN \
        "\n\nFile: %-25s Func: %-20s Line: %-10d ErrorCode: %-8d ErrorInfo: ", \
        FILE_NAME(__FILE__), __func__, __LINE__, (ERR_CODE)); \
    printf(""__VA_ARGS__); \
    printf("\n" ANSI_COLOR_RESET); \
    PrintErrorCodeInfo(ERR_CODE); \
} while (0)
#else
#define ERR_RECORD(ERR_CODE, FORMAT, ...)
#endif

// Function result status codes
enum StatusCode {
	RET_OK = 0,                 // Operation successful
	ERR_NULL_PTR = 1,           // Null pointer error
	ERR_MEMORY_ALLOCATE = 2,    // Memory allocation error
	ERR_EMPTY_STACK = 3,        // Empty stack error
	ERR_FULL_STACK = 4,			// Full stack error
	ERR_EMPTY_QUEUE = 5,        // Empty queue error
	ERR_FULL_QUEUE = 6,         // Full queue error
	ERR_PARA_ILLEGAL = 7,       // Parameter illegal error
	ERR_OPEN_FILE = 8,          // File open error
	ERR_NOT_EXIST = 9,          // Not exist error
};

enum BoolCode {
	TRUE = 1,
	FALSE = 0
};

typedef uint32_t Status;
typedef uint8_t Boolean;

// ANSI 转义码定义
#define ANSI_COLOR_BRIGHT_RED     "\x1b[91m"
#define ANSI_COLOR_BRIGHT_YELLOW  "\x1b[93m"
#define ANSI_COLOR_BRIGHT_CYAN    "\x1b[96m"
#define ANSI_COLOR_RESET          "\x1b[0m"

// Function to print error code information with bright colors
static void PrintErrorCodeInfo(int errorCode)
{
	switch (errorCode) {
		case ERR_NULL_PTR:
			printf(ANSI_COLOR_BRIGHT_RED "Null Pointer Error\n\n" ANSI_COLOR_RESET);
			break;

		case ERR_MEMORY_ALLOCATE:
			printf(ANSI_COLOR_BRIGHT_RED "Memory Allocation Error\n\n" ANSI_COLOR_RESET);
			break;

		case ERR_EMPTY_STACK:
			printf(ANSI_COLOR_BRIGHT_RED "Empty Stack Error\n\n" ANSI_COLOR_RESET);
			break;

		case ERR_FULL_STACK:
			printf(ANSI_COLOR_BRIGHT_RED "Full Stack Error\n\n" ANSI_COLOR_RESET);
			break;

		case ERR_EMPTY_QUEUE:
			printf(ANSI_COLOR_BRIGHT_RED "Empty Queue Error\n\n" ANSI_COLOR_RESET);
			break;

		case ERR_FULL_QUEUE:
			printf(ANSI_COLOR_BRIGHT_RED "Full Queue Error\n\n" ANSI_COLOR_RESET);
			break;

		case ERR_PARA_ILLEGAL:
			printf(ANSI_COLOR_BRIGHT_RED "Illegal Parameter Error\n\n" ANSI_COLOR_RESET);
			break;

		case ERR_OPEN_FILE:
			printf(ANSI_COLOR_BRIGHT_RED "File Open Error\n\n" ANSI_COLOR_RESET);
			break;

		case ERR_NOT_EXIST:
			printf(ANSI_COLOR_BRIGHT_RED "Not Exist Error\n\n" ANSI_COLOR_RESET);
			break;

		default:
			printf(ANSI_COLOR_BRIGHT_YELLOW "Unknown Error Code: %d\n\n" ANSI_COLOR_RESET,
				errorCode);
			break;
	}
}

#endif // !ERROR_RECORD_H

2) sqArray.h

// 数组的顺序存储表示头文件

#ifndef SQ_ARRAY_H
#define SQ_ARRAY_H

#include "errorRecord.h"

#define MAX_ARRAY_DIM 10

typedef int ElemType;

typedef struct {
	ElemType *base;				// 数组元素基址,由InitArray 分配
	int dim;					// 数组维数
	int *bounds;				// 数组维界基址,由 InitArray 分配(用于描述每一维的长度)
	int *constants;				// 数组映像函数常量基址,由 InitArray 分配(用于描述每一维前面一维的元素总量)
} Array;

Status InitArray(int dim, Array *array, ...);

Status DestroyArray(Array *array);

Status GetArrayValue(const Array *array, ElemType *e, ...);

Status AssignArray(ElemType e, Array *array, ...);

#endif // !SQ_ARRAY_H

3) sqArray.c

// 数组的顺序存储实现源文件

#include "sqArray.h"
#include <stdlib.h>
#include <stdarg.h>

/*
	前置条件:维数 dim 和各维长度合法
	操作结果:构造相应的数组 array
*/
Status InitArray(int dim, Array *array, ...)
{
	if (!array) {
		ERR_RECORD(ERR_NULL_PTR);
		return ERR_NULL_PTR;
	}

	if ((dim < 1) || (dim > MAX_ARRAY_DIM)) {
		ERR_RECORD(ERR_PARA_ILLEGAL, "dim = %d", dim);
		return ERR_PARA_ILLEGAL;
	}

	array->dim = dim;
	array->bounds = (int *)malloc(sizeof(int) * dim);
	if (!array->bounds) {
		ERR_RECORD(ERR_MEMORY_ALLOCATE);
		return ERR_MEMORY_ALLOCATE;
	}

	va_list ap;
	va_start(ap, array);
	int elemTotal = 1;
	for (int i = 0; i < dim; ++i) {
		array->bounds[i] = va_arg(ap, int);
		if (array->bounds[i] < 0) {
			ERR_RECORD(ERR_PARA_ILLEGAL);
			return ERR_PARA_ILLEGAL;
		}

		elemTotal *= array->bounds[i];
	}

	va_end(ap);
	array->base = (ElemType *)malloc(sizeof(ElemType) * elemTotal);
	if (!array->base) {
		ERR_RECORD(ERR_MEMORY_ALLOCATE);
		free(array->bounds);
		return ERR_MEMORY_ALLOCATE;
	}

	array->constants = (int *)malloc(sizeof(int) * dim);
	if (!array->constants) {
		ERR_RECORD(ERR_MEMORY_ALLOCATE);
		free(array->bounds);
		free(array->base);
		return ERR_MEMORY_ALLOCATE;
	}

	array->constants[dim - 1] = 1;
	for (int i = dim - 2; i >= 0; --i) {
		array->constants[i] = array->bounds[i + 1] * array->constants[i + 1];
	}

	return RET_OK;
}

/*
	前置条件:数组 array 已存在
	操作结果:销毁数组 array
*/
Status DestroyArray(Array *array)
{
	if (!array) {
		ERR_RECORD(ERR_NULL_PTR);
		return ERR_NULL_PTR;
	}

	free(array->base);
	free(array->bounds);
	free(array->constants);
	array->base = array->bounds = array->constants = NULL;
	array->dim = 0;

	return RET_OK;
}

/*
	前置条件:数组 array 已存在,ap 指示的各下标值合法
	操作结果:求出该元素在 array 中的相对地址 off
*/
static Status Locate(va_list ap, const Array *array, int *off)
{
	if (!array || !off) {
		ERR_RECORD(ERR_NULL_PTR, "array = %p, off = %p", array, off);
		return ERR_NULL_PTR;
	}

	int ind;
	*off = 0;
	for (int i = 0; i < array->dim; ++i) {
		ind = va_arg(ap, int);
		if ((ind < 0) || (ind >= array->bounds[i])) {
			ERR_RECORD(ERR_PARA_ILLEGAL, "ind = %d, array->bounds[%d] = %d", ind, i, array->bounds[i]);
			return ERR_PARA_ILLEGAL;
		}

		*off += array->constants[i] * ind;
	}

	return RET_OK;
}

/*
	前置条件:数组 array 已存在,各维度的数组的下标值合法
	操作结果:将数组相应元素值赋值给 e
*/
Status GetArrayValue(const Array *array, ElemType *e, ...)
{
	if (!array || !e) {
		ERR_RECORD(ERR_NULL_PTR, "array = %p, e = %p", array, e);
		return ERR_NULL_PTR;
	}

	va_list ap;
	va_start(ap, e);
	int off;
	Status ret = Locate(ap, array, &off);
	if (RET_OK != ret) {
		ERR_RECORD(ret);
		return ret;
	}

	*e = *(array->base + off);

	return RET_OK;
}

/*
	前置条件:数组 array 已存在,各维度的数组的下标值合法
	操作结果:将元素值 e 赋值给数组相应元素
*/
Status AssignArray(ElemType e, Array *array, ...)
{
	if (!array) {
		ERR_RECORD(ERR_NULL_PTR);
		return ERR_NULL_PTR;
	}

	va_list ap;
	va_start(ap, array);
	int off;
	Status ret = Locate(ap, array, &off);
	if (RET_OK != ret) {
		ERR_RECORD(ret);
		return ret;
	}

	*(array->base + off) = e;

	return RET_OK;
}

4) main.c

// 入口程序源文件

#include "sqArray.h"

int main(void)
{
	// 数组 array[3][4][2]
	Array array;
	int dim = 3, bound1 = 3, bound2 = 4, bound3 = 2;
	Status ret = InitArray(dim, &array, bound1, bound2, bound3);
	if (RET_OK != ret) {
		ERR_RECORD(ret);
		return ret;
	}

	int *p = array.bounds;
	for (int i = 0; i < dim; ++i) {
		printf("array.bound[%d] = %d ", i, *(p + i));
	}

	printf("\n");
	p = array.constants;
	for (int i = 0; i < dim; ++i) {
		printf("array.constants[%d] = %d ", i, *(p + i));
	}

	printf("\n\n%d pages %d row %d col element: \n", bound1, bound2, bound3);
	ElemType e;
	for (int i = 0; i < bound1; ++i) {
		for (int j = 0; j < bound2; ++j) {
			for (int k = 0; k < bound3; ++k) {
				ret = AssignArray(i * 100 + j * 10 + k, &array, i, j, k);
				ret |= GetArrayValue(&array, &e, i, j, k);
				if (RET_OK != ret) {
					ERR_RECORD(ret, "i = %d, j = %d, k = %d", i, j, k);
					return ret;
				}

				printf("  array[%d][%d][%d] = %3d", i, j, k, e);
			}

			printf("\n");
		}

		printf("\n");
	}

	ElemType *p1 = array.base;
	printf("array.base = \n");
	for (int i = 0; i < bound1 * bound2 * bound3; ++i) {
		printf("%22d", *(p1 + i));
		if (i % 2 == 1) {
			printf("\n");
		}
	}

	DestroyArray(&array);

	return 0;
}

3. 输出示例 (DEBUG OFF)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值