编写函数实现两个同类型值的交换(难度不断升级)

1.采用中间变量

#include<stdio.h>
void swap(int *x,int *y);//函数原型声明
int main(){
    int a=3;
    int b=4;
    printf("交换前 a=%d b=%d\n",a,b);
    swap(&a,&b);
    printf("交换后 a=%d b=%d\n",a,b);
    
}
void swap(int *x,int *y){
    int tmp;
    tmp=*x;
    *x=*y;
    *y=tmp;    
}

tips:

  这里你将会遇见一个问题,如果定义的swap函数为void swap(x,y) ,而不是指针呢,你会发现数值没有交换,这其实是一种假交换,形式参数实际上只是实际参数的一份临时拷贝,在函数内部交换完毕后又被释放了,并没有改变原来的值。

  而使用指针,过程与传值类似,只是传过来的是两个变量的地址,同时在调用swap函数时为swap(&a,&b),确保传入的为地址。

2.不使用中间变量

void swap(int *x,int *y){//假设x为10,y为5
    *x=*x+*y;//x现在是15
    *y=*x-*y;//y现在是15-5=10
    *x=*x-*y;//x现在是15-10=5
    
}

tips:

这里只是单纯的数值操作,大家试试就懂了

3.支持多类型数值的交换

上面我们对int类型进行交换,那怎么对float类型进行交换呢,如果你说直接采用上面的代码,int类型也可以转换为float类型啊,例如采用上面同代码,float a=3.14,float b=4.13,有的编译器可能会交换,但会警告你类型不匹配,当然,大多数的编译器可能无法运行,所以我们用什么方法可以让数值交换不局限于类型呢,这里只列举一种---宏定义



#include <stdio.h>
#include <stdlib.h>
#define SWAP(x,y) x=x+y;y=x-y;x=x-y;
int main()
{
    int a=3;
    int b=4;
    float c=3.14;
    float d=4.13;
    SWAP(a,b);
    SWAP(c,d);
    printf("交换后 a=%d b=%d\n",a,b);
    printf("交换后 c=%.2f d=%.2f\n",c,d);

}

​

怎么样,漂亮的宏定义是不是异常的简洁,同时也解决了我们对类型的要求。

我们使用#define(预处理器指令)来定义宏,现在实例一个简单的宏

#define PI 3.14
//#define 预处理器指令
//PI      宏
//3.14    替换体

定义好这条宏之后,后面所有出现的PI,我们都认为是3.14

宏可以分为无参数类型和有参数类型,上述举例即为无参数类型,而我们定义的SWAP(x,y)即为有参数类型,相信这个不难理解,那么宏在代码中最后是什么样子呢,继续使用上方的SWAP(x,y),我们将宏展开

#include <stdio.h>
#include <stdlib.h>
//#define SWAP(x,y) x=x+y;y=x-y;x=x-y;
int main()
{
    int a=3;
    int b=4;
    float c=3.14;
    float d=4.13;
    //SWAP(x,y)
    a=a+b;
    b=a-b;
    a=a-b;
    //SWAP(x,y)
    c=c+d;
    d=c-d;
    c=c-d;
    
    printf("交换后 a=%d b=%d\n",a,b);
    printf("交换后 c=%.2f d=%.2f\n",c,d);

}

这就是宏的效果,简单来说就是用替换体的内容代替代码中宏出现的位置,现在是不是感觉和函数的作用差不多,那么我们到底是选择函数好一点还是宏好一点呢,这个其实没有硬性规定,宏和函数的选择其实是时间与空间的权衡。

在调用函数的时候,需要开辟栈空间用来储存返回地址,函数返回同时又要释放堆栈,也就是程序的控制必须跳转至函数内,然后再返回主调程序,这种过程将降低代码的运行效率,同时函数的参数必须被声明为某种特定的类型,而宏定义可以应用于各种类型(上面代码很好地体现了这一点),所以使用宏的好处是不是显而易见呢。

当然使用宏不是全无坏处,使用宏将生成内联代码,也就是在程序中生成语句,每一次调用宏,即在程序中插入代码,上面调用了两次SWAP(x,y),程序中就插入了两次代码,那如果我们调用100次呢,要知道每一行代码都是要占用空间的,而调用函数时,假如调用100次,而程序只有一份函数语句的副本,所以节省了空间。

所以在函数和宏的使用中我们需要考虑首先使用宏和函数是否有较大差异,其次使用宏是否有效,毕竟只调用一次宏显然无法明显的减少程序的运行时间,所以在嵌套循环中是不是很合适呢,嘿嘿。

最后,使用宏需要有几点注意:

1.宏名不能有空格,而替换体可以有

2.采用大写字母表示宏的名称,这是一个惯例,当其他人看见大写的常量时,就能意识到这可能是宏

4.不使用赋值符号“=”(提示:直接对内存进行操作)

假如我们不使用宏,还是选择函数来支持多种类型的交换呢,我们都知道c有void*,作为无类型指针,它可以指向任何数据类型,但是按照ANSI标准,不能对void指针进行算法操作。这个时候就可以考虑采用内存拷贝函数了,常用的内存拷贝函数有很多,例如memcpy()、memmove()、strcpy(),他们的使用与具体参数,大家可以参考其他博客,这里我使用memcpy()

