1. 程式人生 > >C ++ 指標 | 指標與函式 實際運用_8

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 的值 大,那就是遞增排序,相反,則 遞減排序。


有編過程的人的程式碼,比那些無知的人使用的軟體更有價值。