1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | // Code derived from Stroustrup's PPP2 book
// § 11.7 Using nonstandard separators
// -and beginning on p 400
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
//------------------------------------------------------------------------------
// like an istream, but the user can add to the set of whitespace characters
class Punct_stream {
public:
Punct_stream(istream& is) : source{is}, sensitive{true} {}
void whitespace(string const& s) { white = s; } // make s the whitespace set
void add_white(char c) { white += c; } // add to the whitespace set
bool is_whitespace(char c); // is c in the whitespace set?
void case_sensitive(bool b) { sensitive = b; }
bool is_case_sensitive() { return sensitive; }
Punct_stream& operator>>(string& s);
operator bool();
private:
istream& source; // character source
istringstream buffer; // we let buffer do our formatting
string white; // characters considered “whitespace”
bool sensitive; // is the stream case-sensitive?
};
Punct_stream& Punct_stream::operator>>(string& s)
{
while (! (buffer >> s)) { // try to read from buffer (skip normal whitespace)
if (buffer.bad() || ! source.good())
return *this;
buffer.clear();
// replenish buffer from source:
string line;
getline(source, line); // get a line from source stream
// do character replacement as needed on that line:
for (char& ch : line)
if (is_whitespace(ch))
ch = ' '; // to space
else if (! sensitive)
ch = tolower(ch); // to lower case
buffer.str(line); // put that now-processed line into buffer's stream
}
return *this; // (see §17.10)
}
bool Punct_stream::is_whitespace(char c)
{
for (char w : white)
if (c == w)
return true;
return false;
}
// "A member function called operator bool() defines a conversion to bool." p404
Punct_stream::operator bool()
{
return (! (source.fail() || source.bad()) && source.good());
}
//------------------------------------------------------------------------------
// given text input, produce a sorted list of all words in that text
// ignore punctuation and case differences
// eliminate duplicates from the output
int main()
{
// example input:
/*
There are only two kinds of languages: languages that people complain
about, and languages that people don't use.
*/
cout << "please enter words (ctrl+d to end input)\n";
Punct_stream ps{cin};
ps.whitespace(";:,.?!()\"{}<>/&$@#%^*|~"); // note \“ means ” in string
ps.case_sensitive(false);
vector<string> vs;
for (string word; ps >> word;) // read words
vs.push_back(word); //
sort(begin(vs), end(vs)); // sort in lexicographical order
for (int i = 0; i < (int)vs.size(); ++i) // print out dictionary
if (i == 0 || vs[i] != vs[i - 1]) //
cout << vs[i] << '\n';
}
|
build & run:
g++ -std=c++20 -O2 -Wall -pedantic ./ch_11/main_p400.cpp && ./a.out