Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2009 лекции ПЯВУ часть1.doc
Скачиваний:
23
Добавлен:
27.03.2015
Размер:
823.3 Кб
Скачать

6.9. Указатель на функцию

Возможны только две операции с функциями [3]:

  1. вызов,

  2. взятие адреса.

Указатель, полученный с помощью последней операции, можно впоследствии использовать для вызова функции (рис. 6.24.)

void error(char* p) { /* ... */ }

void (*efct)(char*); // указатель на функцию

void f() {

efct = &error; // efct настроен на функцию error

(*efct)("error");} // вызов error через указатель efct

Рис. 6.24. Использование указателя на функцию

Для вызова функции с помощью указателя (efctв нашем примере) надо вначале применить операцию разыменования к указателю -*efct. Поскольку приоритет операции вызова()выше, чем приоритет разыменования*, нельзя писать просто*efct("error"). Это будет означать*(efct("error")), что является ошибкой. По той же причине скобки нужны и при описании указателя на функцию. Однако писать простоefct("error")можно, так как транслятор понимает, чтоefctявляется указателем на функцию, и создает команды, делающие вызов нужной функции.

Формальные параметры в указателях на функцию описываются так же, как и в обычных функциях. При присваивании указателю на функцию требуется точное соответствие типа функции и типа присваиваемого значения (рис. 6.25.)

void (*pf)(char*); // указатель на void(char*)

void f1(char*);

int f2(char*);

void f3(int*);

void f() {

pf = &f1; // нормально

pf = &f2; // ошибка: не тот тип возвращаемого значения

pf = &f3; // ошибка: не тот тип параметра

(*pf)("asdf"); // нормально

(*pf)(1); // ошибка: не тот тип параметра

int i = (*pf)("qwer"); // ошибка: void присваивается int

}

Рис. 6.25. Ошибки, возникающие при использовании указателя на функцию

На рис. 6.26 и 6.27 показана функция пузыковой сортировки, которая мортирует массив либо по возрастанию, либо по убыванию в зависимотис от желания пользователя. Третьим параметром функции является указатель на функцию, которая принимает два целых числа и возвращает целое.

#include <iostream>

using namespace std;

void bubble (int *, const int, int(*)(const int, const int));

int ascending(const int, const int);

int descending(const int, const int);

int main(){

const int Size = 10;

int order, a[Size] = {2,6,4,8,10,12,89,68,45,37};

cout<<"Enter order 1 or 2"<<endl;

cin>>order;

for(int i = 0; i<Size; i++)

cout<<a[i]<<'\t';

cout<<endl;

cout<<endl;

if(order==1)

bubble(a, Size, ascending);

else

bubble(a, Size, descending);

for(i = 0; i<Size; i++)

cout<<a[i]<<'\t';

cout<<endl;

return 0;}

Рис. 6.26. Функция mainпрограммы универсальной пузырьковой сортировки

void bubble (int *work, const int size, int(*compare)(int,int)) {

void swap(int *, int*);

for (int k=size-1; k>1;k--)

for(int i = 0; i<k;i++)

if((*compare)(work[i],work[i+1]))

swap(&work[i], &work[i+1]); }

void swap(int * a, int* b) {

int temp;

temp = *a;

*a = *b;

*b = temp; }

int ascending(const int a, const int b)

{

return b<a;

}

int descending(const int a, const int b)

{

return a<b;

}

Рис. 6.27. Функции сортировки, обмена и сравнения

6.10. Командная строка аргументов

Системные средства [11], на которые опирается реализация языка С, позволяют передавать командную строку аргументов или параметров начинающей выполняться программе. Когда функция mainвызывается к исполнению, она вызывается с двумя аргументами. Первый аргумент (условно называемыйargc) указывает число аргументов в командной строке, с которыми происходит обращение к программе; второй аргумент (argv) является указателем на массив символьных строк, содержащих эти аргументы, по одному в строке. Работа с такими строками - это обычное использование многоуровневых указателей.

Самую простую иллюстрацию этой возможности и необходимых при этом описаний дает программа echo, которая просто печатает в одну строку аргументы командной строки, разделяя их пробелами (рис. 6.28). Таким образом, если дана команда

echo Hello, world

то выходом будет

Hello, world

По соглашению argv[0]является именем, по которому вызывается программа, так чтоargcпо меньшей мере равен 1. В приведенном выше примереargcравен 3, аargv[0],argv[1]иargv[2]равны соответственно «echo», «Hello,» и «world». Первым фактическим аргументом являетсяargv[1], а последним -argv[argc-1]. Еслиargcравен 1, то за именем программы не следует никакой командной строки аргументов.

#include <iostream>

using namespace std;

int main(int argc, char* argv[])

{

int i;

//первый вариант*********************************

for(i = 1; i < argc; i++)

cout << argv[i] << (i<argc-1) ? ' ' : '\n';

//***********************************************

//второй вариант*********************************

while (--argc > 0)

cout<<*++argv << (argc > 1) ? ' ' : '\n';

//***********************************************

return 0;

}

Рис. 6.28. Работа команды echo