C: Размер двумерного массива

Мне нужна помощь в подсчете строк и столбцов двумерного массива. Кажется, я не умею считать столбцы?

#include <stdio.h>

int main() {

char result[10][7] = {

    {'1','X','2','X','2','1','1'},
    {'X','1','1','2','2','1','1'},
    {'X','1','1','2','2','1','1'},
    {'1','X','2','X','2','2','2'},
    {'1','X','1','X','1','X','2'},
    {'1','X','2','X','2','1','1'},
    {'1','X','2','2','1','X','1'},
    {'1','X','2','X','2','1','X'},
    {'1','1','1','X','2','2','1'},
    {'1','X','2','X','2','1','1'}

};

int row = sizeof(result) / sizeof(result[0]);
int column = sizeof(result[0])/row;

printf("Number of rows: %d\n", row);
printf("Number of columns: %d\n", column);

}

Вывод:
Количество строк: 10
Количество столбцов: 0


person Wickerman    schedule 07.12.2015    source источник
comment
Поскольку они статичны, зачем вам вообще их считать? Просто определите константы для размера строки и столбца вместо использования магических чисел.   -  person Lundin    schedule 07.12.2015


Ответы (4)


Это проблема целочисленного деления!

int column = sizeof(result[0])/row;

должно быть

int column = 7 / 10;

и в целочисленном делении, 7/10==0.

Что вы хотите сделать, это разделить длину одной строки, например. sizeof(result[0]) по размеру одного элемента этой строки, например. sizeof(result[0][0]):

int column = sizeof(result[0])/sizeof(result[0][0]);
person Marcus Müller    schedule 07.12.2015
comment
Это не правильно. Здесь вы делите 7 (количество элементов в первой строке) на 1 (количество символов в result[0][0]). - person emi; 07.12.2015
comment
Почему это неправильно? sizeof (результат) = 70, sizeof (результат [0]) = 7, sizeof (результат [0] [0]) = 1, поэтому количество строк = 70/7 = 10 правильно, а количество столбцов = 7 /1 = 7 тоже верно. Даже если вы изменили тип с char на int (при условии, что int = 32 бита), sizeof (результат) = 280, sizeof (результат [0]) = 28, sizeof (результат [0] [0]) = 4, поэтому, поскольку вы можете снова заметить, что количество строк = 280/28 = 10 верно, и количество столбцов = 28/4 = 7 также верно. - person ZeZNiQ; 14.02.2020

Гораздо удобнее (и менее подвержено ошибкам) ​​использовать макрос длины массива:

#include <stdio.h>

#define LEN(arr) ((int) (sizeof (arr) / sizeof (arr)[0]))

int main(void)
{
    char result[10][7];

    printf("Number of rows: %d\n", LEN(result));
    printf("Number of columns: %d\n", LEN(result[0]));
    return 0;
}
person August Karlstrom    schedule 07.12.2015
comment
Почему целое число приведено к макросу LEN? Разве массивы не являются однородными структурами данных, то есть числитель всегда будет кратен знаменателю? Кроме того, не должно ли деление возвращать unsigned integer или size_t, которые уже являются целым типом? - person Rafa; 03.05.2017
comment
@Rafa Мы можем обойтись без приведения, если изменим спецификатор формата %d на %lu. Когда LEN используется в защите от цикла for, нам нужно использовать приведение или объявить переменные индекса с типом size_t. - person August Karlstrom; 03.05.2017
comment
Не согласен с менее подверженным ошибкам; идея красивая, но опасная; существует много способов неявного преобразования массива в тип указателя, и один из них особенно опасен: кто-то пытается перебирать строки и делает что-то вроде LEN(result++) в цикле. - person Marcus Müller; 20.01.2021
comment
@MarcusMüller Да, наличие выражений с побочными эффектами уродливо и подвержено ошибкам, и ваш пример показывает, почему этого следует избегать. Даже если вы используете оператор sizeof напрямую, вам все равно нужно знать, есть ли у вас указатель или массив. - person August Karlstrom; 20.01.2021

