简体   繁体   English

读取/解析文本文件输入C ++

[英]Reading/parsing text file input c++

A little background: I am working on a sliding block puzzle for a school project and this is our first using C++ instead of Java. 一点背景知识:我正在为一个学校项目开发滑块游戏,这是我们第一次使用C ++而不是Java。 This is the first time I have had to implement something that reads data from a file. 这是我第一次必须实现从文件读取数据的功能。

I have a simple question regarding reading input from a text file. 我有一个关于从文本文件读取输入的简单问题。 I understand how to read the file line by line and hold each line in a string, I want to know if I can parse the string into different data types as the file is read. 我了解如何逐行读取文件并保持字符串中的每一行,我想知道在读取文件时是否可以将字符串解析为不同的数据类型。

Currently I am reading each line and storing them as strings in a vector for parsing later, and I know there must be a much simpler way to implement this 目前,我正在读取每一行并将它们作为字符串存储在向量中,以供以后解析,而且我知道必须有一种更简单的方法来实现此目的

The first line holds 2 integers which will indicate the length and width of the grid, the following lines will have 4 integers and a char for use as arguments when creating the blocks. 第一行包含2个整数,这些整数将指示网格的长度和宽度,随后几行将具有4个整数和一个char(在创建块时用作参数)。

My question is this, if I read the file character by character instead, is there a function I can use that will detect if the character is an integer or a char (and ignore the spaces) so I can store them immediately and create the block objects as the file is read? 我的问题是,如果我逐个字符地读取文件,是否可以使用一个函数来检测字符是整数还是字符(并忽略空格),因此我可以立即存储它们并创建块对象作为文件被读取? How would i deal with integers >10 in this case? 在这种情况下,我将如何处理大于10的整数?

EDIT: Just noting I am using fstream to read the files, I am unfamiliar with other input methods 编辑:只是注意到我正在使用fstream读取文件,我不熟悉其他输入法

A sample input: 输入示例:

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

To detect whether a piece of string can be parsed as an integer, you just have to parse it and see if you succeed. 要检测一个字符串是否可以解析为整数,只需解析它,看看是否成功。 The best function for that would probably be std::strtoul() , since it can be made to tell you how many characters it consumed, so that you can continue parsing after that. 最好的功能可能是std::strtoul() ,因为它可以告诉您它消耗了多少个字符,以便您可以在此之后继续解析。 (See the man page for details.) (有关详细信息,请参见手册页。)

However, if you already know the format of your file, you can use iostream formatted extraction. 但是,如果您已经知道文件的格式,则可以使用iostream格式的提取。 This is quite straightforward: 这很简单:

#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.
}

Another alternative is to read every line into a string (using std::getline ), then creating a stringstream from that line, and parsing the stringstream with >> . 另一种选择是将每一行读入字符串(使用std::getline ),然后从该行创建一个字符串流,并使用>>解析该字符串流。 This has the added benefit that you can discover and skip bad lines and recover, while in the direct formatted extraction I presented above, you cannot recover from any error. 这具有额外的好处,您可以发现并跳过不良行并进行恢复,而在上面介绍的直接格式化提取中,您无法从任何错误中恢复。

ifstreams are also istreams, so you can use the same operator >> as with std::cin. ifstream也是istream,因此您可以使用与std :: cin相同的运算符>>。

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

Note that this is way not the fastest way of parsing, but that is probably irrelevant to you. 请注意,这不是最快的解析方式,但可能与您无关。

If you can assert each type, I suggest using stream operators, like you would with cin . 如果可以断言每种类型,我建议像使用cin一样使用流运算符。

#include <fstream>

using namespace std;

int main()
{
    fstream fileStream;
    fileStream.open("inputfile.txt");

    int firstNumber;
    fileStream >> firstNumber;

    char firstChar;
    fileStream >> firstChar;
}

This way, you can read by value, instead of reading by line and then parsing the line. 这样,您可以按值读取,而不是按行读取然后解析该行。 Just read in every value you need into a variable, as you discover you need it, like that. 只需将所需的每个值读入变量,即可发现所需的值。

I would read each line into a string (as you have been doing). 我会将每一行读入一个字符串中(就像您一直在做的那样)。
Then I would read the tokens from that line into the appropriate variables. 然后,我将从该行中的标记读取到适当的变量中。

The operator>> when applied to a stream will convert the next value in a stream into the correct type. 将运算符>>应用于流时,会将流中的下一个值转换为正确的类型。 If this is not possable it sets flags on the stream indicating failure that are easy to test. 如果这不可行,它将在流上设置一些标志,以指示易于测试的失败。

 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

Assuming your input: 假设您输入以下内容:

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

Not knowing what the the values mean I will put my assumptions in comments. 不知道这些值意味着什么,我将把我的假设放在注释中。

// 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");
}

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

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