По-видимому самым общим типом массива в "C" являетсямассив символов. Чтобы проиллюстрировать использование мас-сивов символов и обрабатывающих их функций, давайте напишемпрограмму, которая читает набор строк и печатает самую длин-ную из них. Основная схема программы достаточно проста: WHILE (имеется еще строка) IF (эта строка длиннее самой длинной из предыдущих) запомнить эту строку и ее длинунапечатать самую длинную строку По этой схеме ясно, что программа естественным образомраспадается на несколько частей. Одна часть читает новуюстроку, другая проверяет ее, третья запоминает, а остальныечасти программы управляют этим процессом. Поскольку все так прекрасно делится, было бы хорошо инаписать программу соответсвующим образом. Давайте сначаланапишем отдельную функцию GETLINE, которая будет извлекатьследующую строку из файла ввода; это - обобщение функцииGETCHAR. мы попытаемся сделать эту функцию по возможностиболее гибкой, чтобы она была полезной и в других ситуациях.Как минимум GETLINE должна передавать сигнал о возможном по-явлении конца файла; более общий полезный вариант мог бы пе-редавать длину строки или нуль, если встретится конец файла.нуль не может быть длиной строки, так как каждая строка со-держит по крайней мере один символ; даже строка, содержащаятолько символ новой строки, имеет длину 1. Когда мы находим строку, которая длиннее самой длиннойиз предыдущих, то ее надо где-то запомнить. Это наводит намысль о другой функции, COPY , которая будет копировать но-вую строку в место хранения. Наконец, нам нужна основная программа для управленияфункциями GETLINE и COPY . Вот результат : #DEFINE MAXLINE 1000 /* MAXIMUM INPUT LINE SIZE */ MAIN() /* FIND LONGEST LINE */ { INT LEN; /* CURRENT LINE LENGTH */ INT MAX; /* MAXIMUM LENGTH SEEN SO FAR */ CHAR LINE[MAXLINE]; /* CURRENT INPUT LINE */ CHAR SAVE[MAXLINE]; /* LONGEST LINE, SAVED */ MAX = 0; WHILE ((LEN = GETLINE(LINE, MAXLINE)) > 0) IF (LEN > MAX) { MAX = LEN; COPY(LINE, SAVE); } IF (MAX > 0) /* THERE WAS A LINE */ PRINTF("%S", SAVE); } GETLINE(S,LIM) /* GET LINE INTO S,RETURN LENGTH */ CHAR S[]; INT LIM; { INT C, I; FOR(I=0;I<LIM-1 && (C=GETCHAR())!=EOF && C!='\N';++I) S[I] = C; IF (C == '\N') { S[I] = C; ++I; } S[I] = '\0'; RETURN(I); } COPY(S1, S2) /* COPY S1 TO S2; ASSUME S2 BIG ENOUGH */ CHAR S1[], S2[]; { INT I; I = 0; WHILE ((S2[I] = S1[I] != '\0') ++I; } Функция MAIN и GETLINE общаются как через пару аргумен-тов, так и через возвращаемое значение. аргументы GETLINEописаны в строках CHAR S[]; INT LIM; которые указывают, что первый аргумент является массивом, авторой - целым. Длина массива S не указана, так как она определена вMAIN . функция GETLINE использует оператор RETURN для пере-дачи значения назад в вызывающую программу точно так же, какэто делала функция POWER. Одни функции возвращают некотороенужное значение; другие, подобно COPY, используются из-за ихдействия и не возвращают никакого значения. Чтобы пометить конец строки символов, функция GETLINEпомещает в конец создаваемого ей массива символ \0 /нулевойсимвол, значение которого равно нулю/. Это соглашение ис-пользуется также компилятором с языка "C": когда в "C" -программе встречается строчная константа типа "HELLO\N" то компилятор создает массив символов, содержащий символыэтой строки, и заканчивает его символом \0, с тем чтобы фун-кции, подобные PRINTF, могли зафиксировать конец массива: -------------------------------------------! H ! E ! L ! L ! O ! \N ! \0 !------------------------------------------- Спецификация формата %S указывает, что PRINTF ожидает стро-ку, представленную в такой форме. Проанализировав функциюCOPY, вы обнаружите, что и она опирается на тот факт, что еевходной аргумент оканчивается символом \0, и копирует этотсимвол в выходной аргумент S2. /Все это подразумевает, чтосимвол \0 не является частью нормального текста/. Между прочим, стоит отметить, что даже в такой маленькойпрограмме, как эта, возникает несколько неприятных организа-ционных проблем. Например, что должна делать MAIN, если онавстретит строку, превышающую ее максимально возможный раз-мер? Функция GETLINE поступает разумно: при заполнении мас-сива она прекращает дальнейшее извлечение символов, даже ес-ли не встречает символа новой строки. Проверив полученнуюдлину и последний символ, функция MAIN может установить, небыла ли эта строка слишком длинной, и поступить затем, какона сочтет нужным. Ради краткости мы опустили эту проблему. Пользователь функции GETLINE никак не может заранее уз-нать, насколько длинной окажется вводимая строка. Поэтому вGETLINE включен контроль переполнения. в то же время пользо-ватель функции COPY уже знает /или может узнать/, каков раз-мер строк, так что мы предпочли не включать в эту функциюдополнительный контроль. Упражнение 1-14 ----------------- Переделайте ведущую часть программы поиска самой длиннойстроки таким образом, чтобы она правильно печатала длинысколь угодно длинных вводимых строк и возможно большийтекст. Упражнение 1-15 ----------------- Напишите программу печати всех строк длиннее 80 симво-лов. Упражнение 1-16 ----------------- Напишите программу, которая будет удалять из каждойстроки стоящие в конце пробелы и табуляции, а также строки,целиком состоящие из пробелов. Упражнение 1-17 ----------------- Напишите функцию REVERSE(S), которая распологает сим-вольную строку S в обратном порядке. С ее помощью напишитепрограмму, которая обратит каждую строку из файла ввода.