2016-10-03 36 views
0

我在istream中有此格式化的字符串。带格式字符串的istream抽取值

(5,-4)

让说:

  1. 开括号
  2. 的整数
  3. 逗号和空格
  4. 另一个整数
  5. 右括号

我想知道什么是提取两个整数和验证字符串格式的最佳方法。

这是这样一类:

class MyPoint 
{ 
public: 
    MyPoint() = default; 
    ~MyPoint() = default; 
    ... 
    friend ostream & operator>>(ostream & lhs, MyPoint const & rhs); 
    ... 
private: 
    int x, y; 
}; 

ostream & operator>>(ostream & lhs, MyPoint const & rhs) { 
    // ??? 
} 

非常感谢大家。

这里是我的头文件

#ifndef MYPOINT_H 
#define MYPOINT_H 

#include <iostream> 
using namespace std; 

class MyPoint 
{ 
public: 
    MyPoint() : mX{ 0 }, mY{ 0 } { ; } 
    MyPoint(int x, int y) : mX{ x }, mY{ y } { ; } 
    ~MyPoint() = default; 

    int x() const { return mX; } 
    int y() const { return mY; } 
    void setX(int x) { mX = x; } 
    void setY(int y) { mY = y; } 

    MyPoint operator-() const { return MyPoint(-mX, mY); } 
    MyPoint operator+(MyPoint rhs) const { rhs.mX += mX; rhs.mY += mY; return rhs; } 
    MyPoint operator-(MyPoint rhs) const { rhs.mX = mX - rhs.mX; rhs.mY = mY - rhs.mY; return rhs; } 
    MyPoint operator*(MyPoint rhs) const { rhs.mX *= mX; rhs.mY *= mY; return rhs; } 
    MyPoint operator/(MyPoint rhs) const { rhs.mX = mX/rhs.mX; rhs.mY = mY/rhs.mY; return rhs; } 
    MyPoint operator%(MyPoint rhs) const { rhs.mX = mX % rhs.mX; rhs.mY = mY % rhs.mY; return rhs; } 

    friend MyPoint operator+(int lhs, MyPoint const & rhs); 
    friend MyPoint operator-(int lhs, MyPoint const & rhs); 
    friend MyPoint operator*(int lhs, MyPoint const & rhs); 
    friend MyPoint operator/(int lhs, MyPoint const & rhs); 
    friend MyPoint operator%(int lhs, MyPoint const & rhs); 

    friend ostream & operator<<(ostream & lhs, MyPoint const & rhs); 
    friend istream & operator>>(istream & lhs, MyPoint & rhs); 

private: 
    int mX, mY; 

}; 

#endif //MYPOINT_H 

在这里,我的源文件

#include "MyPoint.h" 


MyPoint operator+(int lhs, MyPoint const & rhs) { 
    return MyPoint(lhs + rhs.mX, lhs + rhs.mY); 
} 
MyPoint operator-(int lhs, MyPoint const & rhs) { 
    return MyPoint(lhs - rhs.mX, lhs - rhs.mY); 
} 
MyPoint operator*(int lhs, MyPoint const & rhs) { 
    return MyPoint(lhs * rhs.mX, lhs * rhs.mY); 
} 
MyPoint operator/(int lhs, MyPoint const & rhs) { 
    return MyPoint(lhs/rhs.mX, lhs/rhs.mY); 
} 
MyPoint operator%(int lhs, MyPoint const & rhs) { 
    return MyPoint(lhs % rhs.mX, lhs % rhs.mY); 
} 

ostream & operator<<(ostream & lhs, MyPoint const & rhs) { 
    return lhs << "(" << rhs.mX << "," << rhs.mY << ")"; 
} 
istream & operator >> (istream & lhs, MyPoint & rhs) { 
    return lhs >> "(" >> rhs.mX >> "," >> rhs.mY >> ")"; // HERE is the compiling error 
} 

最后,在主

MyPoint p1, p2(2, -2); 
cout << p1 << endl; 
cout << p2 << endl; 

有了这个文件的测试中,我得到了这个错误: 错误C2679二进制“>>”:找不到操作符,它的右边的操作数是ty PE“为const char [2]”(或没有可接受的转化率)

回答

3

对于这样的情况下,我经常发现它很方便以限定的operator>>的过载来读取从流的预定义字符串:

std::istream &operator>>(std::istream &is, char const *pat) { 

    char ch; 
    while (isspace(static_cast<unsigned char>(is.peek()))) 
     is.get(ch); 

    while (*pat && is && *pat == is.peek() && is.get(ch)) { 
     ++pat; 
    } 

    // if we didn't reach the end of the pattern, matching failed (mismatch, premature EOF, etc.) 
    if (*pat) { 
     is.setstate(std::ios::failbit); 
    } 

    return is; 
} 

有了这个,读你的格式可能是这个样子:

istream & operator>>(istream & lhs, MyPoint & rhs) { 
    return lhs >> "(" >> rhs.x >> "," >> rhs.y >> ")"; 
} 

这将做到像最典型的过载,并设置该流的失败位,如果你给的模式不匹配。就目前而言,输入中的每个字符串都可以前置任意空格(就像数字等的转换一样)。

有技术上这里一个小错误:因为它现在站,这种使用空白的全球语言环境的定义。要真正正确,应该使用与输入流关联的语言环境中提供的定义。

另外请注意,我不得不改变你的operator>>位的定义;在这个问题中,它看起来像是operator<<的超载,只是这两个字符改为operator>>

对于一个简单的例子:

#include <iostream> 

std::istream &operator>>(std::istream &is, char const *pat) { 
    // implementation above 
} 

class Point { 
    int x, y; 

    friend std::istream &operator>>(std::istream &is, Point &p) { 
     return is >> "(" >> p.x >>"," >> p.y >> ")"; 
    } 

    friend std::ostream &operator<<(std::ostream &os, Point const &p) { 
     return os << "(" << p.x <<", " << p.y << ")"; 
    } 
}; 

int main() { 
    Point p; 

    std::cout << "Please enter a point: "; 
    std::cin >> p; 
    std::cout << "Thanks. Point: " << p << '\n'; 
} 

用VC++ 2013,VC++ 2015年,和g ++ 6.1测试(但这并不是推动编译器的界限可言,所以我希望它做工精细即使编译器如此老,它们通常会被破坏得很厉害(例如,gcc 2.x或VC++ 6.0)

+0

嗨,杰里,这正是我在找的东西 另外,我找不到任何有关此文档技术。我的意思是,如果我想查找关于iostream >>(char *)的信息,请使用什么术语? 非常感谢所有细节! – Aesope

+0

@Aesope:我不知道有很多细节超出这个事实,这只是运营商的另一个超载。有一个现有的重载读取字符串(指向缓冲区)的指针。这只是基于指针的“常量”的另一个重载。在C++上任何一本体面的书籍都应该涵盖对常量的重载。这只是一个众所周知的功能的应用。 –

+0

嗨杰瑞。这是我的想法。同时,我在编译时遇到了一个奇怪的错误。我需要一个特殊的头文件吗?或者是其他东西?我从MSVC++ 2015得到这个编译错误: 错误C2679:二进制'>>':找不到运算符类型'const char [2]'的右边操作数(或没有可接受的转换) – Aesope