«Направление» двумерных массивов в C - PullRequest
2 голосов
/ 01 мая 2009

как новичок в C Я немного озадачен двумерными массивами.

Если я хочу представить матрицу из 3 строк и 5 столбцов, я думаю, правильное объявление:

char a[3][5];

Итак, это массив из 3 указателей на 5 массивов символов или как?

Почему каждый раз, когда я пытаюсь просмотреть его, как показано ниже, кажется, что он читает неправильные результаты?

int x, y;
for( x=0; x<3; x++ ){
    for( y=0; y<3; y++ ){
        printf( "%c", a[x][y] );
    }
}

Существуют ли следующие эквивалентные и правильные способы его инициализации?

char a[3][5] = {
               {1,0,0,0,1},
               {1,0,0,0,1},
               {1,0,0,0,1},
               };

char a[3][5] = {1,0,0,0,1,
                1,0,0,0,1,
                1,0,0,0,1};

Спасибо за любое возможное предстоящее объяснение.


EDIT

Извините за опечатки, код не скопирован. Кстати, я продолжаю читать их так, как будто они читаются по вертикали, а не по горизонтали.

Также в примере из этого урока http://www.cplusplus.com/doc/tutorial/arrays/ он считывает массив не так прямолинейно, как мне кажется, работает на 5x3, Высота Ширина, у x, столбцы структура строк вместо 3x5, ширина высота, x y. строки столбцы один:

#define WIDTH 5
#define HEIGHT 3

int jimmy [HEIGHT][WIDTH];
int n,m;

int main ()
{
  for (n=0;n<HEIGHT;n++)
    for (m=0;m<WIDTH;m++)
    {
      jimmy[n][m]=(n+1)*(m+1);
    }
  return 0;
}

Ответы [ 8 ]

4 голосов
/ 02 мая 2009

Только для того, что это такое, а что нет.

char a[3][5];

Указатели не задействованы. Подобный многомерный массив представляет собой массив массивов .... и так далее. В вашем случае у вас есть массив из 3 массивов по 5 символов. Это становится понятнее, когда вы делаете это с typedefs.

typedef char T[5];
T a[3];

Никаких указателей не задействовано. Если вы хотите получить доступ к первому массиву из этих трех, вы можете сделать это:

a[0]; 

И он вернет вам объект типа char[5]. Обычно вы этого не замечаете, потому что обычно индексируете все измерения. Таким образом, массив, который возвращается a[0], является индексом следующего индекса, например a[0][1]. [1] будет применен к массиву, который был возвращен a[0], который, как мы выяснили ранее, имеет тип char[5].

Итак, это массив из 3 указателей на 5 массивов символов или как?

Давайте создадим этот тип и посмотрим, чем он отличается от описанного выше. Создать его просто, как только вы получите основные деклараторы:

  • Создание указателя: *D
  • Создание массива: D[N]

D - просто существующий другой декларатор. Итак, теперь давайте продолжим. Сначала вы говорите array of 3 pointers to 5 arrays of chars.... Я думаю, что вы имели в виду array of 3 pointers to arrays of 5 chars. Во-первых, array of 5 создается как

D1[5]

Теперь давайте заменим D1 на pointer to декларатор:

(*D2)[5]

Нам пришлось вставить круглые скобки, потому что оператор индекса [N] связывается лучше, чем оператор разыменования *, и в противном случае он читался бы как *(D2[5]), что нам не нужно. Теперь у нас есть pointer to array of 5.

Теперь давайте сделаем array of 3. Замена D2 на D3[3] дает это:

(*D3[3])[5]

Отлично, теперь у нас есть array of 3 pointer to array of 5. Простое помещение базового типа, к которому относится этот декларатор, приводит к полному объявлению:

char (*D3[3])[5];

Это, конечно, совсем другое дело :) Вы можете использовать его для хранения указателей на другой массив, который был типа array of 3 arrays of 5 char. Давайте сохраним указатель на первый подмассив a в D3[0]. Ранее мы выяснили, что a[0] имеет тип char[5]. Мы можем сохранить указатель на этот массив в D3[0], потому что D3 - это массив указателей на char[5], какое совпадение!

D3[0] = &a[0]; // works!

Я надеюсь, что это небольшое упражнение показало вам некоторые отношения между указателями и массивами. Ура!

2 голосов
/ 01 мая 2009

Я вижу пару проблем с вашим кодом. Первый (скопировано сверху):

int x, y;
for( x=0; x<3; x++ ){
    for( x=0; x<3; x++ ){
        printf( a[x][y] );
    }
}

В вашем внутреннем цикле похоже, что вы хотите использовать y вместо x, и вы хотите y перейти от 0..5 В настоящее время вы повторяете переменную х. Кроме того, у вас проблема с оператором printf (). Вот исправленный код:

int x, y;
for( x=0; x<3; x++ ){
    for( y=0; y<5; y++ ){
        printf("%d\n", a[x][y] );
    }
}

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

char a[3][5] = {
               {1,0,0,0,1},
               {1,0,0,0,1},
               {1,0,0,0,1}
               };

(я удалил , после самой последней «строки» данных - это была синтаксическая ошибка.)

2-й синтаксис, который вы опубликовали, неверен (тот, у которого нет фигурных скобок).

2 голосов
/ 01 мая 2009

Вы получили неправильные результаты, потому что вы используете x дважды (похоже на ошибку копирования / вставки). Попробуйте

int x, y;
for (x = 0; x < 3; x++) {
    for (y = 0; y < 5; y++) {
        printf("%c", a[x][y]); // Emil H says "%d" might be more useful
    }
}

Редактировать: Я не уверен, что смущает этот учебник. Он точно эквивалентен вашему коду, за исключением того, что вместо печати массива он устанавливает для каждого элемента значение (строка * столбец) (где строка и столбец основаны на одной единице, следовательно, + 1).

1 голос
/ 02 мая 2009

Небольшие ошибки, такие как использование «% c», когда вы, вероятно, хотите «% d», и это не то, что вы действительно хотите получить, я смиренно думаю. Вы говорите, что немного запутались в массивах, а также упоминаете, что ожидаете увидеть указатели в качестве элементов массива массива, содержащего массивы. Вы

Последняя запятая в вашем определении массива массивов НЕ является синтаксической ошибкой. Это разрешено с C99.

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

Вы спрашиваете о том, что символ «а» в вашей программе на самом деле. Это массив массивов. Структура памяти может быть визуализирована как длинная линия, разрезанная на три части, но все еще на непрерывной линии. Затем разрезайте каждый из них на пять частей таким же образом. При обращении к одному элементу вы должны использовать два индекса; сначала для какого пятиэлементного массива вы хотите, а затем для какого пятого этого элемента вы хотите.

Макет памяти не похож на сетку строк и столбцов. Память адресуется одним скаляром, поэтому она линейная. Арифметика указателя может быть следующей вещью, на которую вы могли бы взглянуть, и посмотреть, как работает приращение указателя.

1 голос
/ 02 мая 2009

Изображение в учебном пособии - отличное представление данных: альтернативный текст http://www.cplusplus.com/doc/tutorial/arrays/bidimensional_arrays3.gif

В этом примере вложенный цикл for пересекает (влево -> вправо) массив за строкой и заполняет значение для каждого столбца.

1 голос
/ 01 мая 2009
int x, y;
for( x=0; x<3; x++ ){
    for( x=0; x<3; x++ ){
        printf( a[x][y] );
    }
}

Вам нужно изменить второй цикл for, чтобы он ссылался на «y» вместо «x».

надеюсь, что это поможет.

0 голосов
/ 02 мая 2009

char a [3] [5];

Итак, это массив из 3 указателей на 5 массивов символов или как?

Да, вот что это. Хотя вы также можете манипулировать им как последовательный набор из 15 символов.

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

У конкретной библиотеки для выполнения матричных манипуляций есть соглашение для этого.

0 голосов
/ 01 мая 2009

Вы используете printf неправильно. Попробуйте:

printf("%d", a[x][y]);

Я не уверен, что вы захотите использовать% c или% d. Если вы хотите напечатать номер, используйте% d. Если вы хотите напечатать фактический символ, используйте% c.

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