Часто указатели на функции применяются при реализации обобщенных алгоритмов, например алгоритмов сортировки и поиска. В этом случае критерии сортировки и поиска приобретают вид отдельных функций и передаются при помощи указателей на функции в качестве параметра реализации основного алгоритма.
Пример 9. Написать функцию с пузырьковой сортировкой числового массива, предусмотреть вызов этой функции по ссылке.
Вызов по ссылке означает, что в качестве фактических параметров функций будут использоваться адреса переменных, и в этом случае прототип таких функций будет содержать указатели на соответствующие типы.
Программный код решения примера:
#include <stdio. h> #include <conio. h> // Прототип функции void bsort (int* const, const int); int main (void) { int A[] = {56, 34, 2, 0, 1, -21, 6, 8, 7}; int i, n; //Размерность массива n = sizeof(A)/sizeof(A[0]); puts("\n Data items in original order:"); for (i = 0; i < n; i++) printf(" %3d", A[i]); // Вызов функции сортировки - bsort() bsort (A, n); puts("\n\n Data items in ascending order:"); for (i = 0; i < n; i++) printf(" %3d", A[i]); printf("\n\n... Press any key: "); _getch(); return 0; } // Определение функции void swap(int *pa, int *pb) { int temp; temp = *pa; *pa = *pb; *pb = temp; } void bsort (int *const arr, const int size) { int pass,j; //счетчик проходов и счетчик сравнений // Прототип функции обмена - swap() void swap (int*, int*); // Цикл для контроля проходов for (pass = 0; pass < size - 1; pass++ ) { // цикл для контроля сравнений на данном проходе for (j = 0; j < size - 1; j++) { // обмен значений при нарушении порядка возрастания if (arr[j] > arr[j + 1]) { swap(&arr[j], &arr[j+1]); } } } } |
В функции сортировки bsort() в качестве формального параметра используется константный указатель, который указывает на первый элемент заданного массива. Второй формальный параметр также константный, так подчеркивается его неизменность в теле функции bsort(). Передача функции размера массива в качестве параметра имеет два преимущества: это хороший стиль программирования и, кроме того, такую функцию можно использовать многократно.
Прототип функции swap() включен в тело функции bsort(), потому что это единственная функция, которая вызывает функцию обмена swap().

Пример выполнения программы представлен на рис. 9.2.
Рис. 9.2. Пример сортировки массива методом пузырька
10. Структуры – производные типы данных языка С
Структура – это совокупность нескольких переменных, часто различных типов, объединяемых под одним именем. Переменные, из которых состоит структура, называются ее членами, элементами или полями. С помощью структур удобно размещать в смежных полях связанные между собой элементы информации. Здесь могут быть собраны различные объекты – переменные, массивы, указатели, другие структуры и т. д. Если в массиве представлены переменные одного типа (например, float), то в структуре могут наличествовать переменные различных типов. Объявление структуры подготавливает шаблон, который можно использовать для создания ее объектов (экземпляров этой структуры) . При объявлении структуры определяется агрегатный тип данных, но не переменная.
Определение структуры состоит из двух шагов:
1) объявление шаблона структуры (задание нового типа данных);
2) определение переменных типа объявленного шаблона.
Имена шаблонов должны быть уникальными в пределах области их определения, для того чтобы компилятор мог различать их типы. Задание шаблона осуществляется с помощью ключевого слова struct, за которым следуют его имя и список элементов, заключенных в фигурные скобки. Имена элементов в одном шаблоне также должны быть уникальными. Задание только шаблона не влечет резервирования памяти компилятором. Шаблон предоставляет компилятору необходимую информацию об элементах структурной переменной для выделения места в оперативной памяти и организации доступа к ней при определении структурной переменной и использовании ее отдельных элементов.
Рассмотрим шаблон структуры для определения имени и фамилии работника (служащего – employee), его возраста, почасовой оплаты:
struct employee {
char Name [21]; // имя
char Surname [21]; // фамилия
int age; // возраст
double hourlysalary; // почасовой оклад
};
Как видно, шаблон структуры struct employee состоит из символьных массивов типа char, целого числа типа int и числа с плавающей точкой двойной точности типа double. Описание элементов производится в фигурных скобках, после закрывающей скобки обязательна точка с запятой.
Определение структуры начинается с ключевого слова struct. Идентификатор employee является именем-этикеткой (tag name), дескриптором, именует структуру и используется совместно с ключевым словом struct для объявления переменных структурного типа.
Переменные структуры объявляются так же, как и переменные других типов. На основе приведенного шаблона сделаем несколько объявлений новых структурных переменных:
struct employee new_ employee, * employeePtr, stack[120];
Здесь new_employee – переменная типа struct employee, *employeePtr – указатель на struct employee, stack[120] – массив из 120 элементов типа struct employee.
Переменные new_employee, *employeePtr, stack[102] могут быть объединены с определением структуры, а именно:
struct employee {
char Name [20+1]; // имя
char Surname [20+1]; // фамилия
int age; // возраст
double hourlysalary; // почасовой оклад
} new_employee, *employeePtr, stack[120];
Имя-этикетка не является для структуры обязательным. Если определение структуры не содержит его, то переменные для этой структуры могут быть объявлены только в ее определении, но не отдельно.
При создании структур часто используется ключевое слово typedef (оператор). Оно предоставляет программисту средство создания синонимов (или псевдонимов) для ранее определенных типов данных. К нему часто обращаются для того, чтобы дать укороченное имя структурному типу. Например, оператор вида
typedef struct card Card;
определяет новый тип с именем Card как синоним типа struct card.
Ключевое слово typedef может быть использовано в определении типа структуры без имени-этикетки. Например,
typedef struct {
char *Name; // имя
char *Surname; // фамилия
int age; // возраст
double hourlysalary; // почасовой оклад
} Man;
создает тип Man без использования отдельного оператора typedef. В данном примере необходимо предусмотреть выделение памяти под символьные указатели.
Созданный тип Man можно использовать для объявления структурных переменных типа struct employee, например
Man stack[120];
Примечание. Использование typedef помогает сделать программу более переносимой.
Синтаксис инициализации структур аналогичен инициализации массивов. Например, выполним инициализацию структуры:
struct employee {
char Name [20+1]; // имя
char Surname [20+1]; // фамилия
int age; // возраст
double hourlysalary; // почасовой оклад
} new_employee;
Возможный вариант инициализации:
struct employee {
char Name [20]; // имя
char Surname [20]; // фамилия
int age; // возраст
double hourlysalary; // почасовой оклад
} new_employee = { "Peter", "Smith", 25, 6.78 };
При инициализации структуры ее элементы (инициализаторы) должны соответствовать заданному типу и отделяться друг от друга запятыми.
Доступ к элементам (компонентам, полям) структуры осуществляется двумя способами:
1) с помощью оператора связывающей точки (оператора точки) – . при непосредственной работе со структурой;
2) с помощью стрелки –> при использовании указателей на структуры.
Общий формат доступа к элементам структуры имеет вид
имя_переменной_структуры . имя_поля;
имя_указателя_на_структуру –> имя_поля;
(*имя_указателя_на_структуру) . имя_поля;
Например, для рассмотренной инициализации можно изменить почасовой оклад с помощью оператора точки и указателя на структуру:
new_employee. hourlysalary = 21.0;
employeePtr –> hourlysalary = 21.0;
Следует обратить внимание на то, что new_employee – это имя всего объекта-структуры, а hourlysalary – имя элемента этой структуры. Аналогично и в случае использования указателя *employeePtr на структуру.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
Основные порталы (построено редакторами)
