如何在c中正确使用函数指针

时间:2015-10-19 08:26:33

标签: c function-pointers

我有这个问题:

我有一个程序,计算两个算法(shellsort和插入排序)的执行时间,每个算法分别在三个不同的数组(最有利的情况,最不利的情况和随机的情况),所以基本上我需要做一个相同的功能东西六次(shell排序最有利的情况,shell排序最不利的情况和shell排序随机的情况下,和插入排序相同的东西)但我不想复制和粘贴代码六次,并且一个函数与六个案例并不高效。所以我试图理解功能指针,但我不知道如何在那里使用它。这是我的代码:

void testInsMostUnfavorableCase()
{
    int i,j,n=500,K=1000,p=0;
    double c,d,t1,t2,t;
    printf("Insertion sort on most unfavorable case\n");
    printf("%9s%20s%12s%12s%12s\n", "n","t(n)","t(n)/n^0.8","t(n)/n","t(n)/nlogn");
    for(i=1;i<8;i++)
    {       
        int v[n];
        descending(v,n); //THERE
        c=microseconds();
        ins_sort(v,n); //THERE
        d=microseconds();
        t=d-c;
        if(t<500) /*times <500ms */
        {
            p=1;
            c=microseconds();
            for(j=0;j<K;j++)
            {
                descending(v,n); //THERE
                ins_sort(v,n); //THERE
            }
            d=microseconds();
            t1=d-c;
            c=microseconds();
            for(j=0;j<K;j++)
                descending(v,n); //THERE
            d=microseconds();
            t2=d-c;
            t=(t1-t2)/K;
            printf("%3s%6d%20.3f%12f%12f%12f\n","(*)",n,t,t/pow(n,0.8),t/n,t/(n*log(n)));
        }
        else
            printf("%9d%20.3f%12f%12f%12f\n",n,t,t/pow(n,0.8),t/n,t/(n*log(n)));
        n=n*2;
    }
    if(p==1)
            printf("%s%d%s\n","*: Average time (in microseconds) of ",K," algorithm executions." );
}

void testInsMostFavorableCase() {...}
void testInsRandomCase() {...}
void testShellMostUnfavorableCase() {...}
void testShellMostFavorableCase() {...}
void testShellRandomCase() {...}

问题是我必须重复六次才能使用THERE更改注释行。你有任何其他解决方案使用功能指针吗?

3 个答案:

答案 0 :(得分:1)

  

我不想复制和粘贴代码六次

然后不要。这三个测试用例仅因输入数据而不同 - &gt;

benchmarkInsertionSort( int[] data, int dataSize)

每个算法 每个算法

benchmarkInsertionSort(dataset1, 500);
benchmarkInsertionSort(dataset2, 500);
benchmarkInsertionSort(dataset3, 500);

在您的代码中,将每个测试运行的设置(例如int v[n]; descending(v,n);)与要测试的实际操作分开。

如果你真的想,你可以使用函数指针使基准代码更通用:

// Define a type for a pointer to a void function with two arguments (int[],int):
typedef void (*sort_function_t)(int[] data, int size);

// A function compatible with the pointer type above:
void ins_sort( int[] data, int size ) {
    ...
}

// Another function compatible with the pointer type above:
void shell_sort( int[] data, int size ) {
    ...
}

void benchmarkSortAlgo( sort_function_t sortFunction, int[] data, int dataSize ) {
  ...
  // Call the function pointed to by the sortFuntion parameter:
  sortFunction(data,dataSize);
  ...
}

...
// Pass pointers to the sort function to the benchmark.
// Note that we get the pointer to a function by just using 'functionname' without any parenthesis! 
benchmarkSortAlgo( ins_sort, testData1, 500 );
benchmarkSortAlgo( shell_sort, testData2, 500 );
...

答案 1 :(得分:0)

它遵循一个例子,编译从中获得灵感。 它完全基于您的代码,因此它仍然需要更改,因为我只添加了指向 THERE 标记的函数的指针。

#include <stdio.h>
#include <math.h>

typedef void(*fnptr)(int*, int);