memcpy(void *x,void *y,size_t n),简单理解就是将y指定位置的前n个字节拷贝到x的指定位置,在数组操作中感觉极为有用,这里我们要交换两个值,只要知道值的类型大小,设定好n,是不是就可以对想x,y进行交换呢,以下是最终代码

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
void swap(void *x,void *y,size_t n);//函数原型声明
int main()
{
    int a=3;
    int b=4;
    float c=3.14;
    float d=4.13;
    swap(&a,&b,sizeof(a));
    swap(&c,&d,sizeof(c));
    printf("%d %d\n",a,b);
    printf("%.2f %.2f\n",c,d);
    return 0;

}
void swap(void *x,void *y,size_t n){
    void *tmp=(void *)malloc(n);//申请使用一个大小为n字节的内存
    if(tmp!=NULL){
        memcpy(tmp,x,n);//内存拷贝函数
        memcpy(x,y,n);
        memcpy(y,tmp,n);
        free(tmp);//释放空间
    }
}

 在刚开始的时候,假如我们将y拷贝给了x,这时候x的值发生了改变,那我们怎么将原来x的值拷贝给y呢,我的思路是添加一个新的指针,保存原来x的值,于是就有了下面的代码

void swap(void *x,void *y,size_t n){
    void *tmp=x//我单纯的添加了一个指针
   
    memcpy(x,y,n);
    memcpy(y,tmp,n);
    
    
       
}

这样写其实tmp和x共用了一个内存空间,实际上并没有保存x的值,请原谅一个初学者对指针的单纯理解,所以我们需要对tmp分配一个新的空间,所以用到了malloc()函数,于是代码变成了这样

void swap(void *x,void *y,size_t n){
    void *tmp=(void *)malloc(n);
    
        memcpy(tmp,x,n);
        memcpy(x,y,n);
        memcpy(y,tmp,n);
        free(tmp);
}

malloc()向系统申请分配指定字节的内存空间,返回类型是 void* 类型.在上面代码中由于需要我们将需要的内存空间设定为n,同时由于支持多种类型转换前面的参数依旧为(void *).那这样是不是就大功告成了呢,使用malloc()为动态内存分配,分配与释放时都会占用cpu资源,那我们如何能保障你的内存剩余可以满足程序的需要呢?所以这里我犯了一个错误,因为我们不知道现在的内存是否够用。所幸,malloc()函数的返回值可以解决这个问题

如果分配成功则返回指向被分配内存的指针,否则返回空指针NULL。

所以添加一个判断条件即可,最终代码如下

void swap(void *x,void *y,size_t n){
    void *tmp=(void *)malloc(n);
    if(tmp!=NULL){
        memcpy(tmp,x,n);
        memcpy(x,y,n);
        memcpy(y,tmp,n);
        free(tmp);//使用完记得释放
    }
}

以上就是全部内容了,感谢您的观看,新人学习,如有不当,恳请指正

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用Python中的多重赋实现两个整数的交换,具体代码如下: ```python def swap(a, b): a, b = b, a return a, b ``` 在函数中,我们将a和b的互换,然后返回交换后的结果。使用该函数可以轻松地实现两个整数的交换,例如: ```python a = 10 b = 20 a, b = swap(a, b) print(a, b) # 输出20 10 ``` ### 回答2: Python编写函数实现两个整数的交换非常简单,可以通过定义一个交换函数实现。 代码如下: ```python def swap(a, b): temp = a a = b b = temp print("交换后,a =", a, "b =", b) ``` 这里定义了一个名为swap的函数,该函数接受两个参数a和b,即两个需要交换的整数。在函数中,首先定义了一个temp变量,用来存储a的。然后将变量a的为b,变量b的为temp。最后,使用print语句输出交换后的结果。 调用该函数只需传入两个整数即可,例如: ```python swap(10, 20) ``` 运行后,输出结果为: 交换后,a = 20 b = 10 注意,在Python中,函数内部的变量默认为局部变量。这就意味着,函数内部的变量只在该函数中有效,不能在函数外部使用。因此,在交换函数中,需要通过return语句将交换后的结果返回给调用者,以便在函数外部使用。例如: ```python def swap(a, b): temp = a a = b b = temp return a, b ``` 这里修改了swap函数,使用return语句将交换后的a和b返回给调用者。在函数外部,可以使用多重赋来获取返回,例如: ```python x, y = swap(10, 20) print("交换后,x =", x, "y =", y) ``` 运行后,输出结果为: 交换后,x = 20 y = 10 总之,Python编写函数实现两个整数的交换非常简单,只需要定义一个交换函数,将需要交换的整数传入函数中,即可实现交换。 ### 回答3: 在python中,交换两个整数的最简单的方法是使用一个中间变量。我们可以编写一个函数,该函数接受两个整数作为参数,并以交换后的返回它们。 以下是一个示例函数,可以实现两个整数的交换: ``` def swap(a, b): temp = a a = b b = temp return (a, b) ``` 在此函数中,我们首先创建一个名为temp的变量,并将a的存储在其中。然后,我们将a的设置为b的,最后将b的设置为temp。最后,我们使用tuple类型返回交换后的。 为了测试这个函数,我们可以调用它并传递两个整数作为参数,如下所示: ``` x = 2 y = 4 print(swap(x, y)) ``` 这将输出(4, 2),证明函数已经成功交换了x和y的。 除了使用中间变量的方法,还有其他一些方法可以实现两个整数的交换,例如使用加减法、位运算或tuple类型的解包。但是,这些方法可能不如使用中间变量的方法直观易懂。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值