一点背景:我正在研究一个学校项目的滑块拼图,这是我们第一次使用C ++而不是Java。这是我第一次必须实现从文件中读取数据的东西。
我有一个关于从文本文件中读取输入的简单问题。 我理解如何逐行读取文件并将每行保存在一个字符串中,我想知道是否可以在读取文件时将字符串解析为不同的数据类型。
目前我正在阅读每一行并将它们作为字符串存储在一个向量中以便稍后解析,我知道必须有一种更简单的方法来实现这个
第一行包含2个整数,表示网格的长度和宽度,以下行将有4个整数和一个char,用作创建块时的参数。
我的问题是,如果我逐个字符地读取文件,是否有一个我可以使用的函数,它将检测字符是整数还是字符(并忽略空格),这样我就可以立即存储它们读取文件时创建块对象?在这种情况下,我如何处理整数> 10?
编辑:注意我正在使用fstream来读取文件,我对其他输入法不熟悉示例输入:
4 4
3 1 2 1 b
1 1 1 1 a
答案 0 :(得分:2)
要检测一段字符串是否可以解析为整数,您只需要解析它并查看是否成功。最好的函数可能是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
),然后从该行创建一个字符串流,并使用>>
解析字符串流。这有一个额外的好处,你可以发现和跳过坏线并恢复,而在我上面提到的直接格式化提取中,你无法从任何错误中恢复。
答案 1 :(得分:1)
ifstreams也是istreams,因此您可以使用相同的运算符&gt;&gt;和std :: cin一样。
int main()
{
std::ifstream s("test.txt");
if (s.is_open())
{
int i, j, k;
s >> i >> j >> k;
}
}
请注意,这不是最快的解析方式,但这可能与您无关。
答案 2 :(得分:1)
如果您可以断言每种类型,我建议使用流操作符,就像使用cin一样。
#include <fstream>
using namespace std;
int main()
{
fstream fileStream;
fileStream.open("inputfile.txt");
int firstNumber;
fileStream >> firstNumber;
char firstChar;
fileStream >> firstChar;
}
这样,您可以按值读取,而不是逐行读取然后解析该行。只需在变量中读入您需要的每个值,就像您发现需要它一样。
答案 3 :(得分:1)
我会将每一行读成一个字符串(就像你一直在做的那样) 然后我会将该行中的标记读入适当的变量。
运营商&gt;&gt;应用于流时,会将流中的下一个值转换为正确的类型。如果这是不可能的,它会在流上设置标记,指示容易测试的失败。
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");
}