void test(
    fnptr descending_ptr,
    fnptr ins_sort_ptr
    )
{
    int i,j,n=500,K=1000,p=0;
    double c,d,t1,t2,t;
    printf("%9s%20s%12s%12s%12s\n", "n","t(n)","t(n)/n^0.8","t(n)/n","t(n)/nlogn");
    for(i=1;i<8;i++)
    {
        int v[n];
        descending_ptr(v,n); //THERE
        c=microseconds();
        ins_sort_ptr(v,n); //THERE
        d=microseconds();
        t=d-c;
        if(t<500) /*times <500ms */
        {
            p=1;
            c=microseconds();
            for(j=0;j<K;j++)
            {
                descending_ptr(v,n); //THERE
                ins_sort_ptr(v,n); //THERE
            }
            d=microseconds();
            t1=d-c;
            c=microseconds();
            for(j=0;j<K;j++)
                descending_ptr(v,n); //THERE
            d=microseconds();
            t2=d-c;
            t=(t1-t2)/K;
            printf("%3s%6d%20.3f%12f%12f%12f\n","(*)",n,t,t/pow(n,0.8),t/n,t/(n*log(n)));
        }
        else
            printf("%9d%20.3f%12f%12f%12f\n",n,t,t/pow(n,0.8),t/n,t/(n*log(n)));
        n=n*2;
    }
    if(p==1)
            printf("%s%d%s\n","*: Average time (in microseconds) of ",K," algorithm executions." );
}

void test() { /* ... */ }

double microseconds() { return 0; }
void descendingInsMostFavorableCase(int*, int) { /* ... */ }
void insSortInsMostFavorableCase(int*, int) { /* ... */ }

int main() {
    printf("Insertion sort on most favorable case\n");
    test(&descendingInsMostFavorableCase, &insSortInsMostFavorableCase);
}

答案 2 :(得分:0)

鉴于问题的标题,这里有一些如何使用泛型编程的提示。那就是:如何在学术目的之外实现这些排序算法以供实际使用。

要将参数中的这些不同功能分解,您似乎需要以下内容:

  • 排序算法。
  • 使用
  • 测试数据
  • 数据的大小
  • 在通用算法中,一个数据项的大小
  • 在通用算法中,比较函数(“functor”)

如果要将排序算法作为函数的参数,首先需要标准化其格式。同时将它实现为可以接受任何类型的通用排序函数也是一个好主意。

为实现这一目标,您可以了解如何实现标准C库qsort,以了解如何编写通用排序算法:

void qsort(void *base, size_t nmemb, size_t size,
     int (*compar)(const void *, const void *));

base是数据数组,nmemb是对象数,size是每个对象的大小,compar是指向比较函数的函数指针。

应该实现比较函数,以便给定两个参数ab,如果a > b则返回正值,如果a < b则返回负值0如果a == b。因此对于有符号整数数据,该函数只包含一行return a - b;。 (它的工作原理与strcmp,memcmp等完全相同。)

如果您使用编写排序函数的概念,则可以将比较函数键入:

typedef int compare_t (const void*, const void*);

然后,所有排序函数都将具有标准签名,例如:

void insertion_sort (void*      base,
                     size_t     n,
                     size_t     obj_size,
                     compare_t* comp);

意思是你也可以输入那个函数签名:

typedef void sort_t (void*      base,
                     size_t     n,
                     size_t     obj_size,
                     compare_t* comp);

然后你会得到一个基准函数,如:

void benchmark (sort_t*    sort, 
                void*      base,
                size_t     n,
                size_t     obj_size,
                compare_t* comp)
{
   // set up & start timer etc

   sort(base, n, obj_size, comp);

   // stop timer
   // print results
}

最后,你的主要看起来像这样,例如整数:

benchmark(insertion_sort,
          most_favourable, // this is an int array
          sizeof(most_favourable) / sizeof(*most_favourable),
          sizeof(int),
          compare_int);

benchmark(insertion_sort,
          random_case, // this is an int array
          sizeof(random_case) / sizeof(*random_case),
          sizeof(int),
          compare_int);

等等。在调用者中,您可以创建大量具有不同数据,不同数据类型等的测试用例。