Указатели и функции в языке программирования С
Задание 2
- В качестве первого аргумента функции mean_D_S() используйте указатель на числовой массив.
- Воспользуйтесь справкой по математическим функциям и в программе примените функцию, которая осуществляет возведение в степень.
- Дополните возврат функцией mean_D_S() еще исходного массива, поэлементно возведенного в квадрат. В главной функции main() результаты выведите на консоль.
- Вместо типа double используйте тип float.
Пример 3. Напишите программу с указателем на функции, которые рассчитывают следующие статистические характеристики одномерного числового массива: среднее арифметическое значение, медиану и модус (моду).
Среднее арифметическое рассчитывалось в предыдущем примере.
Приведем определения медианы и модуса, взятые из книги [11.3], из которой также взяты основные фрагменты программных кодов (в книге программы написаны на С++).
Медиана – это серединное значение в наборе данных – т. е. такое, что ровно половина значений располагается выше, и ровно половина ниже его.
Модус – это значение, наиболее часто встречающееся в наборе данных.
Программный код решения примера:
#include <stdio.h> #include <conio.h> double mean(int*, int); double median(int*, int); double mode(int*, int); int main(void) { int mass[] = {5, 6, 5, 5, 3, 6, 5, 3, 1, 4, 5, 3, 1, 6, 5, 2, 5, 2, 3, 4}; int *ptr = mass; int temp, i, j, k, n; // Указатель на функции double (*fun[3])(int*, int) = {mean, median, mode}; n = sizeof(mass)/sizeof(mass[0]); puts("\n The original array:"); j = 0; for (i = 0; i < n; i++) { j++; if ( j%6 ) printf(" %2d", mass[i]); else {puts(""); printf(" %2d", mass[i]); j = 1;} } // Сортировка методом выбора for (i = 0; i < (n - 1); ++i) { temp = ptr[i]; k = i; for (j = i + 1; j < n; ++j) if (ptr[j] < temp) { k = j; temp = ptr[k]; } ptr[k] = ptr[i]; ptr[i] = temp; } puts("\n\n Results - mean, mediana, modus: "); for (i = 0; i < 3; i++) printf("%6g\n",(*fun[i])(ptr, n)); printf("\n\n ... Press any key: "); _getch(); return 0; } // Определения функций double mean(int* arr, int N) { int i; double aver = 0.0; for (i = 0; i < N; i++) aver += arr[i]; return (aver/N); } double median(int* arr, int N) { int i; double med = 0.0; for (i = 0; (i < N/2); i++) med = arr[i]; if ( N % 2) med = arr[i]; else med = (med + arr[i])/2; return med; } double mode(int* arr, int N) { int instances = 0, tempinst = 1, i = 1; double tempmode, mode_return = 1.0; tempmode = (double)arr[0]; while (i < N) { while ((double)arr[i] == tempmode ) { i++; tempinst++; } if (tempinst > instances) { mode_return = tempmode; instances = tempinst; } tempinst = 1; tempmode = (double)arr[i]; i++; } return (mode_return); }
В программе указатель на функции ( *fun ) – это массив указателей на функции, на три функции. В случае, когда возвращаемые значения функций имеют различный тип, то можно определить несколько указателей на функции.
Для понимания работы функции по расчету модуса алгоритм вычислений рекомендуется в [11.3] формулировать следующим образом: "Разбить сортированный список значений на ряд меньших списков, каждый из которых содержит одинаковые значения. Пересчитать число элементов в этих списках, и список с наибольшим числом элементов будет соответствовать модусу данных".
Результат выполнения программы показан на рис. 11.4.
Задание 3
- В функции расчета модуса приведение типов примените только один раз.
- Массив данных задайте случайным образом (целыми числами). Проанализируйте результат работы программы.
- Создайте три указателя на функцию – на функцию расчета среднего арифметического, на функцию расчета медианы и на функцию расчета модуса. При этом для массива целых чисел функция расчета модуса должна возвращать целое значение.
- Объедините три функции – mean(), median(), mode() в одну функцию и определите необходимый тип возвращаемого значения, чтобы в главной функции main() можно была распечатать результаты расчетов статистических характеристик.
- Напишите программу, в которой с помощью указателя на функции можно было вывести на консоль средние оценки за последние три года обучения в школе.
Пример 4. Напишите программу сортировки массива строк с использованием указателей на функции.
Программный код решения примера:
#include <stdio.h> #include <conio.h> #include <string.h> // Прототипы функций void bsort (char **arr, int size, int (*comp) (const char *s1, const char *s2)); int less (const char *s1, const char *s2); int greater (const char *s1, const char *s2); int main (void) { char *Lines[] = { "asd", "aza", "baza", "qwerty", "hello", "world", "aza" }; int n = sizeof (Lines) / sizeof (Lines[0]); int i; // Вызов функции сортировки по возрастанию в алфавитном порядке puts("\n The sorting in ascending order:"); bsort (Lines, n, less); for (i = 0; i < n; ++i) printf("\t %s\n", Lines[i]); // Вызов функции сортировки по убыванию в алфавитном порядке puts("\n The sorting in descending order:"); bsort (Lines, n, greater); for (i = 0; i < n; ++i) printf("\t %s\n", Lines[i]); printf("\n\n ... Press any key: "); _getch(); return 0; } // Определение функции сортировки строк void bsort (char **arr, int size, int (*comp) (const char *s1, const char *s2)) { int i, j; for (i = 0; i < size - 1; ++i) for (j = 0; j < size - 1; ++j) if (comp (arr[j], arr[j + 1]) > 0) { char *s = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = s; } } // Определение функции сравнения строк по возрастанию int less (const char *s1, const char *s2) { return strcmp (s1, s2); } // Определение функции сравнения строк по убыванию int greater (const char *s1, const char *s2) { return -strcmp (s1, s2); }
В программе используются указатель на функцию для вызова двух функций – less() и greater() в процессе сортировки для определения порядка расположения элементов (слов).
Результат выполнения программы показан на рис. 11.5.