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
类创建输入运算符。 title
和author
将不止一个字,因此很适合我需要使用getline
来接收该数据。 getline
的问题在于,它可能会拾取自上次使用'\n'
以来流中剩余的任何cin
。例如;
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
的责任?用户在输入.ignore
对象之前使用Book
还是类作者将.ignore
放在输入操作的开头?
[似乎在前一种情况下,用户将必须了解.ignore
方法,但这样做必须了解Book
的输入运算符的实现,这是不希望的。在后一种情况下,将.ignore
放在运算符中意味着我的运算符可能无法适应某些情况,因为它总是希望在处理之前遇到换行符。例如,从输入文件中读取数据,例如:
book1
author1
1
book2
author2
2
表示book1
被cin.ignore(256,'\n')
忽略。
为了使operator>>
的行为更像内置类型的运算符,可以在阅读输入之前使用ws
操纵器跳过空格。
仅使用
is >> ws;
在输入运算符的开头,流将定位在当前位置之后的第一个非空白字符处。
为了适当地使提取运算符超载,您可以将输入格式更改为要填充的三个变量的序列,即:
(title, author, number)
并将您的operator>>
修改为:
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;
}
将is.ignore();
放在getline(is, rhs.title);
之前