#include <algorithm>
#include <cctype>
#include <iomanip>
#include <iostream>
#include <map>
#include <string>
#include <sstream>
#include <queue>
#include <utility>
inline bool isWordLetter(char c)
{
return std::isalnum(c) || c == '_';
}
inline void skipws(std::queue<char>& q)
{
while (!( q.empty() || isWordLetter(q.front()) ))
q.pop();
}
/* Extracts valid word.
* Returns word or empty string if no word found till the end of queue
*/
std::string extractWord(std::queue<char>& q)
{
std::string word;
bool again = false;
do {
again = false;
skipws(q);
/* Extract all consequent word character */
while( !q.empty() && isWordLetter(q.front()) ) {
word += q.front();
q.pop();
}
/* Check if word extracted is actually word */
if (word.size() < 2 || count_if(word.begin(), word.end(), isalpha) == 0) {
word.clear();
if ( !q.empty() )
again = true;
}
} while (again); //Repeat until we find word or exhaust our queue
std::transform(word.begin(), word.end(), word.begin(), tolower);
return word;
}
std::string getEnvString()
{
extern char **environ; // needed to access your execution environment
std::string envstr;
int k = -1;
while (environ[++k] != NULL) {
envstr += environ[k];
envstr += '\n';
}
return envstr;
}
std::pair<unsigned, std::string> wordEntries(const std::string& source, const std::string& word)
{
std::istringstream inp(source);
unsigned word_count = 0;
std::string output;
std::string line;
while(std::getline(inp, line, '\n')) {
std::string::size_type pos;
if ( (pos = line.find(word)) != std::string::npos ) {
output += line;
output += '\n';
++word_count;
while ( (pos = line.find(word, pos + word.size())) != std::string::npos )
++word_count;
}
}
return std::make_pair(word_count, output);
}
int main()
{
const std::string envstr = getEnvString();
std::cout << envstr << std::endl;;
std::queue<char> line( {envstr.begin(), envstr.end()} );
size_t wordCount = 0;
std::map<std::string, unsigned> entries;
std::string word;
while((word = extractWord(line)) != "" ) {
++wordCount;
++entries[word];
}
std::cout << "There is " << wordCount << " words in envstring\n" <<
"Unique words and their frequency:\n";
for(auto& p: entries) {
std::cout << std::setw(30) << p.first << ' ' << p.second << '\n';
}
std::string envcpy = envstr;
std::transform(envcpy.begin(), envcpy.end(), envcpy.begin(), tolower);
std::cout << "Enter word to search for: ";
std::cin >> word;
std::transform(word.begin(), word.end(), word.begin(), tolower);
auto result = wordEntries(envcpy, word);
std::cout << "Word " << word << " is occured " << result.first << " times\n" <<
"Lines where it appeared:\n" << result.second;
}