【问题标题】:Readling a line and using the next lines information c++读取一行并使用下一行信息 c++
【发布时间】:2020-10-15 10:33:55
【问题描述】:

我是 C++ 新手,在读取和更改输入文件中的行以使用下一行并将其保存到另一个输出文件中时,我需要帮助。

我有一个以 .fastq 格式存储的单个 DNA 序列的示例,其结构如下。

@Read_1
AGACUUUACGCT
+
++//187-,/02

所以每个 DNA 序列都有四行信息。

我的目标是将 DNA 字符串(第 2 行,长度 12)拆分为随机长度的不同片段,并将每个片段保存为单独的新序列。但要保留 .fastq 结构,我需要保留第 3 行和第 4 行的信息!所以理想的输出是:

@Read_1_1
AGAC
+
++//
@Read_1_2
UU
+
18
@Read_1_3
UACGCT
+
7-,/02

在这个理想的输出中,输入的第 4 行已被拆分以匹配每个 DNA 片段(但我可以使用 substr 来做到这一点,所以这不是问题)。我的问题是,当我拆分 DNA 序列(第 2 行)并将它们保存为新读取时,我需要第 3 行和第 4 行的信息。

我正在使用 C++ 进行编码,并且我制作了一些有效的函数,并进行了一些失败的尝试:

当我打开文件时,我创建了一个函数 (DNA_fragmentation),它将 DNA (line2) 随机分成一些片段,如下所示:

AGAC
UU
UACGCT

因此,当我使用此函数时,我正在读取第 2 行,然后将这些片段保存到 std::vectorstd::string 并使用 for 循环将这些片段及其读取(从第 1 行)保存到新文件中,给我输入:

@Read_1_1
AGAC
@Read_1_2
UU
@Read_1_3
UACGCT

我的问题是我不知道如何为每个新片段添加第 3 行和第 4 行,因为它们是在我打开并从原始文件读取第 2 行时创建的。如何从下一行中提取信息?

要读取文件并使用以下功能分隔功能:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

std::string fafq_seq(std::string in_name, std::string out_name) {
    std::ifstream myfile(in_name);
    std::ofstream out_file(out_name);

    if (myfile.is_open() && out_file.is_open())
    {
        std::string line;
        while( std::getline(myfile,line) )
        {
            int ID = 1;
            std::string read_ID;
            
            // This is line 1, which always match with @
            if (line.rfind("@",0) == 0) {
                continue;
            } // Then reading line 2  the DNA sequence
            else if (line.rfind("A", 0) == 0 ||
                line.rfind("T", 0) == 0 ||
                line.rfind("G", 0) == 0 ||
                line.rfind("C", 0) == 0){

                std::string Seq = line;
                
                // creating a vector with each of the DNA pieces using my DNA_fragmentation function
                std::vector<std::string> Damage = DNA_fragmentation(Seq,2,8);
                
                // For each fragment im adding a new read and saving the output
                for (int i=0; i<Damage.size();i++){

                    // adding what corresponds to line 1 starting with @
                    out_file << "@Read_" << ID << "_" << i+1 << std::endl;
                    
                    // adding the DNA pieces
                    out_file << Damage[i] << std::endl;
                }
                ID += 1;
            }
            else {
                // iterating through line 3 and 4, which is where im not sure how to handle my problem
                out_file << line << std::endl;
            }
        }
        out_file.close();
        myfile.close();
    }
}

int main() {

    std::string File = "TestSeq.fastq";
    fafq_seq(File,"Test_out.fastq");

    return 0;
}

我知道这是一个很长的问题,对我来说进一步解释有点困难,但我希望这个问题有意义。但只要任何 cmets 或帮助将不胜感激。谢谢。

【问题讨论】:

    标签: c++ file-io line


    【解决方案1】:

    我认为你可以先读入完整的 fastq 片段,然后将其拆分为多个片段,最后再次输出,从而使你的任务总体上更容易。

    如果你为片段创建一个结构并为其添加输入和输出运算符(operator&gt;&gt;operator&lt;&lt;),那么你可以以非常简单的方式进行读取和写入:

    #include <fstream>
    #include <iostream>
    #include <string>
    #include <vector>
    
    struct FastqFragment
    {
        std::string ID;
        std::string sequence;
        std::string delim;
        std::string quality_value;
    };
    
    std::istream& operator>>(std::istream& in, FastqFragment& frag)
    {
        std::getline(in, frag.ID);
        if (frag.ID.size() == 0 || frag.ID[0] != '@') {
            in.setstate(std::ios_base::failbit);
            return in;
        }
    
        std::getline(in, frag.sequence);
        std::getline(in, frag.delim);
        if (frag.delim.size() == 0 || frag.delim[0] != '+') {
            in.setstate(std::ios_base::failbit);
            return in;
        }
    
        std::getline(in, frag.quality_value);
        return in;
    }
    
    std::ostream& operator<<(std::ostream& out, const FastqFragment& frag)
    {
        out << frag.ID << '\n';
        out << frag.sequence << '\n';
        out << frag.delim << '\n';
        out << frag.quality_value << '\n';
        return out;
    }
    

    如您所见,我尝试向读取运算符添加一些非常基本的验证。现在你可以像这样使用它:

    int main()
    {
        std::ifstream in("sequence.txt");
    
        std::vector<FastqFragment> frags;
        for (FastqFragment tmp; in >> tmp;) {
            frags.push_back(tmp);
        }
    
        // Insert code for mutating the fragments
    
        for (const auto& f : frags)
            std::cout << f;
    
        // or
    
        std::ofstream out("output.txt");
        for (const auto& f : frags)
            out << f;
    }
    

    现在您的DNA_fragmentation 代码可以将 FastqFragment 结构作为参数,同时拆分所有需要拆分的字符串。

    【讨论】:

    • 非常感谢您对结构以及如何使用它们的建议!这很有帮助。
    • 这到底是做什么的? in.setstate(std::ios_base::failbit); ?我可以看到在 frag.ID 的情况下,它检查格式是否正确,但我不确定如何理解“设置状态......”。我可以读到它改变了标志。那么这就像引发错误吗?
    • @RAHenriksen 查看operator bool 的流,这是使while(in&gt;&gt;tmp) 工作的原因。 setstate 所做的是将流标记为“错误”并导致循环终止。这可能不是您在程序中想要的行为,例如您可能还想忽略错误行,然后尝试向前扫描以找到下一个好的片段的开头。但这由您决定。
    • @RAHenriksen 你也可以在这里阅读更多内容:stackoverflow.com/questions/5605125/…
    猜你喜欢
    • 1970-01-01
    • 2020-10-09
    • 1970-01-01
    • 2016-12-26
    • 1970-01-01
    • 1970-01-01
    • 2012-10-16
    • 2018-01-02
    • 1970-01-01
    相关资源
    最近更新 更多