vector in function - how to do return

74,239

Solution 1

If I understood you, your getseq() should return a vector of strings. Therefore you should change

string getseq(char * db_file)

to

vector<string> getseq(char * db_file)

And if you want to print it on main() you should do it in a loop.

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

Solution 2

Your function getseq is declared to return std::string but you are trying to return value of another type - std::vector - therefore you got that compiler error. You need to return variable of type std::string (created by concatenating elements of your vector).

Your function could look like this:

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

Note: string you are returning from a function can be quite big object and returning it by value can be expensive as what is actually returned in this case is a copy of that object (constructed by invoking copy constructor). It would be more efficient if your string is declared as out parameter which you just fill inside the function:

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

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

Solution 3

you try to return a vector and your method must return string. maybe you have to change a signature of method to

vector<string> getseq(char * db_file)

Solution 4

Well, you are trying to return a vector as strings. This won't work because they are different types and have no conversion defined from one to the other. Your function has the return type string.

Solution 1

In your case you could append the lines to a string instead of adding them to a vector? You are using the result as a string anyhow.

You could change seqs to string and append data to it with the += operator.

Solution 2

You could also change the return type to vector<string> but you would need to loop over the items and print them instead in your main.

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

Caveat Lector: this will copy all the items. If you want to avoid this pass the vector as a reference to the function and add to it.

Looping is quite easy using iterators:

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

If you want to avoid copying a vector and all the strings make getseq take a reference to a 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
}

You would then need to create the vector<string> in your main instead, making my above code:

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

Edit after comments

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;
}
Share:
74,239
Mateusz Korycinski
Author by

Mateusz Korycinski

By Day: PhD student in bioinformatics working on protein evolution By Night: As above + learning &amp; exploring Python, Django, HTML &amp; CSS, C++ and few other things.

Updated on July 09, 2022

Comments

  • Mateusz Korycinski
    Mateusz Korycinski almost 2 years

    I've got a function that should read from file line by line, the reading stops when a line does not begin with '>' or ' '. It should store the lines in vector and return it.
    This is code:

        #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++) returns:

        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`
    

    Anyone has any idea?

    Edit: As Skurmendel ask, I am adding whole code because of memory security violation after

    executing compiled code:

    #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;
    }