C 在不使用第三个变量的情况下交换字符
C中的字符实际上是一些ascii数字。那么,为什么下面的代码(应该交换两个字符)会给出错误的结果呢C 在不使用第三个变量的情况下交换字符,c,C,C中的字符实际上是一些ascii数字。那么,为什么下面的代码(应该交换两个字符)会给出错误的结果呢 void swap(char *a,char *b) { *a=*a+*b; *b=*a-*b; *a=*a-*b; } 理论上,这个计算看起来不错。让我们通过示例来了解它: 让我们看一下a='s'=83和b='O'=79 a = a + b = 83 + 79 = 162 如果您的编译器将char定义为无符号,那么溢出就没有问题。如果编译器定义了要签名的char,则这
void swap(char *a,char *b)
{
*a=*a+*b;
*b=*a-*b;
*a=*a-*b;
}
理论上,这个计算看起来不错。让我们通过示例来了解它: 让我们看一下
a='s'=83
和b='O'=79
a = a + b = 83 + 79 = 162
如果您的编译器将char
定义为无符号,那么溢出就没有问题。如果编译器定义了要签名的char
,则这超出范围(>127),并导致a=-94
b = a - b = (-94) - 79 = -173
再次超出范围,收益率为83,这是正常的
a = a - b = (-94) - (-173) - = 79
这看起来也不错
实际上,这段代码对我来说毫无问题:
char a = 'S', b = 'O';
swap(&a, &b);
assert(a == 'O');
assert(b == 'S');
使用您提供的确切的swap
功能
下面是。如果上面的表达式会导致算术溢出,那么结果会很奇怪。如果
a
和b
两个指针都指向同一位置*,上述方法也将失败
试试这个:
void swap(char *a,char *b)
{
if (a == b) // Check if the two addresses are same
return;
*a=*a^*b;
*b=*a^*b;
*a=*a^*b;
}
*如果
a
和b
将指向同一位置,比如x100
,并让存储在该位置的值为0111
(二进制),则:
两个问题
*a=*a-*b
实际上可以归结为*a=*a-*a代码>
char
可以是signed
或unsigned
。这是编译器所做的选择;C标准允许这两种情况。因此,*a-*b
的值可能因平台而异可以在没有临时协议的情况下进行交换。这项技术(异或交换)已经有很好的文档记录,但由于一些恶劣的边缘情况,不建议使用它。如果指针相等,这将不起作用。所以这需要首先检查和处理 为了解决机器上的问题,您应该编写如下测试,并使用其他printf输出分析结果,例如:
void swap(char *a, char *b)
{
/* if (a != b){ */
*a = *a + *b;
*b = *a - *b;
*a = *a - *b;
/*}*/
}
void swapTemp(char *a, char *b)
{
char temp = *a;
*a = *b;
*b = temp;
}
int
main(){
unsigned int errors = 0;
int b;
for (b = 0; b <= 255; b++)
{
int a;
for (a = 0; a <= 255; a++)
{
char a_swap = a;
char a_swapTemp = a;
char b_swap = b;
char b_swapTemp = b;
swap(&a_swap, &b_swap);
swapTemp(&a_swapTemp, &b_swapTemp);
if ((a_swap != a_swapTemp) || (b_swap != b_swapTemp))
++errors;
/* extend to print results here to analyse the problem */
}
}
printf("There where %u errors!", errors);
return 0;
}
void交换(char*a,char*b)
{
/*如果(a!=b){*/
*a=*a+*b;
*b=*a-*b;
*a=*a-*b;
/*}*/
}
无效交换(字符*a,字符*b)
{
字符温度=*a;
*a=*b;
*b=温度;
}
int
main(){
无符号整数错误=0;
int b;
对于(b=0;b您的输入是什么?您得到了什么结果?我发送两个字符的地址,比如swap(&ch1,&ch2)。您也可以使用预处理器:#define swap(a,b)do{a^=b;b^=a;a^=b;}while(0)
@codemonkey,如果a和b相等,它将严重失败。用一个简短的程序显示它失败了如何?我怀疑ch1
和ch2
在您的交换(&ch1,&ch2)中
实际上并不是char
——可能是char*
?或者int
?还有,什么平台?比较地址是不够的。不同位置的相等值仍然会导致0。@Daerst:我正在考虑把我迄今为止的职业收入赌在你这里是不正确的;-)甚至我也尝试用异或交换字符,但没有成功work@user3437973;您的输入是什么?我正在发送两个字符的地址,比如说swap(&ch1,&ch2),上次他设置*a
实际上是a=a-b=(a+b)-a=b
,而不是a=a-b=a-a=0
…因为他当时已经设置了*a=*a+*b;
。他的问题是另外一个问题。#include int main(){int a,b;printf(“输入两个要交换的整数”);scanf(%d%d),&a,&b);a=a+b;b=a-b;printf(“a=%d\n”,a,b);返回0;}此操作有效fine@Daerst您给出的原因实际上是“为什么我不能在同一地址交换值”的原因也就是说,如果a=b,那么为什么我不能自己交换一个数字。我更改了答案并删除了我原来错误的数学解释。代码对我来说很好。@user3437973,请提供失败的实际输入。@Daerst即使对于a='a'和b='b',它也失败了!
void swap(char *a, char *b)
{
/* if (a != b){ */
*a = *a + *b;
*b = *a - *b;
*a = *a - *b;
/*}*/
}
void swapTemp(char *a, char *b)
{
char temp = *a;
*a = *b;
*b = temp;
}
int
main(){
unsigned int errors = 0;
int b;
for (b = 0; b <= 255; b++)
{
int a;
for (a = 0; a <= 255; a++)
{
char a_swap = a;
char a_swapTemp = a;
char b_swap = b;
char b_swapTemp = b;
swap(&a_swap, &b_swap);
swapTemp(&a_swapTemp, &b_swapTemp);
if ((a_swap != a_swapTemp) || (b_swap != b_swapTemp))
++errors;
/* extend to print results here to analyse the problem */
}
}
printf("There where %u errors!", errors);
return 0;
}