我正在尝试编译此代码以反转字符串:
void reverse(char *str, int n)
{
if (n==0 || n==1) {
return; //acts as quit
} else {
char i = str[0]; //1st position of string
char j = str[n-1]; //Last position of string
char temp = str[i];
str[i] = str[j]; //Swap
str[j] = temp;
reverse(str[i+1],n-1); // <-- this line
}
}
#include <iostream>
int main()
{
char *word = "hello";
int n = sizeof word;
reverse(word, n);
std::cout << word << std::endl;
return 0;
}
编译器报告错误,我递归地调用reverse()
:
char
处从char*
到reverse(str[i+1], n-1)
的无效转换。
为什么?
我的代码中对其他问题的任何建议也是受欢迎的。
答案 0 :(得分:2)
str[i+1]
是一个字符,而不是指向字符的指针;因此错误信息。
当您输入该功能时,str
指向您要与n
:字符交换的角色,远离str
。
在递归中你需要做的是增加指针使其指向下一个字符
您还需要将n
减少到两个,因为它应距离str + 1
,而不是str
。
(这很容易出错;请参阅此答案的编辑历史记录。)
交换时,您还使用字符串中的字符作为字符串的索引
(如果你有输入"ab"
,你会char temp = str['a']; str['a'] = str['b']; str['b'] = temp;
。这显然不正确。)
str[0]
不是第一个字符的位置,是第一个字符。
如果您被允许,请使用std::swap
,否则请参阅下文。
更多问题:您不应该使用sizeof word
,因为根据您的目标架构,它是4或8 - 它相当于sizeof(char*)
。
您应该使用strlen
来查找字符串的长度。
此外,您应该收到
的警告char *word = "hello";
因为特定的转化很危险 - "hello"
是const
数组,修改它是未定义的。
(如果你从未修改过阵列,那将是安全的,但你是,所以它不是。)
将其复制到非const数组中:
char word[] = "hello";
并提高编译器的警告级别。
这是一个固定版本:
void reverse(char *str, int n)
{
if(n <= 1) // Play it safe even with negative n
{
return;
}
else
{
// You could replace this with std::swap(str[0], str[n-1])
char temp = str[0]; //1st character in the string
str[0] = str[n-1]; //Swap
str[n-1] = temp;
// n - 2 is one step closer to str + 1 than n is to str.
reverse(str + 1, n - 2);
}
}
int main()
{
char word[] = "hello";
// sizeof would actually work here, but it's fragile so I prefer strlen.
reverse(word, strlen(word));
std::cout << word << std::endl;
}
答案 1 :(得分:0)
我要剖析您的代码,就像您在Code Review上发布一样。毕竟你确实要求其他观察......
首先,
char *word = "hello";
您的编译器应警告您,将char*
指向文字字符串是未定义的行为(如果没有,请确保您实际上已启用了一组良好的警告。许多编译器默认情况下发出的警告非常少,因为历史原因)。你需要确保你有一个可写的字符串;为此你可以使用char[]
:
char word[] = "hello";
下一行
int n = sizeof word;
现在改变了意义,但仍然是错误的。在原始代码中,它是指向char
的指针的大小,它不太可能与单词&#34; hello&#34;的长度相同。更改为char[]
后,它现在是6个字符数组的大小,即6
。第六个字符是结束字符串文字的NUL。您可能不想使用sizeof
运算符,而是使用strlen()
函数。
转到reverse()
:
您从字符串中的位置读取字符,然后使用这些字符对其进行索引。这不是你想要的,GCC警告不要使用普通char
进行索引,因为它可能是签名或未签名的。您只想在一个地方编制索引,而i
和j
是不必要的。
最后,你问的问题。 str[i+1]
是位置i+1
的字符,但您的函数需要一个指向字符的指针,它只是str+i+1
。或者,自从我们制定出来之后,我们不希望i
在那里,只有str+1
。
另请注意,您需要从n
而不是1
中减去2,因为它将用作str+1
中的字符数。如果你只减去1,你将永远与最后一个字符进行交换,并且你将实现“滚动”。而不是反向&#39;
这是一个有效的版本:
void reverse(char *str, int n)
{
if (n < 2)
// end of recursion
return; //acts as quit
char temp = str[0];
str[0] = str[n-1]; //Swap
str[n-1] = temp;
reverse(str+1,n-2);
}
#include <iostream>
#include <cstring>
int main()
{
char word[] = "hello";
int n = std::strlen(word);
reverse(word, n);
std::cout << word << std::endl;
}
我们可以做出进一步的改变。例如,我们可以使用std::swap
更清楚地表达切换。我们可以传递一对指针而不是指针和长度:
#include <utility> // assuming C++11 - else <algorithm>
void reverse(char *str, char *end)
{
if (end <= str)
// end of recursion
return;
std::swap(*str, *end);
reverse(str+1, end-1);
}
并使用reverse(word, word+n-1)
调用它。
最后(因为我不提及std::reverse()
),这是惯用的迭代版本:
void reverse(char *str, char *end)
{
while (str < end)
std::swap(*str++, *end--);
}
答案 2 :(得分:-1)
像这样使用:
reverse(&str[i+1],n-1);
传递第(i + 1)个位置的地址而不是值。