Это работает для меня (комментарии объясняют почему):

#include <stdio.h>

int main() {

   char result[10][7] = {

       {'1','X','2','X','2','1','1'},
       {'X','1','1','2','2','1','1'},
       {'X','1','1','2','2','1','1'},
       {'1','X','2','X','2','2','2'},
       {'1','X','1','X','1','X','2'},
       {'1','X','2','X','2','1','1'},
       {'1','X','2','2','1','X','1'},
       {'1','X','2','X','2','1','X'},
       {'1','1','1','X','2','2','1'},
       {'1','X','2','X','2','1','1'}

   }; 

   // 'total' will be 70 = 10 * 7
   int total = sizeof(result);

   // 'column' will be 7 = size of first row
   int column = sizeof(result[0]);

   // 'row' will be 10 = 70 / 7
   int row = total / column;

   printf("Total fields: %d\n", total);
   printf("Number of rows: %d\n", row);
   printf("Number of columns: %d\n", column);

}

И вывод этого:

Total of fields: 70
Number of rows: 10
Number of columns: 7

ИЗМЕНИТЬ:

Как указывает @AnorZaken, передача массива в функцию в качестве параметра и печать на нем результата sizeof приведет к выводу еще одного total. Это связано с тем, что когда вы передаете массив в качестве аргумента (а не указатель на него), C передаст его как копию и применит некоторую магию C между ними, поэтому вы не передаете точно то же самое, что вы думаете. Чтобы быть уверенным в том, что вы делаете, и избежать дополнительной работы ЦП и потребления памяти, лучше передавать массивы и объекты по ссылке (используя указатели). Таким образом, вы можете использовать что-то вроде этого с теми же результатами, что и оригинал:

#include <stdio.h>

void foo(char (*result)[10][7])
{
   // 'total' will be 70 = 10 * 7
   int total = sizeof(*result);

   // 'column' will be 7 = size of first row
   int column = sizeof((*result)[0]);

   // 'row' will be 10 = 70 / 7
   int row = total / column;

   printf("Total fields: %d\n", total);
   printf("Number of rows: %d\n", row);
   printf("Number of columns: %d\n", column);

}

int main(void) {

   char result[10][7] = {

       {'1','X','2','X','2','1','1'},
       {'X','1','1','2','2','1','1'},
       {'X','1','1','2','2','1','1'},
       {'1','X','2','X','2','2','2'},
       {'1','X','1','X','1','X','2'},
       {'1','X','2','X','2','1','1'},
       {'1','X','2','2','1','X','1'},
       {'1','X','2','X','2','1','X'},
       {'1','1','1','X','2','2','1'},
       {'1','X','2','X','2','1','1'}

   };

   foo(&result);

   return 0;
}
person emi    schedule 07.12.2015
comment
Кодовые ответы без объяснений часто очень бесполезны для будущих посетителей. Попробуйте отредактировать свой ответ, чтобы предоставить дополнительную информацию / представление о вашем процессе решения. - person magisch; 07.12.2015
comment
Код для меня самоочевидный, но я вас понимаю. Теперь редактируем ответ. - person emi; 07.12.2015
comment
Просто указываю, что это не работает с массивами, полученными в качестве аргументов функции, в частности, total = sizeof result; не будет работать: будет генерироваться предупреждение и оцениваться размер одного элемента, а не размер всего массива. Таким образом, либо требуется VLA (и вы передаете аргумент строки и столбца), либо вы должны передать либо строку, либо общее количество в качестве аргумента (столбец все еще может быть определен с помощью sizeof). - person AnorZaken; 25.10.2017
comment
Привет @AnorZaken. Если вы передадите переменную как указатель на то, где находятся данные, sizeof на ней вернет размер указателя на переменную, а не размер самой переменной. В этом случае вы можете попытаться выполнить sizeof для данных, на которые указывает указатель, например: total = sizeof(*result); - person emi; 26.10.2017
comment
@emi я имею в виду, что int foo(char result[10][7]) { int total = sizeof(result); } не сработает. В этом случае значение total будет 1. (Конечно, это может показаться глупым вариантом использования, поскольку вы знаете размер, если указали его в объявлении аргумента функции, но все же... это может иметь значение для целей обслуживания кода.) - person AnorZaken; 28.10.2017
comment
@AnorZaken Только что отредактировал ответ, чтобы ответить на ваш конкретный вопрос. - person emi; 28.10.2017

