2011-02-03 8 views
9

Tengo una función que debe leer del archivo línea por línea, la lectura se detiene cuando una línea no comienza con '>' o ''. Debería almacenar las líneas en vector y devolverlo.
Este es el código:
vector en función - cómo hacerlo return

#include <cstdlib> 
    #include <iostream> 
    #include <string> 
    #include <stdio.h> 
    #include <fstream> 
    #include <vector> 

    using namespace std; 

    string getseq(char * db_file) // gets sequences from file 
      { 
       string seqdb; 
       vector<string> seqs; 
       ifstream ifs(db_file); 
       string line; 

       //vector<char> seqs[size/3]; 

       while(ifs.good()) 
       { 
        getline(ifs, seqdb); 
        if (seqdb[0] != '>' & seqdb[0]!=' ') 
        { 
         seqs.push_back(seqdb); 
        } 
       } 

      ifs.close(); 
      //return seqs; 

      //return seqs; 
      } 

    int main(int argc, char * argv[1]) 
    { 
     cout << "Sequences: \n" << getseq(argv[1]) << endl; 
     return 0; 
    } 

compilador (g ++) devuelve:

fasta_parser.cpp: In function ‘std::string getseq(char*)’: 
    fasta_parser.cpp:32: error: conversion from ‘std::vector<std::basic_string<char, `std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >’ to non-scalar type ‘std::string’ requested` 

Alguien tiene alguna idea?

Editar: Como Skurmendel preguntar, estoy añadiendo código entero debido a la violación de seguridad de memoria después de

la ejecución de código compilado:

#include <cstdlib> 
#include <iostream> 
#include <string> 
#include <stdio.h> 
#include <fstream> 
#include <vector> 

using namespace std; 

vector<string> getseq(char * db_file) // pobiera sekwencje z pliku 
     { 
      string seqdb; 
      vector<string> seqs; 
      ifstream ifs(db_file); 
      string line; 

      //vector<char> seqs[size/3]; 

      while(ifs.good()) 
      { 
       getline(ifs, seqdb); 
       if (seqdb[0] != '>' & seqdb[0]!=' ') 
       { 
        seqs.push_back(seqdb); 
       } 
      } 

     ifs.close(); 
     return seqs; 
     } 

int main(int argc, char * argv[1]) 
{ 
    vector<string> seqs; // Holds our strings. 
    getseq(argv[1]); // We don't return anything. 

    // This is just a matter of taste, we create an alias for the vector<string> iterator type. 
    typedef vector<string>::iterator string_iter; 

    // Print prelude. 
    cout << "Sekwencje: \n"; 

    // Loop till we hit the end of the vector. 
    for (string_iter i = seqs.begin(); i != seqs.end(); i++) 
    { 
     cout << *i << " "; // Do processing, add endlines, commas here etc. 
    } 

    cout << endl; 
} 
+2

¿Qué quiere volver? El vector o la cadena? – SuperSaiyan

+2

[No] (http://stackoverflow.com/questions/4881210/how-to-convert-a-string-to-a-ifstream/4881251#4881251) use [while] (http: // stackoverflow. com/questions/4324441/getlinestreamobj-line-reads-last-line-multiple-times/4324667 # 4324667) (stream. [good] (http://stackoverflow.com/questions/4874530/fstream-unix-problem-in -reading/4874650 # 4874650)()). –

+0

@Thrustmaster: vector @Fred Nurk: ¿Por qué y qué debo usar en su lugar? –

Respuesta

8

Si he entendido usted, su getseq() debería devolver un vector de cadenas. Por lo tanto usted debe cambiar

string getseq(char * db_file) 

a

vector<string> getseq(char * db_file) 

Y si quieres imprimirlo en main() debe hacerlo en un bucle.

int main() { 
    vector<string> str_vec = getseq(argv[1]); 
    for(vector<string>::iterator it = str_vec.begin(); it != str_vec.end(); it++) { 
     cout << *it << endl; 
    } 
} 
+1

O mejor aún, en lugar de un bucle: 'std :: copy (str_vec.begin(), str_vec.end(), std :: ostream_iterator (cout," \ n "));'. –

+0

Lo he intentado pero obtengo un error similar al descrito a continuación (debajo de la respuesta de Skurmedel). –

+0

Ok, este resultado funciona, ahora recupero secuencias! ¡Gracias por todo! ;] Realmente aprecio tu participación. ;] –

1

intenta volver un vector y su método debe devolver cuerda. tal vez usted tiene que cambiar una firma de método para

vector<string> getseq(char * db_file) 
+0

He hecho esto, gracias. Resultado arriba. ;) –

