11

使用时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

4

3 回答 3

9

考虑到先决条件,这实际上非常容易。我有这三个函数,我把它们放在某个地方的标题中。这些允许您输入字符文字和字符串文字。我一直不太明白为什么这些不是标准的。

#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::regexor boost::regex,或者可能是真正的词法分析器/解析器。

于 2013-06-21T21:34:30.463 回答
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>您想使用的函数的任何成员。[至少在某些情况下,它们实际上要好一些]。

于 2013-06-21T21:04:25.370 回答
0

就像您使用 %xx 在 fscanf/scanf 中指定格式一样,您可以使用本教程中详述的流操纵器指定格式 -

http://www.tenouk.com/Module18.html

非常全面。流操纵器位于页面底部附近。

于 2013-06-21T21:17:28.470 回答