Как создать многомерный массив? - 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);
}

Объяснение кода листинга программы

В этом коде создается многомерный массив, используя динамическое выделение памяти. Сначала определяются структура и функции для работы с многомерным массивом:

  1. struct md_array - структура, представляющая многомерный массив. Она содержит поля rank (количество измерений), dimensions (массив размеров каждого измерения) и data (массив данных).
  2. num_elements(unsigned rank, unsigned *dimensions) - функция для вычисления общего количества элементов в многомерном массиве.
  3. make_md_array(unsigned rank, unsigned *dimensions) - функция для создания нового экземпляра многомерного массива. Она выделяет память для структуры и ее компонентов, а затем заполняет поля структуры.
  4. calculate_offset(unsigned rank, unsigned *dimensions, unsigned *indices) - функция для вычисления смещения элемента в многомерном массиве относительно начала массива.
  5. get_item(struct md_array *array, unsigned *indices) - функция для получения указателя на элемент многомерного массива по индексам.
  6. destroy_md_array(struct md_array *array) - функция для освобождения памяти, выделенной под многомерный массив.
  7. gen_walk(struct md_array *array, MD_ARRAY_FUN fun, unsigned *indices, unsigned curr_dim) - рекурсивная функция для обхода всех элементов многомерного массива в заданном порядке.
  8. walk_md_array(struct md_array *array, MD_ARRAY_FUN fun) - функция для обхода всех элементов многомерного массива с использованием функции fun для каждого элемента.
  9. print_indices(unsigned count, unsigned *indices) - функция для печати индексов многомерного массива.
  10. read_array(struct md_array *array, unsigned *indices) - функция для чтения значения элемента многомерного массива по индексам.
  11. print_array(struct md_array *array, unsigned *indices) - функция для печати значения элемента многомерного массива по индексам. Затем в функции main() создается многомерный массив с помощью функций make_md_array() и walk_md_array(). Пользователю предлагается ввести значения массива, и после ввода всех значений они выводятся на экран.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

6   голосов , оценка 4.167 из 5
Похожие ответы