1. 程式人生 > >C/C++ 兩個數交換引發的連環案

C/C++ 兩個數交換引發的連環案

1. 一般法

       如何交換兩個數?一般來說,交換兩個數需要藉助中間變數,即先令中間變數temp存放其中一個數a,然後再把另一個數b賦值給已被轉移資料的a,最後把存有a上午中間變數賦值給b,這樣a和b就完成了交換。下段程式碼就實現了這個功能:

#include <iostream>
using namespace std;
int main(){
    int a=2,b=5;
    int temp=a;
    a=b;
    b=temp;
    cout<<"a="<<a<<";b="<<b<<endl;
    return 0;
}

輸出  a=5;b=2

2. 將交換功能寫成函式

案情一:

#include <iostream>
void swap(int p1,int p2){
    int temp=p1;
    p1=p2;
    p2=temp;
}

int main(){
    int a=2,b=5;
    swap(a,b);
    cout<<"a="<<a<<";b="<<b<<endl;
    return 0;
}

輸出  a=2;b=5

        為什麼沒有實現交換功能?這是因為函式在接收引數的過程是單向一次性的值傳遞

,相當於產生了一個副本,swap函式對副本的操作不會影響main函式中的a,b的值 .下面介紹使用指標的方法 :

       指標變數存放的是地址,那麼使用指標變數作為引數時傳進來的也是地址 .只有在獲取地址的情況下對元素進行的操作才能真正地修改變數 .為此修改上述程式碼:

破案:

#include <iostream>
void swap(int* p1,int* p2){
    int temp=*p1;
    *p1=*p2;
    *p2=temp;
}

int main(){
    int a=2,b=5;
    int *p1=&a,*p2=&b;
    swap(p1,p2);
    cout<<"a="<<a<<";b="<<b<<endl;
    cout<<"*p1="<<*p1<<";*p2="<<*p2<<endl;
    return 0;
}

輸出  a=5;b=2

         *p1=5;*p2=2

        p1,p2中存放的是a,b的地址,*p1,*p2就是地址中存放的元素,對*p1,*p2進行操作就可以起到改變那個儲存的元素的作用 .

———————————————————————————————————————————————————————

如果將函式誤寫成以下三種又會發生什麼?

案情二:

void swap(int* p1,int* p2){
    int* temp=p1;
    p1=p2;
    p2=temp;
}

輸出  a=2;b=5          *p1=2;*p2=5

       這種寫法的思想在於直接把兩個地址交換,認為地址交換之後元素就交換了,這裡產生了很大的誤區 .函式引數的傳送方式是單向一次性的,main函式傳給swap函式的“地址”其實是“無符號整數”,其本身也跟普通變數一樣只是“值傳遞”,swap函式對地址本身進行修改並不能對main函式裡的地址修改,能夠使main函式裡的資料發生變化的只能是swap函式中對地址指向的資料進行修改 .

案情三:

void swap(int* p1,int* p2){
    int* temp=*p1;  //無法編譯
    *p1=*p2;
    *p2=*temp;
}

 案情四:

void swap(int* p1,int* p2){
    int* temp;
    *temp=*p1;
    *p1=*p2;
    *p2=*temp;
}

無輸出

       既然*temp、*p1、*p2都可以“看成”int型變數,那完全就可以像普通變數那樣進行交換操作 .這種想法其實沒什麼問題,但在定義int型的指標變數temp時,temp沒有初始化 .也就是說,指標變數temp中存放的地址是隨機的,如果該隨機地址指向的是系統工作區間,那麼就會出錯 .那麼我們就可以在一開始時為temp賦值這樣就不會出錯了.

破案:

void swap(int* p1,int* p2){
    int x;
    int* temp=&x;
    *temp=*p1;
    *p1=*p2;
    *p2=*temp;
}

輸出  a=5;b=2          *p1=5;*p2=2

————————————————————————————————————————————————————————

上述試圖通過傳入的地址交換來達到交換兩個變數的錯誤寫法案情二:

void swap(int* p1,int* p2){
    int* temp=p1;
    p1=p2;
    p2=temp;
}

破案 :此處通過引用實現上面的效果:

void swap(int* &p1,int* &p2){
    int* temp=p1;
    p1=p2;
    p2=temp;
}

輸出  a=2;b=5          *p1=5;*p2=2

       指標變數其實是unsigned型別的整數,而直接交換這樣的兩個整型變數是需要加引用的.

       需要注意的是,由於引用是產生變數的別名,因此常量不可以使用引用. 於是上面的程式碼中不可以寫成swap(&a,&b),而必須用指標變數p1和p2存放&a和&b,然後把指標變數作為引數傳入.