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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9551014/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 12:58:05  来源:igfitidea点击:

Reading/parsing text file input c++

c++input

提问by Gadesxion

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. This is the first time I have had to implement something that reads data from a file.

一点背景:我正在为一个学校项目开发一个滑块拼图,这是我们第一次使用 C++ 而不是 Java。这是我第一次必须实现从文件中读取数据的东西。

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 个整数和一个字符,用作创建块时的参数。

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 

回答by Kerrek SB

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. (See the man page for details.)

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

However, if you already knowthe format of your file, you can use iostream formatted extraction. This is quite straightforward:

但是,如果您已经知道文件的格式,则可以使用 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.
}

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

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

回答by Martin York

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

回答by cooky451

ifstreams are also istreams, so you can use the same operator >> as with std::cin.

ifstreams 也是 istreams,因此您可以使用与 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.

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

回答by rob05c

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.

这样,您可以按值读取,而不是按行读取然后解析行。只需将您需要的每个值读入一个变量,当您发现您需要它时,就像那样。