Интерфейс с программами и подпрограммами, написанными на разных языках программирования. Указатели на функции

Страницы работы

Содержание работы

                            Интерфейс

   с программами и подпрограммами, написанными на разных языках

                      программирования.

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

Рассматриваются вопросы взаимодействия между программами и подпрограммами, написанными на разных языках программирования.

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

Каждая функция характеризуется типом возвращаемого значения, именем и сигнатурой (количеством, порядком следования и типом операндов). Таким образом, сигнатура – это список параметров функции.

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

 <тип возвращаемого значения функции> (*<имя _ указателя>)

                       (<спецификация параметров>).

Например, создадим пустое меню для вызова некоторых функций:

сhar FileName[30]; //обрабатываемая строка с инициализацией

void act1 (char *name);

void act2 (char *name);

void act3 (char *name);

typedef void (*MENU) (char *) // тип MENU указателей на функцию с

       // возвращаемым значением VOID и с одним операндом типа VOID

MENU MenuAct[3]={act1,act2,act3} //инициализация таблицы адресов

Void main()

{ int num;

  cout << “\n Введите номер пункта меню”;

  cin>>num;

  (*MenuAct[num-1])(FileName);

}

Как видим, в данной программе создан набор функций одного типа и сигнатуры. Используя данный массив указателей на эти функции, можем  их выполнить.

Аналогично предыдущему примеру можно решить алгебраическое уравнение методом деления пополам на отрезке от float A до float B с точностью float E.

#include <stdlib.h>

#include <stdio.h>

float f (float x)

  {return x*x*x*x*10-X*5+3;} //исследуемая функция

typedef float (*PointFunc) (float); //предопределение функции

float des(PointFunc f,float A,float B,float E)

{ float x,y,c,Fx,Fy,Fc;

  x=A; y=B; Fx=(*f)(x); Fy=(*f)(y);

 if (Fx*Fy>0.0)

  { printf (“неверный интервал решения\n”)

    exit(1);

  }    // выход в случае ошибки

 do

  { c=(y-x)/2;

    Fc=(*f)(c);

    if (Fc*Fx>0){x=c; Fx=Fc;}

     else

        {y=c; Fy=Fc;}

  } while (Fc!=0||y-x>E);

 return c;

}

void main()

{ float result;

  result=res(f,0.0,2.0,1e-5);

  printf (“result= %f ”,result);

}

В С функции сами по себе не являются переменными, но как мы уже видели, можно определить указатель на функцию, который может быть может быть присвоен функции, установлен в массиве указателей, передан другой функции, быть возвращаемым значением функции и т.д. Ниже в качестве примера показана модификация процедуры сортировки таким образом, что дополнительный аргумент N позволяет использовать числовую или лексикографическую сортировку.  

Лексикографическое сравнение двух линий выполняется с помощью функции стандартной библиотеки STRCMP, но возвращаемое ей значение такое же как и в функции NUMCMP.

  #include <stdio.h>

  #include <string.h>

  #defineMAXLINES 5000     /* max количество сортируемых линий */

char *lineptr[MAXLINES]; /*указатели на линии текста*/

int readlines (char *lineptr[], int nlines);

  void writelines (char *lineptr[], int nlines);

  void qsort(void *lineptr[], int left, int right,

                    int (*comp) (void *, void *));

  int numcmp (char *, char *);

  /* сортировка вводимых строк */

main (int argc, char *argv[])

    { intnlines;       /*число вводимых строк */

intnumeric = 0;      /* 1если числовая сортировкаt */

if (argc>1 && strcmp(argv[1], "-n") == 0)

                numeric = 1;

      if ((nlines = readlines (lineptr, MAXLINES)) >= 0)

        { qsort( (void **) lineptr, 0, nlines-1,

                       int (*)(void*, void*))(numeric?numcmp:strcmp));

             writelines (lineptr, nlines);

          return 0;

        } else

           {   printf ("input too big to sort\n");

               return 1;

           }

      }

QSORT написана так что может выполняться с любым типом данных, а не только с цифровыми данными. Как следует из прототипа QSORT требует для работы массив указателей, двух целых чисел и функции с двумя аргументами-указателями. Генерированный тип – VOID*, и затем преобразуется к нужному типу операцией преобразования.

/*qsort: sort v[left]...v(right] Into increasing order*/

void qsort(void *v[], int left, int right,

                    int (*comp) (void *, void *))

 { int i, last;

   void swap (void >v[], int, int);

if (left >= right) /*ничего не делать, если в массиве */

return;          /* меньше двух элементов */

swap(v, left, (left + right)/2);

          last = left;

          for (i = left+1; i <= right; i++)

                if ((*comp)(v[i]. v[leftl) < 0)

                     swap(v, ++last, i);

          swap(v, left, last);

          qsort(v, left, last-1, comp);

          qsort(v, last+1, right, comp);

 }

Декларация должна выполняться с некоторой  осторожностью.

  int (*comp) (void *, void *)

которая означает, что COMP это указатель на функцию с двумя аргументами типа  VOID* и возвращает INT. Выражение

  if ((*comp)(v[i], v[left]) < 0

включает декларацию указателя на функцию COMP, которая и будет вызвана

(*comp) (v[i], v[left])

Скобки необходимы, чтобы правильно определить входящие элементы.

   int *comp(void *, void *)    /* WRONG */

  #include <stdlib.h>

  /*  numcmp: выполняет цифровое сравнение s1 и s2 */

int numcmp (char *s1, char *s2)

   {  double v1, v2;

       v1 = atof (s1);

       v2 = atof (s2);

        if (v1 < v2)

           return -1;

        else if (v1 > v2)

           return 1;

        else

           return 0;

Похожие материалы

Информация о работе