结果根据非修改代码

时间:2017-01-31 18:18:45

标签: c++ string c++11 insert

我正在使用Linux服务器,我正在尝试使用字符串作为DNA的长度。我试图看看我是否可以让一组DNA与另一组“碰撞”。碰撞只是意味着两个序列是相同的,但它们并非来自相同长度的DNA。

这是5test.txt中的数据:

03111
11013
22002
22133
33122
33121

这是main.cpp:

#include        <iostream>
#include        <fstream>
#include        <string>
#include        <vector>
#include        <cstdlib>
#include        <typeinfo>
using namespace std;

inline string insert(const string& who, int where, string what)
{
        string temp = who;
        temp.insert(where, what);
        return temp;
}

struct c_mDNA                               //holds the DNA sequences, remembering where it came from
{
        string seq;
        const string* orig;
};

ostream& operator<<(ostream& os, c_mDNA& m) //to print out debug info easier
{
        os << "seq: " << m.seq << "\torig: " << *m.orig << endl;
        return os;
}

int main()
{

        ifstream input; string inputname;               //These next couple lines deal with input
        inputname = "5test.txt";
        input.open(inputname.c_str());
        string line;                                    //line will hold the inputted lines
        int n = 5;                                      //we're working with length 5 as a test
        vector<string> oDNA;                            //this holds all of the original strands
        vector<c_mDNA> mDNA, iDNA;                      //this will hold all of the mutated strands, m being the deleted and i being the possible insertions

        //input loop
        while (getline(input, line))
        {
                //change line from a sequence of numbers to nucleotide ACTG
                ...
                oDNA.push_back(line);
        }

        //insert loop
        for(auto oliga : oDNA)
        {
                for (int i = 0; i < n; i++)
                {
                        iDNA.push_back(c_mDNA { insert(oliga, i, "A"), &oliga } );
                        cout << iDNA.back() << endl;
                        //do the above for the other 3 nucleotides
                        ...                            
                }

                //these next couple lines are important

                //for (auto m : iDNA)
                //{
                //      cout  << m << endl;
                //}
        }

        //mutate loop
        for (auto& oliga : oDNA)
        {   
                for (int i = 0; i < oliga.length(); i++)
                {
                        string temp = oliga;
                        temp.erase(i,1);

                        //There are 16 different combinations of two nucleotides
                        mDNA.push_back(c_mDNA{temp + "AA", &oliga});
                        mDNA.push_back(c_mDNA{temp + "CA", &oliga});
                        mDNA.push_back(c_mDNA{temp + "TA", &oliga});
                        mDNA.push_back(c_mDNA{temp + "GA", &oliga});
                        mDNA.push_back(c_mDNA{temp + "AC", &oliga});
                        mDNA.push_back(c_mDNA{temp + "CC", &oliga});
                        mDNA.push_back(c_mDNA{temp + "TC", &oliga});
                        mDNA.push_back(c_mDNA{temp + "GC", &oliga});
                        mDNA.push_back(c_mDNA{temp + "AT", &oliga});
                        mDNA.push_back(c_mDNA{temp + "CT", &oliga});
                        mDNA.push_back(c_mDNA{temp + "TT", &oliga});
                        mDNA.push_back(c_mDNA{temp + "GT", &oliga});
                        mDNA.push_back(c_mDNA{temp + "AG", &oliga});
                        mDNA.push_back(c_mDNA{temp + "CG", &oliga});
                        mDNA.push_back(c_mDNA{temp + "TG", &oliga});
                        mDNA.push_back(c_mDNA{temp + "GG", &oliga});

                }
        }

        //check loop
        for (auto m : iDNA)
        {
                cout  << m << endl;
        }

        ofstream out("5out_test.txt");    
        int collisions(0);

        //output loop
        for (const auto& m_oliga : mDNA)
        {
                bool collide = false; c_mDNA collude;   //collude stores the collided codeword
                for (const auto& i_oliga : iDNA)
                {
                        if (m_oliga.seq == i_oliga.seq) //if sequences are the same
                        {
                                if ( m_oliga.orig != i_oliga.orig) //if the original seqs are the same
                                {
                                        cout << *m_oliga.orig << " and " << *i_oliga.orig << endl;
                                        cout << m_oliga.orig << " and " << i_oliga.orig << endl;
                                        collide = true;
                                        collude = i_oliga;
                                        collisions++;
                                        break;
                                }
                        }
                }

                if (collide) out << m_oliga.seq << "    orig: " << *m_oliga.orig << "   collides with: " << collude.seq << " from: " << *collude.orig << endl;
                else out << m_oliga.seq << "    orig: " << *m_oliga.orig << endl;
        }

        return 0;
}

我已将五个循环标记为“输入”,“插入”,“变异”,“检查”和“输出”。在我已经注释掉的“插入”循环中有一个“check”循环的副本。

这让我感到沮丧。当我留下那个副本时,我会像“check”循环那样输出垃圾:

 seq: GCGTAT     orig: GCGTAT

orig应该是长度为5的字符串,它应该指向oDNA载体中的元素。从“输出”循环中,当发现碰撞时,它会将其打印到屏幕上:

GGGTA and
0x61cf80 and 0x7fffffffd6a0

第一行不会为* i_oliga.orig打印任何内容。指针仍指向某处。

现在当我取消注释第一个“检查”循环时:

seq: GCGTAT     orig: GCGTT

GGGTA and GCGTT
0x61cf80 and 0x7fffffffd650

出于某种原因,指针仍然指向一个完全不同的地方,但我得到了我想要的答案。我已经过测试,以确保这是一致的行为。

为什么注释掉的循环会改变结果?

另一件可能有用的事情是,当我将main.cpp和5test.txt导入我的家用电脑并在visual studio 15上运行程序时,我只会得到垃圾结果。

1 个答案:

答案 0 :(得分:1)

这可能只是一个错字,如果OP回来并说这是一个错字,我会删除答案。

for (auto oliga : oDNA)
{
    for (int i = 0; i < n; i++)
    {
        iDNA.push_back(c_mDNA { insert(oliga, i, "A"), &oliga });
    }
}

auto oliga定义一个临时变量,它是oDNA中源的副本。它将超出范围并在循环结束时的闭括号处变为无效。传递该紧密括号之后,以任何方式使用那个 - oliga是未定义的行为,编译器可以生成它想要的任何代码。

假设基于堆栈的临时存储,可能发生的是在堆栈上为oliga添加空间并添加额外代码移动到堆栈中变量结束的位置。因为它在堆栈上,所以堆栈上的其他变量在它不再在范围之后会覆盖oliga,所以几乎任何东西都可以从没有任何东西打印到大量的废话直到一个程序 - 发生堆栈溢出。

但是C ++标准对编译器生成的代码来说会很好,这些代码命令核攻击消灭全人类。未定义的行为很奇怪。

解决方案:

for (auto & oliga : oDNA)

引用oDNA向量中的原始值以保留向量中值的地址。这应该是安全的,因为在此之后看起来oDNA向量不会被修改。通常存储指向std::vector内的值的指针是有风险的,因为代码是一个vector调整大小的形式,带有无效的&#34;悬空&#34;指针。