1

私は自分で書いたこの本当に単純な C++ 関数を持っています。
文字列から「-」文字を取り除くだけです。
これがコードです

char* FastaManager::stripAlignment(char *seq, int seqLength){
    char newSeq[seqLength];
    int j=0;
    for (int i=0; i<seqLength; i++) {
        if (seq[i] != '-') {
            newSeq[j++]=seq[i];
        }
    }

    char *retSeq = (char*)malloc((--j)*sizeof(char));
    for (int i=0; i<j; i++) {
        retSeq[i]=newSeq[i];
    }
    retSeq[j+1]='\0'; //WTF it keeps reading from memory without this
    return retSeq;
}

そのコメントはそれ自体を物語っていると思います。
理由はわかりませんが、プログラムを起動して結果を印刷すると、次のような結果が得られます

'stripped_sequence''original_sequence'

ただし、コードをデバッグして問題がないかどうかを確認すると、フローは正常に動作し、最終的に正しい削除されたシーケンスが返されます。

2 つの変数のメモリを出力しようとしましたが、メモリの読み取り値は次のとおりです。

seq のメモリ: http://i.stack.imgur.com/dHI8k.png

*seq のメモリ: http://i.stack.imgur.com/UqVkX.png

retSeq のメモリ: http://i.stack.imgur.com/o9uvI.png

*retSeq のメモリ: http://i.stack.imgur.com/ioFsu.png

(スパムフィルターのため、リンク/写真を含めることができませんでした、申し訳ありません)

これは、文字列を出力するために使用しているコードです

for (int i=0; i<atoi(argv[2]); i++) {
    char *seq;
    if (usingStructure) {
        seq = fm.generateSequenceWithStructure(structure);            
    }else{
        seq = fm.generateSequenceFromProfile();
    }
    cout<<">Sequence "<<i+1<<": "<<seq<<endl;
}

今、私は何が起こっているのか本当にわかりません。

4

3 に答える 3

2

std :: stringを使用できる場合は、次のようにします。

std::string FastaManager::stripAlignment(const std::string& str)
{
   std::string result(str);
   result.erase(std::remove(result.begin(), result.end(), '-'), result.end());
   return result;
}

これは「消去-削除イディオム」と呼ばれます。

于 2012-02-13T11:31:07.797 に答える
1

これは、C 文字列の末尾のゼロを割り当てられたスペースの外に置くために発生します。文字列コピーの最後に余分な文字を 1 つ割り当て、そこに追加する'\0'必要があります。またはさらに良いことに、を使用する必要がありますstd::string

char *retSeq = (char*)malloc((j+1)*sizeof(char));
for (int i=0; i<j; i++) {
    retSeq[i]=newSeq[i];
}
retSeq[j]='\0';

これなしでメモリから読み続けます

これは仕様によるものです。C 文字列はゼロで終了します。'\0'文字列の終わりに達したことを C の文字列ルーチンに通知します。C 文字列を扱う場合、C++ でも同じ規則が適用されます。

于 2012-02-13T11:28:11.863 に答える
1

std::string個人的には、特に正当な理由がない限り、以下を使用するのが最善だと思います。

std::string FastaManager::stripAlignment(std::string value)
{
    value.erase(std::remove(value.begin(), value.end(), value.begin(), '-'), value.end());
    return value;
}

C 文字列を使用している場合は、それらが null で終了していることを認識する必要があります。C 文字列は、見つかった最初の null 文字まで到達します。投稿したコードでは、「j」要素を割り当てたときに範囲外の割り当てを導入しretSeq[j + 1]、文字列の末尾の 2 文字後に割り当てます (retSeq[j] = 0;とにかく意味します)。

于 2012-02-13T11:37:34.380 に答える