在不使用第三个变量的情况下交换字符

时间:2015-01-09 15:25:12

标签: c

C中的

字符实际上是一些ascii数字。那么为什么下面的代码,它应该交换两个字符,给出错误的结果

void swap(char *a,char *b)
{
    *a=*a+*b;
    *b=*a-*b;
    *a=*a-*b;
}

4 个答案:

答案 0 :(得分:4)

理论上,这个计算看起来不错。让我们通过例子来解决它:

我们来看a = 'S' = 83b = '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功能。

这是full working example code

答案 1 :(得分:4)

如果上面的表达式会导致算术溢出,结果会很奇怪。如果指针ab指向同一位置 * ,上述方法也将失败。

试试这个:

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;
}  

*如果ab指向同一位置,请说x100并让存储在该位置的值为0111(二进制),则:

*a = *a ^ *b   // *a will have now 0000 
*b = *a ^ *b   // *b = 0000^0000 = 0000  
*a = *a ^ *b   // *a = 0000^0000 = 0000

答案 2 :(得分:1)

两个问题

  1. 您的上一行*a=*a-*b;实际归结为*a=*a-*a;

  2. char可以是signedunsigned。这是编译器的选择; C标准允许。因此*a-*b的价值可能因平台而异。

  3. 可以在没有临时的情况下进行交换。该技术(XOR交换)已有详细记录,但由于一些令人讨厌的边缘情况,因此不建议使用它。

答案 3 :(得分:0)

如果指针相等,这将不起作用。所以这需要先检查和处理。

要找出您机器上的问题,您应该编写如下所示的测试,并使用其他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;
}

提供有关您的机器,编译器和测试结果的更多信息!