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.
|