5.12. Указатели на функции
В языке “с” сами функции не являются переменными, но
имеется возможность определить указатель на функцию, который
можно обрабатывать, передавать другим функциям, помещать в
массивы и т.д. Мы проиллюстрируем это, проведя модификацию
написанной ранее программы сортировки так, чтобы при задании
необязательного аргумента -N она бы сортировала строки ввода
численно, а не лексикографически.
Сортировка часто состоит из трех частей - сравнения, ко-
торое определяет упорядочивание любой пары объектов, перес-
тановки, изменяющей их порядок, и алгоритма сортировки, осу-
ществляющего сравнения и перестановки до тех пор, пока
объекты не расположатся в нужном порядке. Алгоритм сортиров-
ки не зависит от операций сравнения и перестановки, так что,
передавая в него различные функции сравнения и перестановки,
мы можем организовать сортировку по различным критериям.
Именно такой подход используется в нашей новой программе
сортировки.
Как и прежде, лексикографическое сравнение двух строк
осуществляется функцией STRCMP, а перестановка функцией
SWAP; нам нужна еще функция NUMCMP, сравнивающая две строки
на основе численного значения и возвращающая условное указа-
ние того же вида, что и STRCMP. Эти три функции описываются
в MAIN и указатели на них передаются в SORT. В свою очередь
функция SORT обращается к этим функциям через их указатели.
мы урезали обработку ошибок в аргументах с тем, чтобы сосре-
доточиться на главных вопросах.
· 125 -
#DEFINE LINES 100 /* MAX NUMBER OF LINES
TO BE SORTED */
MAIN(ARGC, ARGV) /* SORT INPUT LINES */ INT ARGC;
CHAR *ARGV[];
\(
CHAR LINEPTR[LINES]; / POINTERS TO TEXT LINES */
INT NLINES; /* NUMBER OF INPUT LINES READ */
INT STRCMP(), NUMCMP(); /* COMPARSION FUNCTIONS */
INT SWAP(); /* EXCHANGE FUNCTION */
INT NUMERIC = 0; /* 1 IF NUMERIC SORT */
IF(ARGC>1 && ARGV[1][0] == '-' && ARGV[1][1]=='N')
NUMERIC = 1;
IF(NLINES = READLINES(LINEPTR, LINES)) >= 0) \(
IF (NUMERIC)
SORT(LINEPTR, NLINES, NUMCMP, SWAP);
ELSE
SORT(LINEPTR, NLINES, STRCMP, SWAP);
WRITELINES(LINEPTR, NLINES);
\) ELSE
PRINTF(“INPUT TOO BIG TO SORT\N”);
\)
Здесь STRCMP, NIMCMP и SWAP - адреса функций; так как извес-
тно, что это функции, операция & здесь не нужна совершенно
аналогично тому, как она не нужна и перед именем массива.
Передача адресов функций организуется компилятором.
Второй шаг состоит в модификации SORT:
SORT(V, N, COMP, EXCH) /* SORT STRINGS V[0] ... V[N-1] */ CHAR V[]; / INTO INCREASING ORDER */ INT N;
INT (*COMP)(), (*EXCH)();
\(
INT GAP, I, J;
FOR(GAP = N/2; GAP > 0; GAP /= 2)
FOR(I = GAP; I < N; I++)
FOR(J = I-GAP; J >= 0; J -= GAP) \(
IF((*COMP)(V[J], V[J+GAP]) <= 0)
BREAK;
(*EXCH)(&V[J], &V[J+GAP]);
\)
\)
· 126 -
Здесь следует обратить определенное внимание на описа-
ния. Описание
INT (*COMP)()
говорит, что COMP является указателем на функцию, которая
возвращает значение типа INT. Первые круглые скобки здесь
необходимы; без них описание
INT *COMP()
говорило бы, что COMP является функцией, возвращающей указа-
тель на целые, что, конечно, совершенно другая вещь.
Использование COMP в строке
IF (*COMP)(V[J], V[J+GAP]) <= 0)
полностью согласуется с описанием: COMP - указатель на функ-
цию, *COMP - сама функция, а
(*COMP)(V[J], V[J+GAP])
· обращение к ней. Круглые скобки необходимы для правильного
объединения компонентов.
Мы уже приводили функцию STRCMP, сравнивающую две строки
по первому численному значению:
NUMCMP(S1, S2) /* COMPARE S1 AND S2 NUMERICALLY */ CHAR *S1, *S2;
\(
DOUBLE ATOF(), V1, V2;
V1 = ATOF(S1);
V2 = ATOF(S2);
IF(V1 < V2)
RETURN(-1);
ELSE IF(V1 > V2)
RETURN(1);
ELSE
RETURN (0);
\)
Заключительный шаг состоит в добавлении функции SWAP,
переставляющей два указателя. Это легко сделать, непосредст-
венно используя то, что мы изложили ранее в этой главе.
·
127 -
SWAP(PX, PY) /* INTERCHANGE *PX AND *PY */
CHAR *PX[], *PY[];
\(
CHAR *TEMP;
TEMP = *PX;
*PX = *PY;
*PY = TEMP;
\)
Имеется множество других необязятельных аргументов, ко-
торые могут быть включены в программу сортировки: некоторые
из них составляют интересные упражнения.
Упражнение 5-11.
Модифицируйте SORT таким образом, чтобы она работала с
меткой -R, указывающей на сортировку в обратном (убывающем)
порядке. Конечно, -R должна работать с -N.
Упражнение 5-12.
Добавьте необязательный аргумент -F, объединяющий вместе
прописные и строчные буквы, так чтобы различие регистров не
учитывалось во время сортировки: данные из верхнего и нижне-
го регистров сортируются вместе, так что буква 'а' прописное
и 'а' строчное оказываются соседними , а не разделенными це-
лым алфавитом.
Упражнение 5-13.
Добавьте необязательный аргумент -D (“словарное упорядо-
чивание”), при наличии которого сравниваются только буквы,
числа и пробелы. Позаботьтесь о том, чтобы эта функция рабо-
тала и вместе с -F.
Упражнение 5-14.
Добавьте возможность обработки полей, так чтобы можно
было сортировать поля внутри строк. Каждое поле должно сор-
тироваться в соответствии с независимым набором необязатель-
ных аргументов. (предметный указатель этой книги сортировал-
ся с помощью аргументов -DF для категории указателя и с -N
для номеров страниц).
· 128 -
... основаниям. При этом философская абстракция языка оказывается неразрывно связана с основными темами и движениями философии в целом. Более конкретно, на ранние стадии традиционно рассматриваемого в рамках АФ анализа обыденного языка глубокое влияние оказала философия Дж. Э. Мура, особенно его учение о здравом смысле, согласно которому такие понятия, как «человек», «мир», «я», «внешний мир», « ...
... и других странах СНГ, а также облегчение доступа к русской и мировой культуре и науке. Таким образом, судя по данным наших исследований, востребованность русского языка осталась в республике достаточно высокой. Многие представители современной молдавской молодежи продолжают, как их отцы и деды, тянуться к русской культуре, научным и техническим достижениям России. Русский язык остается языком ...
... рисуночное словесно-слоговое письмо). Памятники среднеэламского периода (14—12 вв. до н.э.) выполнены аккадской клинописью. Памятники новоэламского периода относятся к 8—6 вв. до н.э. Был официальным языком в персидском государстве Ахеменидов в 6—4 вв. предполагается, что он, подвергшись влиянию древнеперсидского, сохранился до раннего средневековья. 7. Бурушаски язык Язык бурушаски ( ...
... /диалект), скифский, согдийский, среднеперсидский, таджикский, таджриши (язык/диалект), талышский, татский, хорезмийский, хотаносакский, шугнано-рушанская группа языков, ягнобский, язгулямский и др. Они относятся к индоиранской ветви индоевропейских языков. Области распространения: Иран, Афганистан, Таджикистан, некоторые районы Ирака, Турции, Пакистана, Индии, Грузии, Российской Федерации. Общее ...
0 комментариев