从二维整数数组中的文件中读取

Read from a file in a 2d integer array

本文关键字:数组 文件 读取 整数 二维      更新时间:2023-10-16

我是 c++ 编码的新手,我需要从这个结构的文件中读取:

8
1 0 0 0 1
1 1 1 0 0
1 1 0 0 0
1 1 1 1 0
5

我需要将数字读取到 2 个不同的 int 变量(8 和 5)中,其余的在 2D int 数组中。

到目前为止,我有什么:

#include<fstream>
#include<iostream>
#include<conio.h>
using namespace std;
ifstream fin("f.in");
ofstream gout("g.out");
int a[30][30], n, x;
int main()
{
fin>>n;
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
{
fin>>a[i][j];
}
fin>>x; c[1]=x; s[x]=1;
//other function call .....
for(i=1; i<=n; i++)
gout<<c[i]<<" ";
return 0;
}

代码正在构建和编译,但是,它不会从文件中读取。

如果您仍然卡住,那么让我们逐步进行。

首先不要对文件名进行硬编码。(并且不要使用魔术数字,例如卡在代码中的任何数字,而不是正确定义一个常量)。ifstream fin("f.in");如果您有另一个要读取的文件"f.int2"怎么办?这就是函数参数的用途。对于main(),您有argc告诉您给出了多少参数,并且argv指向每个参数的指针数组(后跟一个终止NULL指针)。使用它们。例如:

int main (int argc, char **argv) {
...
if (argc < 2) { /* validate 1-argument available for filename */
std::cerr << "error: insufficnent inputnusage: " << argv[0]
<< " filenamen";
return 1;
}
std::ifstream fin (argv[1]);    /* open filename given by 1st argument */

(注意:第一个参数值argv[0]始终是正在运行的可执行文件名称,因此您必须检查总共两个参数以确保argv[1]中的内容)

接下来验证文件是否已打开以供读取,例如

if (!fin.good()) {  /* validate file open for reading */
std::cerr << "error: file open failed '" << argv[1] << "'.n";
return 1;
}

现在让我们转向读取您的输入文件,我将命名2dintarr+stuff.txt并将其放在dat子目录中,例如

示例输入文件

$ cat dat/2dintarr+stuff.txt
8
1 0 0 0 1
1 1 1 0 0
1 1 0 0 0
1 1 1 1 0
5

"+stuff"是与要存储的值的 2D 数组无关的85。只需将整行读入string,从该行创建一个stringstream,然后从字符串流中循环和读取整数,直到用完要读取的数字,即可轻松处理85。如果您在用完数字之前只读取一个值,那么您可以简单地将这些值存储在不是数组的地方(例如在名为notarr的向量中)。如果行中有多个值,则将所有值存储在一个向量中,并将该向量作为行添加到向量向量中。

听起来很复杂,但事实并非如此。 C++提供了容器,允许您像添加数组一样向它们添加和删除值,但更好的是,容器会自动为您管理内存,根据需要分配更多内存,并在不再引用容器时释放内存。其中一个容器是vector,您可以将其视为简单的一维数组。C++允许容器包含其他容器。因此,当您需要 2D 数组时,您想要的是矢量的向量。

在您的情况下,您需要一个string来保存您读取的每一行数据,您需要数组的向量arr向量,然后是另一个向量来保存不属于数组的"+stuff"- 称为notarr。声明如下:

#include <string>
#include <vector>
...
std::string line;                       /* string for reading each line */
std::vector<std::vector <int>> arr;     /* vector<vector<int>> (2D arr) */
std::vector<int> notarr;                /* vector to hold single values */

现在剩下的就是读取每一行,然后从该行创建一个字符串流,以便您可以循环从该行读取整数,直到要读取的数字用完为止。(你不能只在循环中使用fin >> number;,因为读取 iostream 会跳过前导空格,'n'空格,所以尝试在文件流本身上使用>>- 你永远无法知道行中有多少值,>>只会跳过'n'作为空格。

如何解决?使用stringstream.基本上,字符串流等效于可用作流的缓冲区。因此,您从文件中读取一行数据,从中创建一个字符串流,然后循环while (ss >> value)当它到达字符串流的末尾(即缓冲区)时将停止,因为没有其他内容可以读取,允许您确定原始行中包含多少值。(您将一遍又一遍地使用这种技术)

例:

while (getline (fin, line)) {  /* read each remaining data line */
int i;
std::vector<int> tmp;           /* vector<int> for each line */
std::stringstream ss (line);    /* stringstream to read from */
while (ss >> i)                 /* read int from stringstream */
tmp.push_back(i);           /* add to tmp vector */
if (tmp.size() == 1)            /* if single value in line */
notarr.push_back(i);        /* add value to notarr */
else if (tmp.size() > 1)        /* if multiple values in line */
arr.push_back(tmp);         /* add tmp vector to arr */
}

上面你只需将每一行读入line,创建 stringsteamss,然后使用临时向量tmp,将每个值加载到临时向量中。完成后,您只需检查tmp向量中有多少元素。如果有一个,它是85,将其添加到向量notarr,如果它不止一个,tmp包含一行您的 2D 数组,因此添加它做arr。就是这样。

总而言之,您可以执行以下操作:

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <limits>
int main (int argc, char **argv) {
std::string line;                       /* string for reading each line */
std::vector<std::vector <int>> arr;     /* vector<vector<int>> (2D arr) */
std::vector<int> notarr;                /* vector to hold single values */
if (argc < 2) { /* validate 1-argument available for filename */
std::cerr << "error: insufficnent inputnusage: " << argv[0]
<< " filenamen";
return 1;
}
std::ifstream fin (argv[1]);    /* open filename given by 1st argument */
if (!fin.good()) {  /* validate file open for reading */
std::cerr << "error: file open failed '" << argv[1] << "'.n";
return 1;
}
while (getline (fin, line)) {  /* read each remaining data line */
int i;
std::vector<int> tmp;           /* vector<int> for each line */
std::stringstream ss (line);    /* stringstream to read from */
while (ss >> i)                 /* read int from stringstream */
tmp.push_back(i);           /* add to tmp vector */
if (tmp.size() == 1)            /* if single value in line */
notarr.push_back(i);        /* add value to notarr */
else if (tmp.size() > 1)        /* if multiple values in line */
arr.push_back(tmp);         /* add tmp vector to arr */
}
std::cout << "2D array of values:nn";
for (auto& i : arr) {           /* loop over rows */
for (auto& j : i)           /* loop over each value in column */
std::cout << " " << j;  /* output value */
std::cout << 'n';          /* tidy up with newline */
}
std::cout << "nSingle-values:nn";
for (auto& i: notarr)           /* output values not part of array */
std::cout << " " << i;      
std::cout << 'n';              /* tidy up with newline */
}

(注意:Vector 容器提供.push_back().size()成员函数,以便您向 Vector 添加一个值,并分别告诉您其中包含许多元素。

示例使用/输出

$ ./bin/rd2dintarr+stuff dat/2dintarr+stuff.txt
2D array of values:
1 0 0 0 1
1 1 1 0 0
1 1 0 0 0
1 1 1 1 0
Single-values:
8 5

仔细查看,如果您有其他问题,请告诉我。