考虑我有以下“浮动对”对象输入格式:(第一个变量,第二个变量),例如(1.0,15.6)。
阅读此类结构的最佳方式是什么?在CI中会使用scanf(“(%f,%f)”,&amp; var1,&amp; var2) - 非常好,不是吗?(是的,我知道它不提供类型安全等等)< / p>
但我知道只有一种方法可以使用C ++流:
float var1, var2;
char tmp;
cin >> tmp;
cin >> var1;
cin >> tmp;
cin >> var2;
cin >> tmp;
看起来很难看,它只是一对花车。那么,有一种优雅的方式吗?像
cin >> "(" >> var1 >> ", " >> var2 >> ")";
答案 0 :(得分:2)
可能Boost.Spirit是你能找到的最接近的东西。这是an example如何使用它来实现你想要的。
答案 1 :(得分:1)
我这样做的方法是创建一个代表一对浮点数的类:
class FloatPair {
public:
FloatPair() : a(), b() { }
float a, b;
};
重载operator>>
以使用流:
istream& operator>>(istream& rhs, FloatPair& out) {
rhs.ignore(256, '(');
rhs >> out.a;
rhs.ignore(256, ' ');
rhs >> out.b;
rhs.ignore(256, ')');
return rhs;
}
所以你可以直接在FloatPair
:
FloatPair fp1, fp2;
cin >> fp1 >> fp2;
这有点脆弱,因为如果输入中的格式(float, float)
非常偏离,它就会中断。
答案 2 :(得分:1)
我会写一个输入操作符:
偷走@Seth Carnegie的FloatPair。
因此输入看起来很正常:
FloatPair c;
std::cin >> c;
我会让它看起来像这样。
std::istream& operator>>(std::istream& stream, FloatPair& out)
{
return stream >> I('(') >> out.a >> I(',') >> out.b >> I(')');
}
然后我有一个这样的忽略对象。
如果你愿意,可以很容易地进行模板化。为了使代码更容易,我称之为I
template<typename T>
struct ignore
{
T ignoreItem;
ignore(T const& x): ignoreItem(x) {}
};
template<typename T>
ignore<T> I(T const& x) { return ignore<T>(x);} // This is where I in the above code comes from.
然后输入运算符&gt;&gt;因为忽略看起来像这样。
std::istream& operator>>(std::istream& stream, ignore<T> const& test)
{
T next;
if ((stream >> next) && (test.ignoreItem != next)) // if the stream already failed
{ stream.setstate(std::ios::badbit); // then don't change anything
} // as it may confuse people
return stream;
}
字符串的特化。处理运算符&gt;&gt;的事实字符串只读一个字 注意:在scanf()中,空格与1个或多个空格匹配。因此,如果输入字符串中有空格,则遵循相同的规则。
template<>
struct ignore<std::string>
{
std::vector<std::string> ignoreItemVector;
ignore(std::string const& x)
{
// Split the input into a list of words to ignore.
std::stringstream words(x);
std::copy(std::istream_iterator<std::string>(words),
std::istream_iterator<std::string>(words),
std::back_inserter(ignoreItemVector)
);
}
};
template<>
std::istream& operator>><std::string>(std::istream& stream, ignore<std::string> const& test)
{
// Specifically ignore each word.
foreach(std::string const& loop, test.ignoreItemVector)
{
std::string next;
if ((stream >> next) && (loop != next)) // if the stream already failed
{ stream.setstate(std::ios::badbit); // then don't change anything
} // as it may confuse people
}
return stream;
}