создать многомерный массив для хранения множества массивов разных размеров в C - PullRequest
3 голосов
/ 03 мая 2019

Я задал этот вопрос, но я удалил его, потому что он не был ясен. У меня есть три цикла, которые производят 0, 1 данных. Я хотел бы сохранить их в виде матрицы, поэтому я думаю, что она должна храниться в многомерном массиве, который я называю Third.

for (i = 0; i < m; i++) {
    for (int l = 0; l < n2; ++l) {
        for (x = 0; x < all[i].n; ++x) {
            f = (int)VECTOR(v2)[l];
            if (a[x].vto == f) {
                printf("%d", 1);
            } else {
                printf("%d", 0);
            }
        }
    }
    for (int y = 0; y < n1; ++y) {
        for (x = 0; x < all[i].n; ++x) {
            q = (int)VECTOR(v1)[y];
            if (a[x].vfrom == q) {
                printf("%d", 1);
            } else {
                printf("%d", 0);
            }
        }
    }
    printf("\n");  
}

Печатный результат предыдущего кода - и я хотел бы сохранить его в этой форме:

100010001111
111000000111100100010010001001
111000000000111000000000111100100100010010010001001001
110000001100000011101010010101
111100010001

Моя цель - сохранить распечатанный результат в массиве типа

Third = [[[100][010][001][111]] [[111000][000111][100100][010010][001001]]...[[111][100][010][001]]]

поэтому, если я хочу получить доступ к массиву Third, я делаю Third[3] = [ [110000] [001100] [000011] [101010] [010101] ] или Third[3][1] = [001100] или Third[3][1][2] = 1.

Я был бы очень рад разъяснить что-то непонятное. Спасибо за помощь

РЕДАКТ. 1: Код слишком велик, чтобы его можно было добавить полностью. Я спросил об общем способе достижения того, что я ищу, а именно о том, как построить многомерный массив или массив массивов для хранения результатов данных из любых трех вложенных циклов (не обязательно, чтобы мои циклы).

Я исправил текущий код, так что теперь массив Third содержит все данные, но я не думаю, что это правильный способ хранения данных, чтобы получить к ним доступ позже как Third[3] = [ [110000] [001100] [000011] [101010] [010101] ]

Вот что я сделал:

    int second[n1 + n2][n1 * n2];
    int first[n1 * n2];
    int Third[m][n1 + n2][n1 * n2];

    for (i = 0; i < m; i++) {
        Data *a = all[i].datas;
        igraph_edge(&graph, i, &from, &to);
        igraph_neighbors(&graph, &v1, from, IGRAPH_ALL);
        igraph_neighbors(&graph, &v2, to, IGRAPH_ALL);

        int n2 = igraph_vector_size(&v2);
        int n1 = igraph_vector_size(&v1);
        int f, q, x, l, y;

        for (l = 0; l < n2; ++l) {
            for (x = 0; x < all[i].n; ++x) {
                f = (int)VECTOR(v2)[l];
                if (a[x].vto == f) {
                    first[x] = 1;
                } else {
                    first[x] = 0;
                }
                second[l][x] = first[x];
                Third[i][l][x] = second[l][x]; 
                printf("%d", Third[i][l][x]); 
            }
       }

       for (y = 0; y < n1; ++y) {
           for (x = 0; x < all[i].n; ++x) {
               q = (int)VECTOR(v1)[y];
               if (a[x].vfrom == q) {
                   first[x] = 1;
               } else {
                   first[x] = 0;
               }
               second[y+n2][x] = first[x];
               Third[i][y+n2][x] = second[y+n2][x];
               printf("%d", Third[i][y+n2][x]); 
           }
        }
        printf("\n");  
    }

при компиляции предыдущего кода я получаю

100010001111
111000000111100100010010001001
111000000000111000000000111100100100010010010001001001
110000001100000011101010010101
111100010001

Я не уверен, что это правильный способ сделать это? спасибо

РЕДАКТИРОВАТЬ 2:

