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'

但是,如果我尝试调试代码以查看是否有任何问题,则流程会正常运行,并最终返回正确的剥离序列。

我试图打印出两个变量的内存,这里是内存读数

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 字符串的终止零放在分配的空间之外。您应该在字符串副本的末尾分配一个额外的字符,并'\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 字符串时,您需要意识到它们是以空字符结尾的:C 字符串可以到达找到的第一个空字符。使用您发布的代码,您在分配“j”元素时引入了一个超出范围的分配,并且您分配给retSeq[j + 1]哪个是字符串末尾之后的两个字符(当然您的意思是retSeq[j] = 0;无论如何)。

于 2012-02-13T11:37:34.380 回答