|
| 1 | +/* Exercise 26.2 */ |
| 2 | + |
| 3 | +#include<iostream> |
| 4 | +#include<sstream> |
| 5 | +#include<fstream> |
| 6 | +#include<iomanip> |
| 7 | +#include<vector> |
| 8 | +#include"C26_Exercise_26.2.h" |
| 9 | + |
| 10 | +using namespace std; |
| 11 | + |
| 12 | +inline void error(string s) { throw runtime_error(s); } |
| 13 | +inline void error(const string& s, const string& s2) { error(s + s2); } |
| 14 | +inline void error(const string& s, int i) { ostringstream os; os << s << ": " << i; error(os.str()); } |
| 15 | +inline void keep_window_open() { char ch; cin >> ch; } |
| 16 | +inline int randint(int max) { return rand() % max; } |
| 17 | +inline int randint(int min, int max) { return randint(max - min) + min; } |
| 18 | + |
| 19 | +int main() |
| 20 | +{ |
| 21 | + enum Action { |
| 22 | + EXIT = -1, PRINTACTIONLIST, |
| 23 | + CASE1, CASE2, CASE3, CASE4, CASE5, CASE6, CASE7, CASE8, CASE9, CASE10 |
| 24 | + }; |
| 25 | + const string actionList = "\tList of actions:\n" |
| 26 | + " (1) BinarySearch()\n" |
| 27 | + " (-1) Exit, (0) Print the list of actions\n"; |
| 28 | + cout << actionList; |
| 29 | + int action; |
| 30 | + bool cond{ true }; |
| 31 | + while (cond) try { |
| 32 | + cout << "\nPlease enter the action: "; |
| 33 | + if (!(cin >> action)) { ClearInput(cin); error("Error. Incorrect input"); } |
| 34 | + char ch; |
| 35 | + cin.get(ch); |
| 36 | + switch (action) { |
| 37 | + case CASE1: { |
| 38 | + cout << endl; |
| 39 | + { |
| 40 | + cout << "int:" << endl; |
| 41 | + string fileInput{ "C26_Exercise_26.2_test_int.txt" }; |
| 42 | + ifstream ifs{ fileInput }; |
| 43 | + if (!ifs) error("Error. Can't open input file: ", fileInput); |
| 44 | + cout << sp_2 << "File: " << fileInput << endl; |
| 45 | + TestAll<int>(ifs, cout); |
| 46 | + |
| 47 | + // Test 8 "Sets generated using random numbers" |
| 48 | + constexpr int numberOfElements = 50; |
| 49 | + constexpr int spread = 20; |
| 50 | + stringstream ss; |
| 51 | + for (int i = 1; i <= 20; ++i) { |
| 52 | + vector<int> v; |
| 53 | + int sum = 0; |
| 54 | + for (int j = 0; j < numberOfElements; ++j) { |
| 55 | + sum += randint(spread); |
| 56 | + v.push_back(sum); |
| 57 | + } |
| 58 | + int x = v[randint(v.size())]; |
| 59 | + ss << "{ 8." << i << " " << x << " { "; |
| 60 | + for (int j = 0; j < v.size(); ++j) { |
| 61 | + ss << v[j] << " "; |
| 62 | + } |
| 63 | + ss << "} 1 }" << endl; |
| 64 | + } |
| 65 | + cout << sp_2 << "Sets generated using random numbers" << endl; |
| 66 | + TestAll<int>(ss, cout); |
| 67 | + } |
| 68 | + |
| 69 | + { |
| 70 | + cout << endl << "double:" << endl; |
| 71 | + string fileInput{ "C26_Exercise_26.2_test_double.txt" }; |
| 72 | + ifstream ifs{ fileInput }; |
| 73 | + if (!ifs) error("Error. Can't open input file: ", fileInput); |
| 74 | + cout << sp_2 << "File: " << fileInput << endl; |
| 75 | + TestAll<double>(ifs, cout); |
| 76 | + |
| 77 | + // Test 8 "Sets generated using random numbers" |
| 78 | + constexpr int numberOfElements = 50; |
| 79 | + constexpr int spread = 20; |
| 80 | + stringstream ss; |
| 81 | + for (int i = 1; i <= 20; ++i) { |
| 82 | + vector<double> v; |
| 83 | + double sum = 0; |
| 84 | + for (int j = 0; j < numberOfElements; ++j) { |
| 85 | + sum += double(randint(spread)) + double(randint(1, 99)) / 100; |
| 86 | + v.push_back(sum); |
| 87 | + } |
| 88 | + double x = v[randint(v.size())]; |
| 89 | + ss << "{ 8." << i << " " << x << " { "; |
| 90 | + for (int j = 0; j < v.size(); ++j) { |
| 91 | + ss << v[j] << " "; |
| 92 | + } |
| 93 | + ss << "} 1 }" << endl; |
| 94 | + } |
| 95 | + cout << sp_2 << "Sets generated using random numbers" << endl; |
| 96 | + TestAll<double>(ss, cout); |
| 97 | + } |
| 98 | + |
| 99 | + { |
| 100 | + cout << endl << "string:" << endl; |
| 101 | + string fileInput{ "C26_Exercise_26.2_test_string.txt" }; |
| 102 | + ifstream ifs{ fileInput }; |
| 103 | + if (!ifs) error("Error. Can't open input file: ", fileInput); |
| 104 | + cout << sp_2 << "File: " << fileInput << endl; |
| 105 | + TestAll<string>(ifs, cout); |
| 106 | + |
| 107 | + // Test 8 "Sets generated using random numbers" |
| 108 | + constexpr int numberOfLetters = 'z' - 'a' + 1; |
| 109 | + constexpr int maxLetters = 5; |
| 110 | + constexpr char firstLetter = 'a'; |
| 111 | + stringstream ss; |
| 112 | + for (int i = 1; i <= 20; ++i) { |
| 113 | + vector<string> v; |
| 114 | + string s; |
| 115 | + for (int j = 0; j < numberOfLetters; ++j) { |
| 116 | + s = ""; |
| 117 | + s += firstLetter + j; |
| 118 | + for (int k = 1; k < maxLetters; ++k) { |
| 119 | + s += char(randint('a', 'z' + 1)); |
| 120 | + } |
| 121 | + v.push_back(s); |
| 122 | + } |
| 123 | + string x = v[randint(v.size())]; |
| 124 | + ss << "{ 8." << i << " " << x << " { "; |
| 125 | + for (int j = 0; j < v.size(); ++j) { |
| 126 | + ss << v[j] << " "; |
| 127 | + } |
| 128 | + ss << "} 1 }" << endl; |
| 129 | + } |
| 130 | + cout << sp_2 << "Sets generated using random numbers" << endl; |
| 131 | + TestAll<string>(ss, cout); |
| 132 | + } |
| 133 | + |
| 134 | + cout << vsp_2; |
| 135 | + break; |
| 136 | + } |
| 137 | + case PRINTACTIONLIST: |
| 138 | + cout << actionList; |
| 139 | + break; |
| 140 | + case EXIT: |
| 141 | + cond = false; |
| 142 | + break; |
| 143 | + default: |
| 144 | + error("Error. Incorrect action number"); |
| 145 | + break; |
| 146 | + } |
| 147 | + } |
| 148 | + catch (runtime_error& e) { |
| 149 | + cerr << e.what() << endl; |
| 150 | + } |
| 151 | + catch (...) { |
| 152 | + cerr << "Error. Exception\n"; |
| 153 | + return 1; |
| 154 | + } |
| 155 | + return 0; |
| 156 | +} |
| 157 | + |
| 158 | +void ClearInput(istream& is) |
| 159 | +{ |
| 160 | + is.clear(); |
| 161 | + is.ignore(numeric_limits<streamsize>::max(), '\n'); |
| 162 | +} |
| 163 | + |
| 164 | +template<class T> istream& operator>>(istream& is, Test<T>& t) |
| 165 | +{ |
| 166 | + /* |
| 167 | + format: { N TV { V1 V2 V3 ... } B } |
| 168 | + N - <string> test number |
| 169 | + TV - <T> target value |
| 170 | + V1, V2, V3 ... - <T> sequence of values to search for |
| 171 | + B - <bool> ('0' or '1') the expected result of the search |
| 172 | + */ |
| 173 | + Test<T> test; |
| 174 | + // cb - curly brace |
| 175 | + constexpr char cbLeft{ '{' }; |
| 176 | + constexpr char cbRigth{ '}' }; |
| 177 | + char ch1, ch2; |
| 178 | + is >> ch1 >> test.label >> test.val >> ch2; |
| 179 | + if (!is) return is; |
| 180 | + if (ch1 != cbLeft || ch2 != cbLeft) { |
| 181 | + is.setstate(ios::failbit); |
| 182 | + return is; |
| 183 | + } |
| 184 | + while (true) { |
| 185 | + char ch3; |
| 186 | + is >> ch3; |
| 187 | + if (!is) return is; |
| 188 | + if (ch3 == cbRigth) break; |
| 189 | + is.unget(); |
| 190 | + T val; |
| 191 | + is >> val; |
| 192 | + if (!is) return is; |
| 193 | + test.seq.push_back(val); |
| 194 | + } |
| 195 | + is >> test.res; |
| 196 | + if (!is) return is; |
| 197 | + char ch4; |
| 198 | + is >> ch4; |
| 199 | + if (!is) return is; |
| 200 | + if (ch4 != cbRigth) { |
| 201 | + is.setstate(ios::failbit); |
| 202 | + return is; |
| 203 | + } |
| 204 | + t = test; |
| 205 | + return is; |
| 206 | +} |
| 207 | + |
| 208 | +template<class T> int TestAll(istream& is, ostream& os) |
| 209 | +{ |
| 210 | + int testCount = 0; |
| 211 | + int errorCount = 0; |
| 212 | + os << boolalpha; |
| 213 | + for (Test<T> t; is >> t; ) { |
| 214 | + bool r = BinarySearch(t.seq.begin(), t.seq.end(), t.val); |
| 215 | + if (r != t.res) { |
| 216 | + os << sp_4 << "Failure: test { " << t.label << " }; BinarySearch(): sequence { "; |
| 217 | + for (const T& x : t.seq) { |
| 218 | + os << x << ' '; |
| 219 | + } |
| 220 | + os << "} " << t.seq.size() << " elements; Target value { " << t.val |
| 221 | + << " } -> { " << t.res << " }" << endl; |
| 222 | + ++errorCount; |
| 223 | + } |
| 224 | + ++testCount; |
| 225 | + } |
| 226 | + if (!is && !is.eof()) os << sp_6 << "Invalid test" << endl; |
| 227 | + os << noboolalpha; |
| 228 | + os << sp_8 << "Number of tests: " << testCount << endl; |
| 229 | + os << sp_8 << "Number of errors: " << errorCount << endl; |
| 230 | + return errorCount; |
| 231 | +} |
| 232 | + |
| 233 | +template<class RandomAccessIterator, class T> |
| 234 | +bool BinarySearch(RandomAccessIterator first, RandomAccessIterator last, const T& x) |
| 235 | +{ |
| 236 | + using Iter = RandomAccessIterator; |
| 237 | + if (first == last) return false; |
| 238 | + --last; |
| 239 | + while (first <= last) { |
| 240 | + Iter middle = (last - first) / 2 + first; |
| 241 | + if (*middle == x) return true; |
| 242 | + else if (*middle > x) last = middle - 1; |
| 243 | + else first = middle + 1; // *middle < x |
| 244 | + } |
| 245 | + return false; |
| 246 | +} |
0 commit comments