Мне интересно, правильно ли заявлено так, как указано ниже, или нет? Является ли трехмерный массив Third фиксированного размера или он (как требуется) является динамическим в соответствии с n1 и n2, которые изменяются в зависимости от итерации i.

    int second[n1 + n2][n1 * n2];
    int first[n1 * n2];
    int Third[m][n1 + n2][n1 * n2];

    for (i = 0; i < m; i++) {
        Data *a = all[i].datas;
        igraph_edge(&graph, i, &from, &to);
        igraph_neighbors(&graph, &v1, from, IGRAPH_ALL); //initialize the vector v2 where it's values and it's size vary depending on i
        igraph_neighbors(&graph, &v2, to, IGRAPH_ALL); //initialize the vector v2 where it's values and it's size vary depending on i

        int n2 = igraph_vector_size(&v2); // the size changes depending on i, i.e the change from an iteration to another
        int n1 = igraph_vector_size(&v1); // the size changes depending on i, i.e the change from an iteration to another
        int f, q, x, l, y;

        for (l = 0; l < n2; ++l) {
            for (x = 0; x < all[i].n; ++x) {
                f = (int)VECTOR(v2)[l];
                if (a[x].vto == f) {
                    first[x] = 1;
                } else {
                    first[x] = 0;
                }
                second[l][x] = first[x];
                Third[i][l][x] = second[l][x]; 
            }
        }
    }

1 Ответ

2 голосов
/ 03 мая 2019

Вы хотите это:

Third = [ [[100][010][001][111]] [[111000][000111][100100][010010][001001]]...[[111][100][010][001]] ];

Я буду исходить из того, что тип данных, который вы хотите, - bool, но может быть любым.

Этого нельзя достичь точно в C, так как все элементы массива должны быть одного типа, и это включает его размер, когда мы говорим о массивах.


Вариант 1:

Но у нас есть, например, *argv[], который является массивом указателей, но поскольку указатели могут вести себя как массивы, у нас фактически есть что-то вроде этого (следуя вашей же грамматике):

*argv[] = [ [program\0][arg1\0][arg2\0] ] // Don't forget the ending NULL, but it's not relevant here.

Нечто похожее на то, что вы хотите, может быть:

void *third[n];

И при условии, что у вас есть все ваши вторые массивы, определенные как

bool second_0[4][3];
bool second_1[5][6];
...
bool second_n[4][3];

Тогда вы можете присоединиться к ним всем в third, например:

third[0] = &second_0;
third[1] = &second_1;
...
third[n] = &second_n;

И вы можете использовать third следующим образом: допустим, вы хотите извлечь элемент [i][j][k] во временную переменную, и предположим, что массив second_i имеет размеры second_i[n][m]:

bool tmp = (*(bool (*)[n][m])third[i])[j][k];

Использование не очень приятно, но это самое близкое, что вы можете иметь к тому, что вы хотите.


Вариант 2 (предпочтительно):

У вас может быть большой массив, подобный этому: bool third[100][20][30];, который может содержать всегда больше чисел, чем ваш самый большой ожидаемый второй массив, и просто оставить как 0 неиспользуемые значения. Он будет использовать больше памяти, но не будет нуждаться ни в приведениях, ни в указателях, а будет намного быстрее, поскольку вся память будет смежной.

Если вы используете эту опцию, вам нужна дополнительная переменная

ptrdiff_t third_sizes[ARRAY_SIZE(third)][2];

для хранения размеров каждого второго массива, чтобы вы могли отслеживать, какую часть вы использовали (с первой опцией она вам тоже понадобится). ARRAY_SIZE() должно быть определено так:

#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

Ответ на EDIT 2:

Short: нет, массивы динамического размера не существуют в C. Это невозможно.

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

Существуют динамические решения для некоторых проблем, такие как связанные списки (Google, если вам нужно больше информации об этом), но не массивы. Другим способом достижения чего-то вроде массива массивов динамического размера было бы сочетание «варианта 1» выше с malloc() & free(), но я бы избегал его настолько, насколько смог, из-за производительности и из-за возможного ошибок. Некоторые говорят, что malloc() - это зло . (Не использовать его, но использовать только тогда, когда нет альтернативы).

Тем не менее "вариант 2" выше - это то, что я выбрал бы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...