2012-02-13 3 views
1

私は本当にシンプルなC++関数を持っています。
文字列から ' - '文字を取り除くだけです。
ここで私はコメントは自身のために話すことを考えるコード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つの変数のメモリをプリントアウトしようとした、とここではメモリの測定値は、配列のための

メモリです:*配列のためのhttp://i.stack.imgur.com/dHI8k.png

メモリ:retSeqためhttp://i.stack.imgur.com/UqVkX.png

メモリ: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

char *の代わりにstd :: stringを使用できますか? –

+0

確かに、私は推測する..しかし、私はここで何が起こっているのか把握したい! – XelharK

+0

これは有効な標準C++ではありません。標準C++は可変長配列を提供しません。 – sellibitze

答えて

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'; 

it keeps reading from memory without this

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

+0

ありがとう、私はあなたが探していた答えをくれた! – XelharK

+0

@dasblinkenlight strncpyを使用すると、サンプルコードを少し短くすることができます。 –

+0

@MrListerこれは主にOPのコードで、ポストから10..14行目です。私がしたことは、off - by - oneエラーを避けるためにわずかに修正していました: ' - 'を削除し、一つの場所に '+ 1'を加え、もう一つは' + 1'を削除しました。私はそれが最適化できることを理解していますが、私はできるだけ元のものにできるだけ近づきたいと思っていました。 – dasblinkenlight

2

あなたがのstd ::文字列を使用することができた場合は、単純に次の操作を行います。これは、 "erase-remove idiom" と呼ばれている

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

1

個人的に、私はあなたがそうでなければ、本当に非常に良い理由がない限り、あなたはstd::stringを使用してオフに最善だと思う:

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

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

関連する問題