Массивы и строки
На прошлой неделе одна переменная хранила одно значение. Теперь научимся хранить несколько значений под одним именем — то есть массивы. Затем рассмотрим строки: в C строка на самом деле массив из символов. Каждую идею мы шаг за шагом разберём в живом визуализаторе массивов и отладчике кода в стиле IDE.
Что вы узнаете на этом уроке
4.1 Что такое массив?
Представьте, что вам нужно сохранить оценки 5 учеников одного класса. Со знаниями прошлой недели вы написали бы пять отдельных переменных: ball1, ball2, ball3 и так далее. Для 5 это ещё терпимо, но что, если учеников 30 или 100?
Именно эту задачу решает массив (array). Под массивом понимается хранение нескольких значений одного типа под одним именем. Пять оценок теперь стоят рядом под одним именем ballar:
В одной строке сохранены пять оценок. Все они находятся в одном месте, упорядоченно, и мы можем легко пройти по ним циклом. У массива есть два основных свойства:
- Все элементы одного типа, например все
int - Количество элементов задаётся заранее и потом не меняется, здесь их 5
4.2 Создание и индекс
При создании массива в квадратных скобках мы пишем, сколько в нём элементов, а в фигурных скобках — сами значения. Теперь самая важная идея: у каждого элемента есть свой индекс (номер), и счёт начинается не с 1, а с 0.
Значит, в массиве из 5 элементов индексы будут 0, 1, 2, 3, 4. Первый элемент — ballar[0], а последний — ballar[4]. Нажмите на ячейку ниже:
ballar[5], вы выйдете за границы массива, а это считается серьёзной ошибкой.4.3 Чтение и изменение
С помощью индекса мы можем по отдельности читать или изменять каждую ячейку. Чтобы прочитать, мы просто пишем индекс, а чтобы изменить — присваиваем ему новое значение:
Ниже выберите индекс, введите новое значение и нажмите кнопку Установить. Изменится только выбранная ячейка:
4.4 Цикл по массиву
Настоящая сила массива раскрывается вместе с циклом. Вместо того чтобы писать каждый элемент вручную, мы циклом for проводим индекс от 0 до конца и обращаемся к каждой ячейке по очереди. Программа ниже складывает все оценки и выводит сумму.
Пройдите её по шагам: жёлтая строка показывает текущую строку кода, а зелёная ячейка — элемент, читаемый на этом шаге.
Сумма получилась 428. Чтобы найти среднее, делим её на количество элементов: 428 / 5. По тому же шаблону мы можем посчитать и наибольшее, и наименьшее, и сколько из них прошло.
Сделайте прогноз
Что эта программа выведет в терминал?
4.5 Строки (string)
Теперь переходим к буквам. На прошлой неделе мы видели, что тип char хранит одну букву. Но слово, имя или предложение состоят из множества букв. Чтобы хранить их, мы используем строку (string).
Самая важная идея вот в чём: в C строка на самом деле массив из char. То есть строка такая же, как массив, только внутри неё не числа, а буквы. У каждой буквы есть свой индекс, и счёт снова начинается с 0:
Введите слово и посмотрите, на каком индексе стоит каждая его буква:
4.6 Нулевой терминатор (\0)
Здесь есть тонкое, но очень важное правило C. Как компьютер узнаёт, где строка в памяти заканчивается? Для этого C ставит в конец каждой строки невидимый особый символ: нулевой терминатор, то есть \0. Он означает «строка заканчивается здесь».
Значит, хотя "Ali" — три буквы, в памяти оно занимает четыре ячейки: A, l, i и в конце \0. Введите слово ниже и обратите внимание на ячейку \0 в конце:
\0. Если же вы пишете в кавычках "Ali", C делает это автоматически.4.7 strlen: длина строки
Часто нам нужно знать, из скольких букв состоит строка. Мы не считаем это вручную — есть готовая функция: strlen (string length, то есть длина строки). Она идёт от начала строки, считает буквы и останавливается, дойдя до \0.
Эта функция находится в библиотеке string.h, поэтому в начале программы нужно написать #include <string.h>. Введите слово ниже и нажмите кнопку Посчитать, понаблюдайте, как strlen считает:
\0. Поэтому результат strlen("Ali") равен 3, хотя в памяти 4 ячейки.4.8 Перебор символов
Поскольку строка — это массив, по ней тоже можно пройти циклом. Но здесь есть красивый приём: нам необязательно знать длину заранее, мы просто идём, пока не дойдём до \0. Условие цикла как раз это и проверяет: ism[i] != '\0'.
Например, превратим каждую строчную букву в заглавную. В таблице ASCII строчная 'a' имеет код 97, а заглавная 'A' — 65, то есть разница между ними равна 32. Значит, если вычесть из строчной буквы 32, получится заглавная. Нажмите кнопку Выполнить:
4.9 Практика: поиск наибольшего элемента
Это одна из самых частых задач при работе с массивами, и она станет мостом к алгоритмам, которые мы изучим на следующей неделе. Идея проста: первый элемент мы временно берём за «наибольший», затем по очереди смотрим остальные, и если находим больший, обновляем «наибольший».
Ниже зелёная ячейка показывает текущий наибольший, а синяя ячейка — проверяемый элемент. Идите с помощью кнопки Следующий шаг:
4.10 Глубже advanced
Вы освоили основы массивов и строк. Теперь кратко взглянем ещё на два расширения: изучать их полностью сейчас необязательно, достаточно общего представления.
Двумерный массив (матрица)
Массив мы представляли как ряд. Если ячейки располагаются не только по строке, но и по столбцу, получается двумерный массив: это таблица или матрица. Например, так устроены шахматная доска или лист Excel.
Теперь элемент берётся по двум индексам: jadval[строка][столбец]. Выше jadval[1][2] даёт значение в строке 1, столбце 2, то есть 6.
Массив строк
Подобно тому как строка — это массив из char, несколько строк тоже можно собрать в один массив. Это удобно, например, для хранения дней недели или списка имён:
* выше означает pointer, то есть указатель. Он работает с адресом в памяти, и мы отдельно и глубоко изучим его на следующих неделях. Пока достаточно понимать это как «в каждой ячейке стоит одна строка».Словарь терминов
4.11 Тест знаний
16 вопросов. Чтобы завершить неделю, ответьте правильно как минимум на 11 из них.
Поздравляем! Неделя 4 завершена
Теперь вы умеете работать с массивами и строками: хранить много значений, обращаться по индексу, проходить циклом, нулевой терминатор и strlen. Это основа почти каждой программы, которая работает с данными.
Следующая неделя: Алгоритмы (линейный и двоичный поиск, сортировка, эффективность Big-O).
Перейти к следующему модулю