我正在开展一个小程序,以帮助加快我实验室工作的数据分析速度。它应该从文本文件中读取数据,创建一堆包含这些数据的数组然后做一些数学运算。
我遇到的问题是我不知道原始文本文件会有多少行,所以我不知道制作数组有多大。我对C ++很陌生,现在我对动态大小的数组感到不舒服,这里有一些代码
// 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];
当我尝试编译时,我得到了错误
expected constant expression
cannot allocate an array of constant size 0
'data' : unknown size
但我还没有确定LENGTH是不变的吗?
任何帮助将不胜感激。
修改
按照几乎所有人的建议,我已经开始使用std :: vector了。我有一个最后一个问题,我有点不稳定。
在第一次尝试该程序时,我定义了一个数据结构:
struct dataPoint
{
double x; // x values
double y; // y values
double s; // sigma values
};
然后,当我从文件中读取数据时,我将其发送到这样的结构
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++;
}
有没有办法可以用矢量做到这一点?我的第一个想法是定义向量x,y和s,并在循环中用data[j].x
替换x
,但这不起作用。
答案 0 :(得分:3)
您说您对动态大小的数组或std::vector
感到不舒服。
我担心你必须弄清楚如何在这里感到舒服,因为那正是std::vector
的用途。
唯一的另一种选择是使用gcc
编译器。 gcc
允许您拥有可变大小的数组。它是一个编译器扩展,它不是标准的C或C ++:
void method(size_t n)
{
dataPoint array[n];
// Do something with the array.
}
答案 1 :(得分:3)
首先,C ++中内置的数组必须具有编译时的大小。声明LENGTH
变量const
是不够的。使它成为编译时常量也很重要。您的LENGTH
不是编译时常量,因此无法声明大小为LENGTH
的数组。这就是编译器试图告诉你的。
当您需要构建一个预先不知道其大小的数组时,您通常至少有三种方法可供选择:
双遍阅读。进行&#34;干运行&#34;在数据源上确定未来数组的确切大小。分配数组。对数据源进行第二次传递,以使用数据填充数组。
重新分配。使用可重新分配的数组。分配一些固定大小的数组并用数据填充它。如果阵列被证明太小,请将其重新分配到更大的尺寸并继续填充它。继续阅读并重新分配,直到读完所有数据。
转换。将数据读入便宜且易于扩展的数据结构(如链接列表),然后将其转换为数组。
这些方法中的每一种都有自己的优点和缺点,限制和适用范围。
在您的情况下,您似乎正在尝试使用第一种方法。在处理文件时使用它不是一个好主意。首先,对文件进行两次传递效率不高。其次,在一般情况下,它可能会创建竞争条件:文件可能会在传递之间发生变化。如果您仍想这样做,只需使用std::vector
而不是内置数组。
但是,在您的情况下,我建议使用第二种方法。再次,使用std::vector
来存储您的数据。逐行读取数据并逐项将其附加到矢量。载体将根据需要自动重新分配。
答案 2 :(得分:0)
您可以使用C ++容器,例如std::vector
,也可以使用dataPoint *data = malloc(LENGTH * sizeof(dataPoint))
。在C ++中,使用std::vector
可能是更好的做法。
C99有variable-length arrays,但你的问题似乎是C ++。
但真正的问题是,你想要一次性整个文件。除非您使用的是需要数据存储在内存中的库,否则使用fgetc
或C ++为此迭代文件的文本可能会更容易。毕竟,你需要在某个时候阅读文本;你也可以省去分配内存的麻烦。