C ++ 指標 | 指標與函式 實際運用_8
函式指標的用法
1、
利用指標函式 和 回撥函式 來 列印" Hello ",我們直接上碼:
#include<iostream>
void A()
{
printf("Hello");
}
void B(void (*ptr)())
{
ptr();
}
int main()
{
void (*p)() = A;
B(p);
}
執行結果:
結果正確的,A通過 ptr() 回撥 並 執行成功。
注意:
(1)
void B(void (*ptr)())
{
ptr();
}
第一:這個函式B,將 指標函式 作為 引數。ptr 指向一個 沒有引數 並且 返回空引數的 A函式。
第二:我們通過 ptr() 來呼叫任何東西函式。(A會通過 ptr() 來執行,打印出hello)
第三:我們通過指標函式 呼叫 函式 的這個語句是一個回撥函式。
(2)
int main()
{
void (*p)() = A;
B(p);
}
第一:定義一個函式指標 把 地址A 傳遞給它。
第二:函式B 傳遞給它的 函式指標p。
第三:回撥函式:當函式的引用傳遞給另一個函式時,那個特定的函式 被稱為 回撥函式(Callback Function). 所以,A是一個回撥函式。它可以由B通過引用,通過函式指標回撥。
這裡也可以直接這麼寫:
int main()
{
B(p);
}
2、
函式指標和回撥函式 實際的運用
這個例子是把一維數組裡面的數字按遞增順序進行排序。
#include<iostream> void BubbleSort(int *A, int n) { int i,j,temp; for(i=0; i<n; i++) for(j=0; j<n-1; j++){ if(A[j] > A[j+1]){ temp = A[j]; A[j] = A[j+1]; A[j+1] = temp; } } } int main() { int i, A[] = {3,2,1,5,6,4}; BubbleSort(A, 6); for(i= 0; i< 6;i++){ printf("%d ",A[i]); } }
執行結果:
如果有時候我有要遞增,有些時候我又要遞減,那該怎麼辦哦?寫多一個排序函式嗎?不! 我們使用回撥來解決這個問題:
#include<iostream>
int compare(int a , int b)
{
if(a > b) return 1;
else return -1;
}
void BubbleSort(int *A, int n, int (*compare)(int,int))
{
int i,j,temp;
for(i=0; i<n; i++)
for(j=0; j<n-1; j++){
if(compare(A[j],A[j+1]) > 0){
temp = A[j];
A[j] = A[j+1];
A[j+1] = temp;
}
}
}
int main()
{
int i, A[] = {3,2,1,5,6,4};
BubbleSort(A, 6, compare);
for(i= 0; i< 6;i++) printf("%d ",A[i]);
}
執行結果:
注意:
(1)
void BubbleSort(int *A, int n, int (*compare)(int,int))
{
......
}
BubbleSort函式 將 函式指標int (*compare)(int,int) 作為引數;
int (*compare)(int,int) 意義為:回撥函式 或 該指標應指向的函式 必須取 兩個整數為引數,而且它還會返回一個整數;
(2)
int compare(int a , int b)
{
if(a > b) return 1;
else return -1;
}
compare 是一個回撥函式。
(3)
int main()
{
int i, A[] = {3,2,1,5,6,4};
BubbleSort(A, 6, compare);
for(i= 0; i< 6;i++) printf("%d ",A[i]);
}
BubbleSort函式 加了引數:compare,這個是地址是傳遞給 BubbleSort函式的。也就是傳遞給 int (*compare)(int,int)。
這個時候我們要遞增了,不用重新編碼,直接修改函式即可:
#include<iostream>
int compare(int a , int b)
{
if(a > b) return -1;
else return 1;
}
void BubbleSort(int *A, int n, int (*compare)(int,int))
{
int i,j,temp;
for(i=0; i<n; i++)
for(j=0; j<n-1; j++){
if(compare(A[j],A[j+1]) > 0){
temp = A[j];
A[j] = A[j+1];
A[j+1] = temp;
}
}
}
int main()
{
int i, A[] = {3,2,1,5,6,4};
BubbleSort(A, 6, compare);
for(i= 0; i< 6;i++) printf("%d ",A[i]);
}
執行結果:
注意:
(1)
int compare(int a , int b)
{
if(a > b) return -1;
else return 1;
}
修改這個地方即可:當 a > b 返回 -1;否則 返回 1;
3、
我們使用新的陣列來排序,A[] = {-31,22,-1,50,-6,4};
#include<iostream>
int compare(int a , int b)
{
if(a > b) return -1;
else return 1;
}
int absolute_compare(int a, int b)
{
if(abs(a)>abs(b)) return 1;
return -1;
}
void BubbleSort(int *A, int n, int (*compare)(int,int))
{
int i,j,temp;
for(i=0; i<n; i++)
for(j=0; j<n-1; j++){
if(compare(A[j],A[j+1]) > 0){
temp = A[j];
A[j] = A[j+1];
A[j+1] = temp;
}
}
}
int main()
{
int i, A[] = {-31,22,-1,50,-6,4};
BubbleSort(A, 6, absolute_compare);
for(i= 0; i< 6;i++) printf("%d ",A[i]);
}
執行結果:
看來不起作用,因為我們寫的氣泡排序只能對正數,我們使用 qsort()函式 來實現:
#include<iostream>
#include<algorithm>
int compare(const void* a, const void* b)
{
int A = *((int*)a);
int B = *((int*)b);
return A-B;
}
int main()
{
int i, A[] = {-31,22,-1,50,-6,4};
qsort(A, 6, sizeof(int),compare);
for(i= 0; i< 6;i++) printf("%d ",A[i]);
}
執行結果:
程式碼解析:
(1)
qsort(A, 6, sizeof(int),compare);
C++ 要呼叫qsort庫要使用 #include<algorithm> 。
第一個引數:陣列。第二個引數:陣列長度。第三個引數:資料型別的大小。
第四個引數:函式指標。這個函式指標是指向比較函式的指標。
(2)
int compare(const void* a, const void* b)
{
......
}
解析 比較函式: const void* a,這裡的 const 是不能改變這個變數。
因為qsort函式的通用設計, 我們不得不使用void指標,void 是通用型別,我們可以將它們轉換為任何資料型別的指標,這是qsort函式的規範;
記住,qsort可以對任何陣列排序,而不僅僅是整型陣列。只是,你必須給出比較邏輯。
(3)
int compare(const void* a, const void* b)
{
int A = *((int*)a);
int B = *((int*)b);
return A-B;
}
怎麼理解?????? 一步一步來。
int A = (int*)a;
你可以將此視為作為 void指標傳遞 的第一個元素的引用。
要獲取元素,如果它是一個整數列表,我首先必須對 void指標 進行型別轉換到 int指標。
然後我將不得不使用 * 運算子來指標取值:
int A = *((int*)a);
接下來要講的是: return A-B;
如果A 的值 比B 的值 大,那就是遞增排序,相反,則 遞減排序。
有編過程的人的程式碼,比那些無知的人使用的軟體更有價值。