//---------------------------------------------------------------------------// Unit1.h//---------------------------------------------------------------------------#include <Grids.hpp>#include <vector.h>//--------------------------------------------------------------------------- const int MINW = 1; // мин. длина словаconst int MAXW = 10; // макс. длина слова struct CStats // структура для хранения статистики по данному слову{ String word; // само слово int length; // длина long count; // количество совпадений в тексте double percent; // процент (встречаемость в тексте) __fastcall CStats(const String wd, int len=0, int cnt=0, double perc=0.0f) : word(wd), count(cnt), length(len), percent(perc) { } // оператор < для сортировки в контейнере bool __fastcall operator<(CStats& obj) { return (word < obj.word); } bool __fastcall operator<(const CStats& obj) const { return (word < obj.word); } // оператор == для сравнения 2 структур между собой bool __fastcall operator==(CStats& obj) { return (word == obj.word); } bool __fastcall operator==(const CStats& obj) const { return (word == obj.word); }}; // определени типа контейнера статистики по словам (std::vector)typedef vector<CStats> StatVec;typedef StatVec::iterator StatVec_I; // тип итератораtypedef StatVec::const_iterator StatVec_CI; // константный итератор // объявление формыclass TForm1 : public TForm{__published: void __fastcall Button2Click(TObject *Sender); // ... (остальное)private: StatVec vData; // контейнер данных статистики // функция для предв. форматирования текста void __fastcall PreprocessText(String& Text /* исходный текст */); // подсчет статистики слов в тексте void __fastcall CountStats(String& Text /* исходный текст */, long& TotalWords /* сюда запишется общее кол-во слов */); // подсчет статистики слов в тексте (загрузка из файла) void __fastcall CountStatsFromFile(const String TextFile /* путь текстового файла */, long& TotalWords /* сюда запишется общее кол-во слов */); // вывод статистики в грид void __fastcall StatsToGrid(const StatVec& Data /* контейнер данных статистики */, long TotalWords /* общее кол-во слов */, TStringGrid* Grid /* грид */); // ... (остальное)}; //---------------------------------------------------------------------------// Unit1.cpp//---------------------------------------------------------------------------#include "Unit1.h"#include <algorithm> // для sort, equal_range#include <memory> // для auto_ptr//--------------------------------------------------------------------------- void __fastcall TForm1::PreprocessText(String& Text){ // функция для предв. форматирования текста Text = Text.LowerCase(); // переводим текст в нижний регистр for(long i=1; i<=Text.Length(); i++) { // если буква - не буква алфавита и не пробел, удалить ее if(!isalpha(Text[i]) && !isspace(Text[i])) Text.Delete(i--, 1); }} //---------------------------------------------------------------------------void __fastcall TForm1::CountStats(String& Text, long& TotalWords){ // подсчет статистики слов в тексте // 1. форматируем текст (удаляем знаки препинания и т.д.) PreprocessText(Text); // 2. список для хранения слов std::auto_ptr<TStringList> slWords(new TStringList()); slWords->Delimiter = ' '; // разделитель слов - пробел (а также перенос строки) slWords->DelimitedText = Text; // загружаем слова в список из текста vData.clear(); // очищаем статистику long total(0L); // счетчик слов, по которым ведется статистика int len(0); // длина слова for(long i=0L; i<slWords->Count; i++) { // цикл по словам в тексте len = slWords->Strings[i].Trim().Length(); // получаем длину слова if(len >= MINW && len <= MAXW) { // если длина в пределах [MINW, MAXW]... // добавляем слово в контейнер (пока только само слово + длина) vData.push_back(CStats(slWords->Strings[i].Trim().LowerCase(), len)); total++; // инкремент счетчика слов } } TotalWords = total; // присваем TotalWords значение счетчика слов if(vData.empty()) { // если слов в контейнере нет, выход ShowMessage("Файл не содержит слов!"); return; } std::sort(vData.begin(), vData.end()); // сортировка контейнера статистики (используется оператор <) std::pair<StatVec_I, StatVec_I> bounds; // границы диапазона для equal_range long count; for(StatVec_CI cit=vData.begin(); cit!=vData.end(); ++cit) { // цикл по элементам контейнера статистики // находим диапазон одинаковых слов, равных след. элементу bounds = std::equal_range(vData.begin(), vData.end(), *cit); // указатель на первый элемент в диапазоне StatVec_I first_i = bounds.first; // количество элементов в диапазоне (кол-во одинаковых слов, идущих подряд) count = long(bounds.second - first_i); if(count) { // если диапазон не пустой if(count > 1L) vData.erase(first_i + 1, bounds.second); // удалить из контейнера остальные слова, кроме первого first_i->count = count; // записываем кол-во совпадений (=размер диапазона) first_i->percent = (double)count * 100.0f / (double)total; // процент встречаемости } }}//---------------------------------------------------------------------------void __fastcall TForm1::CountStatsFromFile(const String TextFile, long& TotalWords){ // подсчет статистики слов в тексте (загрузка из файла) if(!FileExists(TextFile)) { ShowMessage("Файл не существует!"); return; } std::auto_ptr<TStringList> slFile(new TStringList()); slFile->LoadFromFile(TextFile); String Text = slFile->Text; CountStats(Text, TotalWords);}//---------------------------------------------------------------------------void __fastcall TForm1::StatsToGrid(const StatVec& Data, long TotalWords, TStringGrid* Grid){ // вывод статистики в грид Grid->RowCount = Data.size() + 2; Grid->ColCount = 4; Grid->Cells[0][0] = "Слово"; Grid->Cells[1][0] = "Длина"; Grid->Cells[2][0] = "Подсчет"; Grid->Cells[3][0] = "Встречаемость"; Grid->Cells[0][1] = "[ВСЕГО СЛОВ]:"; Grid->Cells[1][1] = "-"; Grid->Cells[2][1] = String(TotalWords); // общее кол-во слов Grid->Cells[3][1] = "-"; long i = 2L; for(StatVec_CI cit=vData.begin(); cit!=vData.end(); ++cit, i++) { // цикл по элементам контейнера Grid->Cells[0][i] = cit->word; Grid->Cells[1][i] = String(cit->length); Grid->Cells[2][i] = String(cit->count); Grid->Cells[3][i] = FloatToStr(cit->percent); }}//---------------------------------------------------------------------------void __fastcall TForm1::Button2Click(TObject *Sender){ // подсчет статистики текста в Memo1 // и вывод в StringGrid1 String Text = Memo1->Lines->Text; long w(0L); CountStats(Text, w); Memo1->Lines->Text = Text; StatsToGrid(vData, w, StringGrid1);}
slWords->Delimiter = ' ';slWords->DelimitedText = Text;