Массивы
Как известно, массив - это конечная совокупность данных одного типа. Можно говорить о массивах целых чисел, массивов символов и.т.д. Мы можем даже определить масссив, элементы которого - массивы( массив массивов), определяя, таким образм, многомерные массивы. Любой массив в программе должен быть описан: после имени массива добаляют квадратные скобки [], внутри которых обычно стоит число, показывающее количество элементов массива. Например, запись int x[10]; определяет x как массив из 10 целых чисел. В случае многомерных массивов показывают столько пар скобок , какова размерность массива, а число внутри скобок показывает размер массива по данному измерению. Например, описание двумерного массива выглядит так: int a[2][5];. Такое описание можно трактовать как матрицу из 2 строк и 5 столбцов. Для обрщения к некоторому элементу массива указывают его имя и индекс, заключенный в квадратные скобки(для многомерног массива - несколько индексов , заключенные в отдельные квадратные скобки): a[1][3], x[i] a[0][k+2]. Индексы массива в Си всегда начинаются с 0, а не с 1, т.е. описание int x[5]; порождает элементы x[0], x[1], x[2], x[3], x[4], x[5]. Индекс может быть не только целой константой или целой переменной, но и любым выражением целого типа. Переменная с индексами в программе используется наравне с простой переменной (например, в операторе присваивания, в функциях ввода- вывода). Начальные значения массивам в языке Си могут быть присвоены при компиляции только в том случае, если они объявлены с классом памяти extern или static, например:
static int a[6]={5,0,4,-17,49,1};
обеспечивает присвоения a[0]=5; a[1]=0; a[2]=4 ... a[5]=1. Как видите, для начального присвоения значений некоторому массиву надо в описании поместить справа от знака = список инициирующих значений, заключенные в фигурные скобки и разделенные запятыми. Двумерный массив можно инициировать так:
static int matr[2][5] = {{3,4,0,1,2},{6,5,1,4,9}};
Матрица хранится в памяти построчно, т.е. самый правый индекс в наборе индексов массива меняется наиболее быстро.
Пусть, например, в заданном массиве из 10 целых чисел надо изменить порядок следования его элементов на обратный без привлечения вспомагательного массива. Соответствующая прорамма приведена ниже:
- /*обращение массива*/
- #include <stdio.h>
- main()
- {
- int p,i=0;
- static a[10]={10,11,12,13,14,
- 15,16,17,18,19};
- while(i<10/2)
- {
- p=a[i];
- a[i]=a[9-i];
- a[9-i]=p;
- i++;
- }
- i=0;
- while(i<10) printf(" %d",a[i++]);
- }
Следующяя программа позволяет в целочисленном массиве найти разность максимального и минимального элемента. Обратите внимание, что функция fmax при первом обращении к ней дает максимальный элемент массива, а при повторном вызове - минимальный, так как предварительно мы изменили знаки элементов на противоположные. Это изменение знаков учитывается при вызове функции printf. В языке Си отсутствует возможность динамически распределять память под массивы: надо при описании массива задать точно его размер. Но если тот же массив описывается еще раз в другой программе, размеры можно не указывать;достаточно после имени сохранить пару квадратных скобок, например int x[]. Если при вызове функции в качестве аргумента ей передается имя массива, то, в отличае от простых переменных, берется фактически адрес начала этого массива. Поэтому записи fmax(a, 10) и fmax(&a[0], 10) равносильны.
- /*в массиве найти разность мин. и макс. элементов */
- int fmax(x,n)
- int x[],n;
- {
- int max, i=0; max=x[0];
- while(i
{ - if(x[i]> max)
- max=x[i];
- i++;
- }
- return(max);
- }
- #include <stdio.h>
- main()
- {
- static int a[10]=
- {1,-2,3,-4,5,-6,7,-8,9,-13};
- max=fmax(a,10);
- i=0;
- while(i<10)
- {
- a[i]=-a[i];
- i++;
- }
- main=fmax(a,10);
- printf("макс-мин=%d\n",max+min);
- }
В следующем примере массив описан как внешний. Функция main подсчитывает наибольшее число одинаковых идущих подряд элементов массива, определенного вне функции main.
- /*макс одинаковых подряд*/
- #include <stdio.h>
- int a[]={5,6,6,6,4,3,3,3,3,3,8};
- int n=10;
- main()
- {
- int i,k,max;
- i=k=max=1;
- while(i
{ - if(a[i]==a[i-1]) k++;
- else
- {
- if(k>max)max=k;
- k=1;
- }
- i++;
- }
- printf("kmax=%d\n",(k>max)?k:max);
- }
Если, как в данном примере, размер массива пропущен, то транслятор определит его дляну, считая присваиваемые значения во время начальной инициализации. Условная операция (k>max)?k:max в операторе printf предусмотрена для того частного случая, когда весь массив состоит из одинаковых элементов. Приведем несколько примеров, в которых ведется обработка двумерных массивов. Но прежде одну полезную возможносить языка Си. Речь идет о препроцессорном утверждении #difine, позволяющем присваивать символические имена константам. В общем случае это утверждение записывают так: #define строка1 строка2 (точка с запятой не ставится).
Прежде чем исходный текст программы будет передан компилятору, он обрабатывается препроцессором, котоый всюду в исходном тексте заменит вхождение "строка1" на "строка2". Например, строка #difine max 80, записанная в начале программы, обеспечит всюду замену указанного имени max на соответствующую константу. Замена имени связана не только числами, но и текстами. А теперь вернемся к примерам. В следующей программе (пример 3.9) строится единичная матрица a[m][m], размер которой определяется с помощью конструкции #difine m 5. Сам алгоритм вычисления элементов матрицы основан на возведении (i/j)*(j/i) равно единице тогда и только тогда. когда i равно j. В остальных случаях оно равно нулю.
- #define M 5
- #include <stdio.h>
- main()
- {
- int a[M][M];
- int j,i=0;
- while(i
{ - j=1;
- while(j
{ - a[i][j]=(i/j)*(j/i);
- printf("%d",a[i][j]);
- j++;
- }
- i++;printf("\n");
- }
- }
В последней программе этого раздела определяется минимальный элемент каждой строки матрицы и выполняется обмен местами найденого и диагональю этой же строки.
- /*обмен мин с диагональю*/
- #include <stdio.h>
- #define M 4
- main()
- {
- static a[M][M]={
- { 3,4,1,5),
- {-1,6,7,0},
- { 1,8,7,-1},
- { 4,9,7,-1}};
- int i, j, jmin, amin;
- i=0;
- while(i
{ - amin=a[i][0];
- jmin=0;j=1;
- while(j
{ - if(a[i][j]
{ - amin=a[i][j];
- jmin=j;
- }
- j++;
- }
- a[i][jmin]=a[i][i];
- a[i][i]=amin;
- i++;
- if(a[i][j]
- }
- i=0
- while(i
{ - j=0;
- while(j
printf("%3d",a[i][j++]); - printf("\n");
- i++;
- }
- static a[M][M]={
- }
Обращаем внимание на следующее обстоятельство. Если двумерный массив надо передать функции, то описание параметра в ней должно обязательно включать в себя размер строки массива, а размер столбцов несущественен. Так, массив из трех строк и пяти столбцов можно описать как int a[3][5]; либо int a[][5]; .