Различия
Здесь показаны различия между двумя версиями данной страницы.
Следующая версия | Предыдущая версия | ||
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}} |