Язык программирования Си (Ритчи, Керниган) - страница 96

5.11 Указатели на функции

В Си сама функция не является переменной, но можно определить указатель на функцию и работать с ним, как с обычной переменной: присваивать, размещать в массиве, передавать в качестве параметра функции, возвращать как результат из функции и т. д. Для иллюстрации этих возможностей воспользуемся программой сортировки, которая уже встречалась в настоящей главе. Изменим ее так, чтобы при задании необязательного аргумента -n вводимые строки упорядочивались по их числовому значению, а не в лексикографическом порядке.

Сортировка, как правило, распадается на три части: на сравнение, определяющее упорядоченность пары объектов; перестановку, меняющую местами пару объектов, и сортирующий алгоритм, который осуществляет сравнения и перестановки до тех пор, пока все объекты не будут упорядочены. Алгоритм сортировки не зависит от операций сравнения и перестановки, так что передавая ему в качестве параметров различные функции сравнения и перестановки, его можно настроить на различные критерии сортировки.

Лексикографическое сравнение двух строк выполняется функцией strcmp (мы уже использовали эту функцию в ранее рассмотренной программе сортировки); нам также потребуется программа numcmp, сравнивающая две строки как числовые значения и возвращающая результат сравнения в том же виде, в каком его выдает strcmp. Эти функции объявляются перед main, а указатель на одну из них передается функции qsort. Чтобы сосредоточиться на главном, мы упростили себе задачу, отказавшись от анализа возможных ошибок при задании аргументов.

>#include ‹stdio.h›

>#include ‹string.h›


>#define MAXLINES 5000 /* максимальное число строк */

>char *lineptr[MAXLINES]; /* указатели на строки текста */


>int readlines(char *lineptr[], int nlines);

>void writelines(char *lineptr[], int nlines);

>void qsort(void *lineptr[], int left, int right,

>int (*comp)(void *, void *));

>int numcmp(char *, char *);


>/* сортировка строк */

>main(int argc, char *argv[])

>{

> int nlines; /* количество прочитанных строк */

> int numeric = 0; /* 1, если сорт. по числ. знач. */

> if (argc › 1 && strcmp(argv[1], "-n") == 0)

>  numeric = 1;

> if ((nlines = readlines(lineptr, MAXLINES)) ›= 0) {

>  qsort((void **) lineptr, 0, nlines-1,

>   (int (*)(void*,void*))(numeric ? numcmp : strcmp));

>  writelines(lineptr, nlines);

>  return 0;

> } else {

>  printf("Bведено слишком много строк\n");

>  return 1;

> }

>}

В обращениях к функциям qsort, strcmp и numcmp их имена трактуются как адреса этих функций, поэтому оператор& перед ними не нужен, как он не был нужен и перед именем массива.