Как создать многомерный массив? - C (СИ)
Формулировка задачи:
Подскажите, пожалуйста, возможно ли задать многомерный массив в С, если заранее (на момент написания кода) не известно точное число количества мер? Может, как-то возможно реализовать через указатели или там массивы указателей?
Решение задачи: «Как создать многомерный массив?»
textual
Листинг программы
#include <stdio.h> #include <stdlib.h> #include <string.h> struct md_array { unsigned rank; unsigned *dimensions; int *data; }; unsigned num_elements(unsigned rank, unsigned *dimensions) { unsigned num = 1, i; for(i = 0; i < rank; ++i) num *= dimensions[i]; return num; } struct md_array *make_md_array(unsigned rank, unsigned *dimensions) { struct md_array *array = malloc(sizeof *array); if(array == NULL) goto err_ret; array->dimensions = malloc(rank * sizeof *dimensions); if(array->dimensions == NULL) goto free_array; array->data = malloc(num_elements(rank, dimensions) * sizeof *(array->data)); if(array->data == NULL) goto free_dimensions; array->rank = rank; memcpy(array->dimensions, dimensions, rank * sizeof *dimensions); return array; free_dimensions: free(array->dimensions); free_array: free(array); err_ret: return NULL; } unsigned calculate_offset(unsigned rank, unsigned *dimensions, unsigned *indices) { unsigned offset = 0, i, last_dim = 1; for(i = 0; i < rank; ++i) { offset = offset * last_dim + indices[i]; last_dim = dimensions[i]; } return offset; } int *get_item(struct md_array *array, unsigned *indices) { return &(array->data[calculate_offset(array->rank, array->dimensions, indices)]); } void destroy_md_array(struct md_array *array) { free(array->data); free(array->dimensions); free(array); } typedef int (*MD_ARRAY_FUN)(struct md_array *, unsigned *); int gen_walk(struct md_array *array, MD_ARRAY_FUN fun, unsigned *indices, unsigned curr_dim) { if(curr_dim >= array->rank) return fun(array, indices); for(indices[curr_dim] = 0; indices[curr_dim] < array->dimensions[curr_dim]; ++indices[curr_dim]) if(gen_walk(array, fun, indices, curr_dim + 1) == 0) return 0; return 1; } int walk_md_array(struct md_array *array, MD_ARRAY_FUN fun) { int ret; unsigned *indices = calloc(array->rank, sizeof *indices); if(indices == NULL) return 0; ret = gen_walk(array, fun, indices, 0); free(indices); return ret; } void print_indices(unsigned count, unsigned *indices) { unsigned i; for(i = 0; i < count; ++i) printf("[%u]", indices[i]); } int read_array(struct md_array *array, unsigned *indices) { printf("ARRAY"); print_indices(array->rank, indices); printf(": "); fflush(stdout); if(scanf("%d", get_item(array, indices)) != 1) { perror("scanf"); return 0; } return 1; } int print_array(struct md_array *array, unsigned *indices) { printf("ARRAY"); print_indices(array->rank, indices); printf(" = %d\n", *get_item(array, indices)); return 1; } int main(void) { unsigned rank, i; unsigned *dimensions; struct md_array *array; int ret = EXIT_FAILURE; printf("Rank: "); fflush(stdout); scanf("%u", &rank); dimensions = malloc(rank * sizeof *dimensions); if(dimensions == NULL) { perror("malloc"); goto err_ret; } for(i = 0; i < rank; ++i) { printf("Dim #%u: ", i); fflush(stdout); scanf("%u", &dimensions[i]); } array = make_md_array(rank, dimensions); if(array == NULL) { perror("make_md_array"); goto free_dimensions; } puts("Enter array:"); if(walk_md_array(array, read_array) == 0) goto free_array; puts("Got array:"); if(walk_md_array(array, print_array) == 0) goto free_array; ret = EXIT_SUCCESS; free_array: destroy_md_array(array); free_dimensions: free(dimensions); err_ret: exit(ret); }
Объяснение кода листинга программы
В этом коде создается многомерный массив, используя динамическое выделение памяти. Сначала определяются структура и функции для работы с многомерным массивом:
struct md_array
- структура, представляющая многомерный массив. Она содержит поляrank
(количество измерений),dimensions
(массив размеров каждого измерения) иdata
(массив данных).num_elements(unsigned rank, unsigned *dimensions)
- функция для вычисления общего количества элементов в многомерном массиве.make_md_array(unsigned rank, unsigned *dimensions)
- функция для создания нового экземпляра многомерного массива. Она выделяет память для структуры и ее компонентов, а затем заполняет поля структуры.calculate_offset(unsigned rank, unsigned *dimensions, unsigned *indices)
- функция для вычисления смещения элемента в многомерном массиве относительно начала массива.get_item(struct md_array *array, unsigned *indices)
- функция для получения указателя на элемент многомерного массива по индексам.destroy_md_array(struct md_array *array)
- функция для освобождения памяти, выделенной под многомерный массив.gen_walk(struct md_array *array, MD_ARRAY_FUN fun, unsigned *indices, unsigned curr_dim)
- рекурсивная функция для обхода всех элементов многомерного массива в заданном порядке.walk_md_array(struct md_array *array, MD_ARRAY_FUN fun)
- функция для обхода всех элементов многомерного массива с использованием функцииfun
для каждого элемента.print_indices(unsigned count, unsigned *indices)
- функция для печати индексов многомерного массива.read_array(struct md_array *array, unsigned *indices)
- функция для чтения значения элемента многомерного массива по индексам.print_array(struct md_array *array, unsigned *indices)
- функция для печати значения элемента многомерного массива по индексам. Затем в функцииmain()
создается многомерный массив с помощью функцийmake_md_array()
иwalk_md_array()
. Пользователю предлагается ввести значения массива, и после ввода всех значений они выводятся на экран.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д