伪 istream 指针返回

Pseudo-istream pointer return

本文关键字:返回 指针 istream      更新时间:2023-10-16

我一直在学习Stroustrup的编程和原理来自学c ++ 11。在第11章中,他描述了一个程序,该程序可以从输入流中删除(变成空格)任何不需要的字符。因此,例如,我可以设置一个字符串来保存字符"!"和"."。然后我可以输入 dog! food并接收输出dog food

但是,我不明白字符串如何word在主要

 int main ()
    {
    Punct_stream ps {cin};
    ps.whitespace(";:,.?!()"{}<>/&$@#%^*|~");
    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(";:,.?!()"{}<>/&$@#%^*|~");
    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";
     }

     }

窍在于operator >>内部的while循环与从流中读取时通常执行的操作具有相反的逻辑。通常,你会做这样的事情(事实上,main这样做):

while (stream >> aString)

但是请注意,提取器中的while具有否定:

尝试从buffer中提取s。如果失败,请执行循环的一次迭代,然后重试。

开始时,buffer为空,因此提取s将失败,并且将进入循环体。循环体的作用是从source(被包装的流)中读取一行,将该行的选定字符转换为空格,并将此行设置为buffer的内容 (通过buffer.str(line);调用)。

因此,在转换线路后,它被排队进入buffer。然后循环的下一次迭代来了,它再次尝试从buffer中提取s。如果该行有任何非空格,则将提取第一个单词(其余单词将保留在buffer中以供进一步阅读)。如果该行只有空格,则再次输入循环主体。

成功提取s后,循环终止,函数退出。

在下一次调用时,它将与buffer中剩余的任何内容一起工作,根据需要从source重新填充缓冲区(通过我上面解释的过程)。