1

我正在编写一段代码,旨在使用递归来反转字符串。我相信我的方法是正确的,但我不断收到分段错误,我不确定它来自哪里。我所有的研究都表明这意味着我正在做“一些奇怪的记忆”。我在这方面足够新,这些类型的错误仍然令人困惑,所以这里的任何帮助将不胜感激。这是我的代码:

#include <iostream>
#include <string>
using namespace std;
class Palindrome
{
    int front;
    int back;
public:
    Palindrome();
    string reverse(string word)
    {
        int len = word.length()-1;
        if (back == 0) {
            back = len;
        }
        if (front >= back)
            return word;
        else{
            char first = word[front];
            char last = word[back];
            word[front] = last;
            word[back] = first;
            front += 1;
            back -= 1;
            reverse(word);
        }
    }
};

Palindrome::Palindrome(){
front = 0;
back = 0;
}
4

3 回答 3

1

我认为 Jacob Abrahams 试图说的front是迭代,但永远不会重新设置为零,所以第二次调用它时,它会根据第二个单词是更长还是更短而产生段错误或产生不正确的结果。

此外,Mark B 已经暗示的是,您可以algorithm将整个Palindrome::reverse函数包含并替换为

std::reverse(word.begin(), word.end());

最重要的是,如果您学会了如何使用调试器,或者将来至少为这类问题提供特定的错误消息,这将有所帮助。

编辑:忘记添加递归(例如调用自身的函数)通常是一个坏主意,因为执行堆栈非常小,在这种情况下,即使在解决了上述问题之后,对于特别长的字符串,您也会得到堆栈溢出. 它实际上使这个特定的代码不太清楚。

于 2012-04-25T17:04:56.827 回答
1

即使只有一个电话,我也尝试了您的代码并且也遇到了“访问冲突”。除了其他答案和评论中描述的初始化问题之外,导致您的段错误的是在递归调用“reverse”之前缺少“return”。你需要写return reverse(word);

在 Visual Studio 中,您的原始代码给出:警告 C4715: 'Palindrome::reverse' : 并非所有控制路径都返回一个值。

有关更多详细信息,请参阅此问题

这是一个带有两个修复的 reverse() 版本:

    string reverse(string word)
    {
        int len = word.length()-1;
        if (back == 0) 
        {
            back = len;
        }
        if (front >= back)
        {
            front = 0;
            back = 0;
            return word;
        }
        else
        {
            char first = word.at(front);
            char last = word.at(back);
            word.at(front) = last;
            word.at(back) = first;
            front += 1;
            back -= 1;
            return reverse(word);
        }
    }
于 2012-04-25T17:20:35.103 回答
1

就个人而言,我认为混合递归和对象有点奇怪。对象的基本概念之一是对象保持您想要跟踪的状态。递归的基本概念之一是执行堆栈保存您想要跟踪的状态。

在这种情况下,您要跟踪的状态是已处理了多少字符串/还有多少字符串需要处理。您可以在没有对象的情况下跟踪它。

这闻起来很像家庭作业问题。但是我想不出一个提示给你而不只是给你答案。我能做的最好的就是让我的答案(1)反转任何容器,包括但不限于字符串;(2) 使用类似 STL 的接口(即迭代器);(3) 将字符串反转到位,而不是反转字符串的副本:

#include <algorithm> // std::swap

// the other headers are only for my example on how to use the code
#include <iostream>
#include <iterator>
#include <string>
#include <list>

template<typename Itor> void reverse_with_recursion(Itor begin, Itor end)
{
    using std::swap; // same trick used by the STL to get user-defined swap's,
                     // but fall back to std::swap if nothing else exists:
                     // http://en.wikipedia.org/wiki/Argument-dependent_name_lookup#Interfaces

    // if begin and end are pointing at the same element,
    // then we have an empty string and we're done
    if (begin == end) {
        return;
    }

    // the STL follows the pattern that end is one element after
    // the last element;  right now we want the last element
    --end;

    // if begin and end are pointing at the same element *now*,
    // then we have a single character string and we're done
    if (begin == end) {
        return;
    }

    swap(*begin, *end);
    return reverse_with_recursion(++begin, end);
}

int main()
{
    std::string foo("hello world");
    reverse_with_recursion(foo.begin(), foo.end());

    std::cout << foo << '\n';

    std::list<int> bar;
    for (int i = 0; i < 10; ++i) {
       bar.push_back(i);
    }

    reverse_with_recursion(bar.begin(), bar.end());

    std::copy(bar.begin(),
              bar.end(),
              std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
于 2012-04-25T17:40:47.253 回答