Руководство полного чайника по программированию на языке Си

       

МАССИВЫ


Массив - это несколько пронумерованных переменных, объединенных общим именем. Все переменные имеют ОДИН И ТОТ ЖЕ ТИП.

Рассмотрим ПОЛКУ с 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 - может.


Содержание раздела