具有格式化字符串的istream提取值

时间:2016-10-03 15:53:34

标签: c++ text formatting iostream istream

我在istream中有这个格式化的字符串。

  

(5,-4)

让我们说:

  1. 左括号
  2. 整数
  3. 逗号和空格
  4. 另一个整数
  5. 闭括号
  6. 我想知道提取整数和验证字符串格式的最佳方法是什么。

    这是一个类似这样的课程:

    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二进制&#39;&gt;&gt;&#39;:找不到带有&#39; const char [2]&#39;类型的右手操作数的运算符(或者没有可接受的转换)

1 个答案:

答案 0 :(得分: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)。