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语言中实现模板函数小结 : 不敢流泪的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言程序设计答案黄保和编,C语言程序设
- 下一篇: c语言中二重指针如何赋值,关于二重指针释