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

我的代码有什么问题?

===============>>#1 票数: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!
}

希望能有所帮助。

===============>>#2 票数:1

  1. 在C ++中,数组的类型为std::vector 您应该使用这些,而不是使用[]声明的低级内置数组。
  2. 在C ++中, string [23]有时可以与string*互换,但是string[23][2]绝不能与string**互换。 这是您不应使用内置数组的原因之一。
  3. 在C ++中,您不能返回本地内置数组变量。 它会编译,但是您的程序可能会崩溃。 这是您不应使用内置数组的另一个原因。 (虽然返回静态数组应该可以)。
  4. 还有更多原因。

===============>>#3 票数:1 已采纳

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

但是2D数组不能衰减到T*T**因为该数组的内存布局不同于“ 2D指针数组”(实际上更像是扁平化的),并且不能从函数返回数组。 但是,在C ++中,您可以返回数组引用完整代码

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

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

当然,更建议的“ C ++方式”是使用std::vector (一如既往)。

===============>>#4 票数:1

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

像任何数组一样, flow在大多数情况下将衰减为指向其第一个元素的指针。 将该指针递增将指向下一个元素,即第二行。 从数字上说,编译器必须在流的地址上添加2 * sizeof(string)以便计算流的下一个元素的地址,该下一个元素将是flow [1]。 (它直接位于flow [0]的后面。这里没有魔术。)

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

那么您的函数可以返回什么呢? 当您返回时,流量衰减到什么程度? 它衰减到指向其第一个元素的指针。 元素是两个字符串的数组。 它必须是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字符串数组的指针。 确实如此! 它返回流的第一个元素,该元素恰好是字符串数组。

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

  ask by Amar Agrawal translate from so

未解决问题?本站智能推荐: