Язык С




Циклы - WHILE и FOR - часть 2


В качестве большего по размеру примера приведем другой вариант функции ATOI, преобразующей строку в ее численный эквивалент. Этот вариант является более общим; он допускает присутствие в начале символов пустых промежутков и знака + или -. (В главе 4 приведена функция ATOF, которая выполняет то же самое преобразование для чисел с плавающей точкой). Общая схема программы отражает форму поступающих данных:

- пропустить пустой промежуток, если он имеется - извлечь знак, если он имеется

- извлечь целую часть и преобразовать ее

Каждый шаг выполняет свою часть работы и оставляет все в подготовленном состоянии для следующей части. Весь процесс заканчивается на первом символе, который не может быть частью числа.

ATOI(S) /* CONVERT S TO INTEGER */ CHAR S[]; { INT I, N, SIGN; FOR(I=0;S[I]==' ' \!\! S[I]=='\N' \!\! S[I]=='\T';I++) ; /* SKIP WHITE SPACE */ SIGN = 1; IF(S[I] == '+' \!\! S[I] == '-') /* SIGN */ SIGN = (S[I++]=='+') ? 1 : - 1; FOR( N = 0; S[I] >= '0' && S[I] <= '9'; I++) N = 10 * N + S[I] - '0'; RETURN(SIGN * N); }

Преимущества централизации управления циклом становятся еще более очевидными, когда имеется несколько вложенных цик- лов. Следующая функция сортирует массив целых чисел по мето- ду шелла. основная идея сортировки по шеллу заключается в том, что сначала сравниваются удаленные элементы, а не смеж- ные, как в обычном методе сортировки. Это приводит к быстро- му устранению большой части неупорядоченности и сокращает последующую работу. Интервал между элементами постепенно сокращается до единицы, когда сортировка фактически превра- щается в метод перестановки соседних элементов. SHELL(V, N) /* SORT V[0]...V[N-1] INTO INCREASING ORDER */ INT V[], N; { INT GAP, I, J, TEMP;

FOR (GAP = N/2; GAP > 0; GAP /= 2) FOR (I = GAP; I < N; I++) FOR (J=I-GAP; J>=0 && V[J]>V[J+GAP]; J-=GAP) { TEMP = V[J]; V[J] = V[J+GAP]; V[J+GAP] = TEMP; } }

Здесь имеются три вложенных цикла. Самый внешний цикл управ- ляет интервалом между сравниваемыми элементами, уменьшая его от N/2 вдвое при каждом проходе, пока он не станет равным нулю. Средний цикл сравнивает каждую пару элементов, разде- ленных на величину интервала; самый внутренний цикл перес- тавляет любую неупорядоченную пару. Так как интервал в конце концов сводится к единице, все элементы в результате упоря- дочиваются правильно. Отметим, что в силу общности конструк- ции FOR внешний цикл укладывается в ту же самую форму, что и остальные, хотя он и не является арифметической прогрессией. Последней операцией языка "C" является запятая ",", ко- торая чаще всего используется в операторе FOR. Два выраже- ния, разделенные запятой, вычисляются слева направо, причем типом и значением результата являются тип и значение правого операнда. Таким образом, в различные части оператора FOR можно включить несколько выражений, например, для параллель- ного изменения двух индексов. Это иллюстрируется функцией REVERSE(S), которая располагает строку S в обратном порядке на том же месте.

REVERSE(S) /* REVERSE STRING S IN PLACE */ CHAR S[]; { INT C, I, J;

FOR(I = 0, J = STRLEN(S) - 1; I < J; I++, J--) { C = S[I]; S[I] = S[J]; S[J] = C; } }

Запятые, которые разделяют аргументы функций, переменные в описаниях и т.д., не имеют отношения к операции запятая и не обеспечивают вычислений слева направо.

Упражнение 3-2

--------------- Составьте программу для функции EXPAND(S1,S2), которая расширяет сокращенные обозначения вида а-Z из строки S1 в эквивалентный полный список авс...XYZ в S2. Допускаются сок- ращения для строчных и прописных букв и цифр. Будьте готовы иметь дело со случаями типа а-в-с, а-Z0-9 и -а-Z. (Полезное соглашение состоит в том, что символ -, стоящий в начале или конце, воспринимается буквально).




    Содержание  Назад  Вперед