Язык программирования Си - [50]
>#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 их имена трактуются как адреса этих функций, поэтому оператор& перед ними не нужен, как он не был нужен и перед именем массива.
Мы написали qsort так, чтобы она могла обрабатывать данные любого типа, а не только строки символов. Как видно из прототипа, функция qsort в качестве своих аргументов ожидает массив указателей, два целых значения и функцию с двумя аргументами-указателями. В качестве аргументов-указателей заданы указатели обобщенного типа void *. Любой указатель можно привести к типу void * и обратно без потери информации, поэтому мы можем обратиться к qsort, предварительно преобразовав аргументы в void *. Внутри функции сравнения ее аргументы будут приведены к нужному ей типу. На самом деле эти преобразования никакого влияния на представления аргументов не оказывают, они лишь обеспечивают согласованность типов для компилятора.
>/* qsort: сортирует v[left]…v[right] по возрастанию */
>void qsort(void *v[], int left, int right, int (*comp)(void *, void *))
>{
> int i, last;
> void swap(void *v[], int, int);
> if (left ›= right) /* ничего не делается, если */
> return; /* в массиве менее двух элементов */
> swap(v, left, (left + right)/2);
> last = left;
> for (i = left+1; i ‹= right; i++)
> if ((*comp)(v[i], v[left]) ‹ 0)
> swap(v, ++last, i);
> swap(v, left, last);
> qsort(v, left, last-1, comp);
> qsort(v, last+1, right, comp);
>}
Повнимательней приглядимся к объявлениям. Четвертый параметр функции qsort:
>int (*comp)(void *, void *)
сообщает, что comp - это указатель на функцию, которая имеет два аргумента- указателя и выдает результат типа int. Использование comp в строке
>if ((*comp)(v[i], v[left]) ‹ 0)
согласуется с объявлением "comp - это указатель на функцию", и, следовательно, *comp - это функция, а
>(*comp)(v[i], v[left])
- обращение к ней. Скобки здесь нужны, чтобы обеспечить правильную трактовку объявления; без них объявление
>int *comp(void *, void *) /* НЕВЕРНО */
говорило бы, что comp - это функция, возвращающая указатель на int, а это совсем не то, что требуется.
Мы уже рассматривали функцию strcmp, сравнивающую две строки. Ниже приведена функция numcmp, которая сравнивает две строки, рассматривая их как числа; предварительно они переводятся в числовые значения функцией atof.
>#include ‹stdlib.h›
>/* numcmp: сравнивает s1 и s2 как числа */
>int numcmp(char *s1, char *s2)
>{
> double v1, v2;
> v1 = atof(s1);
> v2 = atof(s2);
> if (v1 ‹ v2)
> return -1;
> else if (v1 › v2)
> return 1;
> else
> return 0;
>}
Функция swap, меняющая местами два указателя, идентична той, что мы привели ранее в этой главе за исключением того, что объявления указателей заменены на void*.
>void swap(void *v[], int i, int j)
>{
> void *temp;
> temp = v[i];
> v[i] = v[j];
> v[j] = temp;
>}
Программу сортировки можно дополнить и множеством других возможностей; реализовать некоторые из них предлагается в качестве упражнений.
Упражнение 5.14. Модифицируйте программу сортировки, чтобы она реагировала на параметр -r, указывающий, что объекты нужно сортировать в обратном порядке, т. е. в порядке убывания. Обеспечьте, чтобы -r работал и вместе с -n.
Упражнение 5.15. Введите в программу необязательный параметр -f, задание которого делало бы неразличимыми символы нижнего и верхнего регистров (например, a и A должны оказаться при сравнении равными).
Упражнение 5.16. Предусмотрите в программе необязательный параметр -d, который заставит программу при сравнении учитывать только буквы, цифры и пробелы. Организуйте программу таким образом, чтобы этот параметр мог работать вместе с параметром -f.
Упражнение 5.17. Реализуйте в программе возможность работы с полями: возможность сортировки по полям внутри строк. Для каждого поля предусмотрите свой набор параметров. Предметный указатель этой книги (Имеется в виду оригинал книги на английским языке. - Примеч. пер.) упорядочивался с параметрами: -df для терминов и -n для номеров страниц.
5.12 Сложные объявления
Иногда Си ругают за синтаксис объявлений, особенно тех, которые содержат в себе указатели на функции. Таким синтаксис получился в результате нашей попытки сделать похожими объявления объектов и их использование. В простых случаях этот синтаксис хорош, однако в сложных ситуациях он вызывает затруднения, поскольку объявления перенасыщены скобками и их невозможно читать слева направо. Проблему иллюстрирует различие следующих двух объявлений:
В книге американских авторов — разработчиков операционной системы UNIX — блестяще решена проблема автоматизации деятельности программиста, системной поддержки его творчества, выходящей за рамки языков программирования. Профессионалам открыт богатый "встроенный" арсенал системы UNIX. Многочисленными примерами иллюстрировано использование языка управления заданиями shell.Для программистов-пользователей операционной системы UNIX.
Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.
Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.