Язык Си - руководство для начинающих
Шрифт:
zippo[0] == &zippo[0][0]
zippo[1] == &zjppo[1][0]
zippo[2] == &zippo[2][0]
zippo[3] == &zippo[3][0]
Это свойство является более, чем новшеством. Оно позволяет использовать функцию, предназначенную для одномерного массива, для работы с двумерным массивом! Вот доказательство (хотя мы надеемся, что теперь вы бы поверили нам и так) использования двумерного массива в нашей программе нахождения среднего значения:
/*
main
{
static int junk[3][4] = {
{2, 4, 6, 8},
{100, 200, 300, 400},
{10, 40, 60, 90} };
int row;
for(row = 0; row < 3; row ++)
printf(" Среднее строки %d равно %d.\n", row, mean(junk[row],4));
/* junk [row] - одномерный массив ИЗ четырех элементов */
}
/* находит среднее в одномерном массиве */
int mean(array,n)
int array[ ], n;
{
int index;
long sum;
if(n > 0) {
for(index = 0, sum = 0; index < n; index++)
sum += (long)array[index];
return((int)(sum/n)); }
else {
printf(" Нет массива. \n");
return(0); }
}
Результат работы программы:
Cреднее строки 0 равно 5.
Cреднее строки 1 равно 250.
Cреднее строки 2 равно 50.
Функции и многомерные массивы
Предположим, что вы хотите иметь функцию, работающую с двумерным массивом, причем со всем целиком, а не с частями. Как вы запишите определения функции и ее описания? Подойдем к этому более конкретно и скажем, что нам нужна функция, управляющая массивом junk[ ][ ] в нашем последнем примере. Пусть функция main выглядит так:
/* junk в main */
main
{
static int junk[3][4] = {
{2, 4, 5, 8},
{100, 200, 300, 400}
{10, 40, 60, 90} };
stuff(junk);
}
Функция stuff использует в качестве аргумента junk,
являющийся указателем на весь массив. Как написать заголовок функции, не зная, что делает stuff?Попробуем написать:
stuff(junk) int junk[ ];
или
stuff(junk) int junk[ ][ ];
Нет и нет. Первые два оператора еще будут работать некоторым образом, но они рассматривают junk как одномерный массив, состоящий из 12 элементов. Информация о расчленении массива на строки отсутствует.
Вторая попытка ошибочна, потому что хотя оператор и указывает что junk является двумерным массивом, но нигде не говорится, из чего он состоит. Из шести строк и двух столбцов? Из двух строк и шести столбцов? Или из чего-нибудь еще? Компилятору недостаточно этой информации. Ее дают следующие операторы:
stuff(junk)
int junk[ ][4];
Они сообщают компилятору, что массив следует разбить на строки по четыре столбца. Массивы символьных строк являются особым случаем, так как у них нулевой символ в каждой строке сообщает компилятору о конце строки. Это разрешает описания, подобные следующему:
char *list[ ];
Символьные строки представляют одно из наиболее частых применений массивов и указателей; мы вернемся к этой теме в гл. 13.
ЧТО ВЫ ДОЛЖНЫ БЫЛИ УЗНАТЬ В ЭТОЙ ГЛАВЕ
Как объявить одномерный массив: long id_no[200];
Как объявить двумерный массив: short chess[8][8];
Какие массивы можно инициализировать: внешние и статические.
Как инициализировать массив: static int hats[3]=[10,20,15];
Другой способ инициализации: static int caps[ ]=[3,56,2];
Как получить адрес переменной: использовать операцию &.
Как получить значение, ссылаясь на указатель: использовать операцию *.
Смысл имени массива: hats == &hats[0].
Соответствие массива и указателя: если ptr = hats; то ptr + 2 == &hat[2]; и *(ptr+2) == hat[2];
Пять операций, которые можно применять для переменных типа указатель: см. текст.
Метод указателей для функций, работающих с массивами.
ВОПРОСЫ И ОТВЕТЫ
Вопросы
1. Что напечатается в результате работы этой программы?
#define PC(X, Y)
printf(" %с %c \n", X, Y)
char ref[ ] = { D, О, L, Т};
main
{
char *ptr;
int index;
for(index =0; ptr = ref; index < 4; index++, ptr++)
PC(ref[indcx], *ptr);