Используйте макросы, показанные в приведенном ниже коде, чтобы получить любой размер одномерных, двухмерных или трехмерных массивов. Подобным образом можно написать больше макросов, чтобы получить размеры для 4D-массивов и выше. (я знаю, что Викерману уже поздно смотреть, но это для всех, кто посещает эту страницу)

// Output of the following program
// [
/*

Demo of the advertised macros :
----------------------------------------------
sizeof(int) = 4
sizeof(Array_1D) = 12
ELEMENTS_IN_1D_ARRAY(Array_1D) = 3
sizeof(Array_2D) = 24
ELEMENTS_IN_2D_ARRAY(Array_2D) = 6
ROWS_IN_2D_ARRAY(Array_2D) = 2
COLUMNS_IN_2D_ARRAY(Array_2D) = 3
sizeof(Array_3D) = 96
ELEMENTS_IN_3D_ARRAY(Array_3D) = 24
MATRICES_IN_3D_ARRAY(Array_3D) = 4
ROWS_IN_3D_ARRAY(Array_3D) = 2
COLUMNS_IN_3D_ARRAY(Array_3D) = 3

Array_3D[][][] Printed :
----------------------------------------------
 001 002 003
 011 012 013
---------------
 101 102 103
 111 112 113
---------------
 201 202 203
 211 212 213
---------------
 301 302 303
 311 312 313
---------------

Wickerman's problem solved :
----------------------------------------------
sizeof(result) = 70
ELEMENTS_IN_2D_ARRAY(result) = 70
ROWS_IN_2D_ARRAY(result) = 10
COLUMNS_IN_2D_ARRAY(result) = 7

*/
// ]

// ====================================================================================================
// Program follows
// ====================================================================================================

// Array Size Macros
// [
#define ELEMENTS_IN_1D_ARRAY(a1D)   ( sizeof( a1D       ) / sizeof( a1D[0]          )) // Total no. of elements in 1D array
#define ELEMENTS_IN_2D_ARRAY(a2D)   ( sizeof( a2D       ) / sizeof( a2D[0][0]       )) // Total no. of elements in 2D array
#define ROWS_IN_2D_ARRAY(a2D)       ( sizeof( a2D       ) / sizeof( a2D[0]          )) // No. of Rows in a 2D array
#define COLUMNS_IN_2D_ARRAY(a2D)    ( sizeof( a2D[0]    ) / sizeof( a2D[0][0]       )) // No. of Columns in a 2D array
#define ELEMENTS_IN_3D_ARRAY(a3D)   ( sizeof( a3D       ) / sizeof( a3D[0][0][0]    )) // Total no. of elements in 3D array
#define MATRICES_IN_3D_ARRAY(a3D)   ( sizeof( a3D       ) / sizeof( a3D[0]          )) // No. of "Matrices" (aka "Slices"/"Pages") in a 3D array
#define ROWS_IN_3D_ARRAY(a3D)       ( sizeof( a3D[0]    ) / sizeof( a3D[0][0]       )) // No. of Rows in each "Matrix" of a 3D array
#define COLUMNS_IN_3D_ARRAY(a3D)    ( sizeof( a3D[0][0] ) / sizeof( a3D[0][0][0]    )) // No. of Columns in each "Matrix" of a 3D array
// ]

#define PRINTF_d(s) (printf(#s " = %d\n", (int)(s)))    // Macro to print a decimal no. along with its corresponding decimal expression string,
                                                        // while avoiding to write the decimal expression twice.

