正在读取/解析文本文件输入c++

Reading/parsing text file input c++

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

一个小背景:我正在为一个学校项目制作一个滑块谜题,这是我们第一次使用C++而不是Java。这是我第一次必须实现从文件中读取数据的功能。

我有一个关于从文本文件中读取输入的简单问题。我了解如何逐行读取文件并将每一行保存在字符串中,我想知道在读取文件时是否可以将字符串解析为不同的数据类型。

目前,我正在读取每一行,并将它们作为字符串存储在一个向量中,以便稍后解析,我知道必须有一种更简单的方法来实现这个

第一行包含2个整数,表示网格的长度和宽度,接下来的行将包含4个整数和一个字符,用作创建块时的参数。

我的问题是,如果我逐个字符读取文件,是否有一个函数可以检测字符是整数还是字符(并忽略空格),这样我就可以立即存储它们,并在读取文件时创建块对象?在这种情况下,我将如何处理>10的整数?

编辑:只是注意到我正在使用fstream来读取文件,我不熟悉的其他输入方法

样本输入:

4  4
3  1  2  1  b
1  1  1  1  a 

要检测一段字符串是否可以被解析为整数,只需要解析它并查看是否成功。最好的函数可能是std::strtoul(),因为它可以告诉你它消耗了多少个字符,这样你就可以在那之后继续解析了。(有关详细信息,请参阅手册页。)

但是,如果您已经知道文件的格式,则可以使用iostream格式的提取。这很简单:

#include <fstream>

std::ifstream infile("thefile.txt");
int n1, n2, x1, x2, x3, x4;
char c;
if (!(infile >> n1 >> n2)) { /* error, could not read first line! Abort. */ }
while (infile >> x1 >> x2 >> x3 >> x4 >> c)
{
    // successfully extracted one line, data is in x1, ..., x4, c.
}

另一种选择是将每一行读取到一个字符串中(使用std::getline),然后从该行创建一个字符串流,并使用>>解析该字符串流。这还有一个额外的好处,即您可以发现和跳过坏行并进行恢复,而在我上面介绍的直接格式化提取中,您无法从任何错误中恢复。

如果可以断言每种类型,我建议使用流运算符,就像使用cin一样。

#include <fstream>
using namespace std;
int main()
{
    fstream fileStream;
    fileStream.open("inputfile.txt");
    int firstNumber;
    fileStream >> firstNumber;
    char firstChar;
    fileStream >> firstChar;
}

通过这种方式,您可以按值读取,而不是按行读取然后解析行。只要把你需要的每一个值读入一个变量,当你发现你需要它时,就这样。

ifstreams也是istream,因此您可以使用与std::cin相同的运算符>>。

int main()
{
    std::ifstream s("test.txt");
    if (s.is_open())
    {
        int i, j, k;
        s >> i >> j >> k;
    }
}

请注意,这不是最快的解析方式,但这可能与您无关。

我会把每一行读成一个字符串(就像您一直在做的那样)
然后,我会将该行中的标记读取到适当的变量中。

运算符>>应用于流时,会将流中的下一个值转换为正确的类型。如果这是不可能的,它会在流上设置易于测试的指示失败的标志。

 int  x;
 stream >> x; // ignores white space then: reads an integer from the stream into x
 char c;
 stream >> c; // ignores white space then: reads an char from the stream into c
 double d;
 stream >> d; // ignores white space then: reads an double from the stream into d

假设您的输入:

4  4
3  1  2  1  b
1  1  1  1  a 

由于不知道这些值意味着什么,我会把我的假设放在评论中。

// Assume that stream is a std::fstream already opened to you file.
std::string line1;
std::getline(stream, line1);           // reads "4 4" into `line1`
std::stringstream  line1stream(line1); // convert line1 into a stream for reading.
int a;
int b;
line1stream >> a >> b;   // reads "4 4" from 'line1' into a (now 4) b (now 4)
if (!stream || !line1stream)
{
     // failed reading the first line.
     // either reading the line failed (!stream)
     // or     reading 2 integers from line1stream failed (!line1stream)
     throw SomeException("Failed");
}

std::string line2;
std::getline(stream, line2);           // reads "3  1  2  1  b" into line2
std::stringstream line2stream(line2);  // convers line2 into a stream for reading.
int  data[4];
char c;
line2stream >> data[0] >> data[1] >> data[2] >> data[3] >> c;
if (!stream || !line2stream)
{
     // failed reading the second line.
     // either reading the line failed (!stream)
     // or     reading 4 integers and one char from line2stream failed (!line2stream)
     throw SomeException("Failed");
}