StoneHaos

Cezar

Dec 12th, 2019
163
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <stdio.h>
  2. #include <iostream>
  3. #include <string>
  4. #include <vector>
  5. #include <algorithm>
  6. #include <windows.h>
  7. using namespace std;
  8.  
  9. typedef unsigned char uc;
  10.  
  11. /*
  12. Программа работает с кодировкой windows-1251 (ansi)
  13. Коды русских символов:
  14. Ё = 168
  15. ё = 184
  16. А = 192
  17. ...
  18. Я = 223
  19. а = 224
  20. ...
  21. я = 255
  22. */
  23.  
  24. // Функция определяет, является ли русская буква заглавной
  25. bool isupper_ru(uc c) {
  26.     return c >= 192 && c <= 223 || c == 168;
  27. }
  28.  
  29. // Функция определяет, является ли символ русской буквой
  30. bool isrus(uc c) {
  31.     return c == 168 || c == 184 || c >= 192 && c <= 255;
  32. }
  33.  
  34. // Функция осуществляет сдвиг ТОЛЬКО русских символов по Цезарю
  35. // s - изменяемая строка, offset - сдвиг по Цезарю
  36. // &s - позволит сделать так, чтобы при изменении объекта s в функции, объект s менялся и вне функции
  37. void crypto(string &s, int offset) {
  38.     for (int i = 0; i < s.size(); ++ i) {
  39.         uc c = (uc)s[i];
  40.         if (isrus(c)) {
  41.             /*
  42.                 Ниже происходит преобразование кодов русских символов
  43.                 в их порядковый номер в алфавите, затем происходит
  44.                 сдвиг по Цезарю и обратное преобразование (из позиции
  45.                 в алфавите в код символа). Действия производятся отдельно
  46.                 для заглавных и отдельно для строчных букв.
  47.             */
  48.             if (isupper_ru(c)) {
  49.                 if (c == 168)
  50.                     c = 6;
  51.                 else {
  52.                     c -= 192;
  53.                     if (c >= 6)
  54.                         ++ c;
  55.                 }
  56.                 c = (c + offset) % 33;
  57.                 if (c == 6)
  58.                     c = 168;
  59.                 else {
  60.                     if (c >= 7)
  61.                         -- c;
  62.                     c += 192;
  63.                 }
  64.             }
  65.             else {
  66.                 if (c == 184)
  67.                     c = 6;
  68.                 else {
  69.                     c -= 224;
  70.                     if (c >= 6)
  71.                         ++ c;
  72.                 }
  73.                 c = (c + offset) % 33;
  74.                 if (c == 6)
  75.                     c = 184;
  76.                 else {
  77.                     if (c >= 7)
  78.                         -- c;
  79.                     c += 224;
  80.                 }
  81.             }
  82.             s[i] = (char)c; // Замена символа строки на новый
  83.         }
  84.     }
  85. }
  86.  
  87. // Функция возвращает vector из n первых слов словаря данной программы
  88. vector<string> read_words(const int n) {
  89.     vector<string> ret(0);
  90.     char buf[128];
  91.     FILE* f = fopen("words.num", "r");
  92.     for (int i = 0; i < n; ++ i) {
  93.         fscanf(f, "%*s%*s%s", buf);
  94.         ret.push_back(string(buf));
  95.     }
  96.     fclose(f);
  97.     return ret;
  98. }
  99.  
  100. // Функция преобразует любой русский символ в строчной и возвращает преобразованный символ
  101. // Если символ строчной, функция не преобразует его.
  102. uc tolower_ru(uc code) {
  103.     if (isupper_ru(code)) {
  104.         if (code == 168)
  105.             code = 184;
  106.         else
  107.             code += 32;
  108.         return code;
  109.     }
  110.     else
  111.         return code;
  112. }
  113.  
  114. // Возвращает строку в нижнем регистре
  115. string stolower_ru(const string s) {
  116.     string ret;
  117.     for (int i = 0; i < s.size(); ++ i) {
  118.         ret.push_back(tolower_ru(s[i]));
  119.     }
  120.     return ret;
  121. }
  122.  
  123. const int _n = 69307; // Количество слов в файле со словами
  124. //69307
  125.  
  126. int main(void) {
  127.  
  128.     SetConsoleCP(1251); // Устанавливает кодировку потока ввода
  129.     SetConsoleOutputCP(1251); // Устанавливает кодировку потока вывода
  130.     vector<string> words = read_words(_n);
  131.     char buf[16384];
  132.     scanf("%[^\n]", buf); // Ввод происходит до перевода строки (enter)
  133.     string s = buf;
  134.     vector<string> strs(33); // Массив для сохранения преобразованных по Цезарю строк
  135.     vector<int> cnts(33); // Массив для сохранения количества соответствий для строк массива strs с соответствующими индексами
  136.     // Перебор каждого смещения
  137.     for (int i = 0; i < 33; ++ i) {
  138.         strs[i] = s;
  139.         cnts[i] = 0;
  140.         uc c;
  141.         string word; // Здесь будут храниться русские слова
  142.         // Ниже перебор каждого символа строки
  143.         for (int j = 0; j < s.size(); ++ j) {
  144.             c = (uc)s[j];
  145.             if (isrus(c))
  146.                 // Если символ является русской буквой
  147.                 word.push_back(c);
  148.             if (!isrus(c) && !word.empty() || j == s.size() - 1) {
  149.                 /*
  150.                     Если символ не является русской буквой
  151.                     и при этом строка не пуста (значит, что русское
  152.                     слово закончилось и его надо сравнить со словами
  153.                     словаря данной программы).
  154.                 */
  155.                 if (!word.empty())
  156.                     // Сравнение
  157.                     if (count(words.begin(), words.end(), stolower_ru(word)))
  158.                         ++ cnts[i]; // +1 к числу соответствий всей строки, если слово найдено в словаре данной программы
  159.                 word.clear(); // Отчистка для записи следующего слова
  160.             }
  161.         }
  162.         if (i != 32)
  163.             crypto(s, 1); // Русские буквы строки s смещаются ещё на одну позицию, если в этом есть смысл ...
  164.             // ... (Если это не последняя итерация цикла)
  165.     }
  166.     int index = max_element(cnts.begin(), cnts.end()) - cnts.begin();
  167.     // Выше поиск максимального числа соответствий и получения индекса элемента в массиве cnts
  168.     cout << "\n" << strs[index] << "\n";
  169.     cout << "Число совпадений: " << cnts[index] << "\n";
  170.     return 0;
  171. }
RAW Paste Data