Creating arrays in C++ without knowing the length ahead of time

时光总嘲笑我的痴心妄想 提交于 2019-12-02 03:58:21

问题


I'm working on a small program to help speed up some data analysis for my lab work. It's supposed to read in data from a text file, create a bunch of arrays containing this data and then do some maths.

The problem I keep running into is that I don't know how many lines the original text file will have, so I don't know how big to make my arrays. I'm very new to C++ and right now I don't feel comfortable with dynamically sized arrays, here's a bit of the code

// first determine the length of the file
ifstream dataFile ("xys_data.txt");
const int LENGTH = count(istreambuf_iterator<char>(dataFile), istreambuf_iterator<char>(), '\n'); // counts the number of new lines

// declare vector of type datapoint
dataPoint data[LENGTH];

When I try and compile this i get the error

expected constant expression
cannot allocate an array of constant size 0
'data' : unknown size

But haven't I defined the LENGTH to be constant?

Any help will be appreciated.

EDIT

Following the advice of almost all of you, I have started using std::vector. I have one last issue that I'm a bit shaky on.

In the first attempt at the program I defined a data structure:

struct dataPoint
{
  double x; // x values
  double y; // y values
  double s; // sigma values
};

Then when I read the data from the file, I sent it to this structure like so

while (!dataFile.eof()) // this loop writes out each row of data to the arrays x, y, s until it reaches the end of the file
{ 
  int j = 0;
  dataFile >> data[j].x >> data[j].y >> data[j].s;
  j++;
}

Is there a way I can do this using vectors? My first thought is to define the vectors x, y and s and replace the data[j].x with x in the loop, but this doesn't work.


回答1:


First and foremost, built in arrays in C++ have to have compile-time size. It is not enough to declare your LENGTH variable const. It is also important to make it a compile-time constant. Your LENGTH is not a compile time constant, so declaring an array of size LENGTH is not possible. This is what the compiler is trying to tell you.

When you need to build an array, whose size is not known in advance, you typically have at least three approaches to choose from:

  1. Two-pass reading. Make a "dry run" over the data source to determine the exact size of the future array. Allocate the array. Make a second pass over the data source to fill the array with data.

  2. Reallocation. Use a reallocatable array. Allocate an array of some fixed size and fill it with data. If the array proves to be too small, reallocate it to bigger size and continue to fill it. Continue to read and reallocate until all data is read.

  3. Conversion. Read the data into a cheaply and easily expandable data structure (like linked list), then convert it to array.

Each of these approaches has it own pros and cons, limitations and areas of applicability.

It looks like in your case you are trying to use the first approach. It is not a very good idea to use it when you are working with files. Firstly, making two passes over a file is not very efficient. Secondly, in general case it might create a race condition: the file might change between the passes. If you still want to go that way, just use std::vector instead of a built-in array.

However, in your case I would recommend using the second approach. Again, use std::vector to store your data. Read your data line by line and append it to the vector, item by item. The vector will automatically reallocate itself as necessary.




回答2:


You say that you're not comfortable with dynamically-sized arrays, or std::vector.

I'm afraid that you'll have to figure out how to get comfortable here, because that's precisely what's std::vector is for.

The only other alternative is to use the gcc compiler. gcc does allow you to have variable-sized arrays. It's a compiler extension, it's not standard C or C++:

void method(size_t n)
{
   dataPoint array[n];

   // Do something with the array.
}



回答3:


You could either use a C++ container, like std::vector, or use dataPoint *data = malloc(LENGTH * sizeof(dataPoint)). In C++, it's probably better practice to use std::vector.

C99 has variable-length arrays, but you're question seems to be C++.

The real problem, though, is that you want to slurp the whole file all at once. Unless you're using a library that requires data to be in memory, it'll probably be easier to iterate over the text of the file using fgetc or whatever C++ has for that. After all, you'll need to go through the text at some point; you might as well save yourself the trouble of allocating memory.



来源:https://stackoverflow.com/questions/26984971/creating-arrays-in-c-without-knowing-the-length-ahead-of-time

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!