C/C++ 两个数交换引发的连环案

1. 一般法

       如何交换两个数?一般来说,交换两个数需要借助中间变量,即先令中间变量temp存放其中一个数a,然后再把另一个数b赋值给已被转移数据的a,最后把存有a的中间变量temp赋值给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>
using namespace std;
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>
using namespace std;
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,然后把指针变量作为参数传入.

猜你喜欢

转载自blog.csdn.net/Liang_xj/article/details/82930795