W. Tidwell
W. Tidwell

Reputation: 25

Is it possible to pass a variable length array as a parameter in C++?

I do not know the value of V before. It is found within a file I open in the program. It cannot be defined as such #DEFINE V __. It does not work as a global variable. The input file changes V based on the contents. Expected the parameters to pass and use the djisktra's algorithm found on Geeks for Geeks.

I have tried declaring V globally, but I am given an error saying "variable must have constant value."

void dijkstra(int graph[V][V], int src, int V)
//array function being pasted, error is the V in graph[V]
//V is defined at beginning of main as 
int V;
//where V is changed
while(std::getline(file2,newstr))
{
    if(newstr.find(check) != std::string::npos)
    {
        V++;
    }
}
//where it is passed in main
for(int i = 0; i < V; i++)
{
    size = V;
    dijkstra(array[size][size], i, V);        
}

Upvotes: 0

Views: 1578

Answers (3)

2785528
2785528

Reputation: 5566

Is it possible to pass a variable length array as a parameter in C++.

No.

Variable length arrays are not supported in std C++, But read on, they have an alternative that is surprisingly better.


I do not know the value of V before it is found within a file I open in the program.

A 1d vector is trivial to create, after your code has found V, no compile time constant required.

Early in the startup in one of my programs, the gBoard vector is built using argv[3] and argv[4]. Here is a snippet:

  aTermPFN               += argv[1];    // ouput tty, /dev/pts/<argv[1]>
  fillPatternChoiceLetter = argv[2][0];
  aMaxRow                 = stoi(argv[3]);
  aMaxCol                 = stoi(argv[4]);
  userDim                 = true;

Clearly, the program has already started ... and V size is easily computed from (aMaxRow * aMaxCol).

I find it easy to access a 1d vector (or 1d array), in row major order, as if it is a 2d matrix, with the following function:

// game-board-index: computes index into the single dimension vector
//                   from 2d (row, col) matrix coordinates
size_t gbIndx(int r, int c) { return static_cast<size_t>((r * maxCol) + c); }

// a 2d game board of cells

// 2d access (row major order) implemented using 1d access
Cell_t*  getCell( int r, int c )   { return (gBoard [gbIndx(r,c)]); } 

// 1d access is surprisingly convenient for many functions
Cell_t*  getCell( uint gbIndex  )  { return (gBoard [gbIndex]);     } 

Sample initialization usage:

//              vvvvvvvvvvvvvvvvvvv_-- 2d matrix access
gBoard [ gbIndx((midRow+1), midCol)   ] -> setOptionX();
//       ^^^^^^--1d row-major order index 

A randomized gGoard is trivial in 1d:

void GOLUtil_t::setRandom() { CellVec_t myVec(gBoard); // copy cell vector

random_device rd; mt19937_64 gen(rd()); shuffle (myVec.begin(), myVec.end(), gen); // shuffle order

int count = 1; for ( auto it : myVec ) // randomly mark half the cells { if(count++ & 1) it->setAlive(); // every odd cell } }


Note from https://en.cppreference.com/w/cpp/container/vector:

"The elements are stored contiguously, which means that elements can be accessed not only through iterators, but also using offsets to regular pointers to elements. This means that a pointer to an element of a vector may be passed to any function that expects a pointer to an element of an array."


I was surprised how often the 1d access enabled simpler code.

for (auto it : gBoard)
   it->init();        // command each cell to init

Summary:

Despite variable-length-arrays (vla) not being supported in std C++, I believe you will find std::vector a better alternative. And you will find that passing the vector within your code works.

Upvotes: 0

Guillaume Racicot
Guillaume Racicot

Reputation: 41770

For c style arrays, you need to know the size at compile time. A variable like int N; is a runtime value. A variable like constexpr int N = 9; is usable at compile time and cannot be mutated.

If you need an array sizeable at runtime, you need some sort of dynamic array. The most common one is std::vector.

void dijkstra(std::vector<int> graph, int src, int V)
std::vector<int> graph;
graph.resize(V * V); // vector are resizable

for(int i = 0; i < V; i++)
{
    size = V;
    dijkstra(graph, i, V);        
}

Upvotes: 1

tadman
tadman

Reputation: 211670

Don't use C-style arrays. Use std::vector and friends from the Standard Library where you can ask for the size if you want to know.

Converted:

void dijkstra(const std::vector<std::vector<int>>& graph, int src) {
  auto v = graph.size();

  // ... Other code.
}

For inserting you can use push_back:

std::vector<std::vector<int>> graph;

while(std::getline(file2,newstr)) {
  if(newstr.find(check) != std::string::npos) {
    std::vector<int> row;

    row.push_back(...);

    graph.push_back(row);
  }
}

Then pass it in like a regular variable:

dijkstra(graph, src);

If all that vector stuff looks really ugly, typedef it to something more friendly looking.

Upvotes: 1

Related Questions