1

This is interesting. I want to make a 2D array where one of the dimensions is a variable. Here is my code:

int main(void) {
     const int rows = numlines("health.txt");
     float data[rows][5] = {0};
     readIntoArray(data, 5, rows, "health.txt");
     return 0;
}

Line 3 "rows" is underlined with an error. It says: "Expression must have a constant value." Apparently it works for other people to use const in these situations. But mine might work differently because my variable is defined by a function. Here is that function:

int numlines(string filename) {
    int number_of_lines = 0;
    ifstream fin(filename);
    string line;
    while (getline(fin, line)) {
        ++number_of_lines;
    }
    return number_of_lines;
}

I have tried following other suggestions and making my code follow this format:
(Replace lines 2 & 3 of the first code block with this.)

int rows = numlines("health.txt");
    float **data;
    data = new float*[rows];    //The height is defined by the function
    for (int i = 0; i < rows; i++) {
    data[i] = new float[5];    //The width is 5
}

But then that causes an error on "data" in line 4 of the first codeblock. The error is Argument of type "float**" is incompatible with parameter of type "float (*)[5]". Here is the first line of the relevant function:

void readIntoArray(float data[][MAXCOLUMNS], int arrayX, int arrayY, string filename)

MAXCOLUMNS is #defined as 5.

How do I pass the 2D array into the function without creating an error?
I am not the most experienced in c++, so I might be missing something obvious.

4
  • 4
    Please don't include line-numbers in code you post, it makes it hard to copy the code to try out ourselves. If you want to tell us about a special line, then add a comment in the code. Commented Nov 4, 2015 at 16:40
  • 4
    In C++, there are no variable-length primitive arrays. Just use std::vector. Commented Nov 4, 2015 at 16:43
  • @JoachimPileborg Thanks for the tip, I am new to Stack Exchange. Commented Nov 4, 2015 at 18:46
  • @JohnArvanitis - you can use alloca() as an equivalent to variable length arrays. I posted an answer showing how this is done. Commented Nov 4, 2015 at 18:48

3 Answers 3

4

There is a difference between:

const int rows = numlines("health.txt");

and

const int rows = 20;

In both cases the value of the variable cannot modified once it is initialzed. The difference is that in the first case, the value won't be known until run time while in the second case, the value is known at compile time.

In C++, an array can be declared using a variable only if its value is known at compile time.

That explains why you cannot use:

 const int rows = numlines("health.txt");
 float data[rows][5] = {0};

but you can use:

 const int rows = 20;
 float data[rows][5] = {0};

You can easily get around that issue by using an std::vector of std::vectors.

 const int rows = numlines("health.txt");
 std::vector<std::vector<float>> data(rows, std::vector<float>(5));

Since you know the size of the inner array, you can also you std::array. It will make the declaration a little simpler.

 std::vector<std::array<float, 5>> data(rows);
Sign up to request clarification or add additional context in comments.

2 Comments

Since the inner array have a size fixed at time of compilation, you could use a vector of std::array instead, will make that declaration a little simpler.
@JoachimPileborg, thanks for the suggestion. It makes perfect sense.
0

In C++,you can use "std::vector< T >" to save your data as a variable size array.

Just learn how to use STL,it would simplify your works.

Comments

0

You can use alloca to implement the equivalent of a variable length array:

    float (*data)[5] = (float (*)[5]) _alloca(rows * 5 * sizeof(float));

This will allocate local (stack) space and set data to point to the first row (with 5 columns) of a matrix of floats. The 5 can be replaced with a constant. You can then use data like a normal local matrix, data[ i ][ j ] ... . Depending on the compiler, the name may be alloca() instead of _alloca(), and the cast (float (*)[5]) may not be needed.

Since this is a local allocation, it's automatically freed when the function exits.

2 Comments

The alloca function is not in the C++ standard nor in the POSIX standards, it's availability isn't universal, and should not be used for any kind of portable code. Also, it's very easy to overflow the stack by allocating more than the stack can hold. I wouldn't recommend it.
@JoachimPileborg - Linux has alloca. It's been in MIcrosoft compilers since the days of MSDOS and still in VS 2015. Gnu article includes pros and cons of alloca. I mostly use alloca to replace VLAs (variable length arrays) when I'm working with someone else's code, which is why I suggested this since the OP appears to want a replacement for VLAs, other than using a container like std::vector.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.