交换两个变量的值,不使用第三个变量的方法及实现

合集下载

c语言交换函数

c语言交换函数

c语言交换函数
c语言交换函数是一种常见的编程技术,它能让两个变量的值交换,大大简化程序的开发。

在c语言编程中,它是一种非常重要的技术,它能让程序更易于编写和理解。

c语言交换函数是用来实现两个变量中的数值交换的函数。

它可以使得一个变量的值等于另一个变量的值,从而实现变量值的交换。

c语言的交换函数的语法如下:swap(&x,&y);其中,x和y是用来交换的变量,&x和&y是变量的指针,表示x和y的地址。

c语言中的交换函数的实现原理是,先将x的值保存在一个临时变量中,然后将y的值放入x中,再将临时变量中的值放入y中,从而实现两个变量的值交换。

具体的实现代码如下:
int tmp;
tmp = x;
x = y;
y = tmp;
在实际的编程过程中,交换函数可以大大简化程序的开发。

通过它,我们可以很容易实现数值的交换,节省时间和精力,让程序的设计和实现更加便捷。

此外,c语言的交换函数还可以用于对象的交换,特别是那些复杂的对象。

它不仅可以交换简单的数值,还能交换指针、结构体、类和其他变量类型,这使得c语言编程更加方便。

另外,c语言的交换函数也很容易理解。

由于它的简单易懂,它
可以让初学者更容易掌握,也能减少开发过程中出现的错误。

总之,c语言的交换函数是一种非常重要的技术,它大大简化了程序的开发,让程序更易于编写和理解,也能节省时间和精力,让程序的设计和实现更加便捷。

它的使用不仅可以实现数值的交换,还可以实现对象的交换,因此在c语言编程中,它是一种非常重要的技术,不容忽视。

交换两个整型变量的值c语言

交换两个整型变量的值c语言

交换两个整型变量的值c语言交换两个整型变量的值是一个常见的编程问题。

在C语言中,有多种方法可以实现这个目标。

下面我将介绍三种常见的交换两个整型变量的方法:使用第三个变量、不使用第三个变量、使用异或运算。

1. 使用第三个变量这是最常见的方法之一。

它的实现方式是:首先将第一个变量的值赋给第三个变量,然后将第二个变量的值赋给第一个变量,最后将第三个变量的值赋给第二个变量。

以下是使用第一个变量实现交换的示例代码:```cvoid swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;}int main() {int num1 = 5;int num2 = 10;printf("交换前的值: num1=%d, num2=%d\n", num1, num2);swap(&num1, &num2);printf("交换后的值: num1=%d, num2=%d\n", num1, num2);return 0;}```2. 不使用第三个变量这种方法利用了算术运算和赋值运算之间的关系。

具体的实现方式是:将第一个变量的值与第二个变量的值相加,然后将和减去第二个变量的值,并将结果赋给第一个变量。

最后,将第一个变量的值减去第二个变量的值,并将结果赋给第二个变量。

以下是不使用第三个变量实现交换的示例代码:```cvoid swap(int *a, int *b) {*a = *a + *b;*b = *a - *b;*a = *a - *b;}int main() {int num1 = 5;int num2 = 10;printf("交换前的值: num1=%d, num2=%d\n", num1, num2);swap(&num1, &num2);printf("交换后的值: num1=%d, num2=%d\n", num1, num2);return 0;}3. 使用异或运算异或运算是一种位运算,它有一个重要的特性:两个相同的数进行异或运算的结果是0。

华为面试 笔试题目(附答案)

华为面试 笔试题目(附答案)

华为面试/笔试题目(附答案)陈晓明2010-05-21 15:45:59要查看更多华为笔经相关信息,请访问华为公司校园招聘club:深圳华为技术有限公司(1)什么是预编译,何时需要预编译:答案:1、总是使用不经常改动的大型代码体。

2、程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。

在这种情况下,可以将所有包含文件预编译为一个预编译头。

(2)char * const p char const * p const char *p 上述三个有什么区别?答案:char * const p; //常量指针,p的值不可以修改char const * p;//指向常量的指针,指向的常量值不可以改 const char *p; //和char const *p(3)char str1[] = "abc"; char str2[] = "abc"; const char str3[] = "abc"; const char str4[] = "abc"; const char *str5 = "abc"; const char *str 6 = "abc"; char *str7 = "abc"; char *str8 = "abc"; cout (y)?(y):(x)) //结尾没有‘;’(10)嵌入式系统中经常要用到无限循环,你怎么用c编写死循环。

答案:while(1){}或者for(;;)(11)关键字static的作用是什么?答案:定义静态变量(12)关键字const有什么含意?答案:表示常量不可以修改的变量。

(13)关键字volatile有什么含意?并举出三个不同的例子?答案:提示编译器对象的值可能在编译器未监测到的情况下改变。

位运算交换两个变量的值原理

位运算交换两个变量的值原理

位运算交换两个变量的值原理宝子!今天咱来唠唠一个超酷的东西——位运算交换两个变量的值。

你可能一听就觉得,啥?位运算?好高深的样子。

其实呀,没那么吓人啦。

咱先来说说普通的交换变量值的方法。

就像你有两个盒子,一个装着苹果,一个装着香蕉,你想把它们交换过来。

一般呢,就会找个临时的小盒子,先把苹果放进去,再把香蕉放到原来装苹果的盒子,最后把临时盒子里的苹果放到原来装香蕉的盒子。

在代码里呢,就是用一个临时变量来实现交换,这是大家都比较熟悉的做法。

但是呢,位运算就像是变魔术一样,不用这个临时变量就能交换。

你看哈,这里面用到的位运算主要是异或(^)操作。

异或这个操作可有意思啦,就像是两个调皮的小精灵在玩游戏。

对于两个二进制位来说,如果它们相同,异或的结果就是0;如果它们不同,异或的结果就是1。

比如说,有两个数a和b。

我们来做a = a ^ b这个操作。

这时候的a就像是被施了魔法一样,它变成了一个新的东西。

这个新的东西其实包含了a和b的一些特殊信息。

就好像a和b的一些小秘密被融合到了这个新的a里面。

然后呢,我们再做b = a ^ b。

哇哦,这时候的b就神奇地变成了原来的a啦。

你可以想象成之前a里面融合的那些小秘密,和现在的b一作用,就把原来的a给还原出来放在b这里了。

最后再做a = a ^ b。

这时候的a就变成了原来的b了。

是不是超级神奇呀?就像魔法棒一挥,两个变量的值就交换过来了。

从原理上讲呢,当我们做a = a ^ b的时候,a其实就变成了a和b的一种特殊组合。

然后b = a ^ b的时候,b就等于(a ^ b) ^ b。

根据异或的性质,(a ^ b) ^ b就等于a。

因为b和b异或就是0,0和a异或就是a。

最后a = a ^ b的时候,a就等于(a ^ b) ^ a,这又根据异或的性质等于b啦。

这就像是一场奇妙的数字舞蹈,每个数字都在按照异或的规则跳动着,最后就完成了这个看似不可思议的交换。

这种位运算交换变量值的方法,不仅很巧妙,而且在一些对性能要求比较高,对空间比较敏感的地方,就特别有用。

程序员笔试题

程序员笔试题

程序员笔试题1。

什么是预编译,何时需要预编译:2。

char * const pchar const * pconst char *p上述三个有什么区别?3。

char str1[] = "abc";char str2[] = "abc";const char str3[] = "abc";const char str4[] = "abc";const char *str5 = "abc";const char *str6 = "abc";char *str7 = "abc";char *str8 = "abc";cout << ( str1 == str2 ) << endl;cout << ( str3 == str4 ) << endl;cout << ( str5 == str6 ) << endl;cout << ( str7 == str8 ) << endl;4。

以下代码中的两个sizeof用法有问题吗?[C易]void UpperCase( char str[] ) // 将 str 中的小写字母转换成大写字母{for( size_t i=0; i<sizeof(str)/sizeof(str[0]); ++i )if( 'a'<=str[i] && str[i]<='z' )str[i] -= ('a'-'A' );}char str[] = "aBcDe";cout << "str字符长度为: " << sizeof(str)/sizeof(str[0]) << endl;UpperCase( str );cout << str << endl;5。

慧通面试题

慧通面试题

1.什么是预编译何时需要预编译:总是使用不经常改动的大型代码体。

程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。

在这种情况下,可以将所有包含文件预编译为一个预编译头。

2.char * const p;char const * pconst char *p上述三个有什么区别?char * const p; //常量指针,p的值不可以修改char const * p;//指向常量的指针,指向的常量值不可以改const char *p; //和char const *p 相同3.char str1[] = "abc";char str2[] = "abc";const char str3[] = "abc";const char str4[] = "abc";const char *str5 = "abc";const char *str6 = "abc";char *str7 = "abc";char *str8 = "abc";cout << ( str1 == str2 ) << endl;cout << ( str3 == str4 ) << endl;cout << ( str5 == str6 ) << endl;cout << ( str7 == str8 ) << endl;结果是:0 0 1 1解答:str1,str2,str3,str4是数组变量,它们有各自的内存空间;而str5,str6,str7,str8是指针,它们指向相同的常量区域。

4.以下代码中的两个sizeof用法有问题吗?void UpperCase( char str[] ) // 将 str 中的小写字母转换成大写字母{for( size_t i=0; i<sizeof(str)/sizeof(str[0]); ++i )if( 'a'<=str[i] && str[i]<='z' )str[i] -= ('a'-'A' );}char str[] = "aBcDe";cout << "str字符长度为: " << sizeof(str)/sizeof(str[0]) << endl;UpperCase( str );cout << str << endl;答:函数内的sizeof有问题。

华为笔试题(附答案)

华为笔试题(附答案)

1什么是预编译,何时需要预编译:答:1)总是使用不经常改动的大型代码体。

2)程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。

在这种情况下,可以将所有包含文件预编译为一个预编译头。

2 char * const p char const * p const char *p 上述三个有什么区别?答: char * const p; //常量指针,p的值不可以修改char const * p;//指向常量的指针,指向的常量值不可以改const char *p; //和char const *p 相同3 char str1[] = "abc";char str2[] = "abc";const char str3[] = "abc";const char str4[] = "abc";const char *str5 = "abc";const char *str6 = "abc";char *str7 = "abc";char *str8 = "abc";cout < < ( str1 == str2 ) < < endl;cout < < ( str3 == str4 ) < < endl;cout < < ( str5 == str6 ) < < endl;cout < < ( str7 == str8 ) < < endl;结果是:0 0 1 1str1,str2,str3,str4是数组变量,它们有各自的内存空间;而str5,str6,str7,str8是指针,它们指向相同的常量区域。

4 以下代码中的两个sizeof用法有问题吗?void UpperCase( char str[] ) // 将 str 中的小写字母转换成大写字母{ for( size_t i=0; i <sizeof(str)/sizeof(str[0]); ++i )if( 'a' <=str && str <='z' ) str -= ('a'-'A' );}char str[] = "aBcDe";cout < < "str字符长度为: " < < sizeof(str)/sizeof(str[0]) < < endl;UpperCase( str );cout < < str < < endl;答案:函数内的sizeof有问题。

Python中四种交换两个变量的值的方法

Python中四种交换两个变量的值的方法

Python中四种交换两个变量的值的⽅法Python中四种交换两个变量的值的⽅法
⽅法⼀:(所有语⾔都可以通过这种⽅式进⾏交换变量)
通过新添加中间变量的⽅式,交换数值.
下⾯通过⼀个demo1函数进⾏演⽰: 
def demo1(a,b):
temp = a
a = b
b = temp
print(a,b)
⽅法⼆:(此⽅法是Python中特有的⽅法)
直接将a, b两个变量放到元组中,再通过元组按照index进⾏赋值的⽅式进⾏重新赋值给两个变量。

下⾯通过⼀个demo2函数进⾏演⽰:
def demo2(a,b):
a,b = b,a
print(a,b)
⽅法三:
通过简单的逻辑运算进⾏将两个值进⾏互换
下⾯通过⼀个demo3函数进⾏演⽰:
def demo3(a, b):
a = a + b
b = a - b
a = a - b
print(a, b)
⽅法四:
通过异或运算将两个值互换异或运算的原理是根据⼆进制中的 "1^1=0 1^0=1 0^0=0"
下⾯通过⼀个demo4函数进⾏演⽰:
def demo4(a,b):
a = a^b
b = a^b # b = (a^b)^b = a
a = a^
b # a = (a^b)^a = b
print(a,b)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

交换两个变量的值,不使用第三个变量的方法及实现:附录中有C/C++代码:通常我们的做法是(尤其是在学习阶段):定义一个新的变量,借助它完成交换。

代码如下:int a,b;a=10; b=15;int t;t=a; a=b; b=t;这种算法易于理解,特别适合帮助初学者了解计算机程序的特点,是赋值语句的经典应用。

在实际软件开发当中,此算法简单明了,不会产生歧义,便于程序员之间的交流,一般情况下碰到交换变量值的问题,都应采用此算法(以下称为标准算法)。

上面的算法最大的缺点就是需要借助一个临时变量。

那么不借助临时变量可以实现交换吗?答案是肯定的!这里我们可以用以下几种算法来实现:1)算术运算;2)指针地址操作;3)位运算;4)栈实现。

1)算术运算int a,b;a=10;b=12;a=b-a; //a=2;b=12b=b-a; //a=2;b=10a=b+a; //a=12;b=10它的原理是:把a、b看做数轴上的点,围绕两点间的距离来进行计算。

具体过程:第一句“a=b-a”求出ab两点的距离,并且将其保存在a中;第二句“b=b-a”求出a到原点的距离(b到原点的距离与ab两点距离之差),并且将其保存在b中;第三句“a=b+a”求出b到原点的距离(a到原点距离与ab两点距离之和),并且将其保存在a中。

完成交换。

此算法与标准算法相比,多了三个计算的过程,但是没有借助临时变量。

(以下称为算术算法)除了使用加、减法外,还可以使用乘、除法实现,实现代码如下://if a=10;b=12;a=a*b; //a=120;b=12b=a/b; //a=120;b=10a=a/b; //a=12;b=10缺点:是只能用于数字类型,字符串之类的就不可以了。

a+b有可能溢出(超出int的范围),溢出是相对的,+了溢出了,-回来不就好了,所以溢出不溢出没关系,就是不安全。

2)指针地址操作因为对地址的操作实际上进行的是整数运算,比如:两个地址相减得到一个整数,表示两个变量在内存中的储存位置隔了多少个字节;地址和一个整数相加即“a+10”表示以a为基地址的在a后10个a类数据单元的地址。

所以理论上可以通过和算术算法类似的运算来完成地址的交换,从而达到交换变量的目的。

即:int *a,*b; //假设*a=new int(10);*b=new int(20); //&a=0x00001000h,&b=0x00001200ha=(int*)(b-a); //&a=0x00000200h,&b=0x00001200hb=(int*)(b-a); //&a=0x00000200h,&b=0x00001000ha=(int*)(b+int(a)); //&a=0x00001200h,&b=0x00001000h通过以上运算a、b的地址真的已经完成了交换,且a指向了原先b指向的值,b指向原先a指向的值了吗?上面的代码可以通过编译,但是执行结果却令人匪夷所思!原因何在?首先必须了解,操作系统把内存分为几个区域:系统代码/数据区、应用程序代码/数据区、堆栈区、全局数据区等等。

在编译源程序时,常量、全局变量等都放入全局数据区,局部变量、动态变量则放入堆栈区。

这样当算法执行到“a=(int*)(b-a)”时,a的值并不是0x00000200h,而是要加上变量a所在内存区的基地址,实际的结果是:0x008f0200h,其中0x008f即为基地址,0200即为a在该内存区的位移。

它是由编译器自动添加的。

因此导致以后的地址计算均不正确,使得a,b指向所在区的其他内存单元。

再次,地址运算不能出现负数,即当a的地址大于b的地址时,b-a<0,系统自动采用补码的形式表示负的位移,由此会产生错误,导致与前面同样的结果。

有办法解决吗?当然!以下是改进的算法:if(a<b){a=(int*)(b-a);b=(int*)(b-(int(a)&0x0000ffff));a=(int*)(b+(int(a)&0x0000ffff));}else{b=(int*)(a-b);a=(int*)(a-(int(b)&0x0000ffff));b=(int*)(a+(int(b)&0x0000ffff));}算法做的最大改进就是采用位运算中的与运算“int(a)&0x0000ffff”,因为地址中高16位为段地址,后16位为位移地址,将它和0x0000ffff进行与运算后,段地址被屏蔽,只保留位移地址。

这样就原始算法吻合,从而得到正确的结果。

此算法同样没有使用第三变量就完成了值的交换,与算术算法比较它显得不好理解,但是它有它的优点即在交换很大的数据类型时,它的执行速度比算术算法快。

因为它交换的时地址,而变量值在内存中是没有移动过的。

(以下称为地址算法)3)位运算int a=10,b=12; //a=1010^b=1100;a=a^b; //a=0110^b=1100;b=a^b; //a=0110^b=1010;a=a^b; //a=1100=12;b=1010;此算法能够实现是由异或运算的特点决定的,通过异或运算能够使数据中的某些位翻转,其他位不变。

这就意味着任意一个数与任意一个给定的值连续异或两次,值不变。

4)栈实现。

不多解释了,栈和相关函数定义省去。

int exchange(int x,int y){stack S;push(S,x);push(S,y);x=pop(S);y=pop(S);}以上算法均实现了不借助其他变量来完成两个变量值的交换,相比较而言算术算法和位算法计算量相当,地址算法中计算较复杂,却可以很轻松的实现大类型(比如自定义的类或结构)的交换,而前两种只能进行整形数据的交换(理论上重载“^”运算符,也可以实现任意结构的交换)。

也有一些资料上采用一句赋值语句实现交换操作,典型的有以下两种:(1) a = a + b - (b = a);(2) b = a + (a = b)*0;但是这两条语句在VS2010上测试,结果为:交换后(1)中,a、b都是a的值,而(2)中,a、b 都是b的值,显然不是我们想要的结果。

对以上结果应该这样理解,(1)中首先执行b=a,此时,a、b 的值都是a,那么再向下执行就相当于,a=a+a-a;(2)也一亲,首先执行a=b;如果再使用a的值应该就是b了,因此再执行就是b=b+(a=b)*0;之所以存在这种方法有可能是从处理器处理的的角度考虑的,例如(1)中,将a、b、(b=a)同时放入寄存器中,这样有可能得到正确结果,但是实际执行过程中,当执行完(b=a)后,立即更新了寄存器的值,因此才不能达到应有目的。

介绍这几种算法并不是要应用到实践当中,而是为了探讨技术,展示程序设计的魅力。

从中可以看出,数学中的小技巧对程序设计而言具有相当的影响力,运用得当会有意想不到的神奇效果。

而从实际的软件开发看,标准算法无疑是最好的,能够解决任意类型的交换问题。

附录1:所有方法的C语言代码由于C标准库中没有栈的函数,因此需要自己写压栈、出栈函数(其实栈就相当于是FILO)。

但是C++中有stack的类。

#include <stdio.h>#include<malloc.h>void MethodA(int a, int b);void MethodB(int a, int b);void MethodC(int a, int b);void MethodD(int *a, int *b);void MethodE(int a, int b);void main(){int x,y;printf("Exchange the two variables,without a third variable!\n");printf("By:zzm\n");MethodA(1,2);MethodB(2,3);MethodC(3,4);x=4;y=5;MethodD(&x,&y);MethodE(5,6);}void MethodA(int a, int b){printf("%s:\n",__FUNCTION__);printf("Before exchange: a = %d, b = %d\n",a,b);//if a=10;b=12;a=b-a;//a=2;b=12b=b-a;//a=2;b=10a=b+a;//a=12;b=10printf("After exchange: a = %d, b = %d\n",a,b);}void MethodB(int a, int b){printf("%s:\n",__FUNCTION__);printf("Before exchange: a = %d, b = %d\n",a,b);//if a=10;b=12;a=a*b;//a=120;b=12b=a/b;//a=120;b=10a=a/b;//a=12;b=10printf("After exchange: a = %d, b = %d\n",a,b);}void MethodC(int a, int b){printf("%s:\n",__FUNCTION__);printf("Before exchange: a = %d, b = %d\n",a,b);// if a=10,b=12; a=1010^b=1100;a=a^b;//a=0110^b=1100;b=a^b;//a=0110^b=1010;a=a^b;//a=1100=12;b=1010;printf("After exchange: a = %d, b = %d\n",a,b);}void MethodD(int *a, int *b){printf("%s:\n",__FUNCTION__);printf("Before exchange: *a = %d, *b = %d\n",*a,*b);if(a<b)//the address must >0{//&a=0x00001000h,&b=0x00001200h a=(int*)(b-a);//&a=0x00000200h,&b=0x00001200hb=(int*)(b-((int)a &0x0000ffff));//&a=0x00000200h,&b=0x00001000ha=(int*)(b+((int)a &0x0000ffff));//&a=0x00001200h,&b=0x00001000h }else{b=(int*)(a-b);a=(int*)(a-((int)b &0x0000ffff));b=(int*)(a+((int)b &0x0000ffff));}printf("After exchange: *a = %d, *b = %d\n",*a,*b);//zzm 地址作差,值为:相差字节数/指针类型的字节数//地址加1,地址的变化:原地址+指针类型占的空间}typedef struct Node{int data;struct Node *pNext;}NODE;//栈可以想象为一个箱子,放东西(进栈)是从栈底放起往上添加,拿出来(出栈)是从上面先来。

相关文档
最新文档