2016-02-24 3 views
1

Я прохожу через Программу и принципы Страустрапа, чтобы научить себя C++ 11. В главе 11 он описывает программу, которая удаляет (превращается в пробел) любые нежелательные символы из входного потока. Так, например, я могу установить строку для хранения символов «!» а также '.'. И тогда я мог бы ввести dog! food и получить вывод dog food.Pseudo-istream pointer return

Однако, я не понимая, как струна, word в главном

int main() 
    { 

    Punct_stream ps {cin}; 
    ps.whitespace(";:,.?!()\"{}<>/&[email protected]#%^*|~"); 
    ps.case_sensitive(false); 

    cout<<"Please input words."<<"\n"; 
    vector<string> vs; 
    for (string word; ps>>word;)// how does word get assigned a string? { 
     vs.push_back(word); 

    } 

    sort(vs.begin(), vs.end()); 

    for (int i = 0; i<vs.size(); ++i) { 
     if (i==0 || vs[i]!=vs[i-1]) cout<<vs[i]<<"\n"; 
    } 


    } 

присваивается значение через перегруженные определения >>.

Punct_stream& Punct_stream::operator>>(string& s) 
{ 
    while (!(buffer>>s)) { 
    if (buffer.bad() || !source.good()) return *this; 
    buffer.clear(); 


    string line; 
    getline(source,line); // get a line from source 

    for (char& ch : line) 
     if (is_whitespace(ch)) 
      ch = ' '; 
     else if (!sensitive) 
      ch = tolower(ch); 
    buffer.str(line); //how does word become this value? 


    } 

    return *this; 
    } 

Очевидно, что указатель this будет результатом >>, но я не понимаю, как этот результат включает в себя назначении слова строки istringstream buffer. Я знаю только основы указателей, возможно, это моя проблема?

#include<iostream> 
#include<sstream> 
#include<string> 
#include<vector> 

using namespace std; 

class Punct_stream { 
public: 
    Punct_stream(istream& is) 
    : source{is}, sensitive{true} { } 
    void whitespace(const string& s) { white = s; } 
    void add_white(char c) { white += c; } 
    bool is_whitespace(char c); 
    void case_sensitive(bool b) { sensitive = b; } 
    bool is_case_sensitive() { return sensitive; } 
    Punct_stream& operator>>(string& s); 

    operator bool(); 
private: 
    istream& source; 
    istringstream buffer; 
    string white; 
    bool sensitive; 
}; 

Punct_stream& Punct_stream::operator>>(string& s) 
{ 
    while (!(buffer>>s)) { 
    if (buffer.bad() || !source.good()) return *this; 
    buffer.clear(); 


    string line; 
    getline(source,line); // get a line from source 

    for (char& ch : line) 
     if (is_whitespace(ch)) 
      ch = ' '; 
     else if (!sensitive) 
      ch = tolower(ch); 
    buffer.str(line); //how does word become this value? 


    } 

    return *this; 
    } 

    Punct_stream::operator bool() 
    { 
     return !(source.fail() || source.bad()) && source.good(); } 

    bool Punct_stream::is_whitespace(char c) { 
     for (char w : white) 
     if (c==w) return true;   return false; 
    } 

int main() 
    { 

    Punct_stream ps {cin}; 
    ps.whitespace(";:,.?!()\"{}<>/&[email protected]#%^*|~"); 
    ps.case_sensitive(false); 

    cout<<"Please input words."<<"\n"; 
    vector<string> vs; 
    for (string word; ps>>word;)// how does word get assigned a string? { 
     vs.push_back(word); 

    } 

    sort(vs.begin(), vs.end()); 

    for (int i = 0; i<vs.size(); ++i) { 
     if (i==0 || vs[i]!=vs[i-1]) cout<<vs[i]<<"\n"; 
    } 


    } 
+0

Значение присваивается вашему параметру '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' оператора'''. 'return * this;' выполняется, потому что автор хотел разрешить цепочку чтения, например: 'ps >> word1 >> word2 >> word3'. Не возвращаясь, вы будете вынуждены использовать один прочитанный за одно утверждение. –

ответ

3

Хитрость заключается в том, что while петля внутри operator >> имеет противоположную логику того, что вы обычно делаете при чтении из потока. Как правило, вы могли бы сделать что-то вроде этого (и main делает это, на самом деле):

while (stream >> aString) 

Заметим, однако, что while в экстрактор имеет отрицанием:

Try извлекая s из buffer. Если вы терпите неудачу, выполните одну итерацию цикла и повторите попытку.

При запуске buffer пуст, поэтому извлечение s не будет выполнено, и тело цикла будет введено. То, что делает тело цикла, считывает строку из source (обтекаемый поток), преобразует выбранные символы этой строки в пробелы, а устанавливает эту строку как содержимое buffer (через звонок buffer.str(line);).

Итак, после того, как линия была преобразована, она помещена в очередь buffer. Затем идет следующая итерация цикла, и она снова пытается извлечь s из buffer. Если строка имела пробелы без пробелов, первое слово будет извлечено (а остальные останутся в buffer для дальнейших чтений). Если линия имеет только пробелы, тело цикла снова вводится.

Как только s успешно извлечен, цикл завершается, и функция завершается.

При следующем вызове он будет работать с тем, что осталось в buffer, с повторным заполнением буфера от source (по описанному выше процессу).

+0

[This] (http://stackoverflow.com/a/28710080/3410396) отвечает на другой вопрос OP: что означает 'return * this'. –

+0

Lol, спасибо. Я так поймал попытку выяснить, что это сделал, когда я пытался прочитать код, я не обращал достаточного внимания на цикл while. –

Смежные вопросы