Теперь, когда мы добавили sizeк передаваемой информации, нужно модифицировать рисунок нашего черного ящика. См. рис. 10.6.

РИС. 10.6. Программ: сортировки, дополнительные детали.
Теперь рассмотрим функцию getarray( ):
/* getarray( ), использующая getint( ) */
#define STOP -1 /* признак EOF */
#define NONUM 1 /* признак нецифровой строки */
#define YESNUM 0 /* признак строки цифр */
getarray(array, limit);
int array[ ], limit;
{
int num, status;
int index = 0; /* индекс массива */
printf(" Эта программа прекращает считывание чисел после %d значений. \n", limit);
printf(" или если введен символ EOF.\n");
while(index < limit && (status = getint(&num)) != STOP)
{ /* прекращает считывание после достижения limit или EOF */
if(status == YESNUM)
{ array[index++] = num;
printf(" число %d принято.\n", num);
} else if(status == NONUM)
printf(" Это было не целое число! Попытайтесь снова. \n");
else
printf(" Этого не может быть! Что-то неправильно. \n");
if(index == limit) /* сообщить, если массив заполнен */
printf(" Все %d элементов массива заполнены. \n ", limit);
return(index);
}
Это значительная часть программы, и у нас есть немало замечаний.
Так как немного трудно вспомнить значение, скажем кода -1, мы используем мнемонические символические константы для представления кодов состояния.
Применяя эти коды, мы создаем getarray( )для управления каждым из возможных значений состояния. Состояние STOPвызывает прекращение цикла чтения, если getint( )находит на своем "пути" EOF. Состояние YESNUMговорит о запоминании числа в предлагаемом массиве. Кроме того, отсылается "эхо-число" пользователю, чтобы он знал, что оно принято. Состояние NONUMпредписывает пользователю попытаться выполнить задачу еще раз. (Это признак "дружелюбия").
У нас есть еще оператор else. Единственный путь достижения этого оператора возможен, если getint( )возвращает значение, отличное от -1, 0 или 1. Однако это единственные значения, которые могут быть возвращены, поэтому elseявляется, по-видимому бесполезным оператором. Почему он включен в программу? Мы вставили его как пример "защитного программирования", как способ защиты программы от будущей ошибки.
Когда-нибудь мы (или кто-нибудь еще), может быть, решим обратиться к функции getint( )и добавить в ее репертуар немного больше возможных значений состояния. Наиболее вероятно, что мы забудем (а они могут никогда не узнать), что getarray( )предполагает только три возможных ответа. Поэтому мы включаем это последнее else, чтобы "поймать" любые новые ответы, которые появятся, и значительно упростить будущую отладку.
Размер массива устанавливается в main(). Поэтому мы не задаем его, когда описываем аргумент-массив в getarray(). Мы ставим только квадратные скобки в оператор, чтобы указать, что аргумент является массивом.
int numbers [MAXSIZE]; /* размер задается в main */
int array[ ] /* нет определения размера в вызвавшей функции */
Использование массивов в функциях обсудим в гл. 12. Мы решили применить ключевое слово returnдля возврата числа прочитанных элементов. Таким образом, вызов нашей функции:
size = getarray(numbers);
присваивает значение переменной sizeи дает значения массиву numbers. Вы можете спросить, почему мы не использовали указатели в вызове
size = getаrray (numbers);
ведь у нас функция изменяет значение чего-то (массива) в вызывающей программе? Ошибаетесь - мы использовали указатель! В языке Си имя массива является также указателем на первый элемент массива, т. е.
numbers == &numbers[0]
Когда функция getarray()создает массив array, то адрес элемента аrrау[0]совпадает с адресом элемента numbers[0]и т. д. для всех других индексов. Поэтому все манипуляции, которые выполняет qetarray( )с аrrау[ ], фактически выполняются с numbers[ ]. Мы будем более подробно говорить о связи между указателями и массивами в гл. 12. Теперь же нам нужно усвоить, что функция воздействует на массив в вызывающей программе, если мы используем массив в качестве аргумента функции.
В функциях, содержащих счетчики и пределы, таких как getarray( ), наиболее вероятным местом появления ошибок являются "граничные условия", где значения счетчиков достигают своих пределов. Мы собираемся прочитать максимальное количество чисел, указанное в MAXSIZE, или же мы намерены ограничиться одним? Хотим обратить внимание на детали, такие, как ++indexили index++и <или <=. Мы также должны помнить, что у массивов индексы начинаются с 0, а не с 1.
Читать дальше