Advertisement
RobertDeMilo

YB3.7 Правило одного определения

Nov 10th, 2023
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.96 KB | None | 0 0
  1. В С++ есть правило одного определения. (One Defenition Rule)
  2. Если функция определена в заголовочном файле, который подключается более чем, в 1 cpp - файл, то
  3. нарушается правило одного определения. (Он попадает в несколько объектных файлов).
  4. Чтобы не нарушать правило надо все определения помещать в сpp файлы.
  5.  
  6. main
  7.  
  8. #include "tests.h"
  9. #include "synonyms.h"
  10.  
  11. #include <iostream>
  12. #include <exception>
  13. #include <vector>
  14.  
  15. using namespace std;
  16.  
  17. int main()
  18. {
  19.     TestAll();
  20.  
  21.     int q;
  22.     cin >> q;
  23.     map<string, set<string>>synonyms;
  24.  
  25.     for (int i = 0; i < q; i++)
  26.     {
  27.         string operation_code;
  28.         cin >> operation_code;
  29.  
  30.         if (operation_code == "ADD")
  31.         {
  32.             string first_word, second_word;
  33.             cin >> first_word >> second_word;
  34.  
  35.             ADDSYNONYMS(synonyms, first_word, second_word);
  36.  
  37.         }
  38.         else if (operation_code == "COUNT")
  39.         {
  40.             string word;
  41.             cin >> word;
  42.  
  43.             cout << GETSYNONYMCOUNT(synonyms, word) << endl;
  44.  
  45.         }
  46.         else if (operation_code == "CHECK")
  47.         {
  48.             string first_word, second_word;
  49.             cin >> first_word >> second_word;
  50.  
  51.             if (ARESYNONYMS(synonyms, first_word, second_word))
  52.             {
  53.                 cout << "YES" << endl;
  54.             }
  55.             else
  56.             {
  57.                 cout << "NO" << endl;
  58.             }
  59.         }
  60.     }
  61.  
  62.     return 0;
  63. }
  64. ###############################################################################################################
  65. synonyms.h
  66.  
  67. #pragma once
  68.  
  69. #include <string>
  70. #include <set>
  71. #include <map>
  72.  
  73. using namespace std;
  74.  
  75. using SYNONYMS = map<string, set<string>>;
  76.  
  77. void ADDSYNONYMS(map<string, set<string>>& synonyms, const string& first_word, const string& second_word);
  78. bool ARESYNONYMS(map<string, set<string>>& synonyms, const string& first_word, const string& second_word);
  79. //size_t GETSYNONYMCOUNT(map<string, set<string>>& synonyms, const string& first_word);
  80. //нельзя
  81. size_t GETSYNONYMCOUNT(map<string, set<string>>& synonyms, const string& first_word)
  82. {
  83.     return synonyms[first_word].size();
  84. }
  85. ###############################################################################################################
  86. synonyms.cpp
  87.  
  88. #include "synonyms.h"
  89.  
  90. void ADDSYNONYMS(map<string, set<string>>& synonyms, const string& first_word, const string& second_word)
  91. {
  92.     synonyms[second_word].insert(first_word);
  93.     synonyms[first_word].insert(second_word);
  94. }
  95.  
  96. //**********************************************************************************************************
  97.  
  98. //size_t GETSYNONYMCOUNT(map<string, set<string>>& synonyms, const string& first_word)
  99. //{
  100. //    return synonyms[first_word].size();
  101. //}
  102.  
  103. //**********************************************************************************************************
  104.  
  105. bool ARESYNONYMS(map<string, set<string>>& synonyms, const string& first_word, const string& second_word)
  106. {
  107.     return synonyms[first_word].count(second_word) == 1;
  108. }
  109. ###############################################################################################################
  110. test_runner.h
  111.  
  112. #pragma once
  113.  
  114. #include <iostream>
  115. #include <sstream>
  116. #include <string>
  117. #include <set>
  118. #include <map>
  119.  
  120. using namespace std;
  121.  
  122. template<class T>
  123. ostream& operator<<(ostream& os, const set<T>& s);
  124.  
  125. template <class K, class V>
  126. ostream& operator<<(ostream& os, const map<K, V>& m);
  127.  
  128. template<class T, class U>
  129. void AssertEqual(const T& t, const U& u, const string& hint);
  130.  
  131. void Assert(bool b, const string& hint);
  132.  
  133.  
  134. template<class T>
  135. ostream& operator<<(ostream& os, const set<T>& s)
  136. {
  137.     os << "{";
  138.     bool first = true;
  139.  
  140.     for (const auto& x : s)
  141.     {
  142.         if (!first)
  143.         {
  144.             os << ", ";
  145.         }
  146.         first = false;
  147.         os << x;
  148.     }
  149.     return os << "}";
  150. }
  151. //**********************************************************************************************************
  152.  
  153. template <class K, class V>
  154. ostream& operator<<(ostream& os, const map<K, V>& m)
  155. {
  156.     os << "{";
  157.     bool first = true;
  158.     for (const auto& kv : m)
  159.     {
  160.         if (!first)
  161.         {
  162.             os << ", ";
  163.         }
  164.         first = false;
  165.         os << kv.first << ": " << kv.second;
  166.     }
  167.     return os << "}";
  168. }
  169.  
  170. //**********************************************************************************************************
  171.  
  172. template<class T, class U>
  173. void AssertEqual(const T& t, const U& u, const string& hint)
  174. {
  175.     if (t != u)
  176.     {
  177.         ostringstream os;
  178.         os << "Assertion failed: " << t << " != " << u << " Hint: " << hint;
  179.         throw runtime_error(os.str());
  180.     }
  181. }
  182.  
  183. //**********************************************************************************************************
  184.  
  185. class TestRunner
  186. {
  187. public:
  188.  
  189.     template <class TestFunc>
  190.     void RunTest(TestFunc func, const string& test_name);
  191.  
  192.     ~TestRunner();
  193.  
  194. private:
  195.  
  196.     int fail_count = 0;
  197. };
  198.  
  199.  
  200. template <class TestFunc>
  201. void TestRunner::RunTest(TestFunc func, const string& test_name)
  202. {
  203.     try
  204.     {
  205.         func();
  206.         cerr << test_name << " OK" << endl;
  207.     }
  208.     catch (runtime_error& e)
  209.     {
  210.         ++fail_count;
  211.         cerr << test_name << " fail: " << e.what() << endl;
  212.     }
  213. }
  214. ###############################################################################################################
  215. test_runner.cpp
  216.  
  217. #include "test_runner.h"
  218.  
  219. void Assert(bool b, const string& hint)
  220. {
  221.     AssertEqual(b, true, hint);
  222. }
  223.  
  224. TestRunner::~TestRunner()
  225. {
  226.     if (fail_count > 0)
  227.     {
  228.         cerr << fail_count << " tests failed. Terminate";
  229.         exit(1);
  230.     }
  231. }
  232. ###############################################################################################################
  233. tests.h
  234. #pragma once
  235.  
  236. #include "test_runner.h"
  237. #include "synonyms.h"
  238.  
  239. // Interface
  240.  
  241. void TESTADDSYNONYMS();
  242. void TESTARESYNONYMS();
  243. void TESTCOUNT();
  244. void TestAll();
  245. ###############################################################################################################
  246. tests.cpp
  247.  
  248. #include "tests.h"
  249.  
  250. // Implementation
  251.  
  252. void TESTADDSYNONYMS()
  253. {
  254.     {
  255.         map<string, set<string>> empty;
  256.         ADDSYNONYMS(empty, "a", "b");
  257.         const map<string, set<string>> expected = { {"a",{"b"}},
  258.                                                     {"b",{"a"}} };
  259.  
  260.         AssertEqual(empty, expected, "Add to empty");
  261.     }
  262.  
  263.     {
  264.         map<string, set<string>> synonyms = { {"a",{"b"}},
  265.                                               {"b",{"a","c"}},
  266.                                               {"c",{"b"}} };
  267.         ADDSYNONYMS(synonyms, "a", "c");
  268.         const map<string, set<string>> expected = { {"a",{"b","c"}},
  269.                                                     {"b",{"a","c"}},
  270.                                                     {"c",{"b","a"}} };
  271.  
  272.         AssertEqual(synonyms, expected, "Add to non-empty");
  273.  
  274.     }
  275. }
  276. //**********************************************************************************************************
  277.  
  278. void TESTCOUNT()
  279. {
  280.     {
  281.         map<string, set<string>> empty;
  282.  
  283.         AssertEqual(GETSYNONYMCOUNT(empty, "a"), 0u, "count for empty");
  284.     }
  285.  
  286.     {
  287.         map<string, set<string>> synonyms = { {"a",{"b","c"}},
  288.                                               {"b",{"a"}},
  289.                                               {"c",{"a"}} };
  290.  
  291.  
  292.         AssertEqual(GETSYNONYMCOUNT(synonyms, "a"), 2u, "count for a");
  293.         AssertEqual(GETSYNONYMCOUNT(synonyms, "b"), 1u, "count for b");
  294.         AssertEqual(GETSYNONYMCOUNT(synonyms, "z"), 0u, "count for z");
  295.     }
  296. }
  297. //**********************************************************************************************************
  298.  
  299. void TESTARESYNONYMS()
  300. {
  301.     {
  302.         map<string, set<string>> empty;
  303.  
  304.         Assert(!ARESYNONYMS(empty, "a", "b"), "empty a b");
  305.         Assert(!ARESYNONYMS(empty, "a", "b"), "empty b a");
  306.     }
  307.  
  308.     {
  309.         map<string, set<string>> synonyms = { {"a",{"b","c"}},
  310.                                               {"b",{"a"}},
  311.                                               {"c",{"a"}} };
  312.  
  313.         Assert(ARESYNONYMS(synonyms, "a", "b"), " ");
  314.         Assert(ARESYNONYMS(synonyms, "b", "a"), " ");
  315.         Assert(ARESYNONYMS(synonyms, "a", "c"), " ");
  316.         Assert(ARESYNONYMS(synonyms, "c", "a"), " ");
  317.         Assert(!ARESYNONYMS(synonyms, "b", "c"), " ");
  318.         Assert(!ARESYNONYMS(synonyms, "c", "b"), " ");
  319.     }
  320.  
  321. }
  322. //**********************************************************************************************************
  323.  
  324. void TestAll()
  325. {
  326.     TestRunner tr;
  327.  
  328.     tr.RunTest(TESTARESYNONYMS, "TESTARESYNONYMS");
  329.     tr.RunTest(TESTADDSYNONYMS, "TESTADDSYNONYMS");
  330.     tr.RunTest(TESTCOUNT, "TESTCOUNT");
  331. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement