МАССИВЫ
Массив - это несколько пронумерованных переменных, объединенных общим именем. Все переменные имеют ОДИН И ТОТ ЖЕ ТИП.
Рассмотрим ПОЛКУ с N ящиками, пусть имя полки - var. Тогда кажждый ящик-ячейка имеет имя var[0] var[1] ... var[N-1]
Нумерация идет с НУЛЯ.
-------- / var / / / ------------------------------------------- ------------------ | | | | | | | | | | .... ... | | | | | | | | ------------------------------------------- ------------------ / var[0] / / var[1] / / var[2] / / var[N-1] / --------- --------- --------- -----------
Массив объявляется так:
int var[N];
здесь N - его размер, число ячеек.
Это описание как бы объявляет N переменных типа int с именами var[0] ... var[N-1];
В операторах для обращения к n-ому ящичку (где 0 <= n < N) используется имя ящика
var[n]
где n - целое значение (или значение целой переменной, или целочисленного выражения), "индекс в массиве". Эта операция [] называется "индексация массива". Индексация - есть ВЫБОР одного из N ящиков при помощи указания целого номера. var - массив (N ячеек) n - выражение (формула), выдающая целое значение в интервале 0..N-1 var[n] - взят один из элементов массива. Один из всех. n - номер ящика - называется еще и "индексом" этой переменной в массиве.
Пример:
int var[5]; /* 1 */
var[0] = 2; /* 2 */ var[1] = 3 + var[0]; /* 3 */ var[2] = var[0] * var[1]; /* 4 */ var[3] = (var[0] + 4) * var[1]; /* 5 */
printf("var третье есть %d\n", var[3]);
В ходе этой программы элементы массива меняются таким образом:
var[0] var[1] var[2] var[3] var[4] ------------------------------------------------ /* 1 */ мусор мусор мусор мусор мусор /* 2 */ 2 мусор мусор мусор мусор /* 3 */ 2 5 мусор мусор мусор /* 4 */ 2 5 10 мусор мусор /* 5 */ 2 5 10 30 мусор
Как видим, каждый оператор изменяет лишь ОДНУ ячейку массива за раз.
Массив - набор переменных, которые не ИМЕНОВАНЫ разными именами, вроде var0, var1, var2, ... а ПРОНУМЕРОВАНЫ под одним именем: var[0], var[1], var[2], ...
Индекс - часть ИМЕНИ ПЕРЕМЕННОЙ.
На самом деле индексация - это 1) выбор элемента в массиве 2) справа от присваиваний и в выражениях - еще и разыменование, то есть взятие вместо имени переменной - значения, в ней хранящегося.
Если в переменную не было занесено значение, а мы используем эту переменную, то в ней лежит МУСОР (любое, непредсказуемое значение).
printf("var4 есть %d\n", var[4]);
напечатает все что угодно.
Поэтому переменные надо всегда инициализировать (давать им начальное значение).
Глобальные переменные автоматически инициализируются нулем, если мы не задали иначе.
Локальные переменные не инициализируются автоматически, и содержат МУСОР.
Массивы НЕЛЬЗЯ присваивать целиком, язык Си этого не умеет.
int a[5]; int b[5];
a = b; /* ошибка */
Также нельзя присвоить значение сразу всем элементам (ячейкам) массива:
a = 0; /* ошибка */
не делает того, что нами ожидалось, а является ошибкой. Для обнуления всех ячеек следует использовать цикл:
int i;
for(i=0; i < 5; i++) /* для каждого i присвоить a[i] = 0; */ a[i] = 0;
СВЯЗЬ МАССИВОВ И ЦИКЛОВ ======================= Вследствие этого массивы приходится копировать (и инициализировать) поэлементно, в цикле перебирая все (или часть) ячейки массива.
int i;
for(i=0; i < 5; i++) a[i] = b[i];
В данном случае индекс цикла служит также и индексом в массиве.
Индексы в массиве идут с НУЛЯ.
Пример инициализации:
int index, array[5];
for(index=0; index < 5; index++) array[index] = index * 2 + 1;
или
int index, array[5];
index = 0; while(index < 5){ array[index] = index * 2 + 1; index++; }
/* В массиве будет: { 1, 3, 5, 7, 9 } */
ИНДЕКС для массивов - номер "ящика/ячейки" в массиве.
для циклов - номер повторения цикла, счетчик. Мы должны изменять его САМИ.
Обычно массивы и циклы совмещаются так: индекс цикла есть индекс в массиве; то есть индекс цикла используется для перебора всех элементов массива:
int a[N], i;
for(i=0; i < N; i++) ...a[i]...
Примеры:
int a[5];
a[0] = 17; a[0] += 4; a[0]++;
Пример: числа Фибоначчи. Задаются математическими формулами:
f[1] = 1 f[2] = 1 f[n+2] = f[n+1] + f[n]
Вот программа:
#include
/* магическая строка */ #define N 20 /* сколько первых чисел посчитать */
void main(){ int fibs[N], index;
fibs[0] = 1; /* индексы отсчитываются с нуля!!! */ fibs[1] = 1;
/* Тут показано, что индекс элемента массива может вычисляться */
for(index=2; index < N; index++) fibs[index] = fibs[index-1] + fibs[index-2];
/* Распечатка в обратном порядке */ for(index = N-1; index >= 0; index--) printf("%d-ое число Фибоначчи есть %d\n", index+1, fibs[index]); }
Здесь мы видим новый для нас оператор #define Он задает текстуальную ЗАМЕНУ слова N на слово 20, в данном случае просто являясь эквивалентом
const int N = 20;
К несчастью размер массива не может быть задан при помощи переменной, а вот при помощи имени, определенного в #define - может.