在C++中创建数组,而无需提前知道长度

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

本文关键字:C++ 创建 数组      更新时间:2023-10-16

我正在开发一个小程序,以帮助加快实验室工作的一些数据分析。它应该从文本文件中读取数据,创建一堆包含这些数据的数组,然后做一些数学运算。

我一直遇到的问题是我不知道原始文本文件会有多少行,所以我不知道我的数组有多大。我对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

但是我还没有将长度定义为常量吗?

任何帮助将不胜感激。

编辑

遵循几乎所有人的建议,我开始使用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,但这不起作用。

首先,在C++中内置数组必须具有编译时大小。仅仅声明您的LENGTH变量const是不够的。使其成为编译时常量也很重要。您的LENGTH不是编译时常量,因此无法声明大小LENGTH数组。这就是编译器试图告诉您的。

当您需要构建一个事先不知道其大小的数组时,您通常至少有三种方法可供选择:

  1. 两次阅读。对数据源进行"试运行",以确定未来数组的确切大小。分配阵列。对数据源进行第二次传递,以用数据填充数组。

  2. 重新分配。使用可重新定位的数组。分配一个固定大小的数组并用数据填充它。如果数组被证明太小,请将其重新分配给更大的大小并继续填充它。继续读取并重新分配,直到读取所有数据。

  3. 转换。将数据读入一个廉价且易于扩展的数据结构(如链表),然后将其转换为数组。

这些方法中的每一种都有其优点和缺点、局限性和适用领域。

看起来在您的情况下,您正在尝试使用第一种方法。在处理文件时使用它不是一个好主意。首先,对一个文件进行两次传递不是很有效。其次,在一般情况下,它可能会产生争用条件:文件可能会在传递之间更改。如果您仍然想这样做,只需使用 std::vector 而不是内置数组。

但是,在您的情况下,我建议您使用第二种方法。同样,使用 std::vector 来存储数据。逐行读取数据并将其逐项附加到向量中。矢量将根据需要自动重新分配自身。

你说你对动态大小的数组不满意,或者std::vector.

恐怕你必须弄清楚如何在这里感到舒适,因为这正是std::vector的目的。

唯一的其他选择是使用 gcc 编译器。 gcc确实允许您拥有可变大小的数组。它是一个编译器扩展,它不是标准的 C 或 C++:

void method(size_t n)
{
   dataPoint array[n];
   // Do something with the array.
}

您可以使用C++容器,如 std::vector ,也可以使用 dataPoint *data = malloc(LENGTH * sizeof(dataPoint)) 。在C++,使用std::vector可能是更好的做法。

C99 具有可变长度数组,但您的问题似乎C++。

但是,真正的问题是您希望一次浏览整个文件。除非您使用的库要求数据在内存中,否则使用 fgetc 或任何C++对此进行迭代的文件文本可能会更容易。毕竟,您需要在某个时候浏览文本;您不妨省去分配内存的麻烦。