【问题标题】:istream extraction values with formatted string带有格式化字符串的 istream 提取值
【发布时间】:2017-02-11 15:14:35
【问题描述】:

我在 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
}

最后是main中的测试

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

有了这个文件,我得到了这个错误: 错误 C2679 二进制“>>”:未找到采用“const char [2]”类型的右侧操作数的运算符(或没有可接受的转换)

【问题讨论】:

    标签: c++ text formatting iostream istream


    【解决方案1】:

    对于这种情况,我经常发现定义 operator&gt;&gt; 的重载以从流中读取预定义字符串很方便:

    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&gt;&gt; 位的定义;在问题中,它看起来像是operator&lt;&lt; 的重载,只是将这两个字符更改为operator&gt;&gt;

    举个简单的例子:

    #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)。

    【讨论】:

    • 嗨,杰瑞。这正是我一直在寻找的。此外,我找不到有关此技术的任何文档。我的意思是,如果我想找到一些关于 iostream >> (char*)something 的信息,使用什么技术术语?非常感谢您提供的所有详细信息!
    • @Aesope:我不知道除了这只是运算符的另一个重载之外还有很多细节。现有的重载将字符串读入(引用的缓冲区)指针。这只是基于指针constness 的另一个重载。任何体面的 C++ 书籍都应该涵盖 const-ness 的重载;这只是众所周知的功能的又一个应用。
    • 嗨,杰瑞。这是我的想法。同时,我在编译时遇到了一个奇怪的错误。我需要一个特殊的头文件吗?或者是其他东西?我从 MSVC++ 2015 中得到了这个编译错误:错误 C2679: binary '>>': no operator found which take a right-hand operand of type 'const char [2]' (或者没有可接受的转换)
    • @Aesope:您必须包含 something 至少声明 std::istream(例如,&lt;iostream&gt;&lt;iosfwd&gt; 等)此代码已经过测试VC++ 2015 虽然...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-15
    • 1970-01-01
    • 2021-12-07
    • 1970-01-01
    相关资源
    最近更新 更多