// Demo of the Array Size Macros defined above
// [
main()
{
    // Sample array definitions
    // [
    int Array_1D[3] = {1, 2, 3};    // 1D array

    int Array_2D[2][3] =            // 2D array
    {
        {1,  2,  3},
        {11, 12, 13}
    };

    int Array_3D[4][2][3] =         // 3D Array
    {
        {
            {1,   2,   3},
            {11,  12,  13}
        },
        {
            {101, 102, 103},
            {111, 112, 113}
        },
        {
            {201, 202, 203},
            {211, 212, 213}
        },
        {
            {301, 302, 303},
            {311, 312, 313}
        }
    };
    // ]

    // Printing sizes and dimensions of arrays with the advertised Array Size Macros
    printf(
    "Demo of the advertised macros :\n"
    "----------------------------------------------\n");
    PRINTF_d(sizeof(int));
    PRINTF_d(sizeof(Array_1D));
    PRINTF_d(ELEMENTS_IN_1D_ARRAY(Array_1D));
    PRINTF_d(sizeof(Array_2D));
    PRINTF_d(ELEMENTS_IN_2D_ARRAY(Array_2D));
    PRINTF_d(ROWS_IN_2D_ARRAY(Array_2D));
    PRINTF_d(COLUMNS_IN_2D_ARRAY(Array_2D));
    PRINTF_d(sizeof(Array_3D));
    PRINTF_d(ELEMENTS_IN_3D_ARRAY(Array_3D));
    PRINTF_d(MATRICES_IN_3D_ARRAY(Array_3D));
    PRINTF_d(ROWS_IN_3D_ARRAY(Array_3D));
    PRINTF_d(COLUMNS_IN_3D_ARRAY(Array_3D));

    // Printing all elements in Array_3D using advertised macros
    // [
    int x, y, z;

    printf(
    "\nArray_3D[][][] Printed :\n"
    "----------------------------------------------\n");

    for(x = 0; x < MATRICES_IN_3D_ARRAY(Array_3D); x++)
    {
        for(y = 0; y < ROWS_IN_3D_ARRAY(Array_3D); y++)
        {
            for(z = 0; z < COLUMNS_IN_3D_ARRAY(Array_3D); z++)
                printf("%4.3i", Array_3D[x][y][z]);
            putchar('\n');
        }
        printf("---------------\n");
    }
    // ]

    // Applying those macros to solve the originally stated problem by Wickerman
    // [
    char result[10][7] = {
        {'1','X','2','X','2','1','1'},
        {'X','1','1','2','2','1','1'},
        {'X','1','1','2','2','1','1'},
        {'1','X','2','X','2','2','2'},
        {'1','X','1','X','1','X','2'},
        {'1','X','2','X','2','1','1'},
        {'1','X','2','2','1','X','1'},
        {'1','X','2','X','2','1','X'},
        {'1','1','1','X','2','2','1'},
        {'1','X','2','X','2','1','1'}
    };

    printf(
    "\nWickerman's problem solved :\n"
    "----------------------------------------------\n");
    PRINTF_d(sizeof(result)); // radha_SIZEOF_2D_ARRAY
    PRINTF_d(ELEMENTS_IN_2D_ARRAY(result)); // radha_SIZEOF_2D_ARRAY
    PRINTF_d(ROWS_IN_2D_ARRAY(result));
    PRINTF_d(COLUMNS_IN_2D_ARRAY(result));
    // ]
}
// ]
person ShreeRadheKrishna    schedule 11.03.2019
comment
привет, пожалуйста, добавьте пояснение к вашему ответу, чтобы сделать его более надежным - person MehrdadEP; 11.03.2019
comment
@MehrdadEP Думал, что код очевиден, поэтому не добавлял никаких объяснений. Добавлены комментарии и вывод сейчас. Надеюсь, это поможет. - person ShreeRadheKrishna; 14.03.2019