1

Bueno, usted está tratando de devolver un vector como cadenas. Esto no funcionará porque son tipos diferentes y no tienen una conversión definida de uno a otro. Su función tiene el tipo de devolución string.

Solución 1

En su caso se podría añadir las siguientes líneas a una cadena en lugar de sumarlos a un vector? Está utilizando el resultado como una cadena de todos modos.

Puede cambiar seqs a string y anexar datos con el operador +=.

Solución 2

También podría cambiar el tipo de retorno a vector<string> pero lo que se necesita para recorrer los elementos e imprimirlas en su lugar main.

vector<string> getseq(char * db_file) 
{ 
    ... 
    return seqs; 
} 

Advertencia Lector: Para que esto copiar todos los elementos. Si desea evitar esto, pase el vector como una referencia a la función y añádala.

bucle es muy fácil de usar iteradores:

// Get the strings as a vector. 
vector<string> seqs = getseq(argv[1]); 

// This is just a matter of taste, we create an alias for the vector<string> iterator type. 
typedef vector<string>:iterator_t string_iter; 

// Loop till we hit the end of the vector. 
for (string_iter i = seqs.begin(); i != seqs.end(); i++) 
{ 
    cout << *i; // you could add endlines, commas here etc. 
} 

Si se quiere evitar la copia de un vector y de todos los hilos hace getseq tomar una referencia a un vector<string>.

void getseq(char * db_file, vector<string> &seqs) 
{ 
    ... 
    // vector<string> seqs; this line is not needed anymore. 

    ... 
    // we don't need to return anything anymore 
} 

A continuación, necesitará crear el vector<string> en su principal lugar, haciendo que mi código anterior:

// Get the strings as a vector. 
vector<string> seqs; // Holds our strings. 
getseq(argv[1], seqs); // We don't return anything. 

// This is just a matter of taste, we create an alias for the vector<string> iterator type. 
typedef vector<string>:iterator_t string_iter; 

// Print prelude. 
cout << "Sekwencje: \n"; 

// Loop till we hit the end of the vector. 
for (string_iter i = seqs.begin(); i != seqs.end(); i++) 
{ 
    cout << *i << " "; // Do processing, add endlines, commas here etc. 
} 

cout << endl; 

Edición después de los comentarios

int main(int argc, char * argv[1]) 
{ 
    // This is what you need, sorry for the confusion. 
    // This copies the vector returned to seqs 
    vector<string> seqs = getseq(argv[1]); 

    // This is just a matter of taste, we create an alias for the vector<string> iterator type. 
    typedef vector<string>::iterator string_iter; 

    // Print prelude. 
    cout << "Sekwencje: \n"; 

    // Loop till we hit the end of the vector. 
    for (string_iter i = seqs.begin(); i != seqs.end(); i++) 
    { 
     cout << *i << " "; // Do processing, add endlines, commas here etc. 
    } 

    cout << endl; 
} 
+0

¡Gracias por este consejo! Quiero pront it solo para verificar si lee line wright. En el programa, quiero tener este vector porque quiero iterar y hacer algunas operaciones en elementos vectoriales: serán algunas secuencias biológicas. –

+0

Mateusz K: Ok :) Agregué un poco más de carne a mi respuesta. – Skurmedel

+0

Gracias. :) Desgraciadamente, después de compilarlo y ejecutar (./fpars seqs.fasta), devuelve algunos signos (como en el archivo binario) y una declaración: Violación de la seguridad de la memoria. Tengo esta declaración en polaco, así que no sé inglés análogo. :/ –

1

Su función getseq se declara para devolver std::string pero están tratando de devolver el valor de otro tipo - std::vector - por lo tanto, tienes que error del compilador. Debe devolver la variable del tipo std::string (creada al concatenar elementos de su vector).

Su función podría tener este aspecto:

string getseq(char* db_file) 
{ 
    string strSeqs; 
    vector<string> seqs; 

    ... // fill the vector; manipulate with ifstream 

    for(vector<string>::iterator it = seqs.begin(); it != seqs.end(); ++it) 
    { 
     strSeqs += *it; 
    } 

    return strSeqs; 
} 

Nota: cadena que está regresando de una función puede ser bastante grande objeto y devolverlo por valor puede ser caro como lo que realmente está vuelto en este caso es una copia de ese objeto (construido invocando el constructor de copia). Sería más eficaz si la cadena se declara como cabo parámetro que acaba de llenar dentro de la función:

void getseq(char* db_file, string& strSeqs);

string strSeqs; 
getseq(argv[1], strSeqs); 
cout << strSeqs << endl; 
Cuestiones relacionadas