繁体   English   中英

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

[英]Read from a file in a 2d integer array

我是 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;
}

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

如果你仍然卡住,那么让我们一步一步来。

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

int main (int argc, char **argv) {
...
    if (argc < 2) { /* validate 1-argument available for filename */
        std::cerr << "error: insufficnent input\nusage: " << argv[0]
                << " filename\n";
        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"85 ,它们与要存储的二维值数组无关。 85很容易处理,只需将整行读入一个string ,从该行创建一个stringstream ,然后循环并从 stringstream 中读取整数,直到读完数字为止。 如果您在用完数字之前只读取一个值,那么您可以简单地将这些值存储在不是您的数组的地方(例如在名为notarr的向量中)。 如果该行中有多个值,则将所有值存储在一个向量中,并将该向量添加为向量向量中的一行。

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

在您的情况下,您需要一个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 ,创建 stringsteam ss ,然后使用临时向量tmp ,将每个值加载到临时向量中。 完成后,您只需检查tmp向量中有多少元素。 如果是85 ,则将其添加到向量notarr ,如果超过 1,则tmp包含二维数组的一行,因此将其添加到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 input\nusage: " << argv[0]
                << " filename\n";
        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:\n\n";
    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:\n\n";
    for (auto& i: notarr)           /* output values not part of array */
        std::cout << " " << i;      
    std::cout << '\n';              /* tidy up with newline */
}

注:矢量容器提供.push_back().size()成员函数,让您有一个值添加到载体,告诉你有很多元素分别被包含在其中。)

示例使用/输出

$ ./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

仔细检查一下,如果您还有其他问题,请告诉我。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM