使用stdio.h
时,我可以轻松阅读某些格式化的输入,如下所示:
FILE* fin = fopen(...);
fscanf(fin, "x = %d, y = %d", &x, &y);
关于这一点的好处是,我不必担心字符'x'和后面的'='之间有多少空格,以及其他小细节。
在C ++中,它似乎在我看来,
ifstream fin(...);
string s;
fin >> s;
可能导致s
"x"
或"x="
,甚至"x=12"
,具体取决于输入的间距。
是否有一种方便的方法可以使用scanf
/ fscanf
获得与iostream
/ fstream
类似的行为?
答案 0 :(得分:8)
考虑到先决条件,这实际上非常简单。我有这三个功能,我坚持在一个标题的某个地方。这些允许您流入字符文字和字符串文字。我从来都不明白为什么这些不是标准的。
#include <iostream>
//These are handy bits that go in a header somewhere
template<class e, class t, int N>
std::basic_istream<e,t>& operator>>(std::basic_istream<e,t>& in, const e(&sliteral)[N]) {
e buffer[N-1] = {}; //get buffer
in >> buffer[0]; //skips whitespace
if (N>2)
in.read(buffer+1, N-2); //read the rest
if (strncmp(buffer, sliteral, N-1)) //if it failed
in.setstate(std::ios::failbit); //set the state
return in;
}
template<class e, class t>
std::basic_istream<e,t>& operator>>(std::basic_istream<e,t>& in, const e& cliteral) {
e buffer(0); //get buffer
in >> buffer; //read data
if (buffer != cliteral) //if it failed
in.setstate(std::ios::failbit); //set the state
return in;
}
//redirect mutable char arrays to their normal function
template<class e, class t, int N>
std::basic_istream<e,t>& operator>>(std::basic_istream<e,t>& in, e(&carray)[N]) {
return std::operator>>(in, carray);
}
鉴于这些,其余的很容易:
in>>'x'>>'='>>data.first>>','>>'y'>>'='>>data.second;
对于更复杂的情况,您可能希望使用std::regex
或boost::regex
,或者使用真正的词法分析器/解析器。
答案 1 :(得分:0)
简短的回答是“不”。
稍微长一点的回答是“你可以建立一些能做到这一点的东西”。例如,您可以读取文本行,然后使用合适的“用空字符串替换空格”类型函数。或许是这样的:
int x, y;
string s;
getline(cin, s, '=');
cin.get(); // Get rid of =
cin >> x;
getline(cin, s, '=');
cin >> y;
或者,使用cin.ignore
来跳过事物(因为字符串读取不是很有用,你想知道'x'和'y'实际上是'x'和'y'=:
int x, y;
cin.ignore(1000000, '='); // Skip up to a '='
cin >> x;
cin.ignore(1000000, '='); // Skip up to a '='
cin >> y;
如果有人在没有=符号的情况下输入超过100k个字符,这将“破坏”,并且需要进行错误检查才能看到“垃圾”没有进入 - 就像fscanf
那样。 if (cin >> x)
会照顾“检测到出了问题,但是你需要做一些明智的事情,因为它出了问题,我现在还不确定......
当然,由于C ++支持(几乎)所有C,因此您当然也可以使用您想要使用的<cstdio>
函数的任何成员。 [至少在某些情况下,它们实际上好一点]。
答案 2 :(得分:0)
就像使用%xx在fscanf / scanf中指定格式一样,您可以使用流操作符指定格式,如本教程中所述 -
非常全面。流操纵器位于页面底部附近。