【问题标题】:Using getline in an overloaded input operator在重载的输入运算符中使用 getline
【发布时间】:2015-09-29 17:49:48
【问题描述】:

Book.h:

#ifndef BOOKDATE
#define BOOKDATE

#include <iostream>
#include <string>

class Book{
    friend std::istream& operator>>(std::istream&, Book&);
private:
    std::string title, author;
    int number;
};

std::istream& operator>>(std::istream&, Book&);

#endif // BOOKDATE

Book.cpp:

#include "BookDate.h"    
using namespace std;

istream& operator>>(istream& is, Book& rhs){
    getline(is, rhs.title); 
    getline(is, rhs.author);
    is >> rhs.number;
    if(!is)
        rhs = Book();
    return is;
}

我想知道我应该如何为Book 类创建输入运算符。 titleauthor 将超过一个词,因此我需要使用 getline 来接收该数据。然后getline 的问题是它可能会拾取自上次使用cin 以来留在流中的任何'\n'。比如;

int x;
cin >> x; //newline is not extracted and left behind
Book a;
cin >> a; //"title" is automatically made empty!

我可以改用cin.ignore(256, '\n'),但谁的责任,用户或author的类,是使用这个吗?用户在输入Book 对象之前是否使用.ignore,或者类作者是否将.ignore 放在输入操作的开头?

似乎在前一种情况下,用户必须了解.ignore 方法是必需的,但这样做必须了解Book 的输入运算符的实现,这是不可取的。在后一种情况下,将.ignore 放在运算符中意味着我的运算符可能无法适应某些情况,因为它总是希望在处理之前遇到换行符。例如从输入文件中读取数据,例如:

book1
author1
1

book2
author2
2

意味着book1cin.ignore(256,'\n') 忽略。

【问题讨论】:

  • 我会说operator&gt;&gt;() 应该假定文件处于开始阅读的正确位置。
  • 另外operator&gt;&gt;()在阅读前跳过空格也不是没有道理的。
  • 正常约定是假定流正确定位在要读取的对象的开头。您定义您的对象是否可以或不能以换行符开头。您的调用者负责定位流

标签: c++ input operator-keyword getline


【解决方案1】:

要使operator&gt;&gt; 的行为更像内置类型的运算符,您可以使用ws 操作符在读取输入之前跳过空格。

随便用

is >> ws;

在输入运算符的开头,流将定位在当前位置之后的第一个非空白字符处。

【讨论】:

    【解决方案2】:

    要正确重载提取运算符,您可以将输入格式更改为要填充的三个变量的序列,即:

    (title, author, number)
    

    并将您的 operator&gt;&gt; 修改为:

    istream& operator>>(istream& is, Book& rhs){
        // just a suggestion: it is better if there is no input to do nothing
        if(!is) return is;
        string title, author;
        int number;
        char par1, comma, par2;
        cin >> skipws >> par1 >> title >> comma >> author>> comma >> number >> par2;
        if (par1 != '(' || comma != ',' || par1 != ')'){
            // set failbit to indicate invalid input format
            is.clear(ios_base::failbit);
        }
        rhs(title, author, number); 
        return is;
    }
    

    【讨论】:

    • 你说它是非法的,因为它是私有的,但是 operator>> 被声明为友元函数?实际上,我从示例中删减了很多内容,以使其简短,只是为了专注于操作员>>。根据您的第二个建议,它不考虑可能是多个单词的标题或作者,这就是我说我需要 getline 的原因,除非我遗漏了什么。
    【解决方案3】:

    is.ignore();放在getline(is, rhs.title);之前

    【讨论】:

    • 这是做什么的?请在您的答案中添加对此的解释。
    • 我真的不知道 :D。看到这个问题已经有 4 年没有得到回答了,我决定再问一次,但我也检查了 stackoverflow 建议为“类似”的 ~7 个问题(第一个是这个),在 5 号或 6 号我找到了这个命令,我试了一下它奏效了
    猜你喜欢
    • 2017-07-08
    • 2013-12-15
    • 2012-12-30
    • 1970-01-01
    • 2015-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多