вектор в функции - как сделать возврат - PullRequest
12 голосов
/ 03 февраля 2011

У меня есть функция, которая должна читать из файла построчно, чтение останавливается, когда строка не начинается с «>» или «».Он должен хранить строки в векторе и возвращать их.
Это код:

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

Компилятор (g ++) возвращает:

    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`

У кого-нибудь есть идеи?

Редактировать:Как просит Скурмендел, я добавляю весь код из-за нарушения безопасности памяти после

выполнения скомпилированного кода:

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

Ответы [ 4 ]

10 голосов
/ 03 февраля 2011

Если я вас понял, ваш getseq () должен возвращать вектор строк. Поэтому вы должны изменить

string getseq(char * db_file)

до

vector<string> getseq(char * db_file)

И если вы хотите напечатать его в main (), вы должны сделать это в цикле.

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 голос
/ 03 февраля 2011

Ваша функция getseq объявлена ​​как возвращающая std::string, но вы пытаетесь вернуть значение другого типа - std::vector - поэтому вы получили эту ошибку компилятора.Вам необходимо вернуть переменную типа std::string (созданную объединением элементов вашего вектора).

Ваша функция может выглядеть следующим образом:

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

Примечание: строка, которую вы возвращаете изФункция может быть довольно большим объектом, и возвращение его по значению может быть дорогостоящим, поскольку то, что фактически возвращается в этом случае, является копией этого объекта (созданного с помощью конструктора копирования).Было бы более эффективно, если бы ваша строка была объявлена ​​как выходной параметр , который вы просто заполняете внутри функции:

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

string strSeqs;
getseq(argv[1], strSeqs);
cout << strSeqs << endl;
1 голос
/ 03 февраля 2011

Ну, вы пытаетесь вернуть вектор в виде строки. Это не будет работать, потому что они разных типов и не имеют преобразования, определенного из одного в другой. Ваша функция имеет тип возврата string.

Раствор 1

В вашем случае вы могли бы добавить строки в строку вместо добавления их в вектор? В любом случае вы используете результат в виде строки.

Вы можете изменить seqs на string и добавить к нему данные с помощью оператора +=.

Решение 2

Вы также можете изменить тип возвращаемого значения на vector<string>, но вам нужно будет зациклить элементы и напечатать их вместо этого в main.

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

Caveat Lector: скопирует все элементы. Если вы хотите избежать этого, передайте вектор как ссылку на функцию и добавьте к ней.

Зацикливание довольно просто, используя итераторы:

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

Если вы хотите избежать копирования вектора и всех строк, сделайте getseq со ссылкой на 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
}

Вместо этого вам нужно будет создать vector<string> в своей главной строке, сделав мой код выше:

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

Редактировать после комментариев

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;
}
1 голос
/ 03 февраля 2011

вы пытаетесь вернуть вектор, и ваш метод должен вернуть строку. возможно, вам придется изменить сигнатуру метода на

vector<string> getseq(char * db_file)
...