日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言中比较大小的函数模板,C语言中实现模板函数小结 : 不敢流泪

發布時間:2023/12/4 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言中比较大小的函数模板,C语言中实现模板函数小结 : 不敢流泪 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

—-by boluor 2009/5/20

如果要寫個函數支持多種數據類型,首先想到的就是C++的模板了,但是有時候只能用C語言,比如在linux內核開發中,為了減少代碼量,或者是某面試官的要求…

考慮了一陣子后,就想到了qsort上.qsort的函數原型:

void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );

快排時,只要自己實現相應數據類型的比較函數cmpare就可以了.如果比較int型時,一個典型的compare函數如下:

int cmp(const void *a,const void *b){

return *((int *)a)-*((int *)b);

}

那么,就是說可以利用void *. void *意指未指定類型,也可以理解為任意類型。其他類型的指針可以直接賦值給void

*變量,但是void *變量需要強制類型轉換為其它指針類型。這個相信大家都知道。那么下面以一個簡單的題目為例,來探討如何在C語言中實現模板函數。

方法1: 利用void *.

在看下面的源程序之前,需要了解幾點。首先,在32位平臺上,任何類型的指針所占的字節都是4個字節,因為32位機器虛擬內存一般為4G,即2的

32次方,只要32位即4個字節就可以足夠尋址,sizeof(void *)=4;

其次,雖然各種不同類型的指針所占的空間都為4個字節,但是不同類型的指針所指的空間的字節數卻不同(這一點尤為重要,下面的程序我在開始沒有調通就因為

這點意識不強)。所以,如果你將一個指針強制轉換為另一個類型的指針,指針本身所占的字節是不變的,但是,如果對這個指針進行運算,比如

*p,p++,p-=1等一般都是不同的。 再次,函數指針應該了解下,這里不多說。

最后,因為Sandy跟我說,C++開始的時候模板的實現其實就是利用宏替換,在編譯的時候確定類型。所以,為了方便,類型也用了預編譯指

令#define。

#include "stdio.h"

#include "stdlib.h"

//typedef int T; //或者下面的也可以.

#define T int

int cmp(const void *a,const void *b){

return *((T *)a)-*((T *)b);

}

/*

//這個FindMin是Sandy寫的.felix021也寫了個,差不多的就不貼出來的.

void FindMin(const void *arr,int arr_size,int arrmembersize,int *index,

int (*cmp)(const void *,const void *b)){

int i;

*index=0;

char *p=(char *)arr;

char *tmp=p;

for (i=1;i

if (cmp(tmp,p)>0){

tmp=p;

}

p+=arrmembersize;

}

(*index)=((int)(tmp-arr))/arrmembersize;

}

*/

int FindMin(const void *arr,int arr_size,int arrmembersize,int (*cmp)(const void *,const void *)){

char *p=(char *)arr;//可以把指針看作是char *,如果轉換為int *,那下面的位移就不正確了.

int index=0;

int i;

for (i=1;i

if (cmp(p+index*arrmembersize,p+i*arrmembersize)>0){

index=i;

}

}

return index;

}

int main(){

int arr[]={2,1,1,2,3,4,5,0,2,3,1,3};

//int *result;

int result;//result保存的是最小值索引.

result=FindMin(arr,12,sizeof(arr[0]),cmp);

printf("%d,%d

",result,arr[result]);

system("PAUSE");

return 0;

}

方法2:利用宏。在編譯的時候確定類型。查閱資料的時候,很多都說這種方法比較好,方便調試,也很直觀,雖然很啰嗦。

#include

#ifndef _INT_

#define _INT_

#endif

int cmp(const void *a,const void *b){

#ifdef _INT_

return (*(int *)a-*(int *)b);

#elif _FLOAT_

return (fabs(*(float *)a-*(float *)b)<1e-6)?-1:1;

#elif _DOUBLE_

return (fabs(*(double *a)-*(double *)b)<1e-9)?-1:1;

#endif

}

#ifdef _INT_

void FindMin(int *arr,int arr_size,int *result,int cmp(const void *a,const void *b))

#elif _FLOAT_

void FindMin(float *arr,int arr_size,float *result,int cmp(const void *a,const void *b))

#elif _DOUBLE_

void FindMin(double *arr,int arr_size,double *result,int cmp(const void *a,const void *b))

#endif

{

int i;

*result=arr[0];

for(i=1;i

if(cmp(&arr[i],result)>0)

*result=arr[i];

}

}

int main(){

int arr1[]={1,2,4,2,1,7};

int result;

FindMin(arr1,6,&result,cmp);

printf("%d

",result);

return 0;

}

方法3:在findmin中,不用強制類型轉換為char *,直接利用memcpy內存拷貝過去,這時,還可以在參數列表中保存結果,而不是索引。此方法由CSDN上的ltc_mouse提供。

#include "stdio.h"

#include "stdlib.h"

#include "string.h"

void FindMin(void *arr,int arr_size,int arrmembersize,void * result,

int (*fpCmp)(const void *,const void *b)){

int i;

unsigned char *pSrc = (unsigned char *)arr;

unsigned char *pRes = (unsigned char *)result;

memcpy( (void *)pRes, (const void *)pSrc, arrmembersize );

for (i=1;i

pSrc += arrmembersize;

if ( fpCmp((const void *)pSrc, result)<0 ){

memcpy( (void *)pRes, (const void *)pSrc, arrmembersize );

}

}

}

int cmp_int(const void *a, const void *b)

{

return ( *(int *)a - *(int *)b );

}

int cmp_double(const void *a, const void *b)

{

return ( (fabs(*(double *)a < *(double *)b ))<1e-9) ? -1 : 1; //這個可能要調整下

}

int main()

{

int iArr[]={1,3,5,-1,3,4,7};

double fArr[]={-3.2, 2.3, 7.8, -9.3, 4.7, 10.5};

int iMin;

double fMin;

FindMin( (void *)iArr, sizeof(iArr)/sizeof(iArr[0]), sizeof(iArr[0]), (void *)&iMin, cmp_int );

FindMin( (void *)fArr, sizeof(fArr)/sizeof(fArr[0]), sizeof(fArr[0]), (void *)&fMin, cmp_double);

printf("Min of iArr is %d

", iMin);

printf("Min of fArr is %lf

", fMin);

return 0;

}

后記:

感謝所有幫助解決這個問題了朋友!這問題糾結了我兩天,通過這個感覺對指針的理解又多了一點。

CSDN上的hikaliv建議看下va_list,va_args等看下可變參數如何讀取,順便理解了下,其實之前Sandy跟我說過,只

是一直沒看,現在看了感覺收獲蠻大。Felix021說我的代碼風格不好,開始不明白,不過等他和Sandy寫出來他們寫的FindMin后,就明白了,

我的代碼太晦澀了,還是寫個自己看的,別人看了看不出大概,真的多注意了。

雖然,在C語言中實現模板不是不可能,但是我還是傾向于用模板,C++我了解的太少了。

總結

以上是生活随笔為你收集整理的C语言中比较大小的函数模板,C语言中实现模板函数小结 : 不敢流泪的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。