c++中的大文件读取错误

Big File reading error in C++

本文关键字:读取 取错误 文件 c++      更新时间:2023-10-16

我需要在c++中读取一个具有这种特定格式的文件:

5
1 2 3 4 1 5 1 5 2 1

所有值之间用空格分隔。第一行的前两个分别是变量N和M,第二行中所有的N个值都需要放在一个名为S的数组中,大小为N。我写的代码对这样的文件没有问题,但是当涉及到真正有数百万的大文件时,它就不起作用了,我需要它工作。下面是代码

int N,M;
FILE *read = fopen("file.in", "r");
fscanf(read, "%d %d ", &N, &M);
int S[N];
for( i =0; i < N; i++){
    fscanf(read, "%d ", &S[i]);        
}

我应该改变什么?

百万整数范围内存在多个潜在问题:

  • int通常为32位,32位有符号整数的取值范围为-2^31到2^31 - 1,因此最大值为2,147,483,647。你应该切换到64位整型

  • 您正在使用int S[N]可变长度数组(VLA),这不是标准c++(它是标准C99,但…有关于这是不是一个好主意的讨论)。然而,重要的细节是VLA存储在堆栈上:32位int的100万是4mb, 200万是8mb,等等……检查您的默认堆栈大小,但它可能小于8 MB,因此您有堆栈溢出(您在正确的站点寻求帮助!)。

那么,让我们切换到c++并消除这些问题:

#include <cstdint> // for int64_t
#include <fstream>
#include <vector>
int main(int argc, char* argv[]) {
   std::ifstream stream("data.txt");
   int64_t n = 0, m = 0;
   stream >> n >> m;
   std::vector<int> data;
   for (int64_t c = 0; c != n; ++c) {
       int i = 0;
       stream >> i;
       data.push_back(i);
   }
   // do your best :)
}

首先,我们使用<cstdint>中的int64_t来解决整数溢出问题。其次,我们使用流(输入文件流:ifstream)来避免必须学习与每个整型相关的格式(这很痛苦)。第三,我们使用vector来存储我们读取的数据,并且消除了堆栈溢出问题。

您正在使用可变大小的数组。这不是标准的,也不是所有编译器都支持。如果您的编译器支持它,并且以百万计,您将耗尽堆栈空间(堆栈溢出)。

或者,您可以将S定义为具有vector<int> S(N);
的向量