2011-02-03 12 views
9

Ho una funzione che dovrebbe leggere da file riga per riga, la lettura si interrompe quando una riga non inizia con '>' o ''. Dovrebbe memorizzare le linee nel vettore e restituirle.
Questo è un codice:
vector in function - how to do 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; 
    } 

Compiler (g ++) restituisce:

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` 

Qualcuno ha qualche idea?

Edit: Come Skurmendel chiedere, sto aggiungendo intero codice a causa della violazione della sicurezza memoria dopo

l'esecuzione di codice compilato:

#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

Cosa vuoi ritornare? Il vettore o la stringa? – SuperSaiyan

+2

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

+0

@Thrustmaster: vector @Fred Nurk: perché e cosa devo invece usare? –

risposta

8

Se ho capito tu, il tuo getseq() dovrebbe restituire un vettore di stringhe. Pertanto si dovrebbe cambiare

string getseq(char * db_file) 

a

vector<string> getseq(char * db_file) 

E se si desidera stampare su main() si dovrebbe fare in un ciclo.

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 meglio ancora, invece di un ciclo: 'std :: copy (str_vec.begin(), str_vec.end(), std :: ostream_iterator (cout," \ n "));'. –

+0

Ho provato ma ho un errore simile a quello descritto di seguito (sotto la risposta di Skurmedel). –

+0

Ok, questo risultato funziona, ora richiamo le sequenze! Grazie di tutto! ;] Apprezzo davvero il tuo coinvolgimento. ;] –

1

si tenta di restituire un vettore e il metodo deve tornare stringa. forse bisogna cambiare una firma di metodo per

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

Ho fatto questo, grazie. Risultato sopra. ;) –

1

Bene, si sta cercando di restituire un vettore come stringhe. Questo non funzionerà perché sono di tipi diversi e non hanno alcuna conversione definita da uno all'altro. La tua funzione ha il tipo di ritorno string.

Soluzione 1

Nel tuo caso si potrebbe aggiungere le linee in una stringa invece di aggiungere ad un vettore? Stai comunque usando il risultato come una stringa.

È possibile modificare seq su string e aggiungere i dati ad esso con l'operatore +=.

Soluzione 2

si potrebbe anche cambiare il tipo di ritorno per vector<string> ma si avrebbe bisogno di un ciclo su voci e stamparle invece nel vostro main.

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

Caveat Lector: questo copierà tutti gli elementi. Se vuoi evitare questo, passa il vettore come riferimento alla funzione e aggiungilo ad esso.

Looping è abbastanza facile utilizzando iteratori:

// 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. 
} 

Se si vuole evitare di copiare un vettore e tutte le stringhe fare getseq prendere un riferimento 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 
} 

Si sarebbe quindi necessario creare la vector<string> nel vostro principale invece, fare il mio codice di cui sopra:

// 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; 

Modifica dopo i commenti

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

Grazie per questo consiglio! Voglio farlo solo per controllare se legge linee wright. Nel programma voglio avere questo vettore perché voglio ripetere e fare alcune operazioni sugli elementi vettoriali - saranno alcune sequenze biologiche. –

+0

Mateusz K: Ok :) Ho aggiunto un po 'più di carne alla mia risposta. – Skurmedel

+0

Grazie. :) Purtroppo dopo averlo compilato ed eseguito (./fpars seqs.fasta) restituisce alcuni segni (come nel file binario) e la dichiarazione: Violazione della sicurezza della memoria. Ho questa affermazione in polacco, quindi non conosco l'analogico inglese. :/ –

1

La funzione getseq è dichiarato per tornare std::string, ma si sta cercando di restituire valore di un altro tipo - std::vector - quindi si ha che l'errore del compilatore. Devi restituire una variabile di tipo std::string (creata concatenando elementi del tuo vettore).

La funzione potrebbe essere la seguente:

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: stringa che si sta tornando da una funzione può essere abbastanza grande oggetto e il ritorno per valore può essere costoso come ciò che è effettivamente restituito in questo caso è un copia di quell'oggetto (costruita invocando il costruttore di copie). Sarebbe più efficiente se la stringa è dichiarata come fuori parametro che basta compilare all'interno della funzione:

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

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