简体   繁体   中英

How to return a 2d array where one dimension is of unknown size?

This is related to this question . I have a function void doConfig(mappings, int& numOfMappings) and I'm not sure how to declare mappings. It is a two dimensional array whose elements are chars. The first dimension is determined at run time, and will be computed in the body of the function. The second dimension is always going to be 2. What is the code for this? I'd imagine it to be char** mappings or something like that. Also in C++ arrays are always passed by reference right? So I don't need to use & even though I intend to use the value when the function returns?

EDIT: Basically I want to return this char (*mapping)[2] = new char[numOfMappings][2];

as per 2to1mux's suggestion I still cannot get it to work. The array appears to getting the right values but something is going wrong when the doConfig() function returns.

int main()
{
    int numOfMappings = 0;
    char **mappings;
    doConfig(mappings, numOfMappings);
    cout << "This is mappings" << mappings << endl;//this address is different than the one given in doConfig(), is that wrong?
    cout << "this is numOfMappings: " << numOfMappings << endl;
    cout << mappings[0][0] << "->" << mappings[0][1] << endl;//program crashes here
    //code removed
    return EXIT_SUCCESS;
}

void doConfig(char **mappings, int& numOfMappings)
{
    //code removed, numOfMappings calculated
    for(int j = 0; j < numOfMappings; j++)
    {
        getline(settingsFile, setting);
        mappings[j] = new char[2];
        mappings[j][0] = setting.at(0);
        mappings[j][1] = setting.at(2);
    }
    for(int j = 0; j < numOfMappings; j++)
        cout << mappings[j][0] << "->" << mappings[j][1] << endl;//everything is as expected so array created ok
    cout << "This is mappings" << mappings << endl;//different address than the one give in main
}

OK I got it working now but mainly from haking around. Could people please explain there solutions as to how they known when to use * and & ?

Since you tagged you question C++, not C, I guess you might want a proper solution.

template<typename T>
using vectorOf2D = std::vector<std::array<T, 2>>;

vectorOf2D<char> getMappings() {
    return /* whatever you do to fill those */;
    // (most probably) using NRVO to ellide the copy
}

And if you are afraid access might be complicated:

auto mappings = getMappings();

functionTakingAMapping(mappings[i]);
char element = mappings[0][1];

(Following up on my answer to the linked question.)

The direct (yet rather convoluted) syntax for this would be

char (*create_mappings(size_t n))[2]
{
  // Allocate an char[n][2] array
  char (*mappings)[2] = new char[n][2];

  // Initailize `mappings[i][j]` in any way you want...

  return mappings;
}

But a better idea would be to make it more readable through typedef

typedef char Char2[2];

Char2 *create_mappings(size_t n)
{
  // Allocate an char[n][2] array
  Char2 *mappings = new Char2[n];

  // Initailize `mappings[i][j]` in any way you want...

  return mappings;
}

I'll answer your questions last-in-first-out:

  1. Correct, you won't need to use & here.

  2. The term by-reference technically doesn't apply to passing arrays, but the simple answer to your question is that you are never passing a copy of an array to a function. Any changes made to a parameter of type array will apply to the original array, not a copy.

  3. I suggest passing a double-pointer:

     void doConfig(char **mappings, int& numOfMappings) 

    You will be able to access members of mappings exactly as you would a 2d array. Example:

     mappings[2][3] = 'b'; 

EDIT: Here is new suggestion based on your clarification

void doConfig(char** mappings, int& numOfMappings){

    /*Compute numOfMappings -- 
      this integer is passed by-reference, so it can be used outside function
      to figure out the size allocated within the function*/

    mappings = new char*[numOfMappings];
    for(int i=0; i < numOfMappings; i++){
        mappings[i] = new char[2];
    }
    /*Do whatever you need to do with mappings*/

    /*Return nothing because function is void -- since mappings is passed as
      pointer, changes are maintained after function ends*/

}

You can return a pointer to the 2D array.

For example,

char **ptr;


return ptr;

While passing the address of arrays you don't have to use the & operator, if you want to pass the address of the starting location of the 2D array rather than the address of a particular element.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM