--- title: Arrays localeTitle: Массивы --- # Массивы в C ## Проблемы Прежде чем пытаться объяснить, какие массивы, давайте посмотрим на код, где мы хотим напечатать 10 номеров, заданных пользователем в обратном порядке. ```C #include int main(void) { int a, b, c, d, e, f, g, i, j, k; scanf("%d", &a); scanf("%d", &b); ... printf("%d", k); printf("%d", j); printf("%d", i); ... //and so on.. return 0; } ``` Итак, это выглядит немного утомительно. До сих пор каждая созданная переменная имела особую роль. Но сейчас было бы здорово, если бы мы могли просто сохранить несколько значений в одном месте и получить доступ к значениям со своим местом в строке (первое значение, второе и т. Д.). Другой способ взглянуть на это - предположим, что вы хотите сохранить набор имен, вам не нужно создавать разные переменные для каждого имени, вместо этого вы можете создать массив имен, где каждое имя имеет свой уникальный идентификатор или _индекс_ . Кроме того, мы могли бы использовать на них циклы, о которых вы узнаете позже, но в основном они делают одно и то же снова и снова. например. чтение от пользователя или печать значений. ## Массивы в C Массивы представляют собой контейнеры с заданным размером. Они содержат переменные того **же типа** . Вы можете получить доступ к переменной, хранящейся в массиве, с _индексом_ . Давайте посмотрим на некоторый код: ```C #include int main(void) { int arr[4] = {1, 2, 3, 88}; int brr[] = {78, 65}; int crr[100] = {3}; int var = arr[0]; return 0; } ``` А теперь немного сломаем синтаксис: ```C int arr[4] = {1, 2, 3, 88}; ``` Здесь вы создали `array` `ints` (целые), называемый `arr` . Этот массив имеет 4 элемента: `1` , `2` , `3` , `88` . Обратите внимание на синтаксис! ```C datatype name[number of elements] ``` Первый элемент этого массива равен `1` , второй - `2` и т. Д. ```C int brr[] = {78, 65}; ``` Вам не нужно заранее указывать размер. Здесь будет создан массив из двух элементов с фигурными скобками. ```C int crr[100] = {3}; ``` Если вы это сделаете, то первый элемент будет равен `3` , но остальные будут равны `0` . ```C int var = arr[0]; ``` Здесь создается int, называемый `var` , и инициализируется 0-м элементом arr. **Очень важно помнить,** что в C индексы начинаются с нуля в противоположность 1. Это означает, что для доступа к первому элементу индекс (между скобками) равен 0, чтобы получить доступ ко второму элементу, индекс равен 1 и т. Д. В этом примере `var` будет хранить значение `1` . ## обзор * Одномерный массив подобен списку; Двумерный массив похож на таблицу; Язык C не ограничивает количество измерений в массиве, хотя могут быть конкретные реализации. * Некоторые тексты относятся к одномерным массивам в виде векторов, двумерных массивов в качестве матриц и используют общие терминальные массивы, когда количество измерений является неопределенным или несущественным. ## Многомерные массивы в C C также поддерживает многомерные массивы. ```C datatype name[size1][size2]...[sizeN] ``` Двумерные массивы являются общими и могут быть инициализированы с использованием следующего синтаксиса. Логически можно считать первый индекс в виде строк, а второй - столбцами. Этот пример имеет 2 строки и 5 столбцов. ```C int arr[2][5] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; ``` Трудно представить двумерный массив с использованием вышеупомянутого синтаксиса, поэтому разработчики часто используют необязательные вложенные скобки для уточнения структуры массива. Это также допустимый способ инициализации двумерного массива. ```C int arr[2][5] = { {0, 1, 2, 3, 4}, {5, 6, 7, 8, 9} }; ``` Два вложенных цикла могут использоваться для печати содержимого двумерного массива в табличном формате. ```C #include int main() { const int rows = 2, cols = 5; int arr[rows][cols] = { {0, 1, 2, 3, 4}, {5, 6, 7, 8, 9} }; for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { printf("%5d", arr[row][col]); } puts(""); } return 0; } ``` ```C 0 1 2 3 4 5 6 7 8 9 ``` ## Струны Чтобы хранить строки / несколько символов, мы используем `char arrays` в C, потому что язык не имеет встроенного специального типа. Одна вещь, о которой нужно знать, заключается в том, что завершающий нуль автоматически добавляется в конец, сигнализируя, что это конец строка. Однако вы можете также инициализировать строку с фигурными фигурными скобками `{}` , но вам нужно вручную добавить завершающий нуль. Вот так: ```C char string[6] = "Hello"; //here you get Hello\0, which is why we need an array with the length of 6 ``` Как и в массивах int в приведенном выше примере, существует несколько способов присвоения значений массивам char: ```C char string[] = "I do not want to count the chars in this."; char string2[] = {'C','h','a','r',' ','b','y',' ','c','h','a','r','\0'}; char string3[] = "This is a string" "with two lines"; ``` Эквивалентный вышеприведенному подходу, вы также можете создать указатель на массив символов: ```C char* string = "I do not want to count the chars in this."; ``` ## Типичные ошибки, советы * Когда у вас есть массив, заполненный значениями, и вы хотите создать другой массив, который точно такой же, как первый, никогда не делайте этого: ```C double first[] = {2,3,7}; double second[] = first; //Or this: double a[5], b[5] a = b; ``` Вы можете обрабатывать **только** значения в массиве один за другим. Вы **не можете назначить все сразу** , когда узнаете о указателях позже, причины будут ясными. > (В принципе, первый элемент массива указывает на адрес памяти, а элементы после этого - «дома» рядом с первым. Так что технически массив - это только адрес памяти первого элемента. Когда вы хотите назначить второй массив первого массива, вы запускаете ошибку из-за разных типов или пытаетесь изменить второй адрес памяти первого элемента во втором массиве.) * Когда вы хотите создать массив, вам нужно либо указать его размер, либо присвоить ему значения. Не делайте этого: ```C int arr[]; ``` Компьютер должен знать, как большой размер хранилища для массива. Позже вы узнаете о способах создания контейнеров, размер которых определяется позже. (Опять же, указатели.) * Когда вы индексируете массив, компилятор не всегда даст вам ошибку. Это называется неопределенным поведением, мы просто не знаем, что произойдет. Это может привести к сбою вашей программы, просто замедлению, чем угодно. ```C int test[6]; int a = test[-2]; int b = test[89]; ``` Причина того, что C не проверяет привязку индексации, проста: C - эффективный язык. Это было сделано, поэтому ваша программа самая быстрая: хорошо общается с оборудованием и т. Д. Хорошо написанный код C не содержит ошибок индексирования, поэтому почему C хочет проверить во время работы? * Когда вы пытаетесь получить доступ к последнему элементу массива. Предположим, что длина массива A равна 4 и при обращении к последнему элементу как A \[4\] вернет ошибку, так как индексирование начинается с 0.