2015-09-29 2 views
0

Book.h:Использование GetLine в перегруженном ввода оператора

#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 «s, это использовать это? Использует ли пользователь .ignore, прежде чем вводит объект Book, или автор класса поставил .ignore в начале операции ввода?

Похоже, что в первом случае пользователь должен был бы понимать способ .ignore, но при этом должен понимать реализацию входного оператора Book, что нежелательно. В последнем случае оператор .ignore в операторе означает, что мой оператор не может адаптироваться к определенным обстоятельствам, так как он всегда ожидает столкновения с новой строкой перед обработкой. Например, чтение из входного файла с данными, такими как:

book1 
author1 
1 

book2 
author2 
2 

Средства book1 получает игнорируются cin.ignore(256,'\n').

+2

я бы сказал, что 'operator >>()' должен предположить, что файл находится в правильном положении, чтобы начать чтение. – Galik

+0

Кроме того, для 'operator >>()' нечего делать, чтобы пропустить пробел перед чтением. – Galik

+1

нормальным соглашением было бы считать поток в правильном положении в начале объекта для чтения. Вы определяете, может ли ваш объект начинать с новой строки или не может начинаться. Ваш абонент отвечает за позицию потока – Les

ответ

0

Чтобы сделать ваш operator>> более похожим на операторов для встроенных типов, вы можете использовать манипулятор ws, чтобы пропустить пробел, прежде чем читать свой ввод.

Просто используйте

is >> ws; 

в начале своего оператора ввода, и поток будет расположен на первом непробельного символа после текущей позиции.

0

Чтобы перегрузить оператор извлечения правильно, вы можете изменить формат ввода, чтобы последовательность из трех переменных, которые вы хотите заполнить, а именно:

(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; 
} 
+0

Вы говорите, что это незаконно, потому что оно личное, но оператор >> объявлен как функция друга? На самом деле я вырезал много из моего примера, чтобы сократить его, чтобы сосредоточиться на операторе >>. Согласно вашему второму предложению, он не учитывает титул или автора, которые могут быть несколькими словами, поэтому я сказал, что мне нужен getline, если я не пропущу что-то. – Silversonic

+0

@ Сильверсон, вы правы! Я обновил его. – Ziezi