Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабы_по_проге_Берлин / Книги / учебное пособие ОАиП.pdf
Скачиваний:
49
Добавлен:
11.02.2015
Размер:
947 Кб
Скачать
// в строке одни пробелы
// пропуск позиции знака // выбор цифр числа из строки
// возврат signed int

int i=0, znak;

 

while(*(ss+i)==' ') i++;

 

if (!*(ss+i)) return 0.;

// в строке одни пробелы

znak=(*(ss+i)=='-')? -1: 1;

 

if (*(ss+i)=='+' || *(ss+i)=='-')

i++; // пропуск позиции знака

for(n=0.0; (*(ss+i)>'0' && *(ss+i)<='9') || *(ss+i)=='.'; i++)

{ if (ii) ii*=10;

// число цифр после десятичной точки

if (*(ss+i)!='.')

n=10.0*n+(*(ss+i)-'0'); // выбор цифр числа из строки

else ii=1;

// выбрана десятичная точка

}

 

if(!ii) ii=1;

// если введено целое число

return znak*n/ii;

// возврат signed double

}

// функция перевода цифровой символьной строки в signed int int atoi(char ss[]) // в функцию передается указатель

{ int n,i=0,znak; while(*(ss+i)==' ') i++; if (!*(ss+i)) return 0;

znak=(*(ss+i)=='-')? -1: 1;

if (*(ss+i)=='+' || *(ss+i)=='-') i++; for(n=0; *(ss+i)>'0' && *(ss+i)<='9'; i++) n=10*n+(*(ss+i)-'0');

return znak*n;

}

// функция перевода signed int в символьную строку

void itoa(int n,char *ss)

 

{ int i=0, znak;

 

if ((znak=n)<0) n=-n;

//

do

//

{ ss[i++]=n%10+'0';

//

} while((n/=10)>0);

//

if (znak<0) ss[i++]='-';

 

ss[i]='\0';

 

for(n=0;n<i/2;n++)

 

{ ss[n]+=ss[i-1-n];

 

ss[i-1-n]=ss[n]-ss[i-1-n]; ss[n]-=ss[i-1-n];

}

}

Указатели на функции

В языке С (С++) функция не может быть значением переменной, в тоже

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

Указатель на функцию – это такой тип переменной, которой можно присваивать адрес точки входа в функцию, то есть адрес первой исполняемой команды. Эта переменная в дальнейшем может использоваться для вызова функции вместо ее имени. Определение указателя на функцию имеет следующий общий вид:

тип_результата (*имя_указателя_на функцию)(список_типов_параметров);

В объявлении

int (*fun)(int, int *);

переменная fun является указателем на функцию с двумя параметрами: типа int и указателем на int. Сама функция должна возвращать значение типа int. Круглые скобки, содержащие имя указателя fun и признак указателя *, обязательны, иначе запись

int *fun (int, int *);

будет интерпретироваться как объявление функции fun возвращающей указатель на int. Это следует из того, что приоритет префиксного оператора * ниже, чем приоритет ().

Вызов функции возможен только после инициализации значения указателя fun и имеет вид:

(*fun)(i,&j);

В этом выражении для получения адреса функции, на которую ссылается указатель fun используется операция разадресации * . Вызов функции через указатель возможен так же в обычным способом:

fun( i,&j);

Ниже приведен пример использования указателя на функцию инициализированного адресом системной функции strcmp.

#include <stdio.h>

#include <string.h>

#define n 80

void check(char *, char , int ( cmp)(const char *,const char *))); void main(void)

{ char s1[n],s2[n];

int (*p)(const char *,const char *); p=strcmp; // p – адрес strcmp() gets(s1); gets(s2); check(s1,s2,p);

}

void check(char *a, char b, int ( cmp)(const char *,const char *)))

{printf("\n строки ");

if (!(*cmp)(a,b)) printf("равны");

else printf("не равны");

}

При вызове check ей передается два указателя на символьные строки и один на функцию. Аналогично можно обращаться к check, используя и указатели на другие функции, если возвращаемый тип и передаваемые параметры, совпадают с рассмотренными выше. Выражение if(!(*cmp)(s1,s2)) можно заменить на if(!cmp(s1,s2)). Можно вызвать функцию check также следующим образом: check(s1,s2,strcmp). При этом не требуется использовать дополнительно указатель p.

Ниже приводятся примеры некоторых более сложных деклараций:

int (*ukz)[10]; - объявление указателя ukz на массив из 10 элементов int; char (*(*fun))[]() - функция, возвращающая указатель на массив из

функций, возвращающих значение типа char;

char (*(*m_ukz[5])())[10] - m_ukz[5] массив из указателей на функции,

возвращающие указатели на массив из [10] элементов char.

Примеры программ

Пример . Использование указателя на функцию в качестве параметра функции вычисляющей производную от функции cos(x).

double proiz(double x, double dx, double (*f)(double x) );

double fun(double z);

 

 

int main()

 

 

{ double x;

//

точка вычисления производной

double dx;

//

приращение

double z;

//

значение производной

scanf("%f,%f",&x,&dx); // ввод значений x и dx

z=proiz(x,dx,fun);

 

// вызов функции

printf("%f",z);

// печать значения производной

return 0;

 

 

}

 

 

double proiz(double x,double dx, double (*f)(double z) ) { // функция вычисляющая производную

double xk,xk1,pr; xk=fun(x); xk1=fun(x+dx); pr=(xk1/xk-1e0)*xk/dx; return pr;

}

double fun( double z)

{ // функция от которой вычисляется производная return (cos(z));