0

So i'm trying to create an array of only the 'active' people stored in a file, using the fstream library. I've browsed and found lots of people identifying what the problem is, but no solution has helped me solve my problem.

My compiler is telling me that a "Constant Expression is Required." All I'm trying to do is use a loop to identify the amount of people that are active, then create an array using this number. Can I really not do this in C++?

MyFile.clear();
MyFile.seekg( 0, ios :: beg );
Person temp;
int j = 0;
MyFile.read(( char* ) &temp, sizeof( Person ));
while ( ! MyFile.eof() )
{
    if ( temp.personActive )
        j++;

    MyFile.read(( char* ) &temp, sizeof( Person ));
}
Person testArray[ j ];
Scott
  • 188
  • 1
  • 9
  • 6
    Sounds like it's time to learn about vectors. – user2357112 supports Monica Sep 25 '17 at 22:48
  • 3
    Which compiler? You are trying to use functionality which is non standard but supported by [some compilers](http://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html). They are called variable length arrays. One example of a relevant question [here](https://stackoverflow.com/questions/8861435/the-array-is-static-but-the-array-size-isnt-know-until-runtime-how-is-this-po). The right way to do it is use vector. You have other issues though. You derive the number of `Person`s by reading the file. You need the array present before you read and so can't know `j` in advance. – Paul Rooney Sep 25 '17 at 22:56
  • Also `while ( ! MyFile.eof() )` is wrong. It doesnt account for errors when reading. There is a canonical explanation of this somewhere on SO. – Paul Rooney Sep 25 '17 at 23:02
  • Dunno if I'd call it canonical, but [Why is iostream::eof inside a loop condition considered wrong?](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) gives a pretty good rundown of the problem. – user4581301 Sep 25 '17 at 23:22
  • I'd add that `while ( ! MyFile.eof() )` is wrong even if no I/O errors occur, since the `eof()` flag isn't necessarily set when you reach the exact eof, until you've tried to actually read past the eof. – Daniel Schepler Sep 26 '17 at 00:33
  • Hm thanks guys, I'm learning C++ now at Uni; it seems there is no instantaneous solution without digging deeper and using either _vectors_ or _new/delete_ I think I must either be doing the exercise wrong or misinterpreted the instructions because my lecturer hasn't touched on either of those topics yet; and while they are no doubt valid ways of solving the problem, if I don't do it _his_ way, I won't get any marks. Thanks heaps! P.S. For this semester, we're not dealing with error handling so I'm not too fussed about the eof issue. – Scott Sep 26 '17 at 00:41

2 Answers2

0

The quick and dirty solution is to declare the array on the heap:

Person *testArray = new Person[j];

You should also insert the following whenever you are done using testArray:

delete [] testArray;

The reason that it does not work currently is that, for an array not constructed with new, some compilers require its exact size to be known when it is compiled. The value of j cannot be determined when it is compiled since it is calculated at runtime.

As mentioned by user2357112, a better solution might be to check out the vector class.

lehiester
  • 726
  • 1
  • 5
  • 16
  • 1
    Also remember that if that code is inside some class that the copy constructor and assignment operator should be deleted or implemented to perform an appropriate copy of `testArray`. If the default copy constructor copies the pointer you will have UB on destruction. See [rule of three](https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)) – Paul Rooney Sep 25 '17 at 23:07
  • 1
    This is NOT the quick solution. Using `std::vector` is quicker, easier, and safer than using `new` and `delete`, which these days are almost never useful. – aschepler Sep 25 '17 at 23:30
  • 2
    I am sorry, I can only down-vote a C++ solution who recommends explicit `new` and `delete`. We got out of the dark age a long time ago. Follow RAII. Use `std::vector` – bolov Sep 25 '17 at 23:46
  • Changed "quick" to "quick and dirty". I would certainly agree that explicitly allocating an array on the heap is not the "right" way to do it, but the question was specifically about the reason for the error, not the optimal implementation. – lehiester Sep 26 '17 at 00:33
0

The problem araise because you are declaring an array withouts a specific size: Person testArray[ j ];. In this case the compiler needs to know the size of the array to reserve memory at compile time to calculate the amount of space required in the Data Segment, but because you didn't do it you are getting this exception.

There are many ways to fix it:

  • Use a std::vector which is a dynamic container, check this link: http://es.cppreference.com/w/cpp/container/vector/insert
  • Use dynamic memory, but you must set a previous size, like: Person testArray* = new Person[500], don't forget to release memory, i.e: delete[] testArray.
  • Use a global array with a fix size, enough to store all the information that you are expecting, like: Person testArray[500]
NathanOliver
  • 150,499
  • 26
  • 240
  • 331
Jorge Omar Medra
  • 839
  • 1
  • 6
  • 16