2012-04-25 16 views
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; 
} 
+2

'gdb'でこれを実行しましたか? segfaultingはどこですか?いずれにしても、無効なメモリアクセスの可能性があります。 – RageD

+1

呼び出しコードも表示する必要があります。 –

+2

あなたは 'std :: reverse'を考えましたか?これは演習ですか?また、どのようにあなたの関数を呼びますか? 1つの単語でこれを1回呼び出すと、 –

答えて

1

私はあなたのコードを試して、1回の呼び出しでも "アクセス違反"を受けました。他の回答とコメントに記載されている初期化の問題のほかに、あなたのsegフォルトの原因となっているのは、 "逆"への再帰呼び出しの前に欠落している "戻り"です。あなたは書く必要がありますreturn reverse(word);

元のコードでは、次のようになります。warning C4715: 'Palindrome :: reverse':すべてのコントロールパスが値を返すわけではありません。

詳細はthis questionを参照してください。

ここでは逆のバージョンは(だ)の両方の修正と:

個人的に
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); 
     } 
    } 
+0

ありがとう!もちろん、カーブを学ぶために関数自体を返す必要があります。とても有難い。 – quipish

1

は、私はヤコブエイブラハムズが言おうとしたと思いますが、frontが繰り返されるが、ゼロに再設定されたことがないので、あなたはそれを呼び出す二回目は、それがセグメンテーション違反またはどちらかが依存する誤った結果が生成されます2番目の単語が長いか短いかに依存します。

さらに、どのようなマークBが既にを示唆することは、algorithmを含めるとでは、デバッガを使用する方法を学んだ場合、それが役立つだろう、すべてのほとんどは

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

で全体Palindrome::reverse機能を交換するか、ということです将来、少なくともこれらの種類の質問に対して特定のエラーメッセージを出してください。

EDIT:実行スタックが非常に小さく、前述の問題を修正した後でもスタックオーバーフローが発生するため、その再帰(たとえば、関数自体を呼び出す関数)を追加するのは忘れてしまいます。特に長い文字列です。実際には、この特定のコードはあまり明確ではありません。

+1

私は手足の外に出て、インタビューの質問か運動のどちらかと推測します。同じ再帰の再帰は一般的に良い考えではありません... –

+0

Hmm didn – smocking

+0

_she_はこれで何の仕事もしなかったことを心配しないでください。そうでなければ、彼はそれを考えません。しかし、それは理にかなっています。これは再帰的な型の状況であり、一連の関数を反復的に書き直して再帰的に書き直し、同じ問題のいくつかを解決するために使用できることを示す演習です。再帰の酒は良いものではありません。ただし、ここでの場合のように、それは役に立つ運動である可能性があります。私はそれが役に立つカテゴリーよりももっと魅力的であることがしばしば見えます。 – quipish

1

、私はやや奇妙な再帰やオブジェクトを混合考えます。オブジェクトの基本概念の1つは、オブジェクトが追跡したい状態を保持していることです。再帰の基本概念の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'; 
関連する問題