2012-02-13 65 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;)。