2012-02-13 106 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'

但是,如果我嘗試調試代碼,看看是否有什麼錯,流程恰到好處,並最終返回正確的剝離序列。

我試圖打印出兩個變量的記憶,這裏是存儲器中的讀數

記憶序列:http://i.stack.imgur.com/dHI8k.png

內存*序列: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

你可以使用std :: string而不是char *嗎? – 2012-02-13 11:29:05

+0

當然,我想..但我想弄清楚這裏發生了什麼! – XelharK 2012-02-13 11:32:08

+0

這不是有效的標準C++。標準C++不提供可變長度數組。 – sellibitze 2012-02-13 11:40:12

回答

1

發生這種情況是因爲您將C字符串的終止零置於分配空間之外。您應該在字符串副本的末尾分配一個額外的字符,並在那裏添加'\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 2012-02-13 11:41:22

+0

@dasblinkenlight您的示例代碼可以通過使用strncpy縮短一點。 – 2012-02-13 11:52:37

+0

@MrLister這主要是OP的代碼,來自帖子的第10..14行。我所做的只是稍微糾正一下,以避免錯誤:刪除'--',在一個地方添加了'+ 1',並在另一個地方刪除了'+ 1'。我明白它可以被優化,但我想盡可能地保持原來的狀態。 – dasblinkenlight 2012-02-13 11:58:29

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

這就是所謂的 「erase-remove idiom」。

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字符串:C字符串達到找到的第一個空字符。使用您發佈的代碼時,您在分配'j'元素時引入了超出範圍的分配,並且您分配給retSeq[j + 1],這是字符串末尾的兩個字符(無論如何,您的意思是retSeq[j] = 0;)。