问题 函数中的向量 - 如何返回


我有一个应该从文件中逐行读取的函数,当一行不以'>'或''开头时,读取停止。它应该将行存储在vector中并返回它。
这是代码:

    #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`

任何人都有任何想法?

编辑: 正如Skurmendel所问,我之后因为内存安全违规而添加了整个代码

执行编译代码:

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

5586
2018-02-03 12:00


起源

你想要什么回报?矢量或字符串? - UltraInstinct
别 使用 而 (流。 好 ())。 - Fred Nurk
@Thrustmaster:vector @Fred Nurk:为什么以及我需要使用什么呢? - Mateusz Korycinski


答案:


如果我理解你,你的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;
     }
}

9
2018-02-03 12:08



或者更好的是,而不是循环: std::copy(str_vec.begin(), str_vec.end(), std::ostream_iterator<std::string>(cout, "\n"));。 - Zac Howland
我已经尝试但是我得到的错误类似于下面描述的(在Skurmedel回答下面)。 - Mateusz Korycinski


你试图返回一个向量,你的方法必须返回字符串。 也许你必须改变方法的签名

vector<string> getseq(char * db_file)

1
2018-02-03 12:05





你的功能 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
2018-02-03 12:10





好吧,你试图将一个向量作为字符串返回。这不起作用,因为它们是不同的类型,并且没有从一个到另一个定义的转换。您的函数具有返回类型 string

解决方案1

在您的情况下,您可以将行附加到字符串而不是将它们添加到向量?无论如何,您将结果用作字符串。

您可以将seqs更改为 string 并使用。附加数据 += 运营商。

解决方案2

您还可以将返回类型更改为 vector<string> 但是你需要在项目上循环并将它们打印出来 main

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

警告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
2018-02-03 12:07



谢谢你的建议!我想要它只是检查它是否读取线路怀特。在程序中我想要这个向量,因为我想迭代并对向量项做一些操作 - 它将是一些生物序列。 - Mateusz Korycinski
Mateusz K:好的:)我在答案中加了一点肉。 - Skurmedel
谢谢。 :)不幸的是,在我编译它之后,执行(./fpars seqs.fasta)它会返回一些符号(比如在二进制文件中)和语句:违反内存安全性。我在波兰语中有这样的陈述,所以我不懂英语。 :/ - Mateusz Korycinski
@Mateusz K:不幸的是,你能将新代码添加到问题的底部吗?我很确定某个地方的东西是用不应该的记忆做事的。 - Skurmedel
好的,我会发布它。 - Mateusz Korycinski