gpt4 book ai didi

c++ - 字符串反向功能不适用于奇数长度的字符串

转载 作者:行者123 更新时间:2023-11-28 04:03:34 26 4
gpt4 key购买 nike

我试图用C ++编写以下代码以反转字符串。由于某些原因,当字符串为奇数长度时,会给出错误的输出。

#include <iostream>
using namespace std;

void swapWithOutThirdVar(char &a, char &b) {
a = a + b;
b = a - b;
a = a - b;
}

void reverse(char string[]) {
int length = 0;
while (string[length] != '\0') {
length++;
}
int left = 0, right = length - 1;
while (left <= right) {
swapWithOutThirdVar(string[left], string[right]);
left++;
right--;
}
}

int main() {
char string[25];
cin>>string;

reverse(string);
cout<<string<<endl;
}


例如,如果我在控制台中输入 lappy,则后续输出为 yp。我是编程新手,所以无论潜在错误有多愚蠢,请对我友善。

最佳答案

有很多方法可以解决代码中的错误,但是代码中的主干错误在于您自己定义的交换函数。

void swapWithOutThirdVar(char &a, char &b) {
a = a + b;
b = a - b;
a = a - b;
}


我知道这是一个非常著名的函数,用于不使用第三个变量就交换两个变量。但是它有两个问题:


对于 ab的某些值,操作 a + b可能导致溢出。
(这里就是这种情况)如果遇到将完全相同的变量传递给函数的情况,交换将最终变得不稳定。原因如下:


假设您要将变量 char c传递给函数的两个参数。由于在函数中参数是通过引用传递的,因此虚拟变量 ab实际上是相同的变量,也就是说,它们是相同的 c的别名。简而言之, ab表示相同的变量 c
因此,现在当您执行 a = a + b时,该操作实际上会导致 c = c + c,这意味着 c的(ASCII)值在该语句执行结束时已加倍。
当第二条语句生效时,乐趣就来了。 b = a - b生成 c = c - c,将 0分配给 c。那是你做错的地方,孩子。
第三条语句对该过程没有任何好处。 a = a - b导致 c = c - c,这仍然使 c保持 0

因此,您的变量被分配了值 0,而不是被交换(本身?)。

现在,您可能想知道到底要在哪里交换相同的变量,对吗?
当您使用奇数长度的字符串时,请注意在第二个 while循环的最后一次迭代中, leftright的值相同。在这种情况下, leftright对于 string具有相同的索引,因此 string[left]string[right]是相同的变量。相同的变量将在该迭代中传递给交换函数。
现在,正如我之前所说:将相同的变量传递给swap函数将最终将 0传递给已传递给它的变量。对于您的示例案例,这是上次迭代结束时 string的样子:
['y', 'p' '\0', 'a', 'l']

在C / C ++中, null0)标记字符串的结尾。因此,奇怪的输出( yp)是合理的。

在偶数长度的字符串中,在第二个 left循环的任何迭代中, right都不会等于 while。这就是为什么永远不会将相同的变量传递给交换函数,这就是为什么 reverse函数的工作原理与从未传递给相同的变量一样好。

因此,首先,您需要注意相同变量的情况。如果 ab是相同的变量,则只需从函数返回即可,因为从技术上讲,将变量与自身交换是毫无意义的。利用以下事实:如果两个变量基本上是对同一变量的引用,则它们必须具有相同的地址。

void swapWithOutThirdVar(char &a, char &b) {
if (&a == &b)
return;

a = a + b;
b = a - b;
a = a - b;
}


但这不能解决溢出问题。因此,您需要做其他事情。

假设这是一个编程分配问题,您需要自己实现所有操作,那么您可以进行XOR交换,该交换使用按位XOR交换两个变量。按照交换函数的名称,我认为您知道老式的三变量交换技术,并且使用第三个变量进行交换也是分配的限制。

对两个数字进行异或运算不会导致溢出,因此该问题已得到解决。尽管XOR方法不能独立解析相同变量的情况,并最终在第一条语句本身中将变量 0交给了它,所以您需要保留地址相等性检查部分:

void swapWithOutThirdVar(char &a, char &b) {
if (&a == &b)
return;

a ^= b;
b ^= a;
a ^= b;
}


另外,您可以保持交换功能不变,并稍微修改第二个 while循环的条件以解决错误:
对于奇数长度的字符串,反转时中间字符的位置保持不变。想一想:当 leftright(都)都指向字符串的中间字符时,出现 left-等于- right的情况。因此,循环只需要运行,只要 left < right保持 true。对于偶数长度的字符串, left永远不会等于 right。当 whileleft是字符串的两个相邻中间元素的索引时, right循环就结束了。因此, left < right修改不会损害均匀长度的情况。因此,相应的修复方法是:

void reverse(char string[]) {
int length = 0;
while (string[length] != '\0') {
length++;
}
int left = 0, right = length - 1;
while (left < right) {
swapWithOutThirdVar(string[left], string[right]);
left++;
right--;
}
}


到此结束了错误的解释和纠正部分。但是,如果这不是针对您必须自己实现所有事情的编程任务,也就是说,您没有限制,则应该考虑以下内容:

从代码中的 using namespace std;来看,它似乎适用于C ++ 0x或更高版本。因此,您应该考虑以下事项:


从C ++ 0x开始,您已经具有预定义的交换功能( std :: swap)。您可以改用它。传递给它的溢出和同变量在这里不是问题。请参见 here
您在程序中使用了C样式的字符串。不再建议使用C型字符串。此外,您正在使用C ++ 0x或更高版本。因此,您应该改用 std :: string。请参见 here
您可以使用 reverse标头中的 algorithm函数。请参见 here

关于c++ - 字符串反向功能不适用于奇数长度的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59128881/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com