Skip to content

Instantly share code, notes, and snippets.

@MighteeCactus
Created March 1, 2017 17:51
Show Gist options
  • Save MighteeCactus/9a1708b0643eb583e52fe098999389d7 to your computer and use it in GitHub Desktop.
Save MighteeCactus/9a1708b0643eb583e52fe098999389d7 to your computer and use it in GitHub Desktop.
Unigine's C++ School entry test
// Быков Александр.
// В общей сложности ушло часов 5. Где-то 80% времени ушло на то,
// чтобы нагуглить и вспомнить как пользоваться классами STL :)
#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <sstream> // для разбивки строки на слова
#include <regex> // regex и regex_replace
#include <iomanip> // для флагов форматирования вывода
#include <algorithm> // sort
#include <memory> // shared_ptr
using namespace std;
// Подсчитывает слова, на вход принимает ifstream
// Может записать результат в файл
// Для удаления лишних символов используется регулярное выражение
class WordCounter
{
private:
// слова используются как ключи, чтобы проще было подсчитывать частоту
map<string, int> *words;
// для форматирования в консоли
int longestWord = 0;
// дефолтный конструктор нам не нужен
WordCounter() = delete;
public:
WordCounter(ifstream &file);
virtual ~WordCounter();
void FlushToFile(ofstream &file);
// тут для форматированного вывода в консоль
friend ostream & operator<<(ostream &os, const WordCounter &wCounter);
};
WordCounter::WordCounter(ifstream &file)
{
words = new map<string, int>();
// создаем регулярку для последующего использования
string rExpStr("[.,?!1-9;:].?");
regex rExpression(rExpStr);
string line;
while (getline(file, line))
{
string strippedLine;
// отсеиваем не нужные символы и цифры
regex_replace(back_inserter(strippedLine), line.begin(), line.end(), rExpression, " ");
// с помощью стрима удобно разделять строку на отдельные слова
// и не заботиться о нескольких пробелах подряд
stringstream sstream(strippedLine);
string word;
// разбиваем строку на отдельные слова
while(sstream >> word)
{
// переводим все слова в нижний регистр (не работает с кириллицей,
// если изначально не указана кодировка)
transform(word.begin(), word.end(), word.begin(), ::tolower);
// длина самого длинного слова нужна для форматирования в консоли
longestWord = max<int>(longestWord, word.length());
// если слово уже записано, то вернется указатель на существующий объект,
// если нет, то добавляем
auto iter = words->emplace(word, 0);
(*iter.first).second++;
}
}
}
WordCounter::~WordCounter()
{
delete words;
}
void WordCounter::FlushToFile(ofstream &file)
{
// вектор с парами (слово, частота). Нужен чтобы отсортировать данные в нужном порядке
shared_ptr<vector<pair<string, int>>> wordPairs(new vector<pair<string, int>>(words->begin(), words->end()));
// компаратор для сортировки
auto cmp = [](const pair<string, int> & a, const pair<string, int> & b)
{
return a.second != b.second ? a.second > b.second : a.first < b.first;
};
sort(wordPairs->begin(), wordPairs->end(), cmp);
for (auto &iter : *wordPairs)
{
file << iter.second << " " << iter.first << endl;
}
}
// friend чтобы можно было использовать cout (или любой другой ostream) для вывода
ostream & operator<<(ostream &os, const WordCounter &wCounter)
{
for (auto &iter : *(wCounter.words))
{
os << "[ " << setw(wCounter.longestWord) << iter.first << setw(0) << " ]: " << iter.second << endl;
}
return os;
}
int main(int argc, char* argv[])
{
// если не хватает аргументов, сообщаем
if (argc < 3)
{
cout << "Usage: " << argv[0] << " <input_file_path> <output_file_path>";
return 1;
}
// файл из которого будем читать
ifstream iFile;
iFile.open(argv[1], ifstream::in);
if ( !iFile.is_open() )
{
cerr << "File " << argv[1] << " can't be opened for read." << endl;
return 2;
}
// читаем и заполняем map
WordCounter counter(iFile);
iFile.close();
cout << counter;
// файл куда будем скидывать результат
ofstream oFile;
oFile.open(argv[2], ofstream::out | ofstream::trunc);
if (!oFile.is_open())
{
cerr << "File " << argv[2] << " can't be opened for write." << endl;
return 3;
}
counter.FlushToFile(oFile);
oFile.close();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment