Позвольте мне начать с заявления, что я новичок в C ++. В любом случае, формат FASTA выглядит следующим образом:
Любая строка, начинающаяся с «>», указывает название / идентификатор последовательности гена прямо под ней. Прямо под идентификатором есть последовательность генов. Эта последовательность гена может состоять из 1 или нескольких строк.
Итак … что я хочу сделать, это напечатать: id << «:» << gene_sequence << епсИ;
Вот мой код:
#include <iostream>
#include <fstream>
int main(int argc, char **argv) {
if (argc < 2) {
std::cerr << " Wrong format: " << argv[0] << " [infile] " << std::endl;
return -1;
}
std::ifstream input(argv[1]);
if (!input.good()) {
std::cerr << "Error opening: " << argv[1] << " . You have failed." << std::endl;
return -1;
}
std::string line, id, DNA_sequence;
while (std::getline(input, line).good()) {
if (line[0] == '>') {
id = line.substr(1);
std::cout << id << " : " << DNA_sequence << std::endl;
DNA_sequence.clear();
}
else if (line[0] != '>'){
DNA_sequence += line;
}
}
}
Для второго аргумента, введенного в командную строку, вот содержимое моего файла:
>DNA_1
GATTACA
>DNA_2
TAGACCA
TAGACCA
>DNA_3
ATAC
>DNA_4
AT
Пожалуйста, скопируйте и вставьте в текстовый файл.
После того, как это будет сделано, и код будет выполнен, я хочу указать на проблему. Код пропускает ввод последовательности DNA_1 на правильное место и вместо этого помещает последовательность DNA_1 в DNA_2. Результаты выдвигаются вперед на 1 в результате. Любая помощь или советы будут с благодарностью?
Как я уже говорил, я новичок в C ++. И семантика довольно сложна для изучения по сравнению с Python.
Я вижу несколько проблем с вашим кодом.
Сначала вы включаете std::ifstream::good()
который не работает, потому что он не учитывает конец файла (что происходит даже после хорошего чтения).
Тогда вы получаете доступ line[0]
без проверки, если строка пуста, что может вызвать ошибку сегмента.
Затем вы выводите «предыдущую строку» еще до того, как соберете ее.
Наконец, вы не выводите последнюю строку, потому что цикл завершается, когда он не находит другой >
,
Я добавил комментарии к своим исправлениям в ваш код:
#include <iostream>
#include <fstream>
int main(int argc, char **argv) {
if (argc < 2) {
std::cerr << " Wrong format: " << argv[0] << " [infile] " << std::endl;
return -1;
}
std::ifstream input(argv[1]);
if (!input.good()) {
std::cerr << "Error opening: " << argv[1] << " . You have failed." << std::endl;
return -1;
}
std::string line, id, DNA_sequence;
// Don't loop on good(), it doesn't allow for EOF!!
// while (std::getline(input, line).good()) {
while (std::getline(input, line)) {
// line may be empty so you *must* ignore blank lines
// or you have a crash waiting to happen with line[0]
if(line.empty())
continue;
if (line[0] == '>') {
// output previous line before overwriting id
// but ONLY if id actually contains something
if(!id.empty())
std::cout << id << " : " << DNA_sequence << std::endl;
id = line.substr(1);
DNA_sequence.clear();
}
else {// if (line[0] != '>'){ // not needed because implicit
DNA_sequence += line;
}
}
// output final entry
// but ONLY if id actually contains something
if(!id.empty())
std::cout << id << " : " << DNA_sequence << std::endl;
}
Выход:
DNA_1 : GATTACA
DNA_2 : TAGACCATAGACCA
DNA_3 : ATAC
DNA_4 : AT
рабочая реализация здесь
https://rosettacode.org/wiki/FASTA_format#C.2B.2B
только исправлено
while( std::getline( input, line ).good() ){
в
while( std::getline( input, line ) ){
Код
#include <iostream>
#include <fstream>
int main( int argc, char **argv ){
if( argc <= 1 ){
std::cerr << "Usage: "<<argv[0]<<" [infile]" << std::endl;
return -1;
}
std::ifstream input(argv[1]);
if(!input.good()){
std::cerr << "Error opening '"<<argv[1]<<"'. Bailing out." << std::endl;
return -1;
}
std::string line, name, content;
while( std::getline( input, line ) ){
if( line.empty() || line[0] == '>' ){ // Identifier marker
if( !name.empty() ){ // Print out what we read from the last entry
std::cout << name << " : " << content << std::endl;
name.clear();
}
if( !line.empty() ){
name = line.substr(1);
}
content.clear();
} else if( !name.empty() ){
if( line.find(' ') != std::string::npos ){ // Invalid sequence--no spaces allowed
name.clear();
content.clear();
} else {
content += line;
}
}
}
if( !name.empty() ){ // Print out what we read from the last entry
std::cout << name << " : " << content << std::endl;
}
return 0;
}
вход:
>Rosetta_Example_1
THERECANBENOSPACE
>Rosetta_Example_2
THERECANBESEVERAL
LINESBUTTHEYALLMUST
BECONCATENATED
выход:
Rosetta_Example_1 : THERECANBENOSPACE
Rosetta_Example_2 : THERECANBESEVERALLINESBUTTHEYALLMUSTBECONCATENATED
Вы сохраняете новый идентификатор перед печатью старого:
id = line.substr(1);
std::cout << id << " : " << DNA_sequence << std::endl;
Поменяйте местами линии для правильного порядка. Вы, вероятно, также хотите проверить, если у вас уже есть идентификатор, чтобы пропустить первую запись.