返回二维数组的字符串

时间:2014-04-21 05:34:02

标签: c++ string

string** flowFile() {
    string line;
    string word[8];
    int i=0;
    static string flow[23][2];
    ifstream myfile ("test.txt");
    if (myfile.is_open())
    {
       while ( getline (myfile,line) )
        {
             strSplit(line,word);
             flow[i][0]=word[1];
             flow[i++][1]=word[2];
        }
        myfile.close();
   }
   else cout << "Unable to open file"; 
   return flow;
 }

 int main()
  {
     string **fl=flowFile();
  }

我收到此错误:

error: cannot convert ‘std::string (*)[2] {aka std::basic_string<char> (*)[2]}’
                to    ‘std::string** {aka std::basic_string<char>**}’
       in return

我的代码出了什么问题?

4 个答案:

答案 0 :(得分:3)

string flow[23][2]string **是两种不同的不兼容类型。一个人无法隐式转换为另一个。就这样。解决方案是通过使后面的string [23][2]返回引用和接受引用来使它们兼容,但这仍然是一个糟糕的解决方案,因为您仍在使用原始数组。

一个好的解决方案是使用std::vectorstd::string。也许,您还需要std::pairstd::array

以下是一种可能的解决方案:

#include <vector>
#include <array>
#include <string>

//C++11 style typedef
using flow_data_t = std::vector<std::array<std::string,2>>; 

//reimplementation of your function
flow_data_t flowFile() 
{
    std::string line;
    std::string word[8];
    int i=0;
    flow_data_t flow;
    std::ifstream myfile ("test.txt");
    if ( !myfile )  
       cout << "Unable to open file"; 
    while ( std::getline (myfile,line) )
    {
       strSplit(line,word);
       flow.push_back({word[0], word[1]});
    }
    return flow;
}

int main()
{
  flow_data_t data=flowFile();

  for(auto const & row : data)
      for(auto const & col : row)
            //work!
}

希望有所帮助。

答案 1 :(得分:1)

  1. 在C ++中,数组的类型为std::vector。您应该使用这些,而不是使用[]声明的低级内置数组。
  2. 在C ++中,string [23]有时可与string*互换,但string[23][2]永远不能与string**互换。这是你不应该使用内置数组的一个原因。
  3. 在C ++中,您无法返回本地内置数组变量。它会编译但是你的程序可能会崩溃。这是你不应该使用内置数组的另一个原因。 (尽管如此,返回静态数组应该没问题。)
  4. 还有很多原因。

答案 2 :(得分:1)

即使您可以返回指针并让数组衰减为指针,也无法从函数返回数组:Array Decay

然而,由于数组的memory layout与&#34; 2D指针数组&#34;不同,因此2D数组既不会衰减到T*也不会T**。 (它实际上更像是扁平的),并且你不能从函数返回数组。但是在C ++中,您可以返回数组引用Full Code

//This does not work
//typedef string * string2d[2];
//typedef string *(&string2d)[2];

typedef string (&string2d)[23][2];

string2d flowFile() {
    static string flow[23][2];
   return flow;
}

数组引用甚至可以保留每行和每列有多大的信息,并且不会发生数组衰减。

当然,更有建议的&#34; C ++方式&#34;要做到这一点,请使用std::vector(一如既往)。

答案 3 :(得分:1)

返回指向静态变量的指针没有错。只是必须正确声明返回类型。如果您尝试重现声明的含义以及编译器相应尝试执行的操作,那么这是有意义的。考虑声明static string flow[23][2];。它声明了23行字符串,每行包含2个元素。如果您将其视为一维数组,它会有所帮助。事实上,数组元素是数组,但现在不是那么重要(但我们会回到它)。从这个角度来看,数组只有23个元素,每个元素的大小为2个字符串。与所有数组一样,元素(这里:2个字符串的arrys)只是在内存中排列。

与任何数组一样,flow在大多数情况下都会衰减为指向其第一个元素的指针。增加指针将指向下一个元素,即第二行。在数值上,编译器必须将2 * sizeof(字符串)添加到流的地址,以便计算流的下一个元素的地址,这将是流[1]。 (它直接来自流[0]。这里没有魔法。)

现在,如果你声明string **flowpp,则flowpp已经是一个指针,不需要衰减。如果我们认为它指向数组中的第一个元素,那么这些元素会有什么类型?果然:简单的指针。增加flowpp会让它指向下一个元素。我的指针大4字节,因此在数字上将 4 添加到flowpp就足以访问flowpp的下一个元素。与需要添加到流程中的内容相比(记住,2 * sizeof(字符串)),这完全不同。 编译器根据指针指向的内容计算元素的偏移量!在两种情况下,这是非常不同的。

那么可以你的函数返回什么?当你返回时,流量会衰减到什么程度?它衰减到指向其第一个元素的指针。元素是两个字符串的数组。它必须是string xxx[2],xxx是指针:因此string (*p)[2]。如果指针实际上是由函数返回的,那么我们有一个函数调用而不是普通的p,所以它是(*f())[2]

这是一个完整的例子:

#include<iostream>
using namespace std;

const int numFlowElems = 3, numArrElems = 2;

/** @return a pointer to the first element of a static array
    of string[numArrElems]s.
*/  
string (*flowFile())[numArrElems]
{   // init so that we see something below.
    static string flow[numFlowElems][numArrElems] 
                = {{"1","2"}, 
                   {"3","4"},
                   {"5","6"}
                  };

    // your function code ...
    return flow;
}

int main()
{
     // array decays to ptr, like usual. Ptr elems are string[numArrElems].
     // ptrToArr is a pointer to arrays of two strings.
     string (*ptrToArr)[numArrElems] = flowFile();

     for( int flowInd= 0; flowInd<numFlowElems; ++flowInd )
     {
        for(int strInd = 0; strInd<numArrElems; ++strInd)
        {
            cout << ptrToArr[flowInd][strInd] << ' ';       
        }
        cout << endl;
     }

     return 0;
}

你如何解析string (*flowFile())[numArrElems]?我需要两次尝试才能使声明正确,如果这是任何安慰。关键是在C和C ++中(不在C#中,请注意!)声明具有表达式的形状。

你可以从内到外:flowFile()是一个函数。结果被取消引用,因为函数调用的优先级高于星号:* flowFile()是解除引用的结果。显然,结果是一个大小为numArrElems的数组,其元素是字符串。

你可以在外面执行:(*flowFile())[numArrElems]的结果被声明为字符串。 (*flowFile())是一个包含numArrElems元素的字符串数组。显然必须取消引用flowFile()才能获得该数组,以便flowfile是一个返回指向numArrElems字符串数组的指针的函数。这是真的!它返回flow的第一个元素,它正是一个字符串数组。

载体载体可能确实更容易;如果你想保留语义,你应该传递引用,正如其他人提到的:毕竟,原始程序中的所有函数都将在同一个静态数组上运行。如果按值传递向量,则不再是这种情况。但那时,这实际上可能是有益的。