├── LICENSE.txt ├── 9781484200056.jpg ├── Chapter 5 ├── Ex5_06 │ ├── Hash_Name.h │ ├── Name.h │ └── Ex5_06.cpp ├── Ex5_01 │ ├── List_Course.h │ ├── Student.h │ └── Ex5_01.cpp ├── Ex5_07 │ ├── List_Course.h │ └── Student.h ├── Ex5_02 │ ├── List_Course.h │ ├── Student.h │ └── Ex5_02.cpp ├── Ex5_03 │ ├── List_Course.h │ └── Student.h ├── Ex5_05 │ ├── Pet_Classes.h │ └── Ex5_05.cpp └── Ex5_04.cpp ├── Chapter 3 ├── Ex3_06 │ ├── Carton.h │ ├── Box.cpp │ ├── Ex3_06.cpp │ └── Box.h ├── Ex3_05 │ ├── Customer.h │ ├── Checkout.h │ └── Ex3_05.cpp ├── Ex3_02 │ ├── Customer.h │ ├── Checkout.h │ └── Ex3_02.cpp ├── Ex3_03.cpp ├── Ex3_04.cpp └── Ex3_01.cpp ├── Chapter 8 ├── Ex8_01.cpp ├── Ex8_07 │ ├── Die.h │ └── Ex8_07.cpp ├── Ex8_02.cpp ├── Ex8_04.cpp ├── Ex8_09.cpp ├── Ex8_08.cpp ├── Ex8_05.cpp ├── Ex8_06.cpp └── Ex8_03.cpp ├── Chapter 10 ├── Data Files │ └── Renewables_vs_kwh_cost.txt ├── Ex10_04.cpp ├── Ex10_03 │ ├── Ex10_03.cpp │ └── gaussian.cpp ├── Ex10_02.cpp ├── Ex10_06.cpp ├── Ex10_05 │ ├── Ex10_05.cpp │ └── gaussian.cpp └── Ex10_01.cpp ├── Chapter 6 ├── Ex6_02 │ ├── Compare_Names.h │ ├── Transaction.h │ ├── Account.h │ └── Ex6_02.cpp ├── Ex6_01 │ ├── Name.h │ └── Ex6_01.cpp ├── Ex6_03.cpp ├── Ex6_04.cpp └── Ex6_05.cpp ├── README.md ├── Chapter 1 ├── Ex1_02.cpp ├── Ex1_01.cpp └── Ex1_03.cpp ├── contributing.md ├── Chapter 2 ├── Ex2_04.cpp ├── Ex2_07 │ ├── Ex2_07.cpp │ └── Numeric_Range.h ├── Ex2_05.cpp ├── Ex2_06 │ ├── Box.h │ └── Ex2_06.cpp ├── Ex2_03.cpp ├── Ex2_02.cpp ├── Ex2_02A.cpp └── Ex2_01.cpp ├── Chapter 4 ├── Ex4_07 │ ├── Hash_Function_Objects.h │ ├── My_Templates.h │ ├── Record_IO.h │ └── Ex4_07.cpp ├── Ex4_01 │ ├── Name.h │ └── Ex4_01.cpp ├── Ex4_03 │ ├── Name.h │ ├── Quotations.h │ └── Ex4_03.cpp ├── Ex4_05.cpp ├── Ex4_02.cpp ├── Ex4_04.cpp └── Ex4_06.cpp ├── Chapter 9 ├── Ex9_05.cpp ├── Ex9_01.cpp ├── Ex9_06.cpp ├── Ex9_09.cpp ├── Ex9_02.cpp ├── Ex9_07.cpp ├── Ex9_03.cpp ├── Ex9_04.cpp ├── Ex9_08.cpp └── Ex9_10.cpp └── Chapter 7 ├── Ex7_03.cpp ├── Ex7_04.cpp ├── Ex7_01.cpp ├── Ex7_02.cpp └── Ex7_05.cpp /LICENSE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/using-cpp-standard-template-libraries/HEAD/LICENSE.txt -------------------------------------------------------------------------------- /9781484200056.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/using-cpp-standard-template-libraries/HEAD/9781484200056.jpg -------------------------------------------------------------------------------- /Chapter 5/Ex5_06/Hash_Name.h: -------------------------------------------------------------------------------- 1 | // Hash_Name.h 2 | // Function object type to hash Name objects for Ex5_06 3 | #ifndef HASH_NAME_H 4 | #define HASH_NAME_H 5 | #include "Name.h" 6 | 7 | class Hash_Name 8 | { 9 | public: 10 | size_t operator()(const Name& name) { return name.hash(); } 11 | }; 12 | #endif -------------------------------------------------------------------------------- /Chapter 3/Ex3_06/Carton.h: -------------------------------------------------------------------------------- 1 | // Carton.h 2 | #ifndef CARTON_H 3 | #define CARTON_H 4 | #include "Box.h" 5 | 6 | class Carton :public Box 7 | { 8 | public: 9 | explicit Carton(size_t l = 1, size_t w = 1, size_t h = 1) : Box {l, w, h}{} 10 | double volume() const override {return 0.85*Box::volume(); } 11 | }; 12 | #endif -------------------------------------------------------------------------------- /Chapter 8/Ex8_01.cpp: -------------------------------------------------------------------------------- 1 | // Ex8_01.cpp 2 | // Generating a succession of 8 seeds 3 | #include // For random_device class 4 | #include // For standard streams 5 | 6 | int main() 7 | { 8 | std::random_device rd; // A function object for generating seeds 9 | for(size_t n {}; n < 8; ++n) 10 | std::cout << rd() << " "; 11 | std::cout << std::endl; 12 | } -------------------------------------------------------------------------------- /Chapter 10/Data Files/Renewables_vs_kwh_cost.txt: -------------------------------------------------------------------------------- 1 | Austria 353 20.21 2 | Belgium 452 20.97 3 | Denmark 956 30.42 4 | Croatia 89 13.12 5 | Finland 114 15.63 6 | Germany 969 29.81 7 | Greece 424 17.67 8 | Hungary 37 12.02 9 | Ireland 483 24.07 10 | Italy 453 24.46 11 | Netherland 234 18.21 12 | Poland 100 14.21 13 | Portuga1 517 21.75 14 | Spain 596 22.52 15 | Sweden 561 19.67 16 | UK 257 19.18 17 | -------------------------------------------------------------------------------- /Chapter 6/Ex6_02/Compare_Names.h: -------------------------------------------------------------------------------- 1 | #ifndef COMPARE_NAMES_H 2 | #define COMPARE_NAMES_H 3 | #include "Account.h" 4 | 5 | // Order Account objects in ascending sequence by Name 6 | class Compare_Names 7 | { 8 | public: 9 | bool operator()(const Account& acc1, const Account& acc2) 10 | { 11 | const auto& name1 = acc1.get_name(); 12 | const auto& name2 = acc2.get_name(); 13 | return (name1.second < name2.second) || ((name1.second == name2.second) && (name1.first < name2.first)); 14 | } 15 | }; 16 | #endif -------------------------------------------------------------------------------- /Chapter 3/Ex3_05/Customer.h: -------------------------------------------------------------------------------- 1 | // Defines a customer by their time to checkout 2 | #ifndef CUSTOMER_H 3 | #define CUSTOMER_H 4 | 5 | class Customer 6 | { 7 | private: 8 | size_t service_t {}; // Time to checkout 9 | 10 | public: 11 | explicit Customer(size_t st = 10) :service_t {st}{} 12 | 13 | // Decrement time remaining to checkout 14 | Customer& time_decrement() 15 | { 16 | --service_t; 17 | return *this; 18 | } 19 | bool done() { return service_t == 0; } 20 | }; 21 | #endif -------------------------------------------------------------------------------- /Chapter 3/Ex3_02/Customer.h: -------------------------------------------------------------------------------- 1 | // Defines a customer by their time to checkout 2 | #ifndef CUSTOMER_H 3 | #define CUSTOMER_H 4 | 5 | class Customer 6 | { 7 | protected: 8 | size_t service_t {}; // Time to checkout 9 | public: 10 | explicit Customer(size_t st = 10) :service_t {st}{} 11 | 12 | // Decrement time remaining to checkout 13 | Customer& time_decrement() 14 | { 15 | if (service_t > 0) 16 | --service_t; 17 | return *this; 18 | } 19 | 20 | bool done() const { return service_t == 0; } 21 | }; 22 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apress Source Code 2 | 3 | This repository accompanies [*Using the C++ Standard Template Libraries*](http://www.apress.com/9781484200056) by Ivor Horton (Apress, 2015). 4 | 5 | ![Cover image](9781484200056.jpg) 6 | 7 | Download the files as a zip using the green button, or clone the repository to your machine using Git. 8 | 9 | ## Releases 10 | 11 | Release v1.0 corresponds to the code in the published book, without corrections or updates. 12 | 13 | ## Contributions 14 | 15 | See the file Contributing.md for more information on how you can contribute to this repository. 16 | -------------------------------------------------------------------------------- /Chapter 3/Ex3_06/Box.cpp: -------------------------------------------------------------------------------- 1 | // Box.cpp 2 | // Function members of the Box class 3 | #include 4 | #include "Box.h" 5 | 6 | // Read a Box object from a stream 7 | std::istream& Box::read(std::istream& in) 8 | { 9 | size_t value {}; 10 | if ((in >> value).eof()) 11 | return in; 12 | length = value; 13 | in >> width >> height; 14 | return in; 15 | } 16 | 17 | // Write a Box object to a stream 18 | std::ostream& Box::write(std::ostream& out) const 19 | { 20 | out << typeid(*this).name() << "(" << length << "," << width << "," << height << ")"; 21 | return out; 22 | } -------------------------------------------------------------------------------- /Chapter 1/Ex1_02.cpp: -------------------------------------------------------------------------------- 1 | // Ex1_02.cpp 2 | // Using stream iterators 3 | #include // For accumulate() - sums a range of elements 4 | #include // For standard streams 5 | #include // For istream_iterator 6 | 7 | int main() 8 | { 9 | std::cout << "Enter numeric values separated by spaces and enter Ctrl+Z to end:" << std::endl; 10 | 11 | std::cout << "\nThe sum of the values you entered is " 12 | << std::accumulate(std::istream_iterator(std::cin), 13 | std::istream_iterator(), 0.0) 14 | << std::endl; 15 | } 16 | -------------------------------------------------------------------------------- /contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to Apress Source Code 2 | 3 | Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers. 4 | 5 | ## How to Contribute 6 | 7 | 1. Make sure you have a GitHub account. 8 | 2. Fork the repository for the relevant book. 9 | 3. Create a new branch on which to make your change, e.g. 10 | `git checkout -b my_code_contribution` 11 | 4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted. 12 | 5. Submit a pull request. 13 | 14 | Thank you for your contribution! -------------------------------------------------------------------------------- /Chapter 1/Ex1_01.cpp: -------------------------------------------------------------------------------- 1 | // Ex1_01.cpp 2 | // Using iterators 3 | #include // For accumulate() - sums a range of elements 4 | #include // For standard streams 5 | #include // For iterators and begin() and end() 6 | 7 | int main() 8 | { 9 | double data[] {2.5, 4.5, 6.5, 5.5, 8.5}; 10 | std::cout << "The array contains:\n"; 11 | for (auto iter = std::begin(data); iter != std::end(data); ++iter) 12 | std::cout << *iter << " "; 13 | auto total = std::accumulate(std::begin(data), std::end(data), 0.0); 14 | std::cout << "\nThe sum of the array elements is " << total << std::endl; 15 | } -------------------------------------------------------------------------------- /Chapter 3/Ex3_06/Ex3_06.cpp: -------------------------------------------------------------------------------- 1 | // Ex3_06.cpp 2 | // Storing derived class objects in a container of base pointers 3 | #include // For standard streams 4 | #include // For smart pointers 5 | #include // For the vector container 6 | #include "Box.h" 7 | #include "Carton.h" 8 | using std::unique_ptr; 9 | using std::make_unique; 10 | 11 | int main() 12 | { 13 | std::vector> boxes; 14 | boxes.push_back(make_unique(1, 2, 3)); 15 | boxes.push_back(make_unique(1, 2, 3)); 16 | boxes.push_back(make_unique(4, 5, 6)); 17 | boxes.push_back(make_unique(4, 5, 6)); 18 | for(auto&& ptr : boxes) 19 | std::cout << *ptr << " volume is " << ptr->volume() << std::endl; 20 | } -------------------------------------------------------------------------------- /Chapter 2/Ex2_04.cpp: -------------------------------------------------------------------------------- 1 | // Ex2_04.cpp 2 | // Using a deque container 3 | #include // For standard streams 4 | #include // For copy() 5 | #include // For deque container 6 | #include // For string classes 7 | #include // For front_insert_iterator & stream iterators 8 | 9 | using std::string; 10 | 11 | int main() 12 | { 13 | std::deque names; 14 | std::cout << "Enter first names separated by spaces. Enter Ctrl+Z on a new line to end:\n"; 15 | std::copy(std::istream_iterator < string > {std::cin}, std::istream_iterator < string > {}, std::front_inserter(names)); 16 | std::cout << "\nIn reverse order, the names you entered are:\n"; 17 | std::copy(std::begin(names), std::end(names), std::ostream_iterator < string > {std::cout, " "}); 18 | std::cout << std::endl; 19 | } -------------------------------------------------------------------------------- /Chapter 6/Ex6_01/Name.h: -------------------------------------------------------------------------------- 1 | #ifndef NAME_H 2 | #define NAME_H 3 | #include // For string class 4 | 5 | class Name 6 | { 7 | private: 8 | std::string first {}; 9 | std::string second {}; 10 | 11 | public: 12 | Name(const std::string& name1, const std::string& name2) : first(name1), second(name2){} 13 | Name()=default; 14 | std::string get_first() const { return first; } 15 | std::string get_second() const { return second; } 16 | 17 | friend std::istream& operator>>(std::istream& in, Name& name); 18 | friend std::ostream& operator<<(std::ostream& out, const Name& name); 19 | }; 20 | 21 | // Stream input for Name objects 22 | inline std::istream& operator>>(std::istream& in, Name& name) 23 | { 24 | return in >> name.first >> name.second; 25 | } 26 | 27 | // Stream output for Name objects 28 | inline std::ostream& operator<<(std::ostream& out, const Name& name) 29 | { 30 | return out << name.first << " " << name.second; 31 | } 32 | #endif -------------------------------------------------------------------------------- /Chapter 4/Ex4_07/Hash_Function_Objects.h: -------------------------------------------------------------------------------- 1 | // Hash_Function_Objects.h 2 | // Hash function object types for Ex4_07 3 | #ifndef HASH_FUNCTION_OBJECTS_H 4 | #define HASH_FUNCTION_OBJECTS_H 5 | 6 | #include // For string class 7 | #include // For pair type 8 | #include // For tuple type 9 | 10 | using Name = std::pair < std::string, std::string >; 11 | using Phone = std::tuple < std::string, std::string, std::string >; 12 | 13 | // Hash a phone number 14 | class PhoneHash 15 | { 16 | public: 17 | size_t operator()(const Phone& phone) const 18 | { 19 | return std::hash()(std::get<0>(phone)+std::get<1>(phone)+std::get<2>(phone)); 20 | } 21 | }; 22 | 23 | // Hash a name 24 | class NameHash 25 | { 26 | public: 27 | size_t operator()(const Name& name) const 28 | { 29 | return std::hash()(name.first + name.second); 30 | } 31 | }; 32 | #endif -------------------------------------------------------------------------------- /Chapter 3/Ex3_02/Checkout.h: -------------------------------------------------------------------------------- 1 | // Supermarket checkout - maintains and processes customers in a queue 2 | #ifndef CHECKOUT_H 3 | #define CHECKOUT_H 4 | #include // For queue container 5 | #include "Customer.h" 6 | 7 | class Checkout 8 | { 9 | private: 10 | std::queue customers; // The queue waiting to checkout 11 | public: 12 | void add(const Customer& customer) { customers.push(customer); } 13 | size_t qlength() const { return customers.size(); } 14 | 15 | // Increment the time by one minute 16 | void time_increment() 17 | { 18 | if (!customers.empty()) 19 | { // There are customers waiting... 20 | if (customers.front().time_decrement().done()) // If the customer is done... 21 | customers.pop(); // ...remove from the queue 22 | } 23 | }; 24 | 25 | bool operator<(const Checkout& other) const { return qlength() < other.qlength(); } 26 | bool operator>(const Checkout& other) const { return qlength() > other.qlength(); } 27 | }; 28 | #endif -------------------------------------------------------------------------------- /Chapter 3/Ex3_05/Checkout.h: -------------------------------------------------------------------------------- 1 | // Supermarket checkout - using smart pointers to customers in a queue 2 | #ifndef CHECKOUT_H 3 | #define CHECKOUT_H 4 | #include // For queue container 5 | #include // For smart pointers 6 | #include "Customer.h" 7 | using PCustomer = std::unique_ptr; 8 | 9 | class Checkout 10 | { 11 | private: 12 | std::queue customers; // The queue waiting to checkout 13 | 14 | public: 15 | void add(PCustomer&& customer) { customers.push(std::move(customer)); } 16 | size_t qlength() const { return customers.size(); } 17 | 18 | // Increment the time by one minute 19 | void time_increment() 20 | { 21 | if (customers.front()->time_decrement().done()) // If the customer is done... 22 | customers.pop(); // ...remove from the queue 23 | }; 24 | 25 | bool operator<(const Checkout& other) const { return qlength() < other.qlength(); } 26 | bool operator>(const Checkout& other) const { return qlength() < other.qlength(); } 27 | }; 28 | #endif -------------------------------------------------------------------------------- /Chapter 5/Ex5_01/List_Course.h: -------------------------------------------------------------------------------- 1 | // List_Courses.h 2 | // Function object to output the students in a group for Ex5_01 3 | #ifndef LIST_COURSE_H 4 | #define LIST_COURSE_H 5 | #include // For standard streams 6 | #include // For string class 7 | #include // For set container 8 | #include // For copy() 9 | #include // For ostream_iterator 10 | #include "Student.h" 11 | 12 | using Subject = std::string; // A course subject 13 | using Group = std::set; // A student group for a subject 14 | using Course = std::pair; // A pair representing a course 15 | 16 | class List_Course 17 | { 18 | public: 19 | void operator()(const Course& course) 20 | { 21 | std::cout << "\n\n" << course.first << " " << course.second.size() << " students:\n "; 22 | std::copy(std::begin(course.second), std::end(course.second), std::ostream_iterator(std::cout, " ")); 23 | } 24 | }; 25 | #endif -------------------------------------------------------------------------------- /Chapter 5/Ex5_07/List_Course.h: -------------------------------------------------------------------------------- 1 | // List_Courses.h 2 | // Function object to output the students in a group for Ex5_01 3 | #ifndef LIST_COURSE_H 4 | #define LIST_COURSE_H 5 | #include // For standard streams 6 | #include // For string class 7 | #include // For set container 8 | #include // For copy() 9 | #include // For ostream_iterator 10 | #include "Student.h" 11 | 12 | using Subject = std::string; // A course subject 13 | using Group = std::set; // A student group for a subject 14 | using Course = std::pair; // A pair representing a course 15 | 16 | class List_Course 17 | { 18 | public: 19 | void operator()(const Course& course) 20 | { 21 | std::cout << "\n\n" << course.first << " " << course.second.size() << " students:\n "; 22 | std::copy(std::begin(course.second), std::end(course.second), std::ostream_iterator(std::cout, " ")); 23 | } 24 | }; 25 | #endif -------------------------------------------------------------------------------- /Chapter 3/Ex3_03.cpp: -------------------------------------------------------------------------------- 1 | // Ex3_03.cpp 2 | // Exercising a priority queue container adapter 3 | #include // For standard streams 4 | #include // For priority_queue 5 | #include // For string class 6 | using std::string; 7 | 8 | // List contents of a priority queue 9 | template 10 | void list_pq(std::priority_queue pq, size_t count = 5) 11 | { 12 | size_t n {count}; 13 | while (!pq.empty()) 14 | { 15 | std::cout << pq.top() << " "; 16 | pq.pop(); 17 | if (--n) continue; 18 | std::cout << std::endl; 19 | n = count; 20 | } 21 | std::cout << std::endl; 22 | } 23 | 24 | int main() 25 | { 26 | std::priority_queue words; 27 | std::string word; 28 | std::cout << "Enter words separated by spaces, enter Ctrl+Z on a separate line to end:\n"; 29 | while (true) 30 | { 31 | if ((std::cin >> word).eof()) 32 | break; 33 | words.push(word); 34 | } 35 | std::cout << "You entered " << words.size() << " words:" << std::endl; 36 | list_pq(words); 37 | } -------------------------------------------------------------------------------- /Chapter 9/Ex9_05.cpp: -------------------------------------------------------------------------------- 1 | // Ex9_05.cpp 2 | // Copying file contents using stream iterators 3 | #include // For standard streams 4 | #include // For file streams 5 | #include // For iterators and begin() and end() 6 | #include // For string class 7 | using std::string; 8 | 9 | int main() 10 | { 11 | string file_in {"G:/Beginning_STL/dictionary.txt"}; 12 | std::ifstream in {file_in}; 13 | if(!in) 14 | { 15 | std::cerr << file_in << " not open." << std::endl; 16 | exit(1); 17 | } 18 | string file_out {"G:/Beginning_STL/dictionary_copy.txt"}; 19 | std::ofstream out {file_out}; 20 | std::copy(std::istream_iterator{in}, std::istream_iterator{}, std::ostream_iterator {out, " "}); 21 | in.clear(); // Clear EOF 22 | std::cout << "Original file length: " << in.tellg() << std::endl; 23 | std::cout << "File copy length: " << out.tellp() << std::endl; 24 | in.close(); 25 | out.close(); 26 | } 27 | -------------------------------------------------------------------------------- /Chapter 6/Ex6_03.cpp: -------------------------------------------------------------------------------- 1 | // Ex6_03.cpp 2 | // Searching using search_n() to find freezing months 3 | #include // For standard streams 4 | #include // For vector container 5 | #include // For search_n() 6 | #include // For string class 7 | using std::string; 8 | 9 | int main() 10 | { 11 | std::vector temperatures {65, 75, 56, 48, 31, 28, 32, 29, 40, 41, 44, 50}; 12 | int max_temp {32}; 13 | int times {3}; 14 | auto iter = std::search_n(std::begin(temperatures), std::end(temperatures), times, max_temp, 15 | [](double v, double max){return v <= max; }); 16 | std::vector months {"January", "February", "March", "April", "May", "June", 17 | "July", "August", "September", "October", "November", "December"}; 18 | if(iter != std::end(temperatures)) 19 | std::cout << "It was " << max_temp << " degrees or below for " << times 20 | << " months starting in " << months[std::distance(std::begin(temperatures), iter)] 21 | << std::endl; 22 | } -------------------------------------------------------------------------------- /Chapter 7/Ex7_03.cpp: -------------------------------------------------------------------------------- 1 | // Ex7_03.cpp 2 | // Finding rearrangements of the letters in a word 3 | #include // For standard streams 4 | #include // For iterators and begin() and end() 5 | #include // For string class 6 | #include // For vector container 7 | #include // For next_permutation() 8 | using std::string; 9 | 10 | int main() 11 | { 12 | std::vector words; 13 | string word; 14 | while(true) 15 | { 16 | std::cout << "\nEnter a word, or Ctrl+z to end: "; 17 | if((std::cin >> word).eof()) break; 18 | string word_copy {word}; 19 | do 20 | { 21 | words.push_back(word); 22 | std::next_permutation(std::begin(word), std::end(word)); 23 | } while(word != word_copy); 24 | 25 | size_t count{}, max{8}; 26 | for(const auto& wrd : words) 27 | std::cout << wrd << ((++count % max == 0) ? '\n' : ' '); 28 | std::cout << std::endl; 29 | words.clear(); // Remove previous permutations 30 | } 31 | } -------------------------------------------------------------------------------- /Chapter 6/Ex6_01/Ex6_01.cpp: -------------------------------------------------------------------------------- 1 | // Ex6_01.cpp 2 | // Sorting class objects 3 | #include // For standard streams 4 | #include // For string class 5 | #include // For vector container 6 | #include // For stream and back insert iterators 7 | #include // For sort() algorithm 8 | #include "Name.h" 9 | 10 | 11 | int main() 12 | { 13 | std::vector names; 14 | std::cout << "Enter names as first name followed by second name. Enter Ctrl+Z to end:"; 15 | std::copy(std::istream_iterator(std::cin), std::istream_iterator(), 16 | std::back_insert_iterator>(names)); 17 | 18 | std::cout << names.size() << " names read. Sorting in ascending sequence...\n"; 19 | std::sort(std::begin(names), std::end(names), [](const Name& name1, const Name& name2) {return name1.get_second() < name2.get_second(); }); 20 | 21 | std::cout << "\nThe names in ascending sequence are:\n"; 22 | std::copy(std::begin(names), std::end(names), std::ostream_iterator(std::cout, "\n")); 23 | } 24 | -------------------------------------------------------------------------------- /Chapter 4/Ex4_01/Name.h: -------------------------------------------------------------------------------- 1 | // Name.h for Ex4_01 2 | // Defines a person's name 3 | #ifndef NAME_H 4 | #define NAME_H 5 | #include // For string class 6 | #include // For output streams 7 | #include // For input streams 8 | 9 | class Name 10 | { 11 | private: 12 | std::string first {}; 13 | std::string second {}; 14 | 15 | public: 16 | Name(const std::string& name1, const std::string& name2) : first (name1), second (name2) {} 17 | Name() = default; 18 | 19 | 20 | // Less-than operator 21 | bool operator<(const Name& name) const 22 | { 23 | return second < name.second || (second == name.second && first < name.first); 24 | } 25 | 26 | friend std::istream& operator>>(std::istream& in, Name& name); 27 | friend std::ostream& operator<<(std::ostream& out, const Name& name); 28 | }; 29 | 30 | // Extraction operator overload 31 | inline std::istream& operator>>(std::istream& in, Name& name) 32 | { 33 | in >> name.first >> name.second; 34 | return in; 35 | } 36 | 37 | // Insertion operator overload 38 | inline std::ostream& operator<<(std::ostream& out, const Name& name) 39 | { 40 | out << name.first + " " + name.second; 41 | return out; 42 | } 43 | 44 | #endif -------------------------------------------------------------------------------- /Chapter 4/Ex4_03/Name.h: -------------------------------------------------------------------------------- 1 | // Name.h for Ex4_03 2 | // Defines a person's name 3 | #ifndef NAME_H 4 | #define NAME_H 5 | #include // For string class 6 | #include // For output streams 7 | #include // For input streams 8 | 9 | class Name 10 | { 11 | private: 12 | std::string first {}; 13 | std::string second {}; 14 | 15 | public: 16 | Name(const std::string& name1, const std::string& name2) : first(name1), second(name2) {} 17 | Name() = default; 18 | 19 | 20 | // Less-than operator 21 | bool operator<(const Name& name) const 22 | { 23 | return second < name.second || (second == name.second && first < name.first); 24 | } 25 | 26 | friend std::istream& operator>>(std::istream& in, Name& name); 27 | friend std::ostream& operator<<(std::ostream& out, const Name& box); 28 | }; 29 | 30 | // Extraction operator overload 31 | inline std::istream& operator>>(std::istream& in, Name& name) 32 | { 33 | in >> name.first >> name.second; 34 | return in; 35 | } 36 | 37 | // Insertion operator overload 38 | inline std::ostream& operator<<(std::ostream& out, const Name& name) 39 | { 40 | out << name.first + " " + name.second; 41 | return out; 42 | } 43 | 44 | #endif -------------------------------------------------------------------------------- /Chapter 2/Ex2_07/Ex2_07.cpp: -------------------------------------------------------------------------------- 1 | // Ex2_07.cpp 2 | // Exercising the Numeric_Range template 3 | #include // For copy() 4 | #include // For accumulate() 5 | #include // For standard streams 6 | #include // For vector container 7 | #include "Numeric_Range.h" // For Numeric_Range & Numeric_Iterator 8 | 9 | int main() 10 | { 11 | Numeric_Range range {1.5, 0.5, 5}; 12 | auto first = range.begin(); 13 | auto last = range.end(); 14 | std::copy(first, last, std::ostream_iterator(std::cout, " ")); 15 | std::cout << "\nSum = " << std::accumulate(std::begin(range), std::end(range), 0.0) << std::endl; 16 | 17 | // Initializing a container from a Numeric_Range 18 | Numeric_Range numbers {15L, 4L, 10}; 19 | std::vector data {std::begin(numbers), std::end(numbers)}; 20 | std::cout << "\nValues in vector are:\n"; 21 | std::copy(std::begin(data), std::end(data), std::ostream_iterator(std::cout, " ")); 22 | std::cout << std::endl; 23 | 24 | // List the values in a range 25 | std::cout << "\nThe values in the numbers range are:\n"; 26 | for (auto n : numbers) 27 | std::cout << n << " "; 28 | std::cout << std::endl; 29 | } -------------------------------------------------------------------------------- /Chapter 5/Ex5_02/List_Course.h: -------------------------------------------------------------------------------- 1 | // List_Courses.h 2 | // Function object to output the students in a group for Ex5_02 3 | #ifndef LIST_COURSE_H 4 | #define LIST_COURSE_H 5 | #include // For standard streams 6 | #include // For string class 7 | #include // For set container 8 | #include // For copy() 9 | #include // For ostream_iterator 10 | #include "Student.h" 11 | 12 | using Subject = std::string; // A course subject 13 | using Group = std::set, std::owner_less>>; // A student group for a subject 14 | using Course = std::pair; // A pair representing a course 15 | 16 | class List_Course 17 | { 18 | public: 19 | void operator()(const Course& course) 20 | { 21 | std::cout << "\n\n" << course.first << " " << course.second.size() << " students:\n "; 22 | std::copy(std::begin(course.second), std::end(course.second), std::ostream_iterator>(std::cout, " ")); 23 | } 24 | }; 25 | 26 | inline std::ostream& operator<<(std::ostream& out, const std::weak_ptr& wss) 27 | { 28 | out << *wss.lock(); 29 | return out; 30 | } 31 | 32 | #endif -------------------------------------------------------------------------------- /Chapter 5/Ex5_03/List_Course.h: -------------------------------------------------------------------------------- 1 | // List_Courses.h 2 | // Function object to output the students in a group for Ex5_03 3 | #ifndef LIST_COURSE_H 4 | #define LIST_COURSE_H 5 | #include // For standard streams 6 | #include // For string class 7 | #include // For set container 8 | #include // For copy() 9 | #include // For ostream_iterator 10 | #include "Student.h" 11 | 12 | using Subject = std::shared_ptr; // A course subject 13 | using Group = std::set, std::owner_less>>; // A student group for a subject 14 | using Course = std::pair; // A pair representing a course 15 | 16 | class List_Course 17 | { 18 | public: 19 | void operator()(const Course& course) 20 | { 21 | std::cout << "\n\n" << *course.first << " " << course.second.size() << " students:\n "; 22 | std::copy(std::begin(course.second), std::end(course.second), std::ostream_iterator>(std::cout, " ")); 23 | } 24 | }; 25 | 26 | inline std::ostream& operator<<(std::ostream& out, const std::weak_ptr& wss) 27 | { 28 | out << *wss.lock(); 29 | return out; 30 | } 31 | 32 | #endif -------------------------------------------------------------------------------- /Chapter 5/Ex5_01/Student.h: -------------------------------------------------------------------------------- 1 | // Student.h 2 | // Student class definition for Ex5_01 3 | #ifndef STUDENT_H 4 | #define STUDENT_H 5 | #include // For string class 6 | #include // For output streams 7 | 8 | class Student 9 | { 10 | private: 11 | std::string first {}; 12 | std::string second {}; 13 | 14 | public: 15 | Student(const std::string& name1, const std::string& name2) : first (name1), second (name2){} 16 | Student(Student&& student) : first(std::move(student.first)), second(std::move(student.second)){} // Move constructor 17 | Student(const Student& student) : first(student.first), second(student.second){} // Copy constructor 18 | Student() {} // Default constructor 19 | 20 | // Less-than operator 21 | bool operator<(const Student& student) const 22 | { 23 | return second < student.second || (second == student.second && first < student.first); 24 | } 25 | 26 | friend std::ostream& operator<<(std::ostream& out, const Student& student); 27 | }; 28 | 29 | // Insertion operator overload 30 | inline std::ostream& operator<<(std::ostream& out, const Student& student) 31 | { 32 | out << student.first + " " + student.second; 33 | return out; 34 | } 35 | #endif -------------------------------------------------------------------------------- /Chapter 5/Ex5_07/Student.h: -------------------------------------------------------------------------------- 1 | // Student.h 2 | // Student class definition for Ex5_01 3 | #ifndef STUDENT_H 4 | #define STUDENT_H 5 | #include // For string class 6 | #include // For output streams 7 | 8 | class Student 9 | { 10 | private: 11 | std::string first {}; 12 | std::string second {}; 13 | 14 | public: 15 | Student(const std::string& name1, const std::string& name2) : first (name1), second (name2){} 16 | Student(Student&& student) : first(std::move(student.first)), second(std::move(student.second)){} // Move constructor 17 | Student(const Student& student) : first(student.first), second(student.second){} // Copy constructor 18 | Student() {} // Default constructor 19 | 20 | // Less-than operator 21 | bool operator<(const Student& student) const 22 | { 23 | return second < student.second || (second == student.second && first < student.first); 24 | } 25 | 26 | friend std::ostream& operator<<(std::ostream& out, const Student& student); 27 | }; 28 | 29 | // Insertion operator overload 30 | inline std::ostream& operator<<(std::ostream& out, const Student& student) 31 | { 32 | out << student.first + " " + student.second; 33 | return out; 34 | } 35 | #endif -------------------------------------------------------------------------------- /Chapter 4/Ex4_07/My_Templates.h: -------------------------------------------------------------------------------- 1 | // Templates for Ex4_07 2 | 3 | // List all elements 4 | template 5 | void list_elements(const Container& container) 6 | { 7 | for(const auto& element : container) 8 | std::cout << element.first << " " << element.second << std::endl; 9 | } 10 | 11 | // List range of elements 12 | template 13 | void list_range(const T& pr) 14 | { 15 | if(pr.first != pr.second) 16 | { 17 | for(auto iter = pr.first; iter != pr.second; ++iter) 18 | std::cout << " " << iter->first << " " << iter->second << std::endl; 19 | } 20 | else 21 | std::cout << "No records found.\n"; 22 | } 23 | 24 | // Find elements for a key entered from the keyboard - C++ 14 version 25 | /* 26 | template 27 | auto find_elements(const Container& container) 28 | { 29 | typename Container::key_type key {}; 30 | std::cin >> key; 31 | auto pr = container.equal_range(key); 32 | return pr; 33 | } 34 | */ 35 | 36 | // Find elements for a key entered from the keyboard - C++ 11 version 37 | template 38 | auto find_elements(const Container& container) -> std::pair 39 | { 40 | typename Container::key_type key {}; 41 | std::cin >> key; 42 | auto pr = container.equal_range(key); 43 | return pr; 44 | } -------------------------------------------------------------------------------- /Chapter 9/Ex9_01.cpp: -------------------------------------------------------------------------------- 1 | // Ex9_01.cpp 2 | // Calling istream_iterator function members 3 | #include // For standard streams 4 | #include // For stream iterators 5 | 6 | int main() 7 | { 8 | std::cout << "Enter some integers - enter Ctrl+Z to end.\n"; 9 | std::istream_iterator iter {std::cin}; // Create begin input stream iterator... 10 | std::istream_iterator copy_iter {iter}; // ...and a copy 11 | std::istream_iterator end_iter; // Create end input stream iterator 12 | 13 | // Read some integers to sum 14 | int sum {}; 15 | while(iter != end_iter) // Continue until Ctrl+Z read 16 | { 17 | sum += *iter++; 18 | } 19 | std::cout << "Total is " << sum << std::endl; 20 | 21 | std::cin.clear(); // Clear EOF state 22 | std::cin.ignore(); // Skip characters 23 | 24 | // Read integers using the copy of the iterator 25 | std::cout << "Enter some more integers - enter Ctrl+Z to end.\n"; 26 | int product {1}; 27 | while(true) 28 | { 29 | if(copy_iter == end_iter) break; // Break if Ctrl+Z was read 30 | product *= *copy_iter++; 31 | } 32 | std::cout << "product is " << product << std::endl; 33 | 34 | } -------------------------------------------------------------------------------- /Chapter 5/Ex5_02/Student.h: -------------------------------------------------------------------------------- 1 | // Student.h 2 | // Student class definition for Ex5_02 - unchanged from Ex5_01 3 | #ifndef STUDENT_H 4 | #define STUDENT_H 5 | #include // For string class 6 | #include // For output streams 7 | 8 | class Student 9 | { 10 | private: 11 | std::string first {}; 12 | std::string second {}; 13 | 14 | public: 15 | Student(const std::string& name1, const std::string& name2) : first (name1), second (name2){} 16 | Student(Student&& student) : first(std::move(student.first)), second(std::move(student.second)){} // Move constructor 17 | Student(const Student& student) : first(student.first), second(student.second){} // Copy constructor 18 | Student() {} // Default constructor 19 | 20 | // Less-than operator 21 | bool operator<(const Student& student) const 22 | { 23 | return second < student.second || (second == student.second && first < student.first); 24 | } 25 | 26 | friend std::ostream& operator<<(std::ostream& out, const Student& student); 27 | }; 28 | 29 | // Insertion operator overload 30 | inline std::ostream& operator<<(std::ostream& out, const Student& student) 31 | { 32 | out << student.first + " " + student.second; 33 | return out; 34 | } 35 | #endif -------------------------------------------------------------------------------- /Chapter 5/Ex5_03/Student.h: -------------------------------------------------------------------------------- 1 | // Student.h 2 | // Student class definition for Ex5_03 - unchanged from Ex5_01 3 | #ifndef STUDENT_H 4 | #define STUDENT_H 5 | #include // For string class 6 | #include // For output streams 7 | 8 | class Student 9 | { 10 | private: 11 | std::string first {}; 12 | std::string second {}; 13 | 14 | public: 15 | Student(const std::string& name1, const std::string& name2) : first (name1), second (name2){} 16 | Student(Student&& student) : first(std::move(student.first)), second(std::move(student.second)){} // Move constructor 17 | Student(const Student& student) : first(student.first), second(student.second){} // Copy constructor 18 | Student() {} // Default constructor 19 | 20 | // Less-than operator 21 | bool operator<(const Student& student) const 22 | { 23 | return second < student.second || (second == student.second && first < student.first); 24 | } 25 | 26 | friend std::ostream& operator<<(std::ostream& out, const Student& student); 27 | }; 28 | 29 | // Insertion operator overload 30 | inline std::ostream& operator<<(std::ostream& out, const Student& student) 31 | { 32 | out << student.first + " " + student.second; 33 | return out; 34 | } 35 | #endif -------------------------------------------------------------------------------- /Chapter 7/Ex7_04.cpp: -------------------------------------------------------------------------------- 1 | // Ex7_04.cpp 2 | // Testing for palindromes using reverse_copy() 3 | #include // For standard streams 4 | #include // For stream iterators and begin() and end() 5 | #include // For reverse_copy() and copy_if() 6 | #include // For toupper() and isalpha() 7 | #include 8 | using std::string; 9 | 10 | int main() 11 | { 12 | while(true) 13 | { 14 | string sentence; 15 | std::cout << "Enter a sentence or Ctrl+Z to end: "; 16 | std::getline(std::cin, sentence); 17 | if(std::cin.eof()) break; 18 | 19 | // Copy as long as the characters are alphabetic & convert to upper case 20 | string only_letters; 21 | std::copy_if(std::begin(sentence), std::end(sentence), std::back_inserter(only_letters), 22 | [](char ch) { return std::isalpha(ch); }); 23 | std::for_each(std::begin(only_letters), std::end(only_letters), [](char& ch) { ch = toupper(ch); }); 24 | 25 | // Make a reversed copy 26 | string reversed; 27 | std::reverse_copy(std::begin(only_letters), std::end(only_letters), std::back_inserter(reversed)); 28 | std::cout << '"' << sentence << '"' 29 | << (only_letters == reversed ? " is" : " is not") << " a palindrome." << std::endl; 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /Chapter 9/Ex9_06.cpp: -------------------------------------------------------------------------------- 1 | // Ex9_05.cpp 2 | // Using count_if() with stream iterators to count word frequencies 3 | #include // For standard streams 4 | #include // For iterators and begin() and end() 5 | #include // For stream manipulators 6 | #include // For ifstream 7 | #include // For count_if() 8 | #include 9 | using std::string; 10 | 11 | int main() 12 | { 13 | string file_in {"G:/Beginning_STL/dictionary.txt"}; 14 | std::ifstream in {file_in}; 15 | if(!in) 16 | { 17 | std::cerr << file_in << " not open." << std::endl; 18 | exit(1); 19 | } 20 | string letters {"abcdefghijklmnopqrstuvwxyz"}; 21 | size_t perline(9); 22 | for(auto ch : letters) 23 | { 24 | std::cout << ch << ": " 25 | << std::setw(5) 26 | << std::count_if(std::istream_iterator{in}, std::istream_iterator{}, 27 | [&ch](const string& s) 28 | { return s[0] == ch; }) 29 | << (((ch - 'a' + 1) % perline) ? " " : "\n"); 30 | in.clear(); // Clear EOF... 31 | in.seekg(0); // ... and back to the beginning 32 | } 33 | std::cout << std::endl; 34 | } -------------------------------------------------------------------------------- /Chapter 9/Ex9_09.cpp: -------------------------------------------------------------------------------- 1 | // Ex9_09.cpp 2 | // Copying a file using stream buffer iterators 3 | #include // For standard streams 4 | #include // For iterators and begin() and end() 5 | #include // For file streams 6 | #include // For string class 7 | using std::string; 8 | 9 | int main() 10 | { 11 | string file_name {"G:/Beginning_STL/dictionary.txt"}; 12 | std::ifstream file_in {file_name}; 13 | if(!file_in) 14 | { 15 | std::cerr << file_name << " not open." << std::endl; 16 | exit(1); 17 | } 18 | string file_copy {"G:/Beginning_STL/dictionary_copy.txt"}; 19 | std::ofstream file_out {file_copy, std::ios_base::out | std::ios_base::trunc}; 20 | 21 | std::istreambuf_iterator in {file_in}; // Input stream buffer iterator 22 | std::istreambuf_iterator end_in; // End of stream buffer iterator 23 | std::ostreambuf_iterator out {file_out}; // Output stream buffer iterator 24 | while(in != end_in) 25 | out = *in++; // Copy character from in to out 26 | 27 | std::cout << "File copy completed." << std::endl; 28 | 29 | file_in.close(); // Close the file 30 | file_out.close(); 31 | } -------------------------------------------------------------------------------- /Chapter 2/Ex2_05.cpp: -------------------------------------------------------------------------------- 1 | // Ex2_05.cpp 2 | // Working with a list 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using std::list; 9 | using std::string; 10 | 11 | // List a range of elements 12 | template 13 | void list_elements(Iter begin, Iter end) 14 | { 15 | while (begin != end) 16 | std::cout << *begin++ << std::endl; 17 | } 18 | 19 | int main() 20 | { 21 | std::list proverbs; 22 | 23 | // Read the proverbs 24 | std::cout << "Enter a few proverbs and enter an empty line to end:" << std::endl; 25 | string proverb; 26 | while (getline(std::cin, proverb, '\n'), !proverb.empty()) 27 | proverbs.push_front(proverb); 28 | 29 | std::cout << "Go on, just one more:" << std::endl; 30 | getline(std::cin, proverb, '\n'); 31 | proverbs.emplace_back(proverb); 32 | 33 | std::cout << "The elements in the list in reverse order are:" << std::endl; 34 | list_elements(std::rbegin(proverbs), std::rend(proverbs)); 35 | 36 | proverbs.sort(); // Sort the proverbs in ascending sequence 37 | std::cout << "\nYour proverbs in ascending sequence are:" << std::endl; 38 | list_elements(std::begin(proverbs), std::end(proverbs)); 39 | 40 | proverbs.sort(std::greater<>()); // Sort the proverbs in descending sequence 41 | std::cout << "\nYour proverbs in descending sequence:" << std::endl; 42 | list_elements(std::begin(proverbs), std::end(proverbs)); 43 | } 44 | -------------------------------------------------------------------------------- /Chapter 6/Ex6_04.cpp: -------------------------------------------------------------------------------- 1 | // Ex6_04.cpp 2 | // Using partition_copy() to find values above average and below average 3 | #include // For standard streams 4 | #include // For vector container 5 | #include // For partition_copy(), copy() 6 | #include // For accumulate() 7 | #include // For back_inserter, ostream_iterator 8 | 9 | int main() 10 | { 11 | std::vector temperatures {65, 75, 56, 48, 31, 28, 32, 29, 40, 41, 44, 50}; 12 | std::vector low_t; // Stores below average temperatures 13 | std::vector high_t; // Stores average or above temperatures 14 | 15 | auto average = std::accumulate(std::begin(temperatures), std::end(temperatures), 0.0) / temperatures.size(); 16 | std::partition_copy(std::begin(temperatures), std::end(temperatures), std::back_inserter(low_t), std::back_inserter(high_t), 17 | [average](double t) { return t < average; }); 18 | 19 | // Output below average temperatures 20 | std::copy(std::begin(low_t), std::end(low_t), std::ostream_iterator{std::cout, " "}); 21 | std::cout << std::endl; 22 | 23 | // Output average or above temperatures 24 | std::copy(std::begin(high_t), std::end(high_t), std::ostream_iterator{std::cout, " "}); 25 | std::cout << std::endl; 26 | } -------------------------------------------------------------------------------- /Chapter 4/Ex4_07/Record_IO.h: -------------------------------------------------------------------------------- 1 | #ifndef RECORD_IO_H 2 | #define RECORD_IO_H 3 | #include // For string class 4 | #include // For istream class 5 | #include // For ostream class 6 | #include // For pair type 7 | #include // For tuple type 8 | 9 | using Name = std::pair < std::string, std::string >; 10 | using Phone = std::tuple < std::string, std::string, std::string >; 11 | 12 | // Phone number output 13 | inline std::ostream& operator<<(std::ostream& out, const Phone& phone) 14 | { 15 | std::string area_code {}, exchange {}, number {}; 16 | std::tie(area_code, exchange, number) = phone; 17 | out << area_code << " " << exchange << " " << number; 18 | return out; 19 | } 20 | 21 | // Name output 22 | inline std::ostream& operator<<(std::ostream& out, const Name& name) 23 | { 24 | out << name.first << " " << name.second; 25 | return out; 26 | } 27 | 28 | // Phone number input 29 | inline std::istream& operator>>(std::istream& in, Phone& phone) 30 | { 31 | std::string area_code {}, exchange {}, number {}; 32 | in >> std::ws >> area_code >> exchange >> number; 33 | phone = std::make_tuple(area_code, exchange, number); 34 | return in; 35 | } 36 | 37 | // Name input 38 | inline std::istream& operator>>(std::istream& in, Name& name) 39 | { 40 | in >> std::ws >> name.first >> name.second; 41 | return in; 42 | } 43 | #endif -------------------------------------------------------------------------------- /Chapter 5/Ex5_05/Pet_Classes.h: -------------------------------------------------------------------------------- 1 | // Pet_Classes.h for Ex5_05 2 | // Classes that define pets 3 | #ifndef PET_CLASSES_H 4 | #define PET_CLASSES_H 5 | #include // For string class 6 | #include // For strcmp() 7 | using std::string; 8 | 9 | class Pet 10 | { 11 | protected: 12 | string name {}; 13 | 14 | public: 15 | virtual ~Pet(){} // Virtual destructor for base class 16 | const string& get_name() const { return name; } 17 | 18 | virtual bool operator<(const Pet& pet) const 19 | { 20 | auto result = std::strcmp(typeid(*this).name(), typeid(pet).name()); 21 | return (result < 0) || ((result == 0) && (name < pet.name)); 22 | } 23 | friend std::ostream& operator<<(std::ostream& out, const Pet& pet); 24 | }; 25 | 26 | class Cat : public Pet 27 | { 28 | public: 29 | Cat() = default; 30 | Cat(const string& cat_name) 31 | { 32 | name = cat_name; 33 | } 34 | }; 35 | 36 | class Dog : public Pet 37 | { 38 | public: 39 | Dog() = default; 40 | Dog(const string& dog_name) 41 | { 42 | name = dog_name; 43 | } 44 | }; 45 | 46 | class Mouse : public Pet 47 | { 48 | public: 49 | Mouse() = default; 50 | Mouse(const string& mouse_name) 51 | { 52 | name = mouse_name; 53 | } 54 | }; 55 | 56 | inline std::ostream& operator<<(std::ostream& out, const Pet& pet) 57 | { 58 | return out << "A " << 59 | string {typeid(pet).name()}.erase(0,6) << " called " << pet.name; 60 | } 61 | #endif -------------------------------------------------------------------------------- /Chapter 4/Ex4_05.cpp: -------------------------------------------------------------------------------- 1 | // Ex4_05.cpp 2 | // Using a multimap 3 | #include // For standard streams 4 | #include // For string class 5 | #include // For multimap container 6 | #include // For toupper() 7 | 8 | using std::string; 9 | using Pet_type = string; 10 | using Pet_name = string; 11 | 12 | int main() 13 | { 14 | std::multimap pets; 15 | Pet_type type {}; 16 | Pet_name name {}; 17 | char more {'Y'}; 18 | while(std::toupper(more) == 'Y') 19 | { 20 | std::cout << "Enter the type of your pet and its name: "; 21 | std::cin >> std::ws >> type >> name; 22 | 23 | // Add element - duplicates will be LIFO 24 | auto iter = pets.lower_bound(type); 25 | if(iter != std::end(pets)) 26 | pets.emplace_hint(iter, type, name); 27 | else 28 | pets.emplace(type, name); 29 | 30 | std::cout << "Do you want to enter another(Y or N)? "; 31 | std::cin >> more; 32 | } 33 | 34 | // Output all the pets 35 | std::cout << "\nPet list by type:\n"; 36 | auto iter = std::begin(pets); 37 | while(iter != std::end(pets)) 38 | { 39 | auto pr = pets.equal_range(iter->first); 40 | std::cout << "\nPets of type " << iter->first << " are:\n"; 41 | for(auto p = pr.first; p != pr.second; ++p) 42 | std::cout << " " << p->second; 43 | std::cout << std::endl; 44 | iter = pr.second; 45 | } 46 | } -------------------------------------------------------------------------------- /Chapter 9/Ex9_02.cpp: -------------------------------------------------------------------------------- 1 | // Ex9_02.cpp 2 | // Using output stream iterator function members 3 | #include // For standard streams 4 | #include // For iterators and begin() and end() 5 | #include // For vector container 6 | #include // For copy() algorithm 7 | #include 8 | using std::string; 9 | 10 | int main() 11 | { 12 | std::vector words {"The", "quick", "brown", "fox", "jumped", "over", "the", "lazy", "dog"}; 13 | 14 | // Write the words container using conventional iterator notation 15 | std::ostream_iterator out_iter1 {std::cout}; // Iterator with no delimiter output 16 | for(const auto& word : words) 17 | { 18 | *out_iter1++ = word; // Write a word 19 | *out_iter1++ = " "; // Write a delimiter 20 | } 21 | *out_iter1++ = "\n"; // Write newline 22 | 23 | // Write the words container again using the iterator 24 | for(const auto& word : words) 25 | { 26 | (out_iter1 = word) = " "; // Write the word and delimiter 27 | } 28 | out_iter1 = "\n"; // Write newline 29 | 30 | // Write the words container using copy() 31 | std::ostream_iterator out_iter2 {std::cout, " "}; 32 | std::copy(std::begin(words), std::end(words), out_iter2); 33 | out_iter2 = "\n"; 34 | } -------------------------------------------------------------------------------- /Chapter 2/Ex2_06/Box.h: -------------------------------------------------------------------------------- 1 | // Box.h 2 | // Defines the Box class for Ex2_06 3 | #ifndef BOX_H 4 | #define BOX_H 5 | #include // For standard streams 6 | #include // For comparison operator templates 7 | using namespace std::rel_ops; // Comparison operator template namespace 8 | 9 | class Box 10 | { 11 | private: 12 | size_t length {}; 13 | size_t width {}; 14 | size_t height {}; 15 | 16 | public: 17 | explicit Box(size_t l = 1, size_t w = 1, size_t h = 1) : length {l}, width {w}, height {h} {} 18 | double volume() const { return length*width*height; } 19 | bool operator<(const Box& box) { return volume() < box.volume(); } 20 | bool operator==(const Box& box) { return length == box.length&& width == box.width&&height == box.height; } 21 | 22 | friend std::istream& operator>>(std::istream& in, Box& box); 23 | friend std::ostream& operator<<(std::ostream& out, const Box& box); 24 | }; 25 | 26 | inline std::istream& operator>>(std::istream& in, Box& box) 27 | { 28 | std::cout << "Enter box length, width, & height separated by spaces - Ctrl+Z to end: "; 29 | size_t value; 30 | in >> value; 31 | if (in.eof()) return in; 32 | 33 | box.length = value; 34 | in >> value; 35 | box.width = value; 36 | in >> value; 37 | box.height = value; 38 | return in; 39 | } 40 | 41 | inline std::ostream& operator<<(std::ostream& out, const Box& box) 42 | { 43 | out << "Box(" << box.length << "," << box.width << "," << box.height << ") "; 44 | return out; 45 | } 46 | #endif -------------------------------------------------------------------------------- /Chapter 1/Ex1_03.cpp: -------------------------------------------------------------------------------- 1 | // Ex1_03.cpp 2 | // Passing functions to an algorithm 3 | #include // For standard streams 4 | #include // For transform() 5 | #include // For iterators 6 | #include // For function 7 | 8 | class Root 9 | { 10 | public: 11 | double operator()(double x) { return std::sqrt(x); }; 12 | }; 13 | 14 | int main() 15 | { 16 | double data[] { 1.5, 2.5, 3.5, 4.5, 5.5}; 17 | 18 | // Passing a function object 19 | Root root; // Function object 20 | std::cout << "Square roots are:" << std::endl; 21 | std::transform(std::begin(data), std::end(data), std::ostream_iterator(std::cout, " "), root); 22 | 23 | // Using an lambda expression as an argument 24 | std::cout << "\n\nCubes are:" << std::endl; 25 | std::transform(std::begin(data), std::end(data), std::ostream_iterator(std::cout, " "), [](double x){return x*x*x; }); 26 | 27 | // Using a variable of type std::function<> as argument 28 | std::function op {[](double x){ return x*x*x; }}; 29 | std::cout << "\n\nSquares are:" << std::endl; 30 | std::transform(std::begin(data), std::end(data), std::ostream_iterator(std::cout, " "), op); 31 | 32 | // Using a lambda expression that calls another lambda expression as argument 33 | std::cout << "\n\n4th powers are:" << std::endl; 34 | std::transform(std::begin(data), std::end(data), std::ostream_iterator(std::cout, " "), [&op](double x){return op(x)*op(x); }); 35 | std::cout << std::endl; 36 | } -------------------------------------------------------------------------------- /Chapter 8/Ex8_07/Die.h: -------------------------------------------------------------------------------- 1 | #ifndef DIE_H 2 | #define DIE_H 3 | #include // For discrete_distribution and random number generator 4 | #include // For vector container 5 | #include // For remove() 6 | #include // For iterators and begin() and end() 7 | 8 | // Alias for param_type for discrete distribution 9 | using Params = std::discrete_distribution::param_type; 10 | 11 | std::default_random_engine& rng(); 12 | 13 | // Class to represent a die with six faces with arbitrary values 14 | // Face values do not need to be unique. 15 | class Die 16 | { 17 | public: 18 | Die() { values.push_back(0); }; 19 | 20 | // Constructor 21 | Die(std::initializer_list init) 22 | { 23 | std::vector faces {init}; // Stores die face values 24 | auto iter = std::begin(faces); 25 | auto end_iter = std::end(faces); 26 | std::vector wts; // Stores weights for face values 27 | while(iter != end_iter) 28 | { 29 | values.push_back(*iter); 30 | wts.push_back(std::count(iter, end_iter, *iter)); 31 | end_iter = std::remove(iter, end_iter, *iter++); 32 | } 33 | dist.param(Params {std::begin(wts), std::end(wts)}); 34 | } 35 | 36 | size_t throw_it() { return values[dist(rng())]; } 37 | 38 | private: 39 | std::discrete_distribution dist; // Probability distributtion for values 40 | std::vector values; // Face values 41 | }; 42 | #endif -------------------------------------------------------------------------------- /Chapter 10/Ex10_04.cpp: -------------------------------------------------------------------------------- 1 | // Ex10_04.cpp 2 | // Arithmetic with time-point objects 3 | #include // For standard streams 4 | #include // For stream manipulators 5 | #include // For duration, time_point templates 6 | #include // For ratio templates 7 | using namespace std::chrono; 8 | 9 | // Outputs the exact interval in seconds for a time_point<> 10 | template 11 | void print_timepoint(const TimePoint& tp, size_t places = 0) 12 | { 13 | auto elapsed = tp.time_since_epoch(); // duration object for the interval 14 | 15 | auto seconds = duration_cast>(elapsed).count(); 16 | std::cout << std::fixed << std::setprecision(places) << seconds << " seconds\n"; 17 | } 18 | 19 | int main() 20 | { 21 | using TimePoint = time_point; 22 | time_point tp1 {duration(20)}; 23 | time_point tp2 {3min}; 24 | time_point tp3 {2h}; 25 | std::cout << "tp1 is "; 26 | print_timepoint(tp1); 27 | 28 | std::cout << "tp2 is "; 29 | print_timepoint(tp2); 30 | 31 | std::cout << "tp3 is "; 32 | print_timepoint(tp3); 33 | 34 | auto tp4 = tp2 + tp3.time_since_epoch(); 35 | std::cout << "tp4 is tp2 with tp3 added: "; 36 | print_timepoint(tp4); 37 | 38 | std::cout << "tp1 + tp2 is "; 39 | print_timepoint(tp1 + tp2.time_since_epoch()); 40 | 41 | tp2 += duration::rep, std::milli> {20'000}; 42 | std::cout << "tp2 incremented by 20,000 milliseconds is "; 43 | print_timepoint(tp2); 44 | } -------------------------------------------------------------------------------- /Chapter 5/Ex5_06/Name.h: -------------------------------------------------------------------------------- 1 | // Name.h for Ex5_06 2 | // Defines a person's name 3 | #ifndef NAME_H 4 | #define NAME_H 5 | #include // For string class 6 | #include // For output streams 7 | #include // For input streams 8 | using std::string; 9 | 10 | class Name 11 | { 12 | private: 13 | string first {}; 14 | string second {}; 15 | 16 | public: 17 | Name(const string& name1, const string& name2) : first (name1), second (name2) {} 18 | Name() = default; 19 | 20 | const string& get_first() const { return first; } 21 | const string& get_second() const { return second; } 22 | 23 | size_t get_length() const { return first.length() + second.length() + 1; } 24 | 25 | // Less-than operator 26 | bool operator<(const Name& name) const 27 | { 28 | return second < name.second || (second == name.second && first < name.first); 29 | } 30 | 31 | // Equality operator 32 | bool operator==(const Name& name) const 33 | { 34 | return (second == name.second) && (first == name.first); 35 | } 36 | 37 | size_t hash() const { return std::hash()(first+second); } 38 | 39 | friend std::istream& operator>>(std::istream& in, Name& name); 40 | friend std::ostream& operator<<(std::ostream& out, const Name& name); 41 | }; 42 | 43 | // Extraction operator overload 44 | inline std::istream& operator>>(std::istream& in, Name& name) 45 | { 46 | in >> name.first >> name.second; 47 | return in; 48 | } 49 | 50 | // Insertion operator overload 51 | inline std::ostream& operator<<(std::ostream& out, const Name& name) 52 | { 53 | out << name.first + " " + name.second; 54 | return out; 55 | } 56 | #endif -------------------------------------------------------------------------------- /Chapter 3/Ex3_06/Box.h: -------------------------------------------------------------------------------- 1 | // Box.h 2 | // Defines the Box class that will be a base for the Carton class 3 | #ifndef BOX_H 4 | #define BOX_H 5 | #include // For standard streams 6 | #include // For stream classes 7 | #include // For comparison operator templates 8 | using namespace std::rel_ops; // Comparison operator template namespace 9 | 10 | class Box 11 | { 12 | protected: 13 | size_t length {}; 14 | size_t width {}; 15 | size_t height {}; 16 | 17 | public: 18 | explicit Box(size_t l = 1, size_t w = 1, size_t h = 1) : length {l}, width {w}, height {h} {} 19 | virtual ~Box() = default; 20 | 21 | virtual double volume() const; // Volume of a box 22 | 23 | // Comparison operators for Box object 24 | bool operator<(const Box& box) const; 25 | bool operator==(const Box& box) const; 26 | 27 | // Stream input and output 28 | virtual std::istream& read(std::istream& in); 29 | virtual std::ostream& write(std::ostream& out) const; 30 | }; 31 | 32 | 33 | inline double Box::volume() const { return length*width*height; } 34 | 35 | // Less-than operator 36 | inline bool Box::operator<(const Box& box) const 37 | { return volume() < box.volume(); } 38 | 39 | //Equality comparion operator 40 | inline bool Box::operator==(const Box& box) const 41 | { 42 | return length == box.length && width == box.width && height == box.height; 43 | } 44 | 45 | // Stream extraction operator 46 | inline std::istream& operator>>(std::istream& in, Box& box) 47 | { 48 | return box.read(in); 49 | } 50 | 51 | // Stream insertion operator 52 | inline std::ostream& operator<<(std::ostream& out, Box& box) 53 | { 54 | return box.write(out); 55 | } 56 | #endif -------------------------------------------------------------------------------- /Chapter 8/Ex8_02.cpp: -------------------------------------------------------------------------------- 1 | // Ex8_02.cpp 2 | // Values generated by seed_seq objects 3 | #include // For seed_seq, random_device 4 | #include // For standard streams 5 | #include // For iterators 6 | #include // For string class 7 | using std::string; 8 | 9 | // Generates and list integers from a seed_seq object 10 | void gen_and_list(const std::seed_seq& ss, const string title = "Values:", size_t count = 8) 11 | { 12 | std::vector values(count); 13 | ss.generate(std::begin(values), std::end(values)); 14 | std::cout << title << std::endl; 15 | std::copy(std::begin(values), std::end(values), std::ostream_iterator{std::cout, " "}); 16 | std::cout << std::endl; 17 | } 18 | 19 | int main() 20 | { 21 | std::random_device rd {}; // Non-deterministic source - we hope! 22 | std::seed_seq seeds1; // Default constructor 23 | std::seed_seq seeds2 {3, 4, 5}; // From consecutive integers 24 | std::seed_seq seeds3 {rd(), rd()}; 25 | 26 | std::vector data {25, 36, 47, 58}; 27 | std::seed_seq seeds4(std::begin(data), std::end(data)); // From a range 28 | gen_and_list(seeds1, "seeds1"); 29 | gen_and_list(seeds1, "seeds1 again"); 30 | gen_and_list(seeds1, "seeds1 again", 12); 31 | gen_and_list(seeds2, "seeds2"); 32 | gen_and_list(seeds3, "seeds3"); 33 | gen_and_list(seeds3, "seeds3 again"); 34 | gen_and_list(seeds4, "seeds4"); 35 | gen_and_list(seeds4, "seeds4 again"); 36 | gen_and_list(seeds4, "seeds4 yet again", 12); 37 | gen_and_list(seeds4, "seeds4 for the last time", 6); 38 | } -------------------------------------------------------------------------------- /Chapter 9/Ex9_07.cpp: -------------------------------------------------------------------------------- 1 | // Ex9_07.cpp 2 | // Using stream iterators to write Fibonacci numbers to a file 3 | #include // For standard streams 4 | #include // For iterators and begin() and end() 5 | #include // For stream manipulators 6 | #include // For fstream 7 | #include // For generate_n() and for_each() 8 | #include 9 | using std::string; 10 | 11 | int main() 12 | { 13 | string file_name {"G:/Beginning_STL/fibonacci.txt"}; 14 | std::fstream fibonacci {file_name, std::ios_base::in | std::ios_base::out | std::ios_base::trunc}; 15 | if(!fibonacci) 16 | { 17 | std::cerr << file_name << " not open." << std::endl; 18 | exit(1); 19 | } 20 | unsigned long long first {0ULL}, second {1ULL}; 21 | auto iter = std::ostream_iterator {fibonacci, " "}; 22 | (iter = first) = second; // Write the first two values 23 | 24 | const size_t n {50}; 25 | std::generate_n(iter, n, [&first, &second] 26 | { auto result = first + second; 27 | first = second; 28 | second = result; 29 | return result; }); 30 | fibonacci.seekg(0); // Back to file beginning 31 | std::for_each(std::istream_iterator {fibonacci}, 32 | std::istream_iterator {}, 33 | [](unsigned long long k) 34 | { const size_t perline {6}; 35 | static size_t count {}; 36 | std::cout << std::setw(12) << k << ((++count % perline) ? " " : "\n"); 37 | }); 38 | std::cout << std::endl; 39 | fibonacci.close(); // Close the file 40 | } -------------------------------------------------------------------------------- /Chapter 9/Ex9_03.cpp: -------------------------------------------------------------------------------- 1 | // Ex9_03.cpp 2 | // Finding anagrams of a word 3 | #include // For standard streams 4 | #include // For file streams 5 | #include // For iterators and begin() and end() 6 | #include // For string class 7 | #include // For set container 8 | #include // For vector container 9 | #include // For next_permutation() 10 | using std::string; 11 | 12 | int main() 13 | { 14 | // Read words from the file into a set container 15 | string file_in {"G:/Beginning_STL/dictionary.txt"}; 16 | std::ifstream in {file_in}; 17 | if(!in) 18 | { 19 | std::cerr << file_in << " not open." << std::endl; 20 | exit(1); 21 | } 22 | std::set dictionary {std::istream_iterator(in), std::istream_iterator()}; 23 | std::cout << dictionary.size() << " words in dictionary." << std::endl; 24 | 25 | std::vector words; 26 | string word; 27 | while(true) 28 | { 29 | std::cout << "\nEnter a word, or Ctrl+z to end: "; 30 | if((std::cin >> word).eof()) break; 31 | string word_copy {word}; 32 | do 33 | { 34 | if(dictionary.count(word)) words.push_back(word); 35 | std::next_permutation(std::begin(word), std::end(word)); 36 | } while(word != word_copy); 37 | 38 | std::copy(std::begin(words), std::end(words), std::ostream_iterator{std::cout, " "}); 39 | std::cout << std::endl; 40 | words.clear(); // Remove previous permutations 41 | } 42 | in.close(); // Close the file 43 | } 44 | -------------------------------------------------------------------------------- /Chapter 6/Ex6_05.cpp: -------------------------------------------------------------------------------- 1 | // Ex 6_05.cpp 2 | // Using partition() and equal_range() to find duplicates of a value in a range 3 | #include // For standard streams 4 | #include // For list container 5 | #include // For copy(), partition() 6 | #include // For ostream_iterator 7 | 8 | int main() 9 | { 10 | std::list values {17, 11, 40, 13, 22, 54, 48, 70, 22, 61, 82, 78, 22, 89, 99, 92, 43}; 11 | 12 | // Output the elements in their original order 13 | std::cout << "The elements in the original sequence are:\n"; 14 | std::copy(std::begin(values), std::end(values), std::ostream_iterator {std::cout, " "}); 15 | std::cout << std::endl; 16 | 17 | int wanted {22}; // What we are looking for 18 | 19 | std::partition(std::begin(values), std::end(values), // Partition the values with (value < wanted) 20 | [wanted](double value) { return value < wanted; }); 21 | std::partition(std::begin(values), std::end(values), // Partition the values with !(wanted < value) 22 | [wanted](double value) { return !(wanted < value); }); 23 | 24 | // Output the elements after partitioning 25 | std::cout << "The elements after partitioning are:\n"; 26 | std::copy(std::begin(values), std::end(values), std::ostream_iterator {std::cout, " "}); 27 | std::cout << std::endl; 28 | 29 | auto pr = std::equal_range(std::begin(values), std::end(values), wanted); 30 | std::cout << "The lower bound for " << wanted << " is " << *pr.first << std::endl; 31 | std::cout << "The upper bound for " << wanted << " is " << *pr.second << std::endl; 32 | 33 | std::cout << "\nThe elements found by equal_range() are:\n"; 34 | std::copy(pr.first, pr.second, std::ostream_iterator {std::cout, " "}); 35 | std::cout << std::endl; 36 | 37 | } -------------------------------------------------------------------------------- /Chapter 4/Ex4_02.cpp: -------------------------------------------------------------------------------- 1 | // Ex4_02.cpp 2 | // Determining word frequency 3 | #include // For standard streams 4 | #include // For stream manipulators 5 | #include // For string class 6 | #include // For istringstream 7 | #include // For replace_if() & for_each() 8 | #include // For map container 9 | #include // For isalpha() 10 | 11 | using std::string; 12 | 13 | int main() 14 | { 15 | std::cout << "Enter some text and enter * to end:\n"; 16 | string text_in {}; 17 | std::getline(std::cin, text_in, '*'); 18 | 19 | // Replace non-alphabetic characters by a space 20 | std::replace_if(std::begin(text_in), std::end(text_in), [](const char& ch){ return !isalpha(ch); }, ' '); 21 | 22 | std::istringstream text(text_in); // Text input string as a stream 23 | std::istream_iterator begin(text); // Stream iterator 24 | std::istream_iterator end; // End stream iterator 25 | 26 | std::map words; // Map to store words & word counts 27 | size_t max_len {}; // Maximum word length 28 | 29 | // Get the words, store in the map, and find maximum length 30 | std::for_each(begin, end, [&max_len, &words](const string& word) 31 | { words[word]++; 32 | max_len = std::max(max_len, word.length()); 33 | }); 34 | 35 | size_t per_line {4}, count {}; 36 | for(const auto& w : words) 37 | { 38 | std::cout << std::left << std::setw(max_len + 1) << w.first 39 | << std::setw(3) << std::right << w.second << " "; 40 | 41 | if(++count % per_line == 0) std::cout << std::endl; 42 | } 43 | std::cout << std::endl; 44 | } 45 | -------------------------------------------------------------------------------- /Chapter 2/Ex2_03.cpp: -------------------------------------------------------------------------------- 1 | // Ex2_03.cpp 2 | // Understanding how capacity is increased in a vector container 3 | #include // For standard streams 4 | #include // For vector container 5 | 6 | int main() 7 | { 8 | std::vector sizes; // Record numbers of elements 9 | std::vector capacities; // and corresponding capacities 10 | size_t el_incr {10}; // Increment to initial element count 11 | size_t incr_count {4 * el_incr}; // Number of increments to element count 12 | 13 | for (size_t n_elements {}; n_elements < incr_count; n_elements += el_incr) 14 | { 15 | std::vector values(n_elements); 16 | std::cout << "\nAppending to a vector with " << n_elements << " initial elements:\n"; 17 | sizes.push_back(values.size()); 18 | size_t space {values.capacity()}; 19 | capacities.push_back(space); 20 | 21 | // Append elements to obtain capacity increases 22 | size_t count {}; // Counts capacity increases 23 | size_t n_increases {10}; 24 | while (count < n_increases) 25 | { 26 | values.push_back(22); // Append a new element 27 | if (space < values.capacity()) // Capacity increased... 28 | { // ...so record size and capacity 29 | space = values.capacity(); 30 | capacities.push_back(space); 31 | sizes.push_back(values.size()); 32 | ++count; 33 | } 34 | } 35 | // Show sizes & capacities when increments occur 36 | std::cout << "Size/Capacity: "; 37 | for (size_t i {}; i < sizes.size(); ++i) 38 | std::cout << sizes.at(i) << "/" << capacities.at(i) << " "; 39 | std::cout << std::endl; 40 | sizes.clear(); // Remove all elements 41 | capacities.clear(); // Remove all elements 42 | } 43 | } -------------------------------------------------------------------------------- /Chapter 9/Ex9_04.cpp: -------------------------------------------------------------------------------- 1 | // Ex9_04.cpp 2 | // Finding anagrams of a word by re-reading the dictionary file 3 | #include // For standard streams 4 | #include // For file streams 5 | #include // For iterators and begin() and end() 6 | #include // For string class 7 | #include // For set container 8 | #include // For vector container 9 | #include // For next_permutation() 10 | using std::string; 11 | 12 | int main() 13 | { 14 | string file_in {"G:/Beginning_STL/dictionary.txt"}; 15 | std::ifstream in {file_in}; 16 | if(!in) 17 | { 18 | std::cerr << file_in << " not open." << std::endl; 19 | exit(1); 20 | } 21 | auto end_iter = std::istream_iterator {}; 22 | 23 | std::vector words; 24 | string word; 25 | while(true) 26 | { 27 | std::cout << "\nEnter a word, or Ctrl+z to end: "; 28 | if((std::cin >> word).eof()) break; 29 | string word_copy {word}; 30 | do 31 | { 32 | in.seekg(0); // File position at beginning 33 | 34 | // Use find() algorithm to read the file to check for an anagram 35 | if(std::find(std::istream_iterator(in), end_iter, word) != end_iter) 36 | words.push_back(word); 37 | else 38 | in.clear(); // Reset EOF 39 | 40 | std::next_permutation(std::begin(word), std::end(word)); 41 | } while(word != word_copy); 42 | 43 | std::copy(std::begin(words), std::end(words), std::ostream_iterator{std::cout, " "}); 44 | std::cout << std::endl; 45 | words.clear(); // Remove previous permutations 46 | } 47 | in.close(); // Close the file 48 | } 49 | -------------------------------------------------------------------------------- /Chapter 6/Ex6_02/Transaction.h: -------------------------------------------------------------------------------- 1 | #ifndef TRANSACTION_H 2 | #define TRANSACTION_H 3 | #include // For stream class 4 | #include // For stream manipulators 5 | #include "Account.h" 6 | 7 | class Transaction 8 | { 9 | private: 10 | size_t account_number {}; // The account number 11 | double amount {}; // The amount 12 | bool credit {true}; // credit = true debit=false 13 | 14 | public: 15 | Transaction()=default; 16 | Transaction(size_t number, double amnt, bool cr) : account_number {number}, amount {amnt}, credit {cr}{} 17 | 18 | size_t get_acc_number() const { return account_number; } 19 | 20 | // Less-than operator - compares account numbers 21 | bool operator<(const Transaction& transaction) const { return account_number < transaction.account_number; } 22 | 23 | // Greater-than operator - compares account numbers 24 | bool operator>(const Transaction& transaction) const { return account_number > transaction.account_number; } 25 | 26 | friend std::ostream& operator<<(std::ostream& out, const Transaction& transaction); 27 | friend std::istream& operator>>(std::istream& in, Transaction& transaction); 28 | 29 | // Making the Account class a friend allows Account objects 30 | // to access private members of Transaction objects 31 | friend class Account; 32 | 33 | }; 34 | // Stream insertion operator for Transaction objects 35 | std::ostream& operator<<(std::ostream& out, const Transaction& transaction) 36 | { 37 | return out << std::right << std::setfill('0') << std::setw(5) << transaction.account_number 38 | << std::setfill(' ') << std::setw(8) << std::fixed << std::setprecision(2) << transaction.amount 39 | << (transaction.credit ? " CR" : " DR"); 40 | } 41 | 42 | // Stream extraction operator for Transaction objects 43 | std::istream& operator>>(std::istream& in, Transaction& tr) 44 | { 45 | if((in >> std::skipws >> tr.account_number).eof()) 46 | return in; 47 | return in >> tr.amount >> std::boolalpha >> tr.credit; 48 | } 49 | 50 | #endif -------------------------------------------------------------------------------- /Chapter 4/Ex4_03/Quotations.h: -------------------------------------------------------------------------------- 1 | #ifndef QUOTATIONS_H 2 | #define QUOTATIONS_H 3 | #include // For vector container 4 | #include // For string class 5 | #include // For out_of_range exception 6 | 7 | class Quotations 8 | { 9 | private: 10 | std::vector quotes; // Container for the quotations 11 | 12 | public: 13 | // Stores a new quotation that is created from a string literal 14 | Quotations& operator<<(const char* quote) 15 | { 16 | quotes.emplace_back(quote); 17 | return *this; 18 | } 19 | 20 | // Copies a new quotation in the vector from a string object 21 | Quotations& operator<<(const std::string& quote) 22 | { 23 | quotes.push_back(quote); 24 | return *this; 25 | } 26 | 27 | // Moves a quotation into the vector 28 | Quotations& operator<<(std::string&& quote) 29 | { 30 | quotes.push_back(std::move(quote)); 31 | return *this; 32 | } 33 | 34 | // Returns a quotation for an index 35 | std::string& operator[](size_t index) 36 | { 37 | if(index < quotes.size()) 38 | return quotes[index]; 39 | else 40 | throw std::out_of_range {"Invalid index to quotations."}; 41 | } 42 | 43 | size_t size() const { return quotes.size(); } // Returns the number of quotations 44 | 45 | // Returns the begin iterator for the quotations 46 | std::vector::iterator begin() 47 | { 48 | return std::begin(quotes); 49 | } 50 | 51 | // Returns the const begin iterator for the quotations 52 | std::vector::const_iterator begin() const 53 | { 54 | return std::begin(quotes); 55 | } 56 | 57 | // Returns the end iterator for the quotations 58 | std::vector::iterator end() 59 | { 60 | return std::end(quotes); 61 | } 62 | 63 | // Returns the const end iterator for the quotations 64 | std::vector::const_iterator end() const 65 | { 66 | return std::end(quotes); 67 | } 68 | }; 69 | #endif -------------------------------------------------------------------------------- /Chapter 8/Ex8_04.cpp: -------------------------------------------------------------------------------- 1 | // Ex8_04.cpp 2 | // Finding pi by throwing a stick 3 | #include // For standard streams 4 | #include // For distributions, random number gen 5 | #include // For sin() function 6 | 7 | int main() 8 | { 9 | const double pi = 3.1415962; 10 | double stick_length {}; // Stick length 11 | double board_width {}; // Board width 12 | 13 | std::cout << "Enter the width of a floorboard: "; 14 | std::cin >> board_width; 15 | std::cout << "Enter the length of the stick (must be less than " << board_width << "): "; 16 | std::cin >> stick_length; 17 | if(board_width < stick_length) stick_length = 0.9*board_width; 18 | 19 | std::uniform_real_distribution<> angle {0.0, pi}; // Distribution for angle of stick 20 | std::uniform_real_distribution<> position {0.0, board_width}; // Distribution for stick center position, relative to board edge 21 | std::random_device rd; // Non-deterministic seed source 22 | std::default_random_engine rng {rd()}; // Create random number generator 23 | const size_t throws {5'000'000}; // Number of random throws 24 | size_t hits {}; // Count of stick intersecting the board 25 | 26 | // Throw the stick down throws times 27 | for(size_t i {}; i < throws; ++i) 28 | { 29 | double y {position(rng)}; 30 | double theta {angle(rng)}; 31 | // Check if the stick crosses the edge of a board 32 | if(((y + stick_length*sin(theta) / 2) >= board_width) || ((y - stick_length*sin(theta) / 2) <= 0)) 33 | ++hits; // It does, so increment count 34 | } 35 | 36 | std::cout << "Probability of the stick crossing the edge of a board is: " 37 | << (static_cast(hits) / throws) << std::endl; 38 | std::cout << "Pi is: " << (2 * stick_length*throws) / (board_width*hits) << std::endl; 39 | } 40 | -------------------------------------------------------------------------------- /Chapter 10/Ex10_03/Ex10_03.cpp: -------------------------------------------------------------------------------- 1 | // Ex10_03.cpp 2 | // Using the Gaussian Elimination method to solve a set of liear equations 3 | #include // For valarray, slice, abs() 4 | #include // For vector container 5 | #include // For ostream iterator 6 | #include // For generate_n() 7 | #include // For swap() 8 | #include // For standard streams 9 | #include // For stream manipulators 10 | #include // For string type 11 | using std::string; 12 | using std::valarray; 13 | using std::slice; 14 | 15 | // Function prototypes 16 | valarray get_data(size_t n); 17 | void reduce_matrix(valarray& equations, std::vector& row_slices); 18 | valarray back_substitution(valarray& equations, const std::vector& row_slices); 19 | 20 | int main() 21 | { 22 | size_t n_rows {}; 23 | std::cout << "Enter the number of variables: "; 24 | std::cin >> n_rows; 25 | auto equations = get_data(n_rows); 26 | 27 | // Generate slice objects for rows in row order 28 | std::vector row_slices; // Objects define rows in sequence 29 | size_t row_len {n_rows + 1}; 30 | std::generate_n(std::back_inserter(row_slices), n_rows, 31 | [row_len]() 32 | { static size_t index {}; 33 | return slice {row_len*index++, row_len, 1}; 34 | }); 35 | 36 | reduce_matrix(equations, row_slices); // Reduce to row echelon form 37 | auto solution = back_substitution(equations, row_slices); 38 | 39 | // Output the solution 40 | size_t count {}, perline {8}; 41 | std::cout << "\nSolution:\n"; 42 | string x{"x"}; 43 | for(const auto& v : solution) 44 | { 45 | std::cout << std::setw(3) << x + std::to_string(count+1) << " = " 46 | << std::fixed << std::setprecision(2) << std::setw(10) 47 | << v; 48 | if(++count % perline) std::cout << '\n'; 49 | } 50 | std::cout << std::endl; 51 | } -------------------------------------------------------------------------------- /Chapter 5/Ex5_04.cpp: -------------------------------------------------------------------------------- 1 | // Ex5_04.cpp 2 | // Determining word frequency 3 | #include // For standard streams 4 | #include // For stream manipulators 5 | #include // For string class 6 | #include // For istringstream 7 | #include // For replace_if() & for_each() 8 | #include // For map container 9 | #include // For advance() 10 | #include // For isalpha() 11 | 12 | using std::string; 13 | 14 | int main() 15 | { 16 | std::cout << "Enter some text and enter * to end:\n"; 17 | string text_in {}; 18 | std::getline(std::cin, text_in, '*'); 19 | 20 | // Replace non-alphabetic characters by a space 21 | std::replace_if(std::begin(text_in), std::end(text_in), [](const char& ch){ return !isalpha(ch); }, ' '); 22 | 23 | std::istringstream text(text_in); // Text input string as a stream 24 | std::istream_iterator begin(text); // Stream iterator 25 | std::istream_iterator end; // End stream iterator 26 | 27 | std::multiset words; // Container to store words 28 | size_t max_len {}; // Maximum word length 29 | 30 | // Get the words, store in the container, and find maximum length 31 | std::for_each(begin, end, [&max_len, &words](const string& word) 32 | { words.emplace(word); 33 | max_len = std::max(max_len, word.length()); 34 | }); 35 | 36 | size_t per_line {4}, // Outputs per line 37 | count {}; // No. of words output 38 | 39 | for(auto iter = std::begin(words); iter != std::end(words); iter = words.upper_bound(*iter)) 40 | { 41 | std::cout << std::left << std::setw(max_len + 1) << *iter 42 | << std::setw(3) << std::right << words.count(*iter) << " "; 43 | if(++count % per_line == 0) std::cout << std::endl; 44 | } 45 | std::cout << std::endl; 46 | } 47 | -------------------------------------------------------------------------------- /Chapter 3/Ex3_04.cpp: -------------------------------------------------------------------------------- 1 | // Ex3_04.cpp 2 | // Using a heap as a priority queue 3 | #include // For standard streams 4 | #include // For stream manipulators 5 | #include // For heap support functions 6 | #include // For string class 7 | #include // For deque container 8 | using std::string; 9 | 10 | // List a deque of words 11 | void show(const std::deque& words, size_t count = 5) 12 | { 13 | if(words.empty()) return; // Ensure deque has elements 14 | 15 | // Find length of longest string 16 | auto max_len = std::max_element(std::begin(words), std::end(words), 17 | [](const string& s1, const string& s2) 18 | {return s1.size() < s2.size(); })->size(); 19 | size_t n {count}; 20 | for(const auto& word : words) 21 | { 22 | std::cout << std::setw(max_len + 1) << word << " "; 23 | if(--n) continue; 24 | std::cout << std::endl; 25 | n = count; 26 | } 27 | std::cout << std::endl; 28 | } 29 | 30 | int main() 31 | { 32 | std::deque words; 33 | std::string word; 34 | std::cout << "Enter words separated by spaces, enter Ctrl+Z on a separate line to end:\n"; 35 | while (true) 36 | { 37 | if ((std::cin >> word).eof()) 38 | { 39 | std::cin.clear(); 40 | break; 41 | } 42 | words.push_back(word); 43 | } 44 | std::cout << "The words in the list are:" << std::endl; 45 | show(words); 46 | 47 | std::make_heap(std::begin(words), std::end(words)); 48 | std::cout << "\nAfter making a heap, the words in the list are:" << std::endl; 49 | show(words); 50 | std::cout << "\nYou entered " << words.size() << " words. Enter some more:" << std::endl; 51 | while (true) 52 | { 53 | if ((std::cin >> word).eof()) 54 | { 55 | std::cin.clear(); 56 | break; 57 | } 58 | words.push_back(word); 59 | std::push_heap(std::begin(words), std::end(words)); 60 | } 61 | std::cout << "\nThe words in the list are now:" << std::endl; 62 | show(words); 63 | } -------------------------------------------------------------------------------- /Chapter 9/Ex9_08.cpp: -------------------------------------------------------------------------------- 1 | // Ex9_08.cpp 2 | // Using stream iterators to create a file of random temperatures 3 | #include // For standard streams 4 | #include // For iterators and begin() and end() 5 | #include // For stream manipulators 6 | #include // For file streams 7 | #include // For generate_n() and for_each() 8 | #include // For distributions and random number generator 9 | #include // For string class 10 | using std::string; 11 | 12 | int main() 13 | { 14 | string file_name {"G:/Beginning_STL/temperatures.txt"}; 15 | std::ofstream temps_out {file_name, std::ios_base::out | std::ios_base::trunc}; 16 | const size_t n {50}; // Number of temperatures required 17 | 18 | std::random_device rd; // Non-determistic source 19 | std::mt19937 rng {rd()}; // Mersenne twister generator 20 | double mu {50.0}, sigma {15.0}; // Mean: 50 degrees SD: 15 21 | std::normal_distribution<> normal {mu, sigma}; // Create distribution 22 | 23 | // Write random temperatures to the file 24 | std::generate_n(std::ostream_iterator { temps_out, " "}, n, 25 | [&rng, &normal] 26 | { return normal(rng); }); 27 | temps_out.close(); // Close the output file 28 | 29 | // List the contents of the file 30 | std::ifstream temps_in {file_name}; // Open the file to read it 31 | for_each(std::istream_iterator {temps_in}, std::istream_iterator {}, 32 | [](double t) 33 | { const size_t perline {10}; 34 | static size_t count {}; 35 | std::cout << std::fixed << std::setprecision(2) << std::setw(5) << t 36 | << ((++count % perline) ? " " : "\n"); 37 | }); 38 | std::cout << std::endl; 39 | temps_in.close(); // Close the input file 40 | } -------------------------------------------------------------------------------- /Chapter 4/Ex4_01/Ex4_01.cpp: -------------------------------------------------------------------------------- 1 | // Ex4_01.cpp 2 | // Storing names and ages 3 | #include // For standard streams 4 | #include // For stream manipulators 5 | #include // For string class 6 | #include // For map container class 7 | #include // For pair<> & make_pair<>() 8 | #include // For toupper() 9 | #include "Name.h" 10 | using std::string; 11 | using Entry = std::pair; 12 | using std::make_pair; 13 | using std::map; 14 | 15 | // Create a map entry from input 16 | Entry get_entry() 17 | { 18 | std::cout << "Enter first and second names followed by the age: "; 19 | Name name {}; 20 | size_t age {}; 21 | std::cin >> name >> age; 22 | return make_pair(name, age); 23 | } 24 | 25 | // Output the elements in a map 26 | void list_entries(const map& people) 27 | { 28 | for(auto& entry : people) 29 | { 30 | std::cout << std::left << std::setw(30) << entry.first 31 | << std::right << std::setw(4) << entry.second << std::endl; 32 | } 33 | } 34 | 35 | 36 | int main() 37 | { 38 | map people {{{"Ann", "Dante"}, 25}, {{"Bill", "Hook"}, 46}, {{"Jim", "Jams"}, 32}, {{"Mark", "Time"}, 32}}; 39 | 40 | std::cout << "\nThe initial contents of the map is:\n"; 41 | list_entries(people); 42 | 43 | char answer {'Y'}; 44 | std::cout << "\nEnter a Name and age entry.\n"; 45 | while(std::toupper(answer) == 'Y') 46 | { 47 | Entry entry {get_entry()}; 48 | auto pr = people.insert(entry); 49 | if(!pr.second) 50 | { // It's there already - check whether we should update 51 | std::cout << "Key \"" << pr.first->first << "\" already present. Do you want to update the age (Y or N)? "; 52 | std::cin >> answer; 53 | if(std::toupper(answer) == 'Y') 54 | pr.first->second = entry.second; 55 | } 56 | // Check whether there are more to be entered 57 | std::cout << "Do you want to enter another entry(Y or N)? "; 58 | std::cin >> answer; 59 | } 60 | 61 | std::cout << "\nThe map now contains the following entries:\n"; 62 | list_entries(people); 63 | } -------------------------------------------------------------------------------- /Chapter 6/Ex6_02/Account.h: -------------------------------------------------------------------------------- 1 | #ifndef ACCCOUNT_H 2 | #define ACCCOUNT_H 3 | #include // For stream class 4 | #include // For stream manipulators 5 | #include // For string class 6 | #include // For pair template type 7 | #include "Transaction.h" 8 | 9 | using first_name = std::string; 10 | using second_name = std::string; 11 | using Name = std::pair; 12 | 13 | class Account 14 | { 15 | private: 16 | size_t account_number {}; // 5-digit account number 17 | Name name {"", ""}; // A pair containing 1st & 2nd names 18 | double balance {}; // The account balance - negative when overdrawn 19 | 20 | public: 21 | Account()=default; 22 | Account(size_t number, const Name& nm) : account_number {number}, name {nm}{} 23 | 24 | double get_balance() const { return balance; } 25 | void set_balance(double bal) { balance = bal; } 26 | 27 | size_t get_acc_number() const {return account_number;} 28 | const Name& get_name() const { return name; } 29 | 30 | // Apply a transaction to the account 31 | bool apply_transaction(const Transaction& transaction) 32 | { 33 | if(transaction.credit) // For a credit... 34 | balance += transaction.amount; // ...add the mount 35 | else // For a debit... 36 | balance -= transaction.amount; // ...subtract the amount 37 | return balance < 0.0; // Return true when overdrawn 38 | } 39 | 40 | // Less-than operator - compares by account number 41 | bool operator<(const Account& acc) const { return account_number < acc.account_number; } 42 | 43 | friend std::ostream& operator<<(std::ostream& out, const Account& account); 44 | }; 45 | 46 | // Stream insertion operator for Account objects 47 | std::ostream& operator<<(std::ostream& out, const Account& acc) 48 | { 49 | return out << std::left << std::setw(20) << acc.name.first + " " + acc.name.second 50 | << std::right << std::setfill('0') << std::setw(5) << acc.account_number 51 | << std::setfill(' ') << std::setw(8) << std::fixed << std::setprecision(2) << acc.balance; 52 | } 53 | #endif 54 | -------------------------------------------------------------------------------- /Chapter 10/Ex10_02.cpp: -------------------------------------------------------------------------------- 1 | // Ex10_02.cpp 2 | // Dropping bricks safely from a tall building using valarray objects 3 | #include // For iota() 4 | #include // For standard streams 5 | #include // For stream manipulators 6 | #include // For for_each() 7 | #include // For valarray 8 | const static double g {32.0}; // Acceleration due to gravity ft/sec/sec 9 | 10 | int main() 11 | { 12 | double height {}; // Building height 13 | std::cout << "Enter the approximate height of the building in feet: "; 14 | std::cin >> height; 15 | 16 | // Calculate brick flight time in seconds 17 | double end_time {std::sqrt(2 * height / g)}; 18 | size_t max_time {1 + static_cast(end_time + 0.5)}; 19 | 20 | std::valarray times(max_time + 1); // Array to accommodate times 21 | std::iota(std::begin(times), std::end(times), 0); // Initialize: 0 to max_time 22 | *(std::end(times) - 1) = end_time; // Set the last time value 23 | 24 | // Calculate distances each second 25 | auto distances = times.apply([](double t) { return 0.5*g*t*t; }); 26 | 27 | // Calculate speed each second 28 | auto v_fps = sqrt(distances.apply([](double d) { return 2 * g*d; })); 29 | 30 | // Lambda expression to output results 31 | auto print = [](double v) { std::cout << std::setw(5) << static_cast(std::round(v)); }; 32 | 33 | // Output the times - the last is a special case... 34 | std::cout << "Time (seconds): "; 35 | std::for_each(std::begin(times), std::end(times) - 1, print); 36 | std::cout << std::setw(5) << std::fixed << std::setprecision(2) << *(std::end(times) - 1); 37 | 38 | std::cout << "\nDistances(feet):"; 39 | std::for_each(std::begin(distances), std::end(distances), print); 40 | 41 | std::cout << "\nVelocity(fps): "; 42 | std::for_each(std::begin(v_fps), std::end(v_fps), print); 43 | 44 | // Get velocities in mph and output them 45 | auto v_mph = v_fps.apply([](double v) { return v * 60 / 88; }); 46 | std::cout << "\nVelocity(mph): "; 47 | std::for_each(std::begin(v_mph), std::end(v_mph), print); 48 | std::cout << std::endl; 49 | } -------------------------------------------------------------------------------- /Chapter 7/Ex7_01.cpp: -------------------------------------------------------------------------------- 1 | // Ex7_01.cpp 2 | // Using the equal() algorithm 3 | #include // For standard streams 4 | #include // For vector container 5 | #include // For equal() algorithm 6 | #include // For stream iterators 7 | #include // For string class 8 | using std::string; 9 | 10 | int main() 11 | { 12 | std::vector words1 {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}; 13 | std::vector words2 {"two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"}; 14 | auto iter1 = std::begin(words1); 15 | auto end_iter1 = std::end(words1); 16 | auto iter2 = std::begin(words2); 17 | auto end_iter2 = std::end(words2); 18 | 19 | std::cout << "Container - words1: "; 20 | std::copy(iter1, end_iter1, std::ostream_iterator{std::cout, " "}); 21 | std::cout << "\nContainer - words2: "; 22 | std::copy(iter2, end_iter2, std::ostream_iterator{std::cout, " "}); 23 | std::cout << std::endl; 24 | 25 | std::cout << "\n1. Compare from words1[1] to end with words2: "; 26 | std::cout << std::boolalpha << std::equal(iter1 + 1, end_iter1, iter2) << std::endl; 27 | 28 | std::cout << "2. Compare from words2[0] to second-to-last with words1: "; 29 | std::cout << std::boolalpha << std::equal(iter2, end_iter2 - 1, iter1) << std::endl; 30 | 31 | std::cout << "3. Compare from words1[1] to words1[5] with words2: "; 32 | std::cout << std::boolalpha << std::equal(iter1 + 1, iter1 + 6, iter2) << std::endl; 33 | 34 | std::cout << "4. Compare first 6 from words1 with first 6 in words2: "; 35 | std::cout << std::boolalpha << std::equal(iter1, iter1 + 6, iter2, iter2 + 6) << std::endl; 36 | 37 | std::cout << "5. Compare all words1 with words2: "; 38 | std::cout << std::boolalpha << std::equal(iter1, end_iter1, iter2) << std::endl; 39 | 40 | std::cout << "6. Compare all of words1 with all of words2: "; 41 | std::cout << std::boolalpha << std::equal(iter1, end_iter1, iter2, end_iter2) << std::endl; 42 | 43 | std::cout << "7. Compare from words1[1] to end with words2 from first to second-to-last: "; 44 | std::cout << std::boolalpha << std::equal(iter1 + 1, end_iter1, iter2, end_iter2 - 1) << std::endl; 45 | 46 | } -------------------------------------------------------------------------------- /Chapter 8/Ex8_09.cpp: -------------------------------------------------------------------------------- 1 | // Ex8_09.cpp 2 | // Demonstrating the piecewise linear distribution 3 | #include // For distributions and random number generator 4 | #include // For vector container 5 | #include // For map container 6 | #include // For pair type 7 | #include // For copy(), count(), remove() 8 | #include // For standard streams 9 | #include // For stream iterators 10 | #include // For stream manipulators 11 | #include // For string class 12 | using std::string; 13 | 14 | int main() 15 | { 16 | std::vector v {10, 30, 40, 55, 60}; // Sample values 17 | std::vector w {6, 12, 9, 6, 0}; // Weights for the samples 18 | std::piecewise_linear_distribution<> d {std::begin(v), std::end(v), std::begin(w)}; 19 | 20 | // Output the interval boundaries and the interval probabilities 21 | auto values = d.intervals(); 22 | std::cout << "Sample values: "; 23 | std::copy(std::begin(values), std::end(values), std::ostream_iterator{std::cout, " "}); 24 | std::cout << " probability densities: "; 25 | auto probs = d.densities(); 26 | std::copy(std::begin(probs), std::end(probs), std::ostream_iterator{std::cout, " "}); 27 | std::cout << '\n' << std::endl; 28 | 29 | std::random_device rd; 30 | std::default_random_engine rng {rd()}; 31 | std::map results; //Stores and counts random values as integers 32 | // Generate a lot of random values... 33 | for(size_t i {}; i < 20000; ++i) 34 | ++results[static_cast(std::round(d(rng)))]; 35 | 36 | // Plot the integer values 37 | auto max_count = std::max_element(std::begin(results), std::end(results), 38 | [](const std::pair& pr1, const std::pair& pr2) 39 | { return pr1.second < pr2.second; })->second; 40 | std::for_each(std::begin(results), std::end(results), 41 | [max_count](const std::pair& pr) 42 | { if(!(pr.first % 10)) // Display value if multiple of 10 43 | std::cout << std::setw(3) << pr.first << "-|"; 44 | else 45 | std::cout << " |"; 46 | std::cout << std::string(pr.second * 80 / max_count, '*') 47 | << '\n'; }); 48 | } -------------------------------------------------------------------------------- /Chapter 9/Ex9_10.cpp: -------------------------------------------------------------------------------- 1 | // Ex9_10.cpp 2 | // Using a string stream as the dictionary source to anagrams of a word 3 | #include // For standard streams 4 | #include // For file streams 5 | #include // For iterators and begin() and end() 6 | #include // For string class 7 | #include // For set container 8 | #include // For vector container 9 | #include // For next_permutation() 10 | #include // For string streams 11 | using std::string; 12 | 13 | int main() 14 | { 15 | string file_in {"G:/Beginning_STL/dictionary.txt"}; 16 | std::ifstream in {file_in}; 17 | if(!in) 18 | { 19 | std::cerr << file_in << " not open." << std::endl; 20 | exit(1); 21 | } 22 | std::stringstream instr; // String stream for file contents 23 | instr << in.rdbuf(); 24 | 25 | //std::copy(std::istreambuf_iterator{in}, std::istreambuf_iterator(), 26 | // std::ostreambuf_iterator{instr}); 27 | in.close(); // Close the file 28 | 29 | std::vector words; 30 | string word; 31 | auto end_iter = std::istream_iterator {}; // End-of-stream iterator 32 | while(true) 33 | { 34 | std::cout << "\nEnter a word, or Ctrl+z to end: "; 35 | if((std::cin >> word).eof()) break; 36 | 37 | string word_copy {word}; 38 | do 39 | { 40 | instr.clear(); // Reset string stream EOF 41 | instr.seekg(0); // String stream position at beginning 42 | 43 | // Use find() to search instr for word 44 | if(std::find(std::istream_iterator(instr), end_iter, word) != end_iter) 45 | words.push_back(word); // Store the word found 46 | 47 | std::next_permutation(std::begin(word), std::end(word)); 48 | } while(word != word_copy); 49 | 50 | std::copy(std::begin(words), std::end(words), std::ostream_iterator{std::cout, " "}); 51 | std::cout << std::endl; 52 | words.clear(); // Remove previous anagrams 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Chapter 2/Ex2_06/Ex2_06.cpp: -------------------------------------------------------------------------------- 1 | // Ex2_06.cpp 2 | // Working with a forward list 3 | #include // For copy() 4 | #include // For standard streams 5 | #include // For forward_list container 6 | #include // For stream iterators 7 | #include "Box.h" 8 | 9 | // List a range of elements 10 | template 11 | void list_elements(Iter begin, Iter end) 12 | { 13 | size_t perline {6}; // Maximum items per line 14 | size_t count {}; // Item count 15 | while (begin != end) 16 | { 17 | std::cout << *begin++; 18 | if (++count % perline == 0) 19 | { 20 | std::cout << "\n"; 21 | } 22 | } 23 | std::cout << std::endl; 24 | } 25 | 26 | int main() 27 | { 28 | std::forward_list boxes; 29 | std::copy(std::istream_iterator(std::cin), std::istream_iterator(), std::front_inserter(boxes)); 30 | 31 | boxes.sort(); // Sort the boxes 32 | std::cout << "\nAfter sorting the sequence is:\n"; 33 | // Just to show that we can with Box objects - use an ostream iterator 34 | std::copy(std::begin(boxes), std::end(boxes), std::ostream_iterator(std::cout, " ")); 35 | std::cout << std::endl; 36 | 37 | // Insert more boxes 38 | std::forward_list more_boxes {Box {3, 3, 3}, Box {5, 5, 5}, Box {4, 4, 4}, Box {2, 2, 2}}; 39 | boxes.insert_after(boxes.before_begin(), std::begin(more_boxes), std::end(more_boxes)); 40 | std::cout << "After inserting more boxes the sequence is:\n"; 41 | list_elements(std::begin(boxes), std::end(boxes)); 42 | 43 | boxes.sort(); // Sort the boxes 44 | std::cout << std::endl; 45 | std::cout << "The sorted sequence is now:\n"; 46 | list_elements(std::begin(boxes), std::end(boxes)); 47 | 48 | more_boxes.sort(); 49 | boxes.merge(more_boxes); // Merge more_boxes 50 | std::cout << "After merging more_boxes the sequence is:\n"; 51 | list_elements(std::begin(boxes), std::end(boxes)); 52 | 53 | boxes.unique(); 54 | std::cout << "After removing successive duplicates the sequence is:\n"; 55 | list_elements(std::begin(boxes), std::end(boxes)); 56 | 57 | // Eliminate the small ones 58 | const double max_v {30.0}; 59 | boxes.remove_if([max_v](const Box& box){ return box.volume() < max_v; }); 60 | std::cout << "After removing those with volume less than 30 the sorted sequence is:\n"; 61 | list_elements(std::begin(boxes), std::end(boxes)); 62 | } -------------------------------------------------------------------------------- /Chapter 7/Ex7_02.cpp: -------------------------------------------------------------------------------- 1 | // Ex7_02.cpp 2 | // Using the mismatch() algorithm 3 | #include // For standard streams 4 | #include // For vector container 5 | #include // For equal() algorithm 6 | #include // For string class 7 | #include // For stream iterators 8 | 9 | using std::string; 10 | using word_iter = std::vector::iterator; 11 | 12 | int main() 13 | { 14 | std::vector words1 {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}; 15 | std::vector words2 {"two", "three", "four", "five", "six", "eleven", "eight", "nine", "ten"}; 16 | auto iter1 = std::begin(words1); 17 | auto end_iter1 = std::end(words1); 18 | auto iter2 = std::begin(words2); 19 | auto end_iter2 = std::end(words2); 20 | 21 | // Lambda expression to output mismatch() result 22 | auto print_match = [](const std::pair& pr, const word_iter& end_iter) 23 | { 24 | if(pr.first != end_iter) 25 | std::cout << "\nFirst pair of words that differ are " 26 | << *pr.first << " and " << *pr.second << std::endl; 27 | else 28 | std::cout << "\nRanges are identical." << std::endl; 29 | }; 30 | 31 | std::cout << "Container - words1: "; 32 | std::copy(iter1, end_iter1, std::ostream_iterator{std::cout, " "}); 33 | std::cout << "\nContainer - words2: "; 34 | std::copy(iter2, end_iter2, std::ostream_iterator{std::cout, " "}); 35 | std::cout << std::endl; 36 | 37 | std::cout << "\nCompare from words1[1] to end with words2:"; 38 | print_match(std::mismatch(iter1 + 1, end_iter1, iter2), end_iter1); 39 | 40 | std::cout << "\nCompare from words2[0] to second-to-last with words1:"; 41 | print_match(std::mismatch(iter2, end_iter2 - 1, iter1), end_iter2 - 1); 42 | 43 | std::cout << "\nCompare from words1[1] to words1[5] with words2:"; 44 | print_match(std::mismatch(iter1 + 1, iter1 + 6, iter2), iter1 + 6); 45 | 46 | std::cout << "\nCompare first 6 from words1 with first 6 in words2:"; 47 | print_match(std::mismatch(iter1, iter1 + 6, iter2, iter2 + 6), iter1 + 6); 48 | 49 | std::cout << "\nCompare all words1 with words2:"; 50 | print_match(std::mismatch(iter1, end_iter1, iter2), end_iter1); 51 | 52 | std::cout << "\nCompare all of words2 with all of words1:"; 53 | print_match(std::mismatch(iter2, end_iter2, iter1, end_iter1), end_iter2); 54 | 55 | std::cout << "\nCompare from words1[1] to end with words2[0] to second-to-last:"; 56 | print_match(std::mismatch(iter1 + 1, end_iter1, iter2, end_iter2 - 1), end_iter1); 57 | } 58 | -------------------------------------------------------------------------------- /Chapter 2/Ex2_02.cpp: -------------------------------------------------------------------------------- 1 | // Ex2_02A.cpp 2 | // Sorting strings in a vector container 3 | #include // For standard streams 4 | #include // For string types 5 | #include // For swap() and copy() functions 6 | #include // For vector (and iterators) 7 | using std::string; 8 | using std::vector; 9 | 10 | // Our very own algorithm to sort a range specified by iterators 11 | template 12 | void bubble_sort(RandomIter start, RandomIter last) 13 | { 14 | std::cout << "Starting sort." << std::endl; 15 | bool out_of_order {false}; // true when values are not in order 16 | while (true) 17 | { 18 | for (auto first = start + 1; first != last; ++first) 19 | { 20 | if (*(first - 1) > *first) 21 | { // Out of order so swap them 22 | std::swap(*first, *(first - 1)); 23 | out_of_order = true; 24 | } 25 | } 26 | if (!out_of_order) // If they are in order (no swaps necessary)... 27 | break; // ...we are done... 28 | out_of_order = false; // ...otherwise, go round again. 29 | } 30 | } 31 | 32 | int main() 33 | { 34 | vector words; // Stores words to be sorted 35 | words.reserve(10); // Allocate some space for elements 36 | std::cout << "Enter words separated by spaces. Enter Ctrl+Z on a separate line to end:" << std::endl; 37 | std::copy(std::istream_iterator < string > {std::cin}, std::istream_iterator < string > {}, 38 | std::back_inserter(words)); 39 | 40 | bubble_sort(std::begin(words), std::end(words)); // Sort the words array 41 | 42 | // Output the sorted vector 43 | std::cout << "your words in ascending sequence:" << std::endl; 44 | std::copy(std::begin(words), std::end(words), std::ostream_iterator < string > {std::cout, " "}); 45 | std::cout << std::endl; 46 | 47 | // Create a new vector by moving elements from words vector 48 | vector words_copy {std::make_move_iterator(std::begin(words)), 49 | std::make_move_iterator(std::end(words))}; 50 | std::cout << "\nAfter moving elements from words, words_copy contains:" << std::endl; 51 | std::copy(std::begin(words_copy), std::end(words_copy), std::ostream_iterator < string > {std::cout, " "}); 52 | std::cout << std::endl; 53 | 54 | // See what's happened to elements in words vector... 55 | std::cout << "\nwords vector has " << words.size() << " elements\n"; 56 | if (words.front().empty()) 57 | std::cout << "First element is empty string object." << std::endl; 58 | 59 | std::cout << "First element is \"" << words.front() << "\"" << std::endl; 60 | } 61 | -------------------------------------------------------------------------------- /Chapter 2/Ex2_02A.cpp: -------------------------------------------------------------------------------- 1 | // Ex2_02A.cpp 2 | // Sorting strings in a vector container 3 | #include // For standard streams 4 | #include // For string types 5 | #include // For swap() and copy() functions 6 | #include // For vector (and iterators) 7 | using std::string; 8 | using std::vector; 9 | 10 | // Our very own algorithm to sort a range specified by iterators 11 | template 12 | void bubble_sort(RandomIter start, RandomIter last) 13 | { 14 | std::cout << "Starting sort." << std::endl; 15 | bool out_of_order {false}; // true when values are not in order 16 | while (true) 17 | { 18 | for (auto first = start + 1; first != last; ++first) 19 | { 20 | if (*(first - 1) > *first) 21 | { // Out of order so swap them 22 | std::swap(*first, *(first - 1)); 23 | out_of_order = true; 24 | } 25 | } 26 | if (!out_of_order) // If they are in order (no swaps necessary)... 27 | break; // ...we are done... 28 | out_of_order = false; // ...otherwise, go round again. 29 | } 30 | } 31 | 32 | int main() 33 | { 34 | vector words; // Stores words to be sorted 35 | words.reserve(10); // Allocate some space for elements 36 | std::cout << "Enter words separated by spaces. Enter Ctrl+Z on a separate line to end:" << std::endl; 37 | std::copy(std::istream_iterator < string > {std::cin}, std::istream_iterator < string > {}, 38 | std::back_inserter(words)); 39 | 40 | bubble_sort(std::begin(words), std::end(words)); // Sort the words array 41 | 42 | // Output the sorted vector 43 | std::cout << "your words in ascending sequence:" << std::endl; 44 | std::copy(std::begin(words), std::end(words), std::ostream_iterator < string > {std::cout, " "}); 45 | std::cout << std::endl; 46 | 47 | // Create a new vector by moving elements from words vector 48 | vector words_copy {std::make_move_iterator(std::begin(words)), 49 | std::make_move_iterator(std::end(words))}; 50 | std::cout << "\nAfter moving elements from words, copy_words contains:" << std::endl; 51 | std::copy(std::begin(words_copy), std::end(words_copy), std::ostream_iterator < string > {std::cout, " "}); 52 | std::cout << std::endl; 53 | 54 | // See what's happened to elements in words vector... 55 | std::cout << "\nwords vector has " << words.size() << " elements\n"; 56 | if (!words.front().length()) 57 | std::cout << "First element is empty string object." << std::endl; 58 | 59 | std::cout << "First element is \"" << words.front() << "\"" << std::endl; 60 | } 61 | -------------------------------------------------------------------------------- /Chapter 10/Ex10_06.cpp: -------------------------------------------------------------------------------- 1 | // Ex10_06.cpp 2 | // Using complex object to generate a fractal image of a Julia set 3 | #include // For standard streams 4 | #include // For stream manipulators 5 | #include // For complex types 6 | #include // For clocks, duration, and time_point 7 | using std::complex; 8 | using namespace std::chrono; 9 | using namespace std::literals; 10 | 11 | // Outputs the exact interval in seconds for a time_point<> 12 | template 13 | void print_timepoint(const TimePoint& tp, size_t places = 0) 14 | { 15 | auto elapsed = tp.time_since_epoch(); // duration object for the interval 16 | 17 | auto seconds = duration_cast>(elapsed).count(); 18 | std::cout << std::fixed << std::setprecision(places) << seconds << " seconds\n"; 19 | } 20 | 21 | int main() 22 | { 23 | const int width {100}, height {100}; // Image width and height 24 | size_t count {100}; // Iterate count for recursion 25 | char image[width][height]; 26 | auto start_time = std::chrono::steady_clock::now(); // time_point object for start 27 | complex c {-0.7, 0.27015}; // Constant in z = z*z + c 28 | 29 | for(int i {}; i < width; ++i) // Iterate over pixels in the width 30 | { 31 | for(int j {}; j < height; ++j) // Iterate over pixels in the height 32 | { 33 | // Scale real and imaginary parts to be between -1 and +1 34 | auto re = 1.5*(i - width/2) / (0.5*width); 35 | auto im = (j - height/2) / (0.5*height); 36 | complex z {re,im}; // Point in the complex plane 37 | image[i][j] = ' '; // Point not in the Julia set 38 | // Iterate z=z*z+c count times 39 | for(size_t k {}; k < count; ++k) 40 | { 41 | z = z*z + c; 42 | } 43 | if(std::abs(z) < 2.0) // If point not escaping... 44 | image[i][j] = '*'; // ...it's in the Julia set 45 | } 46 | } 47 | auto end_time = std::chrono::steady_clock::now(); // time_point object for end 48 | auto elapsed = end_time - start_time.time_since_epoch(); 49 | std::cout << "Time to generate a Julia set with " << width << "x" << height << " pixels is "; 50 | print_timepoint(elapsed, 9); 51 | 52 | std::cout << "The Julia set looks like this:\n"; 53 | for(size_t i {}; i < width; ++i) 54 | { 55 | for(size_t j {}; j < height; ++j) 56 | std::cout << image[i][j]; 57 | std::cout << '\n'; 58 | } 59 | } -------------------------------------------------------------------------------- /Chapter 8/Ex8_08.cpp: -------------------------------------------------------------------------------- 1 | // Ex8_08.cpp 2 | // Demonstrating the piecewise constant distribution 3 | #include // For distributions and random number generator 4 | #include // For vector container 5 | #include // For map container 6 | #include // For pair type 7 | #include // For copy(), count(), remove() 8 | #include // For standard streams 9 | #include // For stream iterators 10 | #include // For stream manipulators 11 | #include // For string class 12 | using std::string; 13 | 14 | int main() 15 | { 16 | std::vector b {10, 20, 35, 55}; // Intervals: 10-20, 20-35, 35-55 17 | std::vector w {4, 10, 6}; // Weights for the intervals 18 | std::piecewise_constant_distribution<> d {std::begin(b), std::end(b), std::begin(w)}; 19 | 20 | // Output the interval boundaries and the interval probabilities 21 | auto intvls = d.intervals(); 22 | std::cout << "intervals: "; 23 | std::copy(std::begin(intvls), std::end(intvls), std::ostream_iterator{std::cout, " "}); 24 | std::cout << " probability densities: "; 25 | auto probs = d.densities(); 26 | std::copy(std::begin(probs), std::end(probs), std::ostream_iterator{std::cout, " "}); 27 | std::cout << '\n' << std::endl; 28 | 29 | std::random_device rd; 30 | std::default_random_engine rng {rd()}; 31 | std::map results; //Stores and counts random values as integers 32 | // Generate a lot of random values... 33 | for(size_t i {}; i < 20000; ++i) 34 | ++results[static_cast(std::round(d(rng)))]; 35 | 36 | // Plot the integer values 37 | auto max_count = std::max_element(std::begin(results), std::end(results), 38 | [](const std::pair& pr1, const std::pair& pr2) 39 | { return pr1.second < pr2.second; })->second; 40 | std::for_each(std::begin(results), std::end(results), 41 | [max_count](const std::pair& pr) 42 | { if(!(pr.first % 10)) // Display value if multiple of 10 43 | std::cout << std::setw(3) << pr.first << "-|"; 44 | else 45 | std::cout << " |"; 46 | std::cout << std::string(pr.second * 80 / max_count, '*') 47 | << '\n'; }); 48 | } -------------------------------------------------------------------------------- /Chapter 2/Ex2_01.cpp: -------------------------------------------------------------------------------- 1 | // Ex2_01.cpp 2 | /* 3 | Using array to create a Body Mass Index (BMI) table 4 | BMI = weight/(height*height) 5 | weight is in kilograms, height is in meters 6 | */ 7 | 8 | #include // For standard streams 9 | #include // For stream manipulators 10 | #include // For array 11 | 12 | int main() 13 | { 14 | const unsigned int min_wt {100U}; // Minimum weight in table in lbs 15 | const unsigned int max_wt {250U}; // Maximum weight in table in lbs 16 | const unsigned int wt_step {10U}; // Weight increment 17 | const size_t wt_count {1 + (max_wt - min_wt) / wt_step}; 18 | 19 | const unsigned int min_ht {48U}; // Minimum height in table in inches 20 | const unsigned int max_ht {84U}; // Maximum height in table in inches 21 | const unsigned int ht_step {2U}; // Height increment 22 | const size_t ht_count {1 + (max_ht - min_ht) / ht_step}; 23 | 24 | const double lbs_per_kg {2.20462}; // Conversion factor lbs to kg 25 | const double ins_per_m {39.3701}; // Conversion factor ins to m 26 | 27 | std::array weight_lbs; 28 | std::array height_ins; 29 | 30 | // Create weights from 100lbs in steps of 10lbs 31 | for (size_t i {}, w {min_wt}; i < wt_count; w += wt_step, ++i) 32 | { 33 | weight_lbs.at(i) = w; 34 | } 35 | 36 | // Create heights from 48 inches in steps of 2 inches 37 | unsigned int h {min_ht}; 38 | for (auto& height : height_ins) 39 | { 40 | height = h; 41 | h += ht_step; 42 | } 43 | 44 | // Output table headings 45 | std::cout << std::setw(7) << " |"; 46 | for (const auto& w : weight_lbs) 47 | std::cout << std::setw(5) << w << " |"; 48 | std::cout << std::endl; 49 | 50 | // Output line below headings 51 | for (size_t i {1}; i < wt_count; ++i) 52 | std::cout << "---------"; 53 | std::cout << std::endl; 54 | 55 | double bmi {}; // Stores BMI 56 | unsigned int feet {}; // Whole feet for output 57 | unsigned int inches {}; // Whole inches for output 58 | const unsigned int inches_per_foot {12U}; 59 | for (const auto& h : height_ins) 60 | { 61 | feet = h / inches_per_foot; 62 | inches = h % inches_per_foot; 63 | std::cout << std::setw(2) << feet << "'" << std::setw(2) << inches << "\"" << "|"; 64 | std::cout << std::fixed << std::setprecision(1); 65 | for (const auto& w : weight_lbs) 66 | { 67 | bmi = h / ins_per_m; 68 | bmi = (w / lbs_per_kg) / (bmi*bmi); 69 | std::cout << std::setw(2) << " " << bmi << " |"; 70 | } 71 | std::cout << std::endl; 72 | } 73 | // Output line below table 74 | for (size_t i {1}; i < wt_count; ++i) 75 | std::cout << "---------"; 76 | std::cout << "\nBMI from 18.5 to 24.9 is normal" << std::endl; 77 | } 78 | -------------------------------------------------------------------------------- /Chapter 10/Ex10_05/Ex10_05.cpp: -------------------------------------------------------------------------------- 1 | // Ex10_05.cpp 2 | // Determining the time to solve a set of linear equations 3 | #include // For valarray, slice, abs() 4 | #include // For vector container 5 | #include // For ostream iterator 6 | #include // For generate_n() 7 | #include // For swap() 8 | #include // For standard streams 9 | #include // For stream manipulators 10 | #include // For string type 11 | #include // For clocks, duration, and time_point 12 | using std::string; 13 | using std::valarray; 14 | using std::slice; 15 | using namespace std::chrono; 16 | 17 | // Function prototypes 18 | valarray get_data(size_t n); 19 | void reduce_matrix(valarray& equations, std::vector& row_slices); 20 | valarray back_substitution(valarray& equations, const std::vector& row_slices); 21 | 22 | // Outputs the exact interval in seconds for a time_point<> 23 | template 24 | void print_timepoint(const TimePoint& tp, size_t places = 0) 25 | { 26 | auto elapsed = tp.time_since_epoch(); // duration object for the interval 27 | 28 | auto seconds = duration_cast>(elapsed).count(); 29 | std::cout << std::fixed << std::setprecision(places) << seconds << " seconds\n"; 30 | } 31 | 32 | int main() 33 | { 34 | size_t n_rows {}; 35 | std::cout << "Enter the number of variables: "; 36 | std::cin >> n_rows; 37 | auto equations = get_data(n_rows); 38 | 39 | auto start_time = steady_clock::now(); // time_point object 40 | 41 | // Generate slice objects for rows in row order 42 | std::vector row_slices; // Objects define rows in sequence 43 | size_t row_len {n_rows + 1}; 44 | std::generate_n(std::back_inserter(row_slices), n_rows, 45 | [row_len]() 46 | { static size_t index {}; 47 | return slice {row_len*index++, row_len, 1}; 48 | }); 49 | 50 | reduce_matrix(equations, row_slices); // Reduce to row echelon form 51 | auto solution = back_substitution(equations, row_slices); 52 | 53 | auto end_time = steady_clock::now(); // time_point object 54 | auto elapsed = end_time - start_time.time_since_epoch(); 55 | std::cout << "Time to solve " << n_rows << " equations is "; 56 | print_timepoint(elapsed, 9); 57 | 58 | // Output the solution 59 | size_t count {}, perline {8}; 60 | std::cout << "\nSolution:\n"; 61 | string x {"x"}; 62 | for(const auto& v : solution) 63 | { 64 | std::cout << std::setw(3) << x + std::to_string(count + 1) << " = " 65 | << std::fixed << std::setprecision(2) << std::setw(10) 66 | << v; 67 | if(++count % perline) std::cout << '\n'; 68 | } 69 | std::cout << std::endl; 70 | } -------------------------------------------------------------------------------- /Chapter 10/Ex10_01.cpp: -------------------------------------------------------------------------------- 1 | // Ex10_01.cpp 2 | // Least squares regression 3 | #include // For accumulate(), inner_product() 4 | #include // For vector container 5 | #include // For standard streams 6 | #include // For stream manipulators 7 | #include // For file streams 8 | #include // For iterators and begin() and end() 9 | #include // For string class 10 | using std::string; 11 | 12 | int main() 13 | { 14 | // File contains country_name renewables_per_person kwh_cost 15 | string file_in {"G:/Beginning_STL/renewables_vs_kwh_cost.txt"}; 16 | std::ifstream in {file_in}; 17 | 18 | if(!in) // Verify we have a file 19 | { 20 | std::cerr << file_in << " not open." << std::endl; 21 | exit(1); 22 | } 23 | 24 | std::vector x; // Renewables per head 25 | std::vector y; // Corresponding cost for a kilowatt hour 26 | 27 | // Read the file and show the data 28 | std::cout << " Country " << " Watts per Head " << " kwh cost(cents) " << std::endl; 29 | while(true) 30 | { 31 | string country; 32 | double renewables {}; 33 | double kwh_cost {}; 34 | 35 | if((in >> country).eof()) break; // EOF read - we are done 36 | in >> renewables >> kwh_cost; 37 | x.push_back(renewables); 38 | y.push_back(kwh_cost); 39 | std::cout << std::left << std::setw(12) << country // Output the record 40 | << std::right 41 | << std::fixed << std::setprecision(2) << std::setw(12) << renewables 42 | << std::setw(16) << kwh_cost << std::endl; 43 | } 44 | 45 | auto n = x.size(); // Number of points 46 | auto sx = std::accumulate(std::begin(x), std::end(x), 0.0); // Sum of x values 47 | auto sy = std::accumulate(std::begin(y), std::end(y), 0.0); // Sum of y values 48 | auto mean_x = sx/n; // Mean of x values 49 | auto mean_y = sy/n; // Mean of y values 50 | 51 | // Sum of x*y values and sum of x-squared 52 | auto sxy = std::inner_product(std::begin(x), std::end(x), std::begin(y), 0.0); 53 | auto sx_2 = std::inner_product(std::begin(x), std::end(x), std::begin(x), 0.0); 54 | 55 | double a {}, b {}; // Line coefficients 56 | auto num = n*sxy - sx*sy; // Numerator for a 57 | auto denom = n*sx_2 - sx*sx; // Denominator for a 58 | a = num / denom; 59 | b = mean_y - a*mean_x; 60 | std::cout << std:: fixed << std::setprecision(3) << "\ny = " // Output equation 61 | << a << "*x + " << b << std::endl; // for regression line 62 | } -------------------------------------------------------------------------------- /Chapter 5/Ex5_05/Ex5_05.cpp: -------------------------------------------------------------------------------- 1 | // Ex5_05.cpp 2 | // Storing pointers to derived class objects in a multiset container 3 | #include // For standard streams 4 | #include // For string class 5 | #include // For copy() algorithm 6 | #include // For ostream_iterator 7 | #include // For map container 8 | #include // For multiset container 9 | #include // For smart pointers 10 | #include // For toupper() 11 | #include "Pet_Classes.h" 12 | 13 | using std::string; 14 | using Name = string; 15 | using Pet_ptr = std::shared_ptr; // A smart pointer to a pet 16 | using Pets = std::multiset ; // A set of smart pointers to pets 17 | 18 | // Compare shared pointers to pets 19 | inline bool operator<(const Pet_ptr& p1, const Pet_ptr& p2) 20 | { 21 | return *p1 < *p2; 22 | } 23 | 24 | // Stream insertion operator for pointers to pets 25 | inline std::ostream& operator<<(std::ostream& out, const Pet_ptr& pet_ptr) 26 | { 27 | return out << " " << *pet_ptr; 28 | } 29 | 30 | // Read in all the pets for a person 31 | Pets get_pets(const Name& person) 32 | { 33 | Pets pets; 34 | std::cout << "Enter " << person << "'s pets:\n"; 35 | char ch {}; 36 | Name name {}; 37 | while(true) 38 | { 39 | std::cin >> ch; 40 | if(toupper(ch) == 'Q') break; 41 | std::cin >> name; 42 | switch(std::toupper(ch)) 43 | { 44 | case 'C': 45 | pets.insert(std::make_shared(name)); 46 | break; 47 | case 'D': 48 | pets.insert(std::make_shared(name)); 49 | break; 50 | case 'M': 51 | pets.insert(std::make_shared(name)); 52 | break; 53 | default: 54 | std::cout << "Invalid pet ID - try again.\n"; 55 | } 56 | } 57 | return pets; 58 | } 59 | 60 | // REad all the pets for a given person 61 | void list_pets(const std::pair& pr) 62 | { 63 | std::cout << "\n" << pr.first << ":\n"; 64 | std::copy(std::begin(pr.second), std::end(pr.second), std::ostream_iterator(std::cout, "\n")); 65 | } 66 | 67 | int main() 68 | { 69 | std::map peoples_pets; // The people and their pets 70 | char answer {'Y'}; 71 | string name {}; 72 | std::cout << "You'll enter a person's name followed by their pets.\n" 73 | << "Pets can be identified by C for cat, D for dog, or M for mouse.\n" 74 | << "Enter the character to identify each pet type followed by the pet's name.\n" 75 | << "Enter Q to end pet input for a person.\n"; 76 | while(std::toupper(answer) == 'Y') 77 | { 78 | std::cout << "Enter a name: "; 79 | std::cin >> name; 80 | peoples_pets.emplace(name, get_pets(name)); 81 | std::cout << "Another person(Y or N)? "; 82 | std::cin >> answer; 83 | } 84 | 85 | // Output the pets for everyone 86 | std::cout << "\nThe people and their pets are:\n"; 87 | for(const auto& pr : peoples_pets) 88 | list_pets(pr); 89 | } -------------------------------------------------------------------------------- /Chapter 5/Ex5_06/Ex5_06.cpp: -------------------------------------------------------------------------------- 1 | // Ex5_06.cpp 2 | // Using an unordered_multiset container 3 | #include // For standard streams 4 | #include // For stream manipulators 5 | #include // For string class 6 | #include // For unordered_multiset containers 7 | #include // For copy(), max(), find_if(), for_each() 8 | #include "Name.h" 9 | #include "Hash_Name.h" 10 | 11 | using std::string; 12 | using Names = std::unordered_multiset; 13 | 14 | // Create the elements representing friends 15 | void make_friends(Names& names) 16 | { 17 | // Names are duplicated to get duplicate elements 18 | std::vector first_names {"John", "John", "John", "Joan", "Joan", "Jim", "Jim", "Jean"}; 19 | std::vector second_names {"Smith", "Jones", "Jones", "Hackenbush", "Szczygiel"}; 20 | 21 | for(const auto& name1 : first_names) 22 | for(const auto& name2:second_names) 23 | names.emplace(name1,name2); 24 | } 25 | 26 | // List the container elements within bucket 27 | void list_buckets(const Names& names) 28 | { 29 | for(size_t n_bucket {} ; n_bucket < names.bucket_count(); ++n_bucket) 30 | { 31 | std::cout << "Bucket " << n_bucket << ":\n"; 32 | std::copy(names.begin(n_bucket), names.end(n_bucket), std::ostream_iterator < Name > {std::cout, " "}); 33 | std::cout << std::endl; 34 | } 35 | } 36 | 37 | int main() 38 | { 39 | Names pals {8}; // 8 buckets 40 | pals.max_load_factor(8.0); // Average no. of elements per bucket max 41 | make_friends(pals); // Load up the container with Name objects 42 | list_buckets(pals); // List the contents by bucket 43 | 44 | // Report the number of John Smith's that are pals 45 | Name js {"John", "Smith"}; 46 | std::cout << "\nThere are " << pals.count(js) << " " << js << "'s.\n" << std::endl; 47 | 48 | // Remove all the John Jones's - we just don't get on... 49 | pals.erase(Name {"John", "Jones"}); 50 | 51 | // Get rid of the Hackenbushes - they never invite us... 52 | while(true) 53 | { 54 | auto iter = std::find_if(std::begin(pals), std::end(pals), 55 | [](const Name& name){ return name.get_second() == "Hackenbush"; }); 56 | if(iter == std::end(pals)) 57 | break; 58 | pals.erase(iter); 59 | } 60 | 61 | // List the friends we still have... 62 | size_t max_length {}; // Stores the maximum name length 63 | std::for_each(std::begin(pals), std::end(pals), // Find the maximum name length 64 | [&max_length](const Name name){ max_length = std::max(max_length, name.get_length()); }); 65 | 66 | size_t count {}; // No. of names written out 67 | size_t perline {6}; // No. of names per line 68 | for(const auto& pal : pals) 69 | { 70 | std::cout << std::setw(max_length+2) << std::left << pal; 71 | if((++count % perline) == 0) std::cout << "\n"; 72 | } 73 | std::cout << std::endl; 74 | } -------------------------------------------------------------------------------- /Chapter 8/Ex8_05.cpp: -------------------------------------------------------------------------------- 1 | // Ex8_05.cpp 2 | // Checking out normal distributions 3 | #include // For distributions and random number generators 4 | #include // For generate(), for_each(), max_element(), transform() 5 | #include // For accumulate() 6 | #include // For vector container 7 | #include // For map container 8 | #include // For pow(), round() functions 9 | #include // For standard streams 10 | #include 11 | #include 12 | using std::string; 13 | using Params = std::normal_distribution<>::param_type; 14 | 15 | // Template to plot a distribution from a range of sample values 16 | template 17 | void dist_plot(Iter& beg_iter, Iter& end_iter, size_t width=90) 18 | { 19 | // Create data for distribution plot 20 | std::map plot_data; // Elements are pair 21 | 22 | // Make sure all values are present in the plot 23 | auto pr = std::minmax_element(beg_iter, end_iter, [](const double v1, const double v2) {return v1 < v2; }); 24 | for(int n {static_cast(*pr.first)}; n < static_cast(*pr.second); ++n) 25 | plot_data.emplace(n,0); 26 | 27 | // Create the plot data 28 | std::for_each(beg_iter, end_iter, 29 | [&plot_data](double value) { ++plot_data[static_cast(std::round(value))]; }); 30 | 31 | // Find maximum frequency to be plotted - must fit within page width 32 | size_t max_f {std::max_element(std::begin(plot_data), std::end(plot_data), 33 | [](const std::pair& v1, const std::pair& v2) { return v1.second < v2.second; })->second}; 34 | 35 | // Draw distribution as histogram 36 | std::for_each(std::begin(plot_data), std::end(plot_data), 37 | [max_f, width](const std::pair& v) 38 | {std::cout << std::setw(3) << v.first << " -| " << string((width*v.second) / max_f, '*') << std::endl; }); 39 | } 40 | 41 | int main() 42 | { 43 | std::random_device rd; 44 | std::default_random_engine rng {rd()}; 45 | std::normal_distribution<> norm; 46 | double mu {}, sigma {}; 47 | const size_t sample_count{20000}; 48 | std::vector values(sample_count); 49 | while(true) 50 | { 51 | std::cout << "\nEnter values for the mean and standard deviation, or Ctrl+Z to end: "; 52 | if((std::cin >> mu).eof()) break; 53 | std::cin >> sigma; 54 | norm.param(Params{mu, sigma}); 55 | std::generate(std::begin(values), std::end(values), [&norm, &rng]{ return norm(rng); }); 56 | 57 | // Create data to plot histogram and plot it 58 | dist_plot(std::begin(values), std::end(values)); 59 | 60 | // Get the mean and standard deviation for the generated random values 61 | double mean {std::accumulate(std::begin(values), std::end(values), 0.0)/ values.size()}; 62 | 63 | std::transform(std::begin(values), std::end(values), std::begin(values), 64 | [&mean](double value) { return std::pow(value-mean,2); }); 65 | double s_dev{std::sqrt(std::accumulate(std::begin(values), std::end(values), 0.0) /(values.size() - 1))}; 66 | std::cout << "For generated values, mean = " << mean << " standard deviation = " << s_dev << std::endl; 67 | } 68 | } -------------------------------------------------------------------------------- /Chapter 4/Ex4_03/Ex4_03.cpp: -------------------------------------------------------------------------------- 1 | // Ex4_03.cpp 2 | // Stores one or more quotations for a name in a map 3 | #include // For standard streams 4 | #include // For toupper() 5 | #include // For map containers 6 | #include // For string class 7 | #include "Quotations.h" 8 | #include "Name.h" 9 | 10 | using std::string; 11 | 12 | // Read a name from standard input 13 | inline Name get_name() 14 | { 15 | Name name {}; 16 | std::cout << "Enter first name and second name: "; 17 | std::cin >> std::ws >> name; 18 | return name; 19 | } 20 | 21 | // Read a quotation from standard input 22 | inline string get_quote(const Name& name) 23 | { 24 | std::cout << "Enter the quotation for " << name 25 | << ". Enter * to end:\n"; 26 | string quote; 27 | std::getline(std::cin >> std::ws, quote, '*'); 28 | return quote; 29 | } 30 | 31 | int main() 32 | { 33 | std::map quotations; // Container for name/quotes pairs 34 | 35 | std::cout << "Enter 'A' to add a quote." 36 | "\nEnter 'L' to list all quotes." 37 | "\nEnter 'G' to get a quote." 38 | "\nEnter 'Q' to end.\n"; 39 | Name name {}; // Stores a name 40 | string quote {}; // Stores a quotation 41 | char command {}; // Stores a command 42 | 43 | while(command != 'Q') 44 | { 45 | std::cout << "\nEnter command: "; 46 | std::cin >> command; 47 | command = static_cast(std::toupper(command)); 48 | switch(command) 49 | { 50 | case 'Q': 51 | break; // Quit operations 52 | 53 | case 'A': 54 | name = get_name(); 55 | quote = get_quote(name); 56 | quotations[name] << quote; 57 | break; 58 | 59 | case 'G': 60 | { 61 | name = get_name(); 62 | const auto& quotes = quotations[name]; 63 | size_t count = quotes.size(); 64 | if(!count) 65 | { 66 | std::cout << "There are no quotes recorded for " 67 | << name << std::endl; 68 | continue; 69 | } 70 | size_t index {}; 71 | if(count > 1) 72 | { 73 | std::cout << "There are " << count << " quotes for " << name << ".\n" 74 | << "Enter an index from 0 to " << count - 1 << ": "; 75 | std::cin >> index; 76 | } 77 | std::cout << quotations[name][index] << std::endl; 78 | } 79 | break; 80 | case 'L': 81 | if(quotations.empty()) // Test for no pairs 82 | { 83 | std::cout << "\nNo quotations recorded for anyone." << std::endl; 84 | } 85 | // List all quotations 86 | for(const auto& pr : quotations) // Iterate over pairs 87 | { 88 | std::cout << '\n' << pr.first << std::endl; 89 | for(const auto& quote : pr.second) // Iterate over quotations 90 | { 91 | std::cout << " " << quote << std::endl; 92 | } 93 | } 94 | break; 95 | 96 | default: 97 | std::cout << " Command must be 'A', 'G', 'L', or 'Q'. Try again.\n"; 98 | continue; 99 | break; 100 | } 101 | } 102 | } -------------------------------------------------------------------------------- /Chapter 8/Ex8_07/Ex8_07.cpp: -------------------------------------------------------------------------------- 1 | // Ex8_07.cpp 2 | // Implementing a dice throwing game using discrete distributions 3 | #include // For discrete_distribution and random number generator 4 | #include // For array container 5 | #include // For pair type 6 | #include // For count(), remove() 7 | #include // For standard streams 8 | #include // For stream manipulators 9 | #include "Die.h" // Class to define a die 10 | 11 | // Random number generator available throughout the program code 12 | std::default_random_engine& rng() 13 | { 14 | static std::default_random_engine engine {std::random_device()()}; 15 | return engine; 16 | } 17 | 18 | int main() 19 | { 20 | size_t n_games {}; // Number of games played 21 | const size_t n_dice {4}; // Number of dice 22 | 23 | std::array dice // The dice 24 | { 25 | Die {3, 3, 3, 3, 3, 3}, 26 | Die {0, 0, 4, 4, 4, 4}, 27 | Die {1, 1, 1, 5, 5, 5}, 28 | Die {2, 2, 2, 2, 6, 6} 29 | }; 30 | 31 | std::cout << "For each game, select a die from the following by entering 1, 2, 3, or 4 (or Ctrl+Z to end):\n" 32 | << "die 1: 3 3 3 3 3 3\n" 33 | << "die 2: 0 0 4 4 4 4\n" 34 | << "die 3: 1 1 1 5 5 5\n" 35 | << "die 4: 2 2 2 2 6 6\n"; 36 | size_t you {}, me {}; // Stores index of my dice and your dice 37 | 38 | while(true) 39 | { 40 | std:: cout << "\nChoose a die: "; 41 | if((std::cin >> you).eof()) break; // For EOF - it's all over 42 | 43 | if(you == 0 || you > n_dice) // Only 1 to 4 allowed 44 | { 45 | std::cout << "Selection must be from 1 to 4, try again.\n"; 46 | continue; 47 | } 48 | 49 | // Choose my die as next in sequence 50 | me = you-- % n_dice; // you from 0 to 3, and me you+1 mod 4 51 | std::cout << "I'll choose: " << (me+1) << std::endl; 52 | 53 | 54 | // Throw the dice 55 | const size_t n_throws {15}; 56 | std::array, n_throws> goes; // Results of goes - pair 57 | std::generate(std::begin(goes), std::end(goes), // Make the throws 58 | [&dice, me, you] { return std::make_pair(dice[me].throw_it(), dice[you].throw_it()); }); 59 | 60 | // Output result of game 61 | std::cout << "\nGame " << ++n_games << ":\n"; 62 | 63 | // Output results of my throws... 64 | std::cout << "Me : "; 65 | std::for_each(std::begin(goes), std::end(goes), 66 | [](const std::pair& pr) 67 | { std::cout << std::setw(3) << pr.first; }); 68 | auto my_wins = std::count_if(std::begin(goes), std::end(goes), 69 | [](const std::pair& pr) { return pr.first > pr.second; }); 70 | std::cout << " My wins: " << std::setw(2) << std::right << my_wins 71 | << " I " << ((my_wins > n_throws / 2) ? "win!!" : "lose {:-(") << std::endl; 72 | 73 | // Output results of your corresponding throws - aligned below mine... 74 | std::cout << "You: "; 75 | std::for_each(std::begin(goes), std::end(goes), 76 | [](const std::pair& pr) 77 | { std::cout << std::setw(3) << pr.second; }); 78 | std::cout << " Your wins: " << std::setw(2) << std:: right << n_throws - my_wins << " You " << ((my_wins <= n_throws / 2) ? "win!!" : "lose!!!") << std::endl; 79 | } 80 | } -------------------------------------------------------------------------------- /Chapter 8/Ex8_06.cpp: -------------------------------------------------------------------------------- 1 | // Ex8_06.cpp 2 | // Checking out lognormal distributions 3 | #include // For distributions and random number generators 4 | #include // For generate(), for_each(), max_element(), transform() 5 | #include // For accumulate() 6 | #include // For back_inserter() 7 | #include // For vector container 8 | #include // For map container 9 | #include // For pow(), round(), log() functions 10 | #include // For standard streams 11 | #include // For stream manipulators 12 | #include 13 | using std::string; 14 | using Params = std::lognormal_distribution<>::param_type; 15 | 16 | // Template to plot a distribution from a range of sample values 17 | template 18 | void dist_plot(Iter& beg_iter, Iter& end_iter, size_t width = 90) 19 | { 20 | // Create data for distribution plot 21 | std::map plot_data; // Elements are pair 22 | 23 | // Make sure all values are present in the plot 24 | auto pr = std::minmax_element(beg_iter, end_iter, [](const double v1, const double v2) {return v1 < v2; }); 25 | for(int n {static_cast(*pr.first)}; n < static_cast(*pr.second); ++n) 26 | plot_data.emplace(n, 0); 27 | 28 | // Create the plot data 29 | std::for_each(beg_iter, end_iter, 30 | [&plot_data](double value) { ++plot_data[static_cast(std::round(value))]; }); 31 | 32 | // Find maximum frequency to be plotted - must fit within page width 33 | size_t max_f {std::max_element(std::begin(plot_data), std::end(plot_data), 34 | [](const std::pair& v1, const std::pair& v2) { return v1.second < v2.second; })->second}; 35 | 36 | // Draw distribution as histogram 37 | std::for_each(std::begin(plot_data), std::end(plot_data), 38 | [max_f, width](const std::pair& v) 39 | { if((width*v.second) / max_f > 0) 40 | std::cout << std::setw(3) << v.first << " -| " << string((width*v.second) / max_f, '*') << std::endl; 41 | }); 42 | } 43 | 44 | int main() 45 | { 46 | std::random_device rd; 47 | std::default_random_engine rng {rd()}; 48 | std::lognormal_distribution<> log_norm; 49 | double mu {}, sigma {}; 50 | const size_t sample_count {20000}; 51 | std::vector values(sample_count); 52 | std::vector log_values; 53 | while(true) 54 | { 55 | std::cout << "\nEnter values for the mean and standard deviation, or Ctrl+Z to end: "; 56 | if((std::cin >> mu).eof()) break; 57 | std::cin >> sigma; 58 | log_norm.param(Params {mu, sigma}); 59 | std::generate(std::begin(values), std::end(values), [&log_norm, &rng] { return log_norm(rng); }); 60 | 61 | // Create data to plot lognormal curve 62 | dist_plot(std::begin(values), std::end(values)); 63 | 64 | // Create logarithms of values 65 | std::vector log_values; 66 | std::transform(std::begin(values), std::end(values), std::back_inserter(log_values), 67 | [] (double v){ return log(v); }); 68 | 69 | // Create data to plot curve for logarithms of values 70 | std::cout << "\nThe distribution for logarithms of the values:\n"; 71 | dist_plot(std::begin(log_values), std::end(log_values)); 72 | 73 | // Get the mean and standard deviation - for the logarithms of the values 74 | double mean {std::accumulate(std::begin(log_values), std::end(log_values), 0.0) / log_values.size()}; 75 | 76 | std::transform(std::begin(log_values), std::end(log_values), std::begin(log_values), 77 | [&mean](double value) { return std::pow(value - mean, 2); }); 78 | double s_dev {std::sqrt(std::accumulate(std::begin(log_values), std::end(log_values), 0.0) / (log_values.size() - 1))}; 79 | std::cout << "For generated values, mean = " << mean << " standard deviation = " << s_dev << std::endl; 80 | } 81 | } -------------------------------------------------------------------------------- /Chapter 4/Ex4_07/Ex4_07.cpp: -------------------------------------------------------------------------------- 1 | // Ex4_07.cpp 2 | #include // For standard streams 3 | #include // For toupper() 4 | #include // For string class 5 | #include // For unordered_map container 6 | 7 | #include "Record_IO.h" 8 | #include "My_Templates.h" 9 | #include "Hash_Function_Objects.h" 10 | 11 | using std::string; 12 | using std::unordered_multimap; 13 | using Name = std::pair < string, string >; 14 | using Phone = std::tuple < string, string, string >; 15 | 16 | // Display command prompt 17 | void show_operations() 18 | { 19 | std::cout << "Operations:\n" 20 | << "A: Add an element.\n" 21 | << "D: Delete elements.\n" 22 | << "F: Find elements.\n" 23 | << "L: List all elements.\n" 24 | << "Q: Quit the program.\n\n"; 25 | } 26 | 27 | int main() 28 | { 29 | unordered_multimap by_name {8, NameHash()}; 30 | unordered_multimap by_number {8, PhoneHash()}; 31 | show_operations(); 32 | 33 | char choice {}; // Operation selection 34 | Phone number {}; // Records a number 35 | Name name {}; // Records a name 36 | 37 | while(std::toupper(choice) != 'Q') // Go until you quit... 38 | { 39 | std::cout << "Enter a command: "; 40 | std::cin >> choice; 41 | switch(std::toupper(choice)) 42 | { 43 | case 'A': // Add a record 44 | std::cout << "Enter first & second names, area code, exchange, and number separated by spaces:\n"; 45 | std::cin >> name >> number; 46 | by_name.emplace(name, number); // Create in place... 47 | by_number.emplace(number, name); // ...in both containers 48 | break; 49 | case 'D': // Delete records 50 | { 51 | std::cout << "Enter a name: "; // Only find by name 52 | auto pr = find_elements(by_name); 53 | auto count = std::distance(pr.first, pr.second); // Number of elements 54 | if(count == 1) 55 | { // If there's just the one... 56 | by_number.erase(pr.first->second); // ...delete from numbers container 57 | by_name.erase(pr.first); // ...delete from names container 58 | } 59 | else if(count > 1) 60 | { // There's more than one 61 | std::cout << "There are " << count << " records for " 62 | << pr.first->first << ". Delete all(Y or N)? "; 63 | std::cin >> choice; 64 | if(std::toupper(choice) == 'Y') 65 | { // Erase records from by_number container first 66 | for(auto iter = pr.first; iter != pr.second; ++iter) 67 | { 68 | by_number.erase(iter->second); 69 | } 70 | by_name.erase(pr.first, pr.second); // Now delete from by_name 71 | } 72 | } 73 | } 74 | break; 75 | 76 | case 'F': // Find a record 77 | std::cout << "Find by name(Y or N)? "; 78 | std::cin >> choice; 79 | if(std::toupper(choice) == 'Y') 80 | { 81 | std::cout << "Enter first name and second name: "; 82 | list_range(find_elements(by_name)); 83 | } 84 | else 85 | { 86 | std::cout << "Enter area code, exchange, and number separated by spaces: "; 87 | list_range(find_elements(by_number)); 88 | } 89 | break; 90 | 91 | case 'L': //List all records 92 | std::cout << "List by name(Y or N)? "; 93 | std::cin >> choice; 94 | if(std::toupper(choice) == 'Y') 95 | list_elements(by_name); 96 | else 97 | list_elements(by_number); 98 | break; 99 | case 'Q': 100 | break; 101 | 102 | default: 103 | std::cout << "Invalid command - try again.\n"; 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /Chapter 2/Ex2_07/Numeric_Range.h: -------------------------------------------------------------------------------- 1 | // Numeric_Range.h for Ex2_07 2 | // Defines class templates for a range and iterators for the range 3 | #ifndef NUMERIC_RANGE_H 4 | #define NUMERIC_RANGE_H 5 | 6 | #include // For standard exception types 7 | #include // For iterator type 8 | #include // For compile-time type checking 9 | 10 | template class Numeric_Iterator; // Template type declaration 11 | 12 | // Defines a numeric range 13 | template 14 | class Numeric_Range 15 | { 16 | static_assert(std::is_integral::value || std::is_floating_point::value, 17 | "Numeric_Range type argument must be numeric."); 18 | 19 | friend class Numeric_Iterator < T >; 20 | 21 | protected: 22 | T start; // First value in the range 23 | T step; // Increment between successive values 24 | size_t count; // Number of values in the range 25 | public: 26 | Numeric_Range(T first=0, T incr=1, size_t n=2) : start {first}, step {incr}, count {n}{} 27 | 28 | // Return the begin iterator for the range 29 | Numeric_Iterator begin(){ return Numeric_Iterator(*this); } 30 | 31 | // Return the end iterator for the range 32 | Numeric_Iterator end() 33 | { 34 | Numeric_Iterator end_iter(*this); 35 | end_iter.value = start + count*step; // End iterator value is one step over the last 36 | return end_iter; 37 | } 38 | }; 39 | 40 | // Iterator class template- it's a forward iterator 41 | template 42 | class Numeric_Iterator : public std::iterator < std::forward_iterator_tag, T > 43 | { 44 | friend class Numeric_Range < T >; 45 | 46 | protected: 47 | Numeric_Range& range; // Reference to the range for this iterator 48 | T value; // Value pointed to 49 | 50 | public: 51 | explicit Numeric_Iterator(Numeric_Range& a_range) : range {a_range}, value {a_range.start} {}; 52 | 53 | // Assignment operator 54 | Numeric_Iterator& operator=(const Numeric_Iterator& src) 55 | { 56 | range = src.range; 57 | value = src.value; 58 | } 59 | 60 | // Dereference an iterator 61 | T& operator*() 62 | { 63 | // When the value is one step more than the last, it's an end iterator 64 | if (value == static_cast(range.start + range.count*range.step)) 65 | { 66 | throw std::logic_error("Cannot dereference an end iterator."); 67 | } 68 | return value; 69 | } 70 | 71 | // Prefix increment operator 72 | Numeric_Iterator& operator++() 73 | { 74 | // When the value is one step more than the last, it's an end iterator 75 | if (value == static_cast(range.start + range.count*range.step)) 76 | { 77 | throw std::logic_error("Cannot increment an end iterator."); 78 | } 79 | value += range.step; // Increment the value by the range step 80 | return *this; 81 | } 82 | 83 | // Postfix increment operator 84 | Numeric_Iterator operator++(int) 85 | { 86 | // When the value is one step more than the last, it's an end iterator 87 | if (value == static_cast(range.start + range.count*range.step)) 88 | { 89 | throw std::logic_error("Cannot increment an end iterator."); 90 | } 91 | auto temp = *this; 92 | value += range.step; // Increment the value by the range step 93 | return temp; // The iterator before it's incremented 94 | } 95 | 96 | // Comparisons 97 | bool operator<(const Numeric_Iterator& iter) const { return value < iter.value; } 98 | bool operator==(const Numeric_Iterator& iter) const { return value == iter.value; } 99 | bool operator!=(const Numeric_Iterator& iter) const { return value != iter.value; } 100 | bool operator>(const Numeric_Iterator& iter) const { return value > iter.value; } 101 | bool operator<=(const Numeric_Iterator& iter) const { *this < iter || *this == iter; } 102 | bool operator>=(const Numeric_Iterator& iter) const { *this > iter || *this == iter; } 103 | }; 104 | #endif 105 | -------------------------------------------------------------------------------- /Chapter 3/Ex3_01.cpp: -------------------------------------------------------------------------------- 1 | // Ex3_01.cpp 2 | // A simple calculator using stack containers 3 | 4 | #include // For pow() function 5 | #include // For standard streams 6 | #include // For stack container 7 | #include // For remove() 8 | #include // For runtime_error exception 9 | #include // For string class 10 | using std::string; 11 | 12 | // Returns value for operator precedence 13 | inline size_t precedence(const char op) 14 | { 15 | if (op == '+' || op == '-') 16 | return 1; 17 | if (op == '*' || op == '/') 18 | return 2; 19 | if (op == '^') 20 | return 3; 21 | throw std::runtime_error {string {"invalid operator in precedence() function: "} + op}; 22 | } 23 | 24 | // Execute an operation 25 | double execute(std::stack& ops, std::stack& operands) 26 | { 27 | double result {}; 28 | double rhs {operands.top()}; // Get rhs... 29 | operands.pop(); // ...and delete from stack 30 | double lhs {operands.top()}; // Get lhs... 31 | operands.pop(); // ...and delete from stack 32 | 33 | switch (ops.top()) // Execute current op 34 | { 35 | case '+': 36 | result = lhs + rhs; 37 | break; 38 | case '-': 39 | result = lhs - rhs; 40 | break; 41 | case '*': 42 | result = lhs * rhs; 43 | break; 44 | case '/': 45 | result = lhs / rhs; 46 | break; 47 | case '^': 48 | result = std::pow(lhs, rhs); 49 | break; 50 | default: 51 | throw std::runtime_error {string{"invalid operator in execute() function: "} + ops.top()}; 52 | } 53 | ops.pop(); // Delete op just executed 54 | operands.push(result); 55 | return result; 56 | } 57 | 58 | int main() 59 | { 60 | std::stack operands; // Push-down stack of operands 61 | std::stack operators; // Push-down stack of operators 62 | string exp; // Expression to be evaluated 63 | std::cout << "An arithmetic expression can include the operators +, -, *, /, and ^ for exponentiation." << std::endl; 64 | try 65 | { 66 | while (true) 67 | { 68 | std::cout << "Enter an arithmetic expression and press Enter - enter an empty line to end:" << std::endl; 69 | std::getline(std::cin, exp, '\n'); 70 | if (exp.empty()) break; 71 | 72 | // Remove spaces 73 | exp.erase(std::remove(std::begin(exp), std::end(exp), ' '), std::end(exp)); 74 | 75 | size_t index {}; // Index to expression string 76 | 77 | // Every expression must start with a numerical operand 78 | operands.push(std::stod(exp, &index)); // Push the first (lhs) operand on the stack 79 | 80 | while (true) 81 | { 82 | operators.push(exp[index++]); // Push the operator on to the stack 83 | 84 | // Get rhs operand 85 | size_t i {}; // Index to substring 86 | operands.push(std::stod(exp.substr(index), &i)); // Push rhs operand 87 | index += i; // Increment expression index 88 | 89 | if (index == exp.length()) // If we are at end of exp... 90 | { 91 | while (!operators.empty()) // ...execute outstanding ops 92 | execute(operators, operands); 93 | break; 94 | } 95 | 96 | // If we reach here, there's another op... 97 | // If there's a previous op of equal or higher precedence execute it 98 | while (!operators.empty() && precedence(exp[index]) <= precedence(operators.top())) 99 | execute(operators, operands); // Execute previous op. 100 | } 101 | std::cout << "result = " << operands.top() << std::endl; 102 | } 103 | } 104 | catch (const std::exception& e) 105 | { 106 | std::cerr << e.what() << std::endl; 107 | } 108 | std::cout << "Calculator ending..." << std::endl; 109 | } 110 | -------------------------------------------------------------------------------- /Chapter 10/Ex10_03/gaussian.cpp: -------------------------------------------------------------------------------- 1 | // Gaussian.cpp 2 | // Functions to implement Gaussian elimination 3 | #include // For valarray, slice, abs() 4 | #include // For vector container 5 | #include // For ostream iterator 6 | #include // For copy_n() 7 | #include // For swap() 8 | #include // For standard streams 9 | #include // For stream manipulators 10 | using std::valarray; 11 | using std::slice; 12 | 13 | // Read the data for n equations in n unknowns 14 | valarray get_data(size_t n) 15 | { 16 | valarray equations(n*(n + 1)); // n rows of n+1 elements 17 | std::cout << "Enter " << n + 1 18 | << " values for each of "<< n << " equations.\n" 19 | << "(i.e. including coefficients that are zero and the rhs:\n"; 20 | for(auto& coeff: equations) std::cin >> coeff; 21 | return equations; 22 | } 23 | 24 | // Selects the best pivot in row n (rows indexed from 0) 25 | void set_pivot(const valarray& equations, std::vector& row_slices, size_t n) 26 | { 27 | size_t n_rows {row_slices.size()}; // Number of rows 28 | size_t row_len {n_rows + 1}; // Row length = number of columns 29 | 30 | // Create an object containing the elements in column n, starting row n 31 | valarray column {equations[slice {n*row_len + n, n_rows - n, row_len}]}; 32 | column = std::abs(column); // Absolute values 33 | 34 | size_t max_index {}; // Index to best pivot in column 35 | for(size_t i {1}; i < column.size(); ++i) // Find index for max value 36 | { 37 | if(column[max_index] < column[i]) max_index = i; 38 | } 39 | 40 | if(max_index > 0) 41 | { // Pivot is not the 1st in column - so swap rows to make it so 42 | std::swap(row_slices[n], row_slices[n + max_index]); 43 | } 44 | else if(!column[0]) // Check for zero pivot 45 | { // When pivot is 0, matrix is singular 46 | std::cerr << "No solution. Ending program." << std::endl; 47 | std::exit(1); 48 | } 49 | } 50 | 51 | // Reduce the equations matrix to row echelon form 52 | // The equations object stores the matrix for n equations in n unknowns 53 | // The elements in the row_slices container define the rows in equations 54 | void reduce_matrix(valarray& equations, std::vector& row_slices) 55 | { 56 | size_t n_rows {row_slices.size()}; // Number of rows 57 | size_t row_len {n_rows + 1}; // Row length 58 | for(size_t row {}; row < n_rows - 1; ++row) // From 1st row to second-to-last 59 | { 60 | set_pivot(equations, row_slices, row); // Find best pivot 61 | 62 | // Create an object containing element values for pivot row 63 | valarray pivot_row {equations[row_slices[row]]}; 64 | auto pivot = pivot_row[row]; 65 | pivot_row /= pivot; // Divide pivot row by pivot 66 | 67 | // For each of the rows following the current row, 68 | // subtract the pivot row multiplied by the row element in the pivot column 69 | for(size_t next_row {row + 1}; next_row < n_rows; ++next_row) 70 | { 71 | equations[row_slices[next_row]] -= equations[row_slices[next_row].start() + row] * pivot_row; 72 | } 73 | } 74 | } 75 | 76 | // Perform back substitution and return the solution 77 | valarray back_substitution(valarray& equations, const std::vector& row_slices) 78 | { 79 | size_t n_rows{row_slices.size()}; 80 | size_t row_len {n_rows + 1}; 81 | 82 | // Divide the last row by the second to last element 83 | // Multiply the last row by the second to last element in each row and subtract it from the row. 84 | // Repeat for all the other rows 85 | valarray results(n_rows); // Stores the solution 86 | for(int row {static_cast(n_rows - 1)}; row >= 0; --row) 87 | { 88 | equations[row_slices[row]] /= valarray(equations[row_slices[row].start() + row], row_len); 89 | valarray last_row {equations[row_slices[row]]}; 90 | results[row] = last_row[n_rows]; // Store value for x[row] 91 | for(int i {}; i < row; ++i) 92 | { 93 | equations[row_slices[i]] -= equations[row_slices[i].start() + row] * last_row; 94 | } 95 | } 96 | return results; 97 | } 98 | -------------------------------------------------------------------------------- /Chapter 10/Ex10_05/gaussian.cpp: -------------------------------------------------------------------------------- 1 | // Gaussian.cpp 2 | // Functions to implement Gaussian elimination 3 | #include // For valarray, slice, abs() 4 | #include // For vector container 5 | #include // For ostream iterator 6 | #include // For copy_n() 7 | #include // For swap() 8 | #include // For standard streams 9 | #include // For stream manipulators 10 | using std::valarray; 11 | using std::slice; 12 | 13 | // Read the data for n equations in n unknowns 14 | valarray get_data(size_t n) 15 | { 16 | valarray equations(n*(n + 1)); // n rows of n+1 elements 17 | std::cout << "Enter " << n + 1 18 | << " values for each of "<< n << " equations.\n" 19 | << "(i.e. including coefficients that are zero and the rhs:\n"; 20 | for(auto& coeff: equations) std::cin >> coeff; 21 | return equations; 22 | } 23 | 24 | // Selects the best pivot in row n (rows indexed from 0) 25 | void set_pivot(const valarray& equations, std::vector& row_slices, size_t n) 26 | { 27 | size_t n_rows {row_slices.size()}; // Number of rows 28 | size_t row_len {n_rows + 1}; // Row length = number of columns 29 | 30 | // Create an object containing the elements in column n, starting row n 31 | valarray column {equations[slice {n*row_len + n, n_rows - n, row_len}]}; 32 | column = std::abs(column); // Absolute values 33 | 34 | size_t max_index {}; // Index to best pivot in column 35 | for(size_t i {1}; i < column.size(); ++i) // Find index for max value 36 | { 37 | if(column[max_index] < column[i]) max_index = i; 38 | } 39 | 40 | if(max_index > 0) 41 | { // Pivot is not the 1st in column - so swap rows to make it so 42 | std::swap(row_slices[n], row_slices[n + max_index]); 43 | } 44 | else if(!column[0]) // Check for zero pivot 45 | { // When pivot is 0, matrix is singular 46 | std::cerr << "No solution. Ending program." << std::endl; 47 | std::exit(1); 48 | } 49 | } 50 | 51 | // Reduce the equations matrix to row echelon form 52 | // The equations object stores the matrix for n equations in n unknowns 53 | // The elements in the row_slices container define the rows in equations 54 | void reduce_matrix(valarray& equations, std::vector& row_slices) 55 | { 56 | size_t n_rows {row_slices.size()}; // Number of rows 57 | size_t row_len {n_rows + 1}; // Row length 58 | for(size_t row {}; row < n_rows - 1; ++row) // From 1st row to second-to-last 59 | { 60 | set_pivot(equations, row_slices, row); // Find best pivot 61 | 62 | // Create an object containing element values for pivot row 63 | valarray pivot_row {equations[row_slices[row]]}; 64 | auto pivot = pivot_row[row]; 65 | pivot_row /= pivot; // Divide pivot row by pivot 66 | 67 | // For each of the rows following the current row, 68 | // subtract the pivot row multiplied by the row element in the pivot column 69 | for(size_t next_row {row + 1}; next_row < n_rows; ++next_row) 70 | { 71 | equations[row_slices[next_row]] -= equations[row_slices[next_row].start() + row] * pivot_row; 72 | } 73 | } 74 | } 75 | 76 | // Perform back substitution and return the solution 77 | valarray back_substitution(valarray& equations, const std::vector& row_slices) 78 | { 79 | size_t n_rows{row_slices.size()}; 80 | size_t row_len {n_rows + 1}; 81 | 82 | // Divide the last row by the second to last element 83 | // Multiply the last row by the second to last element in each row and subtract it from the row. 84 | // Repeat for all the other rows 85 | valarray results(n_rows); // Stores the solution 86 | for(int row {static_cast(n_rows - 1)}; row >= 0; --row) 87 | { 88 | equations[row_slices[row]] /= valarray(equations[row_slices[row].start() + row], row_len); 89 | valarray last_row {equations[row_slices[row]]}; 90 | results[row] = last_row[n_rows]; // Store value for x[row] 91 | for(int i {}; i < row; ++i) 92 | { 93 | equations[row_slices[i]] -= equations[row_slices[i].start() + row] * last_row; 94 | } 95 | } 96 | return results; 97 | } 98 | -------------------------------------------------------------------------------- /Chapter 8/Ex8_03.cpp: -------------------------------------------------------------------------------- 1 | // Ex8_03.cpp 2 | // Dealing cards at random with a distribution 3 | #include // For standard streams 4 | #include // For ostream stream 5 | #include // For stream manipulators 6 | #include // For iterators and begin() and end() 7 | #include // For random number generators & distributions 8 | #include // For pair template 9 | #include // For vector container 10 | #include // For list container 11 | #include // For stack container 12 | #include // For array container 13 | #include // For string class 14 | #include // For is_same predicate 15 | 16 | using std::string; 17 | enum class Suit : size_t {Clubs, Diamonds, Hearts, Spades}; 18 | enum class Face : size_t {Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace}; 19 | using Card = std::pair; // The type of a card 20 | using Hand = std::list; // Type for a hand of cards 21 | using Deck = std::list; // Type for a deck of cards 22 | using Hands = std::vector; // Type for a container of hands 23 | using Range = std::uniform_int_distribution::param_type; 24 | 25 | // Stream insertion operator for a Card object 26 | std::ostream& operator<<(std::ostream& out, const Card& card) 27 | { 28 | static std::array suits {"C", "D", "H", "S"}; // Suit names 29 | static std::array values {"2", "3", "4", "5", "6", // Face value names 30 | "7", "8", "9", "10", "J", "Q", "K", "A"}; 31 | string suit {suits[static_cast(card.first)]}; 32 | string value {values[static_cast(card.second)]}; 33 | return out << std::setw(2) << value << suit; 34 | } 35 | 36 | 37 | // Random number generator available throughout the program code 38 | std::default_random_engine& rng() 39 | { 40 | static std::default_random_engine engine {std::random_device()()}; 41 | return engine; 42 | } 43 | 44 | // Uniform distribution for type int available throughout the program code 45 | std::uniform_int_distribution& dist() 46 | { 47 | static std::uniform_int_distribution d ; 48 | return d; 49 | } 50 | 51 | // Initialize a deck to a full set of 52 cards 52 | Deck& init_deck(Deck& deck) 53 | { 54 | static std::array suits{Suit::Clubs, Suit::Diamonds, Suit::Hearts, Suit::Spades}; 55 | static std::array values {Face::Two, Face::Three, Face::Four, Face::Five, Face::Six, 56 | Face::Seven, Face::Eight, Face::Nine, Face::Ten, 57 | Face::Jack, Face::Queen, Face::King, Face::Ace}; 58 | deck.clear(); 59 | for(auto&& suit : suits) 60 | for(auto&& value : values) 61 | deck.emplace_back(Card {suit, value}); 62 | return deck; 63 | } 64 | 65 | // Deal the complete deck 66 | void deal(Hands& hands, Deck& deck) 67 | { 68 | auto d = dist(); 69 | while(!deck.empty()) 70 | { 71 | for(auto&& hand : hands) 72 | { 73 | size_t max_index = deck.size() - 1; 74 | d.param(Range{0, max_index}); 75 | auto iter = std::begin(deck); 76 | std::advance(iter, d(rng())); 77 | hand.push_back(*iter); 78 | deck.erase(iter); 79 | } 80 | } 81 | } 82 | 83 | // Sort cards in hands in card sequence 84 | void sort_hands(Hands& hands) 85 | { 86 | for(auto&& hand : hands) 87 | hand.sort([](const auto& crd1, const auto crd2) { return crd1.first < crd2.first || 88 | (crd1.first == crd2.first && crd1.second < crd2.second); }); 89 | } 90 | 91 | // Output all hands 92 | void show_hands(const Hands& hands) 93 | { 94 | for(auto&& hand : hands) 95 | { 96 | std::copy(std::begin(hand), std::end(hand), std::ostream_iterator {std::cout, " "}); 97 | std::cout << std::endl; 98 | } 99 | } 100 | 101 | int main() 102 | { 103 | // Create the deck 104 | Deck deck; 105 | init_deck(deck); 106 | 107 | // Create and deal the hands 108 | Hands hands(4); 109 | deal(hands, deck); 110 | 111 | // Sort and show the hands 112 | sort_hands(hands); 113 | show_hands(hands); 114 | } -------------------------------------------------------------------------------- /Chapter 3/Ex3_02/Ex3_02.cpp: -------------------------------------------------------------------------------- 1 | // Ex3_02.cpp 2 | // Simulating a supermarket with multiple checkouts 3 | #include // For standard streams 4 | #include // For stream manipulators 5 | #include // For vector container 6 | #include // For string class 7 | #include // For accumulate() 8 | #include // For min_element & max_element 9 | #include // For random number generation 10 | #include "Customer.h" 11 | #include "Checkout.h" 12 | 13 | using std::string; 14 | using distribution = std::uniform_int_distribution<>; 15 | 16 | // Output histogram of service times 17 | void histogram(const std::vector& v, int min) 18 | { 19 | string bar (60, '*'); // Row of asterisks for bar 20 | for (size_t i {}; i < v.size(); ++i) 21 | { 22 | std::cout << std::setw(3) << i+min << " " // Service time is index + min 23 | << std::setw(4) << v[i] << " " // Output no. of occurrences 24 | << bar.substr(0, v[i]) // ...and that no. of asterisks 25 | << (v[i] > static_cast(bar.size()) ? "...": "") 26 | << std::endl; 27 | } 28 | } 29 | 30 | int main() 31 | { 32 | std::random_device random_n; 33 | 34 | // Setup minimum & maximum checkout periods - times in minutes 35 | int service_t_min {2}, service_t_max {15}; 36 | distribution service_t_d {service_t_min, service_t_max}; 37 | 38 | // Setup minimum & maximum number of customers at store opening 39 | int min_customers {15}, max_customers {20}; 40 | distribution n_1st_customers_d {min_customers, max_customers}; 41 | 42 | // Setup minimum & maximum intervals between customer arrivals 43 | int min_arr_interval {1}, max_arr_interval {5}; 44 | distribution arrival_interval_d {min_arr_interval, max_arr_interval}; 45 | 46 | size_t n_checkouts {}; 47 | std::cout << "Enter the number of checkouts in the supermarket: "; 48 | std::cin >> n_checkouts; 49 | if (!n_checkouts) 50 | { 51 | std::cout << "Number of checkouts must be greater than 0. Setting to 1." << std::endl; 52 | n_checkouts = 1; 53 | } 54 | 55 | std::vector checkouts {n_checkouts}; 56 | std::vector service_times(service_t_max-service_t_min+1); 57 | 58 | // Add customers waiting when store opens 59 | int count {n_1st_customers_d(random_n)}; 60 | std::cout << "Customers waiting at store opening: " << count << std::endl; 61 | int added {}; 62 | int service_t {}; 63 | while (added++ < count) 64 | { 65 | service_t = service_t_d(random_n); 66 | std::min_element(std::begin(checkouts), std::end(checkouts))->add(Customer(service_t)); 67 | ++service_times[service_t - service_t_min]; 68 | } 69 | 70 | size_t time {}; // Stores time elapsed 71 | const size_t total_time {600}; // Duration of simulation - minutes 72 | size_t longest_q {}; // Stores longest checkout queue length 73 | 74 | // Period until next customer arrives 75 | int new_cust_interval {arrival_interval_d(random_n)}; 76 | 77 | // Run store simulation for period of total_time minutes 78 | while (time < total_time) // Simulation loops over time 79 | { 80 | ++time; // Increment by 1 minute 81 | 82 | // New customer arrives when arrival interval is zero 83 | if (--new_cust_interval == 0) 84 | { 85 | service_t = service_t_d(random_n); // Random customer service time 86 | std::min_element(std::begin(checkouts), std::end(checkouts))->add(Customer(service_t)); 87 | ++service_times[service_t - service_t_min]; // Record service time 88 | 89 | // Update record of the longest queue occurring 90 | for (auto & checkout : checkouts) 91 | longest_q = std::max(longest_q, checkout.qlength()); 92 | 93 | new_cust_interval = arrival_interval_d(random_n); 94 | } 95 | 96 | // Update the time in the checkouts - serving the 1st customer in each queue 97 | for (auto & checkout : checkouts) 98 | checkout.time_increment(); 99 | } 100 | 101 | std::cout << "Maximum queue length = " << longest_q << std::endl; 102 | std::cout << "\nHistogram of service times:\n"; 103 | histogram(service_times, service_t_min); 104 | 105 | std::cout << "\nTotal number of customers today: " 106 | << std::accumulate(std::begin(service_times), std::end(service_times), 0) 107 | << std::endl; 108 | } 109 | 110 | 111 | -------------------------------------------------------------------------------- /Chapter 6/Ex6_02/Ex6_02.cpp: -------------------------------------------------------------------------------- 1 | // Ex6_02.cpp 2 | // Sorting and inplace merging 3 | #include // For standard streams 4 | #include // For string class 5 | #include // For sort(), inplace_merge() 6 | #include // For greater 7 | #include // For vector container 8 | #include // For pair template type 9 | #include // For map container 10 | #include // For stream and back insert iterators 11 | #include "Account.h" 12 | #include "Transaction.h" 13 | #include "Compare_Names.h" 14 | 15 | using std::string; 16 | using first_name = string; 17 | using second_name = string; 18 | using Name = std::pair; 19 | using Account_Number = size_t; 20 | 21 | // Read the name of an account holder 22 | Name get_holder_name(Account_Number number) 23 | { 24 | std::cout << "Enter the holder's first and second names for account number " << number << ": "; 25 | string first {}; 26 | string second {}; 27 | std::cin >> first >> second; 28 | return std::make_pair(first, second); 29 | } 30 | 31 | int main() 32 | { 33 | std::vector transactions; 34 | 35 | std::cout << "Enter each transaction as:\n 5 digit account number amount credit(true or false).\n" 36 | << "Enter Ctrl+Z to end.\n"; 37 | 38 | // Read 1st set of transactions 39 | std::copy(std::istream_iterator {std::cin}, std::istream_iterator {}, std::back_inserter(transactions)); 40 | std::cin.clear(); // Clear the EOF flag for the stream 41 | 42 | // Sort 1st set in descending account sequence 43 | std::stable_sort(std::begin(transactions), std::end(transactions), std::greater<>()); 44 | 45 | // List the transactions 46 | std::cout << "First set of transactions after sorting...\n"; 47 | std::copy(std::begin(transactions), std::end(transactions), std::ostream_iterator{std::cout, "\n"}); 48 | 49 | 50 | // Read 2nd set of transactions 51 | std::cout << "\nEnter more transactions:\n"; 52 | std::copy(std::istream_iterator {std::cin}, std::istream_iterator {}, std::back_inserter(transactions)); 53 | std::cin.clear(); // Clear the EOF flag for the stream 54 | 55 | // List the transactions 56 | std::cout << "\nSorted first set of transactions with second set appended...\n"; 57 | std::copy(std::begin(transactions), std::end(transactions), std::ostream_iterator{std::cout, "\n"}); 58 | 59 | // Sort second set into descending account sequence 60 | auto iter = std::is_sorted_until(std::begin(transactions), std::end(transactions), std::greater<>()); 61 | std::stable_sort(iter, std::end(transactions), std::greater<>()); 62 | 63 | // List the transactions 64 | std::cout << "\nSorted first set of transactions with sorted second set appended...\n"; 65 | std::copy(std::begin(transactions), std::end(transactions), std::ostream_iterator{std::cout, "\n"}); 66 | 67 | // Merge transactions in place 68 | std::inplace_merge(std::begin(transactions), iter, std::end(transactions), std::greater<>()); 69 | 70 | // List the transactions 71 | std::cout << "\nMerged sets of transactions...\n"; 72 | std::copy(std::begin(transactions), std::end(transactions), std::ostream_iterator{std::cout, "\n"}); 73 | 74 | // Process transactions creating Account objects when necessary 75 | std::map accounts; 76 | for(const auto& tr : transactions) 77 | { 78 | Account_Number number = tr.get_acc_number(); 79 | auto iter = accounts.find(number); 80 | if(iter == std::end(accounts)) 81 | iter = accounts.emplace(number, Account {number, get_holder_name(number)}).first; 82 | 83 | if(iter->second.apply_transaction(tr)) 84 | { 85 | const auto& name = iter->second.get_name(); 86 | std::cout << "\nAccount number " << number 87 | << " for " << name.first << " " < accs; 94 | for(const auto& pr :accounts) 95 | accs.push_back(pr.second); 96 | 97 | // List accounts after sorting in name sequence 98 | std::stable_sort(std::begin(accs), std::end(accs), Compare_Names()); 99 | std::copy(std::begin(accs), std::end(accs), std::ostream_iterator < Account > {std::cout, "\n"}); 100 | } -------------------------------------------------------------------------------- /Chapter 5/Ex5_01/Ex5_01.cpp: -------------------------------------------------------------------------------- 1 | // Ex5_01.cpp 2 | // Registering students on Subjects 3 | #include // For standard streams 4 | #include // For string class 5 | #include // For map container 6 | #include // For set container 7 | #include // For vector container 8 | #include // For random number generation 9 | #include // For for_each(), count_if() 10 | #include "Student.h" 11 | #include "List_Course.h" 12 | 13 | using std::string; 14 | using Distribution = std::uniform_int_distribution; 15 | using Subject = string; // A course subject 16 | using Subjects = std::vector; // A vector of subjects 17 | using Group = std::set; // A student group for a subject 18 | using Students = std::vector; // All the students 19 | using Course = std::pair; // A pair representing a course 20 | using Courses = std::map; // The container for courses 21 | 22 | static std::default_random_engine gen_value; 23 | 24 | // Creates a vector of students 25 | Students create_students() 26 | { 27 | Students students; 28 | string first_names[] {"Ann", "Jim", "Eve", "Dan", "Ted"}; 29 | string second_names[] {"Smith", "Jones", "Howe", "Watt", "Beck"}; 30 | 31 | for(const auto& first : first_names) 32 | { 33 | for(const auto& second : second_names) 34 | { 35 | students.emplace_back(first, second); 36 | } 37 | } 38 | return students; 39 | } 40 | 41 | // Create a group of students for a subject 42 | Group make_group(const Students& students, size_t group_size, const Distribution& choose_student) 43 | { 44 | Group group; // The group of students for a subject 45 | 46 | // Select students for the subject group 47 | // Insert a random student into the group until there are group_size students in it 48 | while(group.size() < group_size) 49 | { 50 | group.insert(students[choose_student(gen_value)]); 51 | } 52 | return group; 53 | } 54 | 55 | int main() 56 | { 57 | Students students = create_students(); 58 | Subjects subjects {"Biology", "Physics", "Chemistry", "Mathematics", "Astronomy", 59 | "Drama", "Politics", "Philosophy", "Economics"}; 60 | Courses courses; // All the courses with subject keys 61 | 62 | 63 | size_t min_subjects {4}; // Minimum number of Subjects per student 64 | size_t min_group {min_subjects}; // Minimum no. of students per course 65 | size_t max_group {(students.size()*min_subjects)/subjects.size()}; // Maximum initial students per course 66 | 67 | // Create groups of students for each subject 68 | Distribution group_size {min_group, max_group}; // Distribution for students per course 69 | Distribution choose_student {0, students.size() - 1}; // Random student selector 70 | for(const auto& subject : subjects) 71 | courses.emplace(subject, make_group(students, group_size(gen_value), choose_student)); 72 | 73 | Distribution choose_course {0, subjects.size() - 1}; // Random course selector 74 | 75 | // Every student must attend a minimum number of Subjects... 76 | // ...but students being students we must check... 77 | for(const auto& student : students) 78 | { // Verify the minimum number of Subjects has been met 79 | 80 | // Count how many Subjects the student is on 81 | size_t course_count = std::count_if(std::begin(courses), std::end(courses), [&student](const Course& course) 82 | { return course.second.count(student); }); 83 | if(course_count >= min_subjects) continue; // On to the next student 84 | 85 | // Minimum no. of Subjects not signed up for 86 | size_t additional {min_subjects - course_count}; // Additional no. of Subjects needed 87 | if(!course_count) // If none have been chosen... 88 | std::cout << student << " is work-shy, having signed up for NO Subjects!\n"; 89 | else // Some have - but E for effort 90 | std::cout << student << " is only signed up for " << course_count << " Subjects!\n"; 91 | 92 | std::cout << "Registering " << student << " for " << additional 93 | << " more course" << (additional > 1 ? "s" : "") << ".\n\n"; 94 | 95 | // Register for additional Subjects up to the minimum 96 | while(course_count < min_subjects) 97 | if((courses.find(subjects[choose_course(gen_value)])->second.insert(student)).second) ++course_count; 98 | } 99 | 100 | // Output the students attending each course 101 | std::for_each(std::begin(courses), std::end(courses), List_Course()); 102 | std::cout << std::endl; 103 | } -------------------------------------------------------------------------------- /Chapter 4/Ex4_04.cpp: -------------------------------------------------------------------------------- 1 | // Ex4_04.cpp 2 | // Using tuples and pairs 3 | #include // For standard streams 4 | #include // For stream manipulators 5 | #include // For string class 6 | #include // For toupper() 7 | #include // For map container 8 | #include // For vector container 9 | #include // For tuple template 10 | #include // For sort() template 11 | 12 | using std::string; 13 | using Name = std::pair < string, string >; // Defines a name pair 14 | using DOB = std::tuple ; // Month, day, year tuple 15 | using Details = std::tuple < DOB, size_t, string > ; // DOB, height(inches), occupation 16 | using Element_type = std::map::value_type; // Type of map element 17 | using People = std::map; // Type of people container 18 | 19 | // Read people from standard input 20 | void get_people(People& people) 21 | { 22 | string first {}, second {}; // Stores name inputs 23 | size_t month {}, day {}, year {}; // Stores dOB input 24 | size_t height {}; // Stores height input 25 | string occupation {}; // Stores occupation input 26 | char answer {'Y'}; 27 | 28 | while(std::toupper(answer) == 'Y') 29 | { 30 | std::cout << "Enter a first name and a second name: "; 31 | std::cin >> std::ws >> first >> second; 32 | 33 | std::cout << "Enter date of birth as month day year (integers): "; 34 | std::cin >> month >> day >> year; 35 | DOB dob {month, day, year}; // Create DOB tuple 36 | 37 | std::cout << "Enter height in inches: "; 38 | std::cin >> height; 39 | 40 | std::cout << "Enter occupation: "; 41 | std::getline(std::cin >> std::ws, occupation, '\n'); 42 | 43 | // Create the map element in place- a pair containing a Name pair and a tuple object 44 | people.emplace(std::make_pair(Name {first, second}, std::make_tuple(dob, height, occupation))); 45 | 46 | std::cout << "Do you want to enter another(Y or N): "; 47 | std::cin >> answer; 48 | } 49 | } 50 | 51 | // Output name, DOB, and occupation 52 | void list_DOB_Job(const People& people) 53 | { 54 | DOB dob; 55 | string occupation {}; 56 | std::cout << '\n'; 57 | for(auto iter = std::begin(people); iter != std::end(people); ++iter) 58 | { 59 | std::tie(dob, std::ignore, occupation) = iter->second; 60 | std::cout << std::setw(20) << std::left << (iter->first.first + " " + iter->first.second) 61 | << "DOB: " << std::right << std::setw(2) << std::get<0>(dob) << "-" 62 | << std::setw(2) << std::setfill('0') << std::get<1>(dob) << "-" 63 | << std::setw(4) << std::get<2>(dob) << std::setfill(' ') 64 | << " Occupation: " << occupation << std::endl; 65 | } 66 | } 67 | 68 | // Output the map elements in a chosen sequence determined by a function object 69 | template 70 | void list_sorted_people(const People& people, Compare comp) 71 | { 72 | std::vector folks; 73 | for(const auto& pr : people) 74 | folks.push_back(&pr); 75 | 76 | // Lambda to compare via pointers 77 | auto ptr_comp = [&comp](const Element_type* pr1, const Element_type* pr2)->bool 78 | { return comp(*pr1, *pr2); }; 79 | 80 | std::sort(std::begin(folks), std::end(folks), ptr_comp); // Sort the pointers to elements 81 | 82 | // Output the sorted elements 83 | DOB dob {}; 84 | size_t height {}; 85 | string occupation {}; 86 | std::cout << '\n'; 87 | 88 | for(const auto& p : folks) 89 | { 90 | std::tie(dob, height, occupation) = p->second; 91 | std::cout << std::setw(20) << std::left << (p->first.first + " " + p->first.second) 92 | << "DOB: " << std::right << std::setw(2) << std::get<0>(dob) << "-" 93 | << std::setw(2) << std::setfill('0') << std::get<1>(dob) << "-" 94 | << std::setw(4) << std::get<2>(dob) << std::setfill(' ') 95 | << " Height: " << height 96 | << " Occupation: " << occupation << std::endl; 97 | } 98 | } 99 | 100 | int main() 101 | { 102 | std::map people; // Records of the people 103 | get_people(people); // Read all the people 104 | 105 | std::cout << "\nThe DOB & jobs are: \n"; 106 | list_DOB_Job(people); // List names, DOB & job 107 | 108 | // Define height comparison for people 109 | auto comp = [](const Element_type& pr1, const Element_type& pr2) 110 | { 111 | return std::get<1>(pr1.second) < std::get<1>(pr2.second); 112 | }; 113 | 114 | std::cout << "\nThe people in height order are : \n"; 115 | list_sorted_people(people, comp); 116 | } -------------------------------------------------------------------------------- /Chapter 4/Ex4_06.cpp: -------------------------------------------------------------------------------- 1 | // Ex4_06.cpp 2 | // Analyzing how and when the number of buckets in an unordered_map container increases 3 | #include // For standard streams 4 | #include // For stream manipulators 5 | #include // For string class 6 | #include // For unordered_map container 7 | #include // For vector container 8 | #include // For max_element() algorithm 9 | 10 | using std::string; 11 | using std::unordered_map; 12 | 13 | // Outputs number of elements in each bucket 14 | void list_bucket_counts(const std::vector& counts) 15 | { 16 | for(size_t i {}; i < counts.size(); ++i) 17 | { 18 | std::cout << "bucket[" << std::setw(2) << i << "] = " << counts[i] << " "; 19 | if((i + 1) % 6 == 0) std::cout << '\n'; 20 | } 21 | std::cout << std::endl; 22 | } 23 | 24 | int main() 25 | { 26 | unordered_map people; 27 | float mlf {people.max_load_factor()}; // Current maximum load factor 28 | size_t n_buckets {people.bucket_count()}; // Number of buckets in container 29 | 30 | std::vector bucket_counts (people.bucket_count()); // Records number of elements per bucket 31 | string name {"Name"}; // Key - with value appended 32 | size_t value {1}; // Element value 33 | size_t max_count {8192}; // Maximum number of elements to insert 34 | auto lf = people.load_factor(); // Current load factor 35 | bool rehash {false}; // Records when rehash occurs 36 | 37 | while(mlf <= 1.5f) // Loop until max load factor is 1.5 38 | { 39 | std::cout << "\n\n***************New Container***************" 40 | << "\nNumber of buckets: " << n_buckets << " Maximum load factor: " << mlf << std::endl; 41 | 42 | // Insert max elements in container 43 | for(size_t n_elements {}; n_elements < max_count; ++n_elements) 44 | { 45 | lf = people.load_factor(); // Record load factor 46 | people.emplace("name" + std::to_string(++value), value); 47 | auto new_count = people.bucket_count(); // Current bucket count 48 | if(new_count > n_buckets) // If bucket count increases... 49 | { // Output info 50 | std::cout << "\nBucket count increased to " << new_count 51 | << ". Load factor was " << lf << " and is now " << people.load_factor() 52 | << "\nMaximum elements in a bucket was " 53 | << *std::max_element(std::begin(bucket_counts), std::end(bucket_counts)) << std::endl; 54 | if(n_buckets <= 64) 55 | { 56 | std::cout << "Bucket counts before increase were: " << std::endl; 57 | list_bucket_counts(bucket_counts); 58 | } 59 | n_buckets = new_count; // Update bucket count 60 | bucket_counts = std::vector < size_t > (n_buckets); // New vector for counts 61 | rehash = true; // Record rehash occurred 62 | } 63 | 64 | // Record current bucket counts 65 | for(size_t i {}; i < n_buckets; ++i) 66 | bucket_counts[i] = people.bucket_size(i); 67 | 68 | if(rehash) // If the container was rehashed... 69 | { // ...output info 70 | rehash = false; // Reset rehash indicator 71 | 72 | std::cout << "\nRehashed container. Bucket count is " << n_buckets << ". Element count is " << people.size() 73 | << "\nMaximum element count in a bucket is now " 74 | << *std::max_element(std::begin(bucket_counts), std::end(bucket_counts)) << std::endl; 75 | 76 | if(n_buckets <= 64) // If no more than 64 buckets... 77 | { 78 | std::cout << "\nBucket counts after rehash are:\n"; 79 | list_bucket_counts(bucket_counts); 80 | } 81 | } 82 | } 83 | std::cout << "Final state for this container is:\n" 84 | << "Bucket count: " << people.bucket_count() << " Element count: " << people.size() 85 | << " Maximum element count in a bucket: " 86 | << *std::max_element(std::begin(bucket_counts), std::end(bucket_counts)) << std::endl; 87 | value = 1; // Reset key suffix 88 | people = unordered_map(); // New empty container 89 | n_buckets = people.bucket_count(); 90 | bucket_counts = std::vector < size_t >(n_buckets); // New vector for bucket counts 91 | mlf += 0.25f; // Increase max load factor... 92 | people.max_load_factor(mlf); // ...and set for container 93 | } 94 | } -------------------------------------------------------------------------------- /Chapter 3/Ex3_05/Ex3_05.cpp: -------------------------------------------------------------------------------- 1 | // Ex3_05.cpp 2 | // Using smart pointer to simulate supermarket checkouts 3 | #include // For standard streams 4 | #include // For stream manipulators 5 | #include // For vector container 6 | #include // For string class 7 | #include // For accumulate() 8 | #include // For min_element & max_element 9 | #include // For random number generation 10 | #include // For smart pointers 11 | #include "Checkout.h" 12 | #include "Customer.h" 13 | 14 | using std::string; 15 | using distribution = std::uniform_int_distribution<>; 16 | using PCheckout = std::unique_ptr; 17 | 18 | // Output histogram of service times 19 | void histogram(const std::vector& v, int min) 20 | { 21 | string bar (60, '*'); // Row of asterisks for bar 22 | for (size_t i {}; i < v.size(); ++i) 23 | { 24 | std::cout << std::setw(3) << i+min << " " // Service time is index + min 25 | << std::setw(4) << v[i] << " " // Output no. of occurrences 26 | << bar.substr(0, v[i]) // ...and that no. of asterisks 27 | << (v[i] > static_cast(bar.size()) ? "...": "") 28 | << std::endl; 29 | } 30 | } 31 | 32 | int main() 33 | { 34 | std::random_device random_n; 35 | 36 | // Setup minimum & maximum checkout periods - times in minutes 37 | int service_t_min {2}, service_t_max {15}; 38 | std::uniform_int_distribution<> service_t_d {service_t_min, service_t_max}; 39 | 40 | // Setup minimum & maximum number of customers at store opening 41 | int min_customers {15}, max_customers {20}; 42 | distribution n_1st_customers_d {min_customers, max_customers}; 43 | 44 | // Setup minimum & maximum intervals between customer arrivals 45 | int min_arr_interval {1}, max_arr_interval {5}; 46 | distribution arrival_interval_d {min_arr_interval, max_arr_interval}; 47 | 48 | size_t n_checkouts {}; 49 | std::cout << "Enter the number of checkouts in the supermarket: "; 50 | std::cin >> n_checkouts; 51 | if(!n_checkouts) 52 | { 53 | std::cout << "Number of checkouts must be greater than 0. Setting to 1." << std::endl; 54 | n_checkouts = 1; 55 | } 56 | 57 | std::vector checkouts; 58 | checkouts.reserve(n_checkouts); // Reserve memory for pointers 59 | 60 | // Create the checkouts 61 | for (size_t i {}; i < n_checkouts; ++i) 62 | checkouts.push_back(std::make_unique()); 63 | std::vector service_times(service_t_max-service_t_min+1); 64 | 65 | // Add customers waiting when store opens 66 | int count {n_1st_customers_d(random_n)}; 67 | std::cout << "Customers waiting at store opening: " << count << std::endl; 68 | int added {}; 69 | int service_t {}; 70 | 71 | // Define comparison lambda for pointers to checkouts 72 | auto comp = [](const PCheckout& pc1, const PCheckout& pc2){ return *pc1 < *pc2; }; 73 | while (added++ < count) 74 | { 75 | service_t = service_t_d(random_n); 76 | auto iter = std::min_element(std::begin(checkouts), std::end(checkouts), comp); 77 | (*iter)->add(std::make_unique(service_t)); 78 | ++service_times[service_t - service_t_min]; 79 | 80 | } 81 | 82 | size_t time {}; // Stores time elapsed 83 | const size_t total_time {600}; // Duration of simulation - minutes 84 | size_t longest_q {}; // Stores longest checkout queue length 85 | 86 | // Period until next customer arrives 87 | int new_cust_interval {arrival_interval_d(random_n)}; 88 | 89 | // Run store simulation for period of total_time minutes 90 | while (time < total_time) // Simulation loops over time 91 | { 92 | ++time; // Increment by 1 minute 93 | 94 | // New customer arrives when arrival interval is zero 95 | if (--new_cust_interval == 0) 96 | { 97 | service_t = service_t_d(random_n); // Random customer service time 98 | (*std::min_element(std::begin(checkouts), std::end(checkouts), comp))->add(std::make_unique(service_t)); 99 | ++service_times[service_t - service_t_min]; // Record service time 100 | 101 | // Update record of the longest queue length 102 | for (auto& pcheckout : checkouts) 103 | longest_q = std::max(longest_q, pcheckout->qlength()); 104 | 105 | new_cust_interval = arrival_interval_d(random_n); 106 | } 107 | 108 | // Update the time in the checkouts - serving the 1st customer in each queue 109 | for (auto& pcheckout : checkouts) 110 | pcheckout->time_increment(); 111 | } 112 | 113 | std::cout << "Maximum queue length = " << longest_q << std::endl; 114 | std::cout << "\nHistogram of service times:\n"; 115 | histogram(service_times, service_t_min); 116 | 117 | std::cout << "\nTotal number of customers today: " 118 | << std::accumulate(std::begin(service_times), std::end(service_times), 0) 119 | << std::endl; 120 | } 121 | 122 | 123 | -------------------------------------------------------------------------------- /Chapter 7/Ex7_05.cpp: -------------------------------------------------------------------------------- 1 | // Ex7_05.cpp 2 | // Apply some algorithms to plotting curves 3 | // To get the output with the correct aspect ratio, set the characters 4 | // in the standard output stream destination to a square font, such as 8 x 8 pixels 5 | #include // For standard streams 6 | #include // For iterators and begin() and end() 7 | #include // For string class 8 | #include // For vector container 9 | #include // For algorithms 10 | #include // For sin(), cos() 11 | using std::string; 12 | using Point = std::pair; 13 | 14 | static const double pi {3.1415926}; 15 | 16 | // Function template to plot a range of x,y values on cout 17 | template 18 | void plot(Iterator begin_iter, Iterator end_iter, string name = "Curve", size_t n_x = 100) 19 | { // n_x is plot width in characters, so it's the number of characters along the x axis 20 | 21 | // Comparison functions for x and for y 22 | auto x_comp = [](const Point& p1, const Point& p2) {return p1.first < p2.first; }; 23 | auto y_comp = [](const Point& p1, const Point& p2) {return p1.second < p2.second; }; 24 | 25 | // Minimum and maximum x values 26 | auto min_x = std::min_element(begin_iter, end_iter, x_comp)->first; 27 | auto max_x = std::max_element(begin_iter, end_iter, x_comp)->first; 28 | 29 | // Step length for output - same step applies to x and y 30 | double step {(max_x - min_x) / (n_x + 1)}; 31 | 32 | // Minimum and maximum y values 33 | auto min_y = std::min_element(begin_iter, end_iter, y_comp)->second; 34 | auto max_y = std::max_element(begin_iter, end_iter, y_comp)->second; 35 | 36 | size_t nrows {1 + static_cast(1 + (max_y - min_y)/step)}; 37 | std::vector rows(nrows, string(n_x + 1, ' ')); 38 | 39 | // Create x-axis at y=0 if this is within range of points 40 | if(max_y > 0.0 && min_y <= 0.0) 41 | rows[1 + static_cast(max_y/step)] = string(n_x+1, '-'); 42 | 43 | // Create y-axis at x=0 if this is within range of points 44 | if(max_x > 0.0 && min_x <= 0.0) 45 | { 46 | size_t x_axis {static_cast(-min_x/step)}; 47 | std::for_each(std::begin(rows), std::end(rows), 48 | [x_axis](string& row) { row[x_axis] = row[x_axis] == '-' ? '+' : '|'; }); 49 | } 50 | 51 | std::cout << "\n\n " << name << ":\n\n"; 52 | // Generate the rows for output 53 | auto y {max_y}; // Upper y for current output row 54 | for(auto& row : rows) 55 | { 56 | // Find points to be included in an output row 57 | std::vector row_pts; // Stores points for this row 58 | std::copy_if(begin_iter, end_iter, std::back_inserter(row_pts), 59 | [&y, &step](const Point& p) { return p.second < y + step && p.second >= y; }); 60 | 61 | std::for_each(std::begin(row_pts), std::end(row_pts), // Set * for pts in the row 62 | [&row, min_x, step](const Point& p) {row[static_cast((p.first - min_x) / step)] = '*'; }); 63 | y -= step; 64 | } 65 | // Output the plot - which is all the rows. 66 | std::copy(std::begin(rows), std::end(rows), std::ostream_iterator{std::cout, "\n"}); 67 | std::cout << std::endl; 68 | } 69 | 70 | // Generate x,y points on curve y = sin(x) for x values 0 to 4? 71 | std::vector sine_curve(size_t n_pts = 100) 72 | { // n_pts is number of data points for the curve 73 | std::vector x_values(n_pts); 74 | double value {}; 75 | double step {4 * pi / (n_pts - 1)}; 76 | std::generate(std::begin(x_values), std::end(x_values), 77 | [&value, &step]() { double v {value}; 78 | value += step; 79 | return v; }); 80 | std::vector curve_pts; 81 | std::transform(std::begin(x_values), std::end(x_values), std::back_inserter(curve_pts), 82 | [](double x) { return Point {x, sin(x)}; }); 83 | return curve_pts; 84 | } 85 | 86 | // Generate x,y points on a cardioid defined by parametric equations: 87 | // x = a(2cos(t) - cos(2t)) y = a(sin(t) - sin(2t) 88 | // A cardioid is the path of a point on one circle 89 | // that is rolling around another with the same radius 90 | std::vector cardioid_curve(double r = 1.0, size_t n_pts = 100) 91 | { // n_pts is number of data points 92 | double step = 2 * pi / (n_pts - 1); // Step length for x and y 93 | double t_value {}; // Curve parameter 94 | 95 | // Create parameter values that define the curve 96 | std::vector t_values(n_pts); 97 | std::generate(std::begin(t_values), std::end(t_values), [&t_value, step]() { auto value = t_value; 98 | t_value += step; 99 | return value; }); 100 | 101 | // Function to define an x,y point on the cardioid for a given t 102 | auto cardioid = [r](double t) { return Point {r*(2 * cos(t) + cos(2 * t)), r*(2 * sin(t) + sin(2 * t))}; }; 103 | 104 | // Create the points for the cardioid 105 | std::vector curve_pts; 106 | std::transform(std::begin(t_values), std::end(t_values), std::back_inserter(curve_pts), 107 | cardioid); 108 | return curve_pts; 109 | } 110 | 111 | int main() 112 | { 113 | auto curve1 = sine_curve(50); 114 | plot(std::begin(curve1), std::end(curve1), "Sine curve", 90); 115 | auto curve2 = cardioid_curve(1.5, 120); 116 | plot(std::begin(curve2), std::end(curve2), "Cardioid", 60); 117 | } -------------------------------------------------------------------------------- /Chapter 5/Ex5_02/Ex5_02.cpp: -------------------------------------------------------------------------------- 1 | // Ex5_02.cpp 2 | // Registering smart pointers to students on Subjects 3 | #include // For standard streams 4 | #include // For string class 5 | #include // For map container 6 | #include // For set container 7 | #include // For vector container 8 | #include // For random number generation 9 | #include // For for_each(), count_if() 10 | #include // For shared_ptr and weak_ptr 11 | #include "Student.h" 12 | #include "List_Course.h" 13 | 14 | using std::string; 15 | using Distribution = std::uniform_int_distribution; 16 | using Subject = string; // A course subject 17 | using Subjects = std::vector; // A vector of subjects 18 | using Group = std::set, std::owner_less>>; // A student group for a subject 19 | using Students = std::vector>; // All the students 20 | using Course = std::pair; // A pair representing a course 21 | using Courses = std::map; // The container for courses 22 | 23 | static std::default_random_engine gen_value; 24 | 25 | // Creates a vector of smart pointers to students 26 | Students create_students() 27 | { 28 | Students students; 29 | string first_names[] {"Ann", "Jim", "Eve", "Dan", "Ted"}; 30 | string second_names[] {"Smith", "Jones", "Howe", "Watt", "Beck"}; 31 | 32 | for(const auto& first : first_names) 33 | for(const auto& second : second_names) 34 | { 35 | students.emplace_back(std::make_shared(first, second)); 36 | } 37 | 38 | return students; 39 | } 40 | 41 | // Create a group of students for a subject 42 | Group make_group(const Students& students, size_t group_size, const Distribution& choose_student) 43 | { 44 | Group group; // The group of students for a subject 45 | 46 | // Select students for the subject group 47 | size_t count {}; // No. of students in the group 48 | std::pair pr; // Stores return from inserting a student 49 | 50 | // Insert a random student into the group until there are group_size students in it 51 | while(count < group_size) 52 | { // Increment count for a successful insertion... 53 | if(group.insert(students[choose_student(gen_value)]).second) ++count; 54 | } 55 | return group; 56 | } 57 | 58 | int main() 59 | { 60 | Students students = create_students(); 61 | Subjects subjects {"Biology", "Physics", "Chemistry", "Mathematics", "Astronomy", 62 | "Drama", "Politics", "Philosophy", "Economics"}; 63 | Courses courses; // All the courses with subject keys 64 | 65 | 66 | size_t min_subjects {4}; // Minimum number of Subjects per student 67 | size_t min_group {min_subjects}; // Minimum no. of students per course 68 | size_t max_group {(students.size()*min_subjects) / subjects.size()}; // Maximum initial students per course 69 | 70 | // Create groups of students for each subject 71 | Distribution group_size {min_group, max_group}; // Distribution for students per course 72 | Distribution choose_student {0, students.size() - 1}; // Random student selector 73 | for(const auto& subject : subjects) 74 | courses.emplace(subject, make_group(students, group_size(gen_value), choose_student)); 75 | 76 | Distribution choose_course {0, subjects.size() - 1}; // Random course selector 77 | 78 | // Every student must attend a minimum number of Subjects... 79 | // ...but students being students we must check... 80 | for(const auto& student : students) 81 | { // Verify the minimum number of Subjects has been met 82 | 83 | // Count how many Subjects the student is on 84 | size_t course_count = std::count_if(std::begin(courses), std::end(courses), [&student](const Course& course) 85 | { return course.second.count(student); }); 86 | if(course_count >= min_subjects) continue; // On to the next student 87 | 88 | // Minimum no. of Subjects not signed up for 89 | size_t additional {min_subjects - course_count}; // Additional no. of Subjects needed 90 | if(!course_count) // If none have been chosen... 91 | std::cout << *student << " is work-shy, having signed up for NO Subjects!\n"; 92 | else // Some have - but E for effort 93 | std::cout << *student << " is only signed up for " << course_count << " Subjects!\n"; 94 | 95 | std::cout << "Registering " << *student << " for " << additional 96 | << " more course" << (additional > 1 ? "s" : "") << ".\n\n"; 97 | 98 | // Register for additional Subjects up to the minimum 99 | while(course_count < min_subjects) 100 | if((courses.find(subjects[choose_course(gen_value)])->second.insert(student)).second) ++course_count; 101 | } 102 | 103 | // Output the students attending each course 104 | std::for_each(std::begin(courses), std::end(courses), List_Course()); 105 | std::cout << std::endl; 106 | } 107 | --------------------------------------------------------------------------------