Различия
Здесь показаны различия между двумя версиями данной страницы.
| Следующая версия | Предыдущая версия | ||
|
fullcircle:21:программа_на_си_ч5 [2010/04/02 21:36] создано |
fullcircle:21:программа_на_си_ч5 [2010/04/14 00:30] (текущий) |
||
|---|---|---|---|
| Строка 1: | Строка 1: | ||
| ======HOW-TO: Программа на Си. Часть 5====== | ======HOW-TO: Программа на Си. Часть 5====== | ||
| - | \ | + | |
| + | - [[..:17:программа_на_си_ч1|Программа на Си. Часть 1]] | ||
| + | - [[..:18:программа_на_си_ч2|Программа на Си. Часть 2]] | ||
| + | - [[..:19:программа_на_си_ч3|Программа на Си. Часть 3]] | ||
| + | - [[..:20:программа_на_си_ч4|Программа на Си. Часть 4]] | ||
| + | - [[..:21:программа_на_си_ч5|Программа на Си. Часть 5]] | ||
| + | - [[..:22:программа_на_си_ч6|Программа на Си. Часть 6]] | ||
| + | - [[..:23:программа_на_си_ч7|Программа на Си. Часть 7]] | ||
| + | - [[..:24:программа_на_си_ч8|Программа на Си. Часть 8]] | ||
| + | |||
| + | ---- | ||
| <style right> | <style right> | ||
| //Автор: Эли Дэ Брувэр (Elie De Brauwer)// | //Автор: Эли Дэ Брувэр (Elie De Brauwer)// | ||
| Строка 9: | Строка 20: | ||
| =====Указатели на функции===== | =====Указатели на функции===== | ||
| Как уже говорилось, если int a является целой переменной, то int * b=&a создаёт и инициализирует указатель b на a. Посмотрите на Листинг 1. В нём есть функция divide (строки 1-4), а на строке 6 - команда typedef, определяющая новый тип данных "mathFun". Это указатель на функцию, которая возвращает целое число и принимает два целых в качестве аргументов. В строках с 8 по 12 определяется структура, которая объединяет символ с функцией. Этот приём называется "обратный вызов" (callback) или обработчик (handler), и его используют очень часто. Этот приём может быть использован, чтобы симулировать объектно-ориентированное программирование в Си. Нужно определить структуру с некоторыми данными и указателями на функции, и в результате получится практически класс. Но наиболее часто он используется в GUI-программировании для регистрации функции, которая вызывается, когда пользователь совершает какое-либо действие. Если у вас установлен пакет manpages-dev, то набрав "man qsort" вы увидите определение функции, которая реализует алгоритм (см. Листинг 2). Как видите, эта функция способна сортировать данные и указатель на неё должен быть передан функции, которая может выполнять сравнения, что полезно при сортировке массива значений независимо от их характера. | Как уже говорилось, если int a является целой переменной, то int * b=&a создаёт и инициализирует указатель b на a. Посмотрите на Листинг 1. В нём есть функция divide (строки 1-4), а на строке 6 - команда typedef, определяющая новый тип данных "mathFun". Это указатель на функцию, которая возвращает целое число и принимает два целых в качестве аргументов. В строках с 8 по 12 определяется структура, которая объединяет символ с функцией. Этот приём называется "обратный вызов" (callback) или обработчик (handler), и его используют очень часто. Этот приём может быть использован, чтобы симулировать объектно-ориентированное программирование в Си. Нужно определить структуру с некоторыми данными и указателями на функции, и в результате получится практически класс. Но наиболее часто он используется в GUI-программировании для регистрации функции, которая вызывается, когда пользователь совершает какое-либо действие. Если у вас установлен пакет manpages-dev, то набрав "man qsort" вы увидите определение функции, которая реализует алгоритм (см. Листинг 2). Как видите, эта функция способна сортировать данные и указатель на неё должен быть передан функции, которая может выполнять сравнения, что полезно при сортировке массива значений независимо от их характера. | ||
| - | Листинг 1: | + | |
| + | **Листинг 1:** | ||
| <code c> | <code c> | ||
| 01.int divide(int a, int b) | 01.int divide(int a, int b) | ||
| Строка 23: | Строка 35: | ||
| 11. mathFun f; | 11. mathFun f; | ||
| 12.}; | 12.}; | ||
| + | </code> | ||
| + | |||
| + | **Листинг 2: отрывок из man 3 qsort** | ||
| + | <code c> | ||
| + | NAME | ||
| + | qsort - sorts an array | ||
| + | SYNOPSIS | ||
| + | #include <stdlib.h> | ||
| + | |||
| + | void qsort(void *base, size_t nmemb, size_t size, | ||
| + | int(*compar)(const void *, const void *)); | ||
| + | DESCRIPTION | ||
| + | The qsort() function sorts an array with nmemb elements of size size. | ||
| + | The base argument points to the start of the array. | ||
| </code> | </code> | ||
| Строка 29: | Строка 55: | ||
| В Листинге 3 приведена простая реализация этой программы. В строке 3 происходит выделение хранилища для четырёх структур, которые заполняются оператором и указателями на функции в строках 4 по 7. Далее на строках 12-18 обрабатывается ввод пользователя. Когда пользователь что-то ввёл, в строках 20-32 производится поиск в массиве команд значения, соответствующего знаку операции. Если значение найдено, происходит обратный вызов с прочитанными данными, и выводится результат. И больше ничего делать не нужно. | В Листинге 3 приведена простая реализация этой программы. В строке 3 происходит выделение хранилища для четырёх структур, которые заполняются оператором и указателями на функции в строках 4 по 7. Далее на строках 12-18 обрабатывается ввод пользователя. Когда пользователь что-то ввёл, в строках 20-32 производится поиск в массиве команд значения, соответствующего знаку операции. Если значение найдено, происходит обратный вызов с прочитанными данными, и выводится результат. И больше ничего делать не нужно. | ||
| + | |||
| + | **Листинг 3: основной цикл calc.c** | ||
| + | <code c> | ||
| + | 01.int main() | ||
| + | 02.{ | ||
| + | 03. struct operator functs[4]; | ||
| + | 04. functs[0].c='-'; functs[0].f=− | ||
| + | 05. functs[1].c='+'; functs[1].f=&add; | ||
| + | 06. functs[2].c='*'; functs[2].f=&multiply; | ||
| + | 07. functs[3].c='/'; functs[3].f=÷ | ||
| + | 08. while(1) | ||
| + | 09. { | ||
| + | 10. int a,b,i; | ||
| + | 11. char c; | ||
| + | 12. printf("Введите a:\n"); | ||
| + | 13. scanf("%d",&a); | ||
| + | 14. printf("Введите b:\n"); | ||
| + | 15. scanf("%d",&b); | ||
| + | 16. printf("Введите оператор:\n"); | ||
| + | 17. scanf("%c",&c); // Перенос строки | ||
| + | 18. scanf("%c",&c); | ||
| + | 19. i=0; | ||
| + | 20. while(i<4) | ||
| + | 21. { | ||
| + | 22. if(functs[i].c==c) | ||
| + | 23. { | ||
| + | 24. printf("Результат: %d\n",functs[i].f(a,b)); | ||
| + | 25. break; | ||
| + | 26. } | ||
| + | 27. i++; | ||
| + | 28. } | ||
| + | 29. if(i==4) | ||
| + | 30. { | ||
| + | 31. printf("Неизвестный оператор: %c\n",c); | ||
| + | 32. } | ||
| + | 33. } | ||
| + | 34. return 0; | ||
| + | 35. } | ||
| + | </code> | ||
| =====Ввод пользователя===== | =====Ввод пользователя===== | ||
| Строка 39: | Строка 104: | ||
| * Сделайте, чтобы пользователь мог выйти из приложения введя "q". | * Сделайте, чтобы пользователь мог выйти из приложения введя "q". | ||
| * Измените приложение, чтобы пользователь мог вводить не символы, а фразы "5 плюс 6" или "6 минус 5". Для этого необходимо будет изменить структуры, чтобы в качестве оператора была строка, а вместо считывания символа нужно будет считывать строку. Будет прекрасно, если вы сможете написать этот код без ошибок переполнения буфера (см. man getline) и утечек памяти. | * Измените приложение, чтобы пользователь мог вводить не символы, а фразы "5 плюс 6" или "6 минус 5". Для этого необходимо будет изменить структуры, чтобы в качестве оператора была строка, а вместо считывания символа нужно будет считывать строку. Будет прекрасно, если вы сможете написать этот код без ошибок переполнения буфера (см. man getline) и утечек памяти. | ||
| + | * | ||
| + | <note tip>Elie De Brauwer - фанатик Linux из Бельгии. Когда он не со своей семьёй, он любит играть с технологиями и проводит дни, ожидая, когда Blizzard наконец выпустит Diablo III. </note> | ||
| + | |||
| + | |||
| + | ---- | ||
| + | <style center> | ||
| + | - [[..:17:программа_на_си_ч1|Программа на Си. Часть 1]] | ||
| + | - [[..:18:программа_на_си_ч2|Программа на Си. Часть 2]] | ||
| + | - [[..:19:программа_на_си_ч3|Программа на Си. Часть 3]] | ||
| + | - [[..:20:программа_на_си_ч4|Программа на Си. Часть 4]] | ||
| + | - [[..:21:программа_на_си_ч5|Программа на Си. Часть 5]] | ||
| + | - [[..:22:программа_на_си_ч6|Программа на Си. Часть 6]] | ||
| + | - [[..:23:программа_на_си_ч7|Программа на Си. Часть 7]] | ||
| + | - [[..:24:программа_на_си_ч8|Программа на Си. Часть 8]] | ||
| + | |||
| + | ---- | ||
| + | |||
| + | //[[..:21|К содержанию номера]]// | ||
| + | |||
| + | //[[:fullcircle|К архиву журналов]]// | ||
| + | </style> | ||
| + | |||
| + | {{tag>howto Си Программирование Full_Circle}} | ||