197 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			197 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ---
 | ||
| title: Arrays
 | ||
| localeTitle: Массивы
 | ||
| ---
 | ||
| # Массивы в C
 | ||
| 
 | ||
| ## Проблемы
 | ||
| 
 | ||
| Прежде чем пытаться объяснить, какие массивы, давайте посмотрим на код, где мы хотим напечатать 10 номеров, заданных пользователем в обратном порядке.
 | ||
| 
 | ||
| ```C
 | ||
| #include <stdio.h> 
 | ||
|  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 <stdio.h> 
 | ||
|  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 <stdio.h> 
 | ||
|  
 | ||
|  
 | ||
|  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. |