在C++中创建数组,而无需提前知道长度
Creating arrays in C++ without knowing the length ahead of time
我正在开发一个小程序,以帮助加快实验室工作的一些数据分析。它应该从文本文件中读取数据,创建一堆包含这些数据的数组,然后做一些数学运算。
我一直遇到的问题是我不知道原始文本文件会有多少行,所以我不知道我的数组有多大。我对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
数组。这就是编译器试图告诉您的。
当您需要构建一个事先不知道其大小的数组时,您通常至少有三种方法可供选择:
-
两次阅读。对数据源进行"试运行",以确定未来数组的确切大小。分配阵列。对数据源进行第二次传递,以用数据填充数组。
-
重新分配。使用可重新定位的数组。分配一个固定大小的数组并用数据填充它。如果数组被证明太小,请将其重新分配给更大的大小并继续填充它。继续读取并重新分配,直到读取所有数据。
-
转换。将数据读入一个廉价且易于扩展的数据结构(如链表),然后将其转换为数组。
这些方法中的每一种都有其优点和缺点、局限性和适用领域。
看起来在您的情况下,您正在尝试使用第一种方法。在处理文件时使用它不是一个好主意。首先,对一个文件进行两次传递不是很有效。其次,在一般情况下,它可能会产生争用条件:文件可能会在传递之间更改。如果您仍然想这样做,只需使用 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++对此进行迭代的文件文本可能会更容易。毕竟,您需要在某个时候浏览文本;您不妨省去分配内存的麻烦。
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 使用std::multimap迭代器创建std::list
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 使用CMake创建QML插件
- 如何在c++中为模板函数实例创建快捷方式
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- OpenCV EqualizeHist()从彩色图像创建黑白图像
- 试图在visual studio上用C++创建一个桌面应用程序
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 如何在C++20中创建模板别名的推导指南
- 如何为模板化对象创建模板向量?VS正在投掷C3203
- 如何创建一个空的全局类并在启动时实例化它
- 无法创建抽象类的实例
- 链接到自行创建的dll失败
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 如何在C++类内存结构中创建"spacer"?
- 终端不会为C++文件创建.exe文件吗
- 在createdialog创建的窗口中捕获用于编辑控件的OnMouseMove消息