diff --git a/chapter_01/examples/CMakeLists.txt b/chapter_01/examples/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..2d5c64a0cd2c6875c949ebb70926a71cb2f066ee --- /dev/null +++ b/chapter_01/examples/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.28) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +project(cxx_course_examples CXX) + + +FILE (GLOB sources ./ *.cc) +foreach(source ${sources}) + get_filename_component(withoutext "${source}" NAME_WE) + add_executable("${withoutext}" "${source}") +endforeach() + + diff --git a/chapter_01/examples/binforms.cc b/chapter_01/examples/binforms.cc new file mode 100644 index 0000000000000000000000000000000000000000..edc62a5d59c120375fc4563ed5d44ff496a6ede7 --- /dev/null +++ b/chapter_01/examples/binforms.cc @@ -0,0 +1,38 @@ +#include "binform.hh" +#include <iostream> + +template <class T> +void handle() +{ + std::cout << "Enter value: "; + T v; + std::cin >> v; + cxx_course::showbits(v); +} + +auto main() -> int +{ + bool keeplooping{true}; + while (keeplooping) { + int ch{}; + std::cout << "Select type (1: int, 2: unsigned int, 3: long, 4: unsigned long, 5: float, 6: double): "; + std::cin >> ch; + switch (ch) { + case 1: + handle<int>(); break; + case 2: + handle<unsigned int>(); break; + case 3: + handle<long>(); break; + case 4: + handle<unsigned long>(); break; + case 5: + handle<float>(); break; + case 6: + handle<double>(); break; + case 0: keeplooping = false; break; + default:; + }; + } +} + diff --git a/chapter_01/examples/check_prime.cc b/chapter_01/examples/check_prime.cc new file mode 100644 index 0000000000000000000000000000000000000000..ed41b4ddf1f4c6f231b13854f84330dbc9eb1432 --- /dev/null +++ b/chapter_01/examples/check_prime.cc @@ -0,0 +1,20 @@ +#include <iostream> + +auto is_prime(unsigned int n) -> bool +{ + // recipe to tell if n is a prime or not + return false; +} + +auto main() -> int +{ + std::cout << "Number to check: "; + unsigned int inp{}; + std::cin >> inp; + if (is_prime(n)) + std::cout << "Yes, that's a prime.\n"; + else + std::cout << "Not a prime.\n"; +} + + diff --git a/chapter_01/examples/dangling_pr/outer_ptr.cc b/chapter_01/examples/dangling_pr/outer_ptr.cc new file mode 100644 index 0000000000000000000000000000000000000000..e2d23a62cf2021e3e46abbedb74aaa34f6fe1f14 --- /dev/null +++ b/chapter_01/examples/dangling_pr/outer_ptr.cc @@ -0,0 +1,26 @@ +#include <iostream> +#include <string> + +auto main(int argc, char* argv[]) -> int +{ + unsigned long* p = nullptr; + if (argc > 1) { + auto i = std::stoul(argv[1]); + + p = &i; + // Since p outlives i, storing address + // of i in p is a bad idea + + std::cout << "p is pointing at " << p << " storing a value " << *p << "\n"; + } else { + std::cout << "Needs one integer command line argument!\n"; + } + + // At this point, if argc > 1, p is pointing to + // a location where there was a variable called i + // which has run out of scope. Accessing p here is + // undefined behaviour. + if (p) + std::cout << "p is pointing at " << p << " storing a value " << *p << "\n"; +} + diff --git a/chapter_01/examples/dangling_pr/ref_heap.cc b/chapter_01/examples/dangling_pr/ref_heap.cc new file mode 100644 index 0000000000000000000000000000000000000000..ebd40845b072e3a2c02598f9d385663edf4e2317 --- /dev/null +++ b/chapter_01/examples/dangling_pr/ref_heap.cc @@ -0,0 +1,15 @@ +#include <vector> +#include <iostream> + +auto main() -> int +{ + std::vector v{1, 2, 3}; + const auto& vstart = v.front(); + v.push_back(4); + v.push_back(5); + v.push_back(6); + v.push_back(7); + v.push_back(8); + std::cout << "Start element of v = " << vstart << "\n"; +} + diff --git a/chapter_01/examples/dangling_pr/ref_local.cc b/chapter_01/examples/dangling_pr/ref_local.cc new file mode 100644 index 0000000000000000000000000000000000000000..b58d4f1644d1236572e068784020c2f19cace3a3 --- /dev/null +++ b/chapter_01/examples/dangling_pr/ref_local.cc @@ -0,0 +1,16 @@ +#include <iostream> +#include <string> + +auto f(double x) -> double& +{ + auto y = x * x; + return y; +} + +auto main() -> int +{ + auto a = 4.0; + auto&& z = f(a); + std::cout << z << "\n"; +} + diff --git a/chapter_01/examples/exception.cc b/chapter_01/examples/exception.cc new file mode 100644 index 0000000000000000000000000000000000000000..ad6a36692767e3ba48fed3db6e4977aa10229951 --- /dev/null +++ b/chapter_01/examples/exception.cc @@ -0,0 +1,32 @@ +#include <iostream> +#include <stdexcept> + +double f(double x) +{ + double answer=1; + if (x>=0 and x<10) { + while (x>0) { + answer*=x; + x-=1; + } + } else { + throw(std::invalid_argument("Bad parameter value " + std::to_string(x))); + } + return answer; +} + + +int main() +{ + double x=9.0; + try { + std::cout<<"Enter start point : "; + std::cin >> x; + auto res=f(x); + std::cout <<"The result is "<<res<<'\n'; + } catch (std::exception &ex) { + std::cerr<<"Cought exception "<<ex.what()<<'\n'; + } +} + + diff --git a/chapter_01/examples/fibonacci.cc b/chapter_01/examples/fibonacci.cc new file mode 100644 index 0000000000000000000000000000000000000000..e7717436308b93747a0f4bd210ee8df7a70c316a --- /dev/null +++ b/chapter_01/examples/fibonacci.cc @@ -0,0 +1,16 @@ +#include <iostream> +#include <limits> +#include <format> + +auto main() -> int +{ + using namespace std; + size_t umax{ numeric_limits<size_t>::max() }; + unsigned nfib = 0; + size_t f0{ 0 }, f1{ 1 }; + // Insert your code here + + cout << format(R"(The largest number in the Fibonacci sequence under {0:} is {1:}, +and there are {2:} entries under {0:} in that sequence. +)" , umax, f1, nfib); +} diff --git a/chapter_01/examples/gcd.cc b/chapter_01/examples/gcd.cc new file mode 100644 index 0000000000000000000000000000000000000000..baf9a4ebf1c7ca7cebe5af549e239e57ce04ed31 --- /dev/null +++ b/chapter_01/examples/gcd.cc @@ -0,0 +1,21 @@ +#include <iostream> + +auto euclid_gcd(unsigned long smaller, unsigned long larger) -> unsigned long +{ + if (smaller > larger) + std::swap(smaller, larger); + // Fill in your code to implement Euclid's algorithm here. + + return ? ? ? ; +} + +auto main(int argc, char* argv[]) -> int +{ + if (argc != 3) { + std::cout << "Usage:\n" + << argv[0] << " number1 number2\n"; + return 1; + } + unsigned long n1 = std::stoul(argv[1]), n2 = std::stoul(argv[2]); + std::cout << euclid_gcd(n1, n2) << "\n"; +} diff --git a/chapter_01/examples/hanoi.cc b/chapter_01/examples/hanoi.cc new file mode 100644 index 0000000000000000000000000000000000000000..c2f76cd036cef0f88786d51038e887d2d360f740 --- /dev/null +++ b/chapter_01/examples/hanoi.cc @@ -0,0 +1,20 @@ +#include <iostream> +#include <string> + +auto the_other(int i, int j) -> int { return 3 - i - j; } + +void transfer(unsigned long n, int from, int to) +{ + int oth = the_other(from, to); + if (n > 1) + transfer(n - 1, from, oth); + std::cout << n << ": " << from << "->" << to << "\n"; + if (n > 1) + transfer(n - 1, oth, to); +} + +auto main() -> int +{ + size_t N = 6; + transfer(N, 0, 1); +} diff --git a/chapter_01/examples/hello_qa.cc b/chapter_01/examples/hello_qa.cc new file mode 100644 index 0000000000000000000000000000000000000000..59919565aa469df4b65a6c1601897b46cc4e4d9d --- /dev/null +++ b/chapter_01/examples/hello_qa.cc @@ -0,0 +1,12 @@ +// examples/hello_qa.cc +#include <string> +#include <iostream> + +auto main() -> int +{ + std::string name; + std::cout << "What's your name ? "; + std::cin >> name; + std::cout << "Hello, " << name << "\n"; +} + diff --git a/chapter_01/examples/hello_xyz.cc b/chapter_01/examples/hello_xyz.cc new file mode 100644 index 0000000000000000000000000000000000000000..b75bb497765a0e4bb3416e3ce21170dc63544215 --- /dev/null +++ b/chapter_01/examples/hello_xyz.cc @@ -0,0 +1,10 @@ +// examples/hello_xyz.cc +#include <iostream> +auto main(int argc, char* argv[]) -> int +{ + std::cout << "Hello, "; + if (argc > 1) + std::cout << argv[1] << "!\n"; + else + std::cout << "world!\n"; +} diff --git a/chapter_01/examples/midpt.cc b/chapter_01/examples/midpt.cc new file mode 100644 index 0000000000000000000000000000000000000000..c132f0b3bbe0817cae56882629682412c750b00f --- /dev/null +++ b/chapter_01/examples/midpt.cc @@ -0,0 +1,17 @@ +// examples/midpt.cc +#include <iostream> + +auto mid(int a, int b) -> int +{ + // recipe needed! + return a; +} +auto main() -> int +{ + int i = 0, j = 0; + std::cout << "Enter i, j: "; + std::cin >> i >> j; + std::cout << "A number half way between " << i << " and " << j + << " is " << mid(i, j) << "\n"; +} + diff --git a/chapter_01/examples/min_of_three.cc b/chapter_01/examples/min_of_three.cc new file mode 100644 index 0000000000000000000000000000000000000000..b43152f7a23ae9b0f65be45e8cf11e741508b55b --- /dev/null +++ b/chapter_01/examples/min_of_three.cc @@ -0,0 +1,16 @@ +// examples/min_of_three.cc +#include <iostream> + +auto min_of_three(int a, int b, int c) -> int +{ + // recipe needed! + return a; +} +auto main() -> int +{ + int i = 0, j = 0, k = 0; + std::cout << "Enter i, j and k: "; + std::cin >> i >> j >> k; + std::cout << "The smallest of the three is " << min_of_three(i, j, k) << "\n"; +} + diff --git a/chapter_01/examples/namespaces.cc b/chapter_01/examples/namespaces.cc new file mode 100644 index 0000000000000000000000000000000000000000..f942db055453c300fe5af13cf7e6dac3368592de --- /dev/null +++ b/chapter_01/examples/namespaces.cc @@ -0,0 +1,16 @@ +#include <iostream> + +using namespace std; + +namespace UnitedKingdom { +string London = "Big city"; +} +namespace UnitedStates { +string London = "Small town in Kentucky"; +} +auto main() -> int +{ + using namespace UnitedKingdom; + cout << London << "\n"; + cout << UnitedStates::London << "\n"; +} diff --git a/chapter_01/examples/namespaces2.cc b/chapter_01/examples/namespaces2.cc new file mode 100644 index 0000000000000000000000000000000000000000..1a1d03329ebe3796960c5bcd7a4ebd50229bdde7 --- /dev/null +++ b/chapter_01/examples/namespaces2.cc @@ -0,0 +1,22 @@ +#include <iostream> +namespace UnitedKingdom { +std::string London = "Big city"; +} +namespace UnitedStates { +namespace KY { + std::string London = "Small town in Kentucky"; +} +namespace OH { + std::string London = "Small town in Ohio"; +} +} +// The following definition is ok since C++17 +//namespace mylibrary::onefeature { +// double solve(int i); +//} +auto main() -> int +{ + namespace USOH = UnitedStates::OH; + std::cout << USOH::London << "\n"; +} + diff --git a/chapter_01/examples/numsort.cc b/chapter_01/examples/numsort.cc new file mode 100644 index 0000000000000000000000000000000000000000..9ca16d003d611b59fe54b00b40daf7b2f5bc91b8 --- /dev/null +++ b/chapter_01/examples/numsort.cc @@ -0,0 +1,36 @@ +#include <iostream> +#include <string> +#include <fstream> +#include <filesystem> +#include <vector> +#include <ranges> +#include <algorithm> + +namespace fs = std::filesystem; +auto as_lines(fs::path file) -> std::vector<std::string> +{ + std::ifstream fin{ file }; + std::string line; + std::vector<std::string> lines; + while (getline(fin, line)) lines.push_back(line); + return lines; +} + +auto main(int argc, char* argv[]) -> int +{ + if (argc != 2) { + std::cerr << "Usage:\n" + << argv[0] << " filename\n"; + return 1; + } + auto content = as_lines(argv[1]); + std::ranges::sort(content, + [](auto l1, auto l2) { + return std::stod(l1) < std::stod(l2); + } + ); + for (std::string_view line : content) { + std::cout << line << "\n"; + } +} + diff --git a/chapter_01/examples/onespace.cc b/chapter_01/examples/onespace.cc new file mode 100644 index 0000000000000000000000000000000000000000..8b1037a9b6ea80f37411ae0ec4146aa917b80ae9 --- /dev/null +++ b/chapter_01/examples/onespace.cc @@ -0,0 +1,24 @@ +// examples/onespace.cc +#include <iostream> + +auto main(int argc, char* argv[]) -> int +{ + std::string line; + while (getline(std::cin, line)) { + if (line.empty()) { + continue; + } + bool sp{true}; + for (auto c : line) { + if (isspace(c)) { + if (not sp) std::cout << '\t'; + sp = true; + } else { + sp = false; + std::cout << c; + } + } + std::cout << "\n"; + } +} + diff --git a/chapter_01/examples/pyscope2.py b/chapter_01/examples/pyscope2.py new file mode 100644 index 0000000000000000000000000000000000000000..c49fc39bc9b3eba33c188c0ec1cd5ec1038338a5 --- /dev/null +++ b/chapter_01/examples/pyscope2.py @@ -0,0 +1,17 @@ +import sys +if __name__ == "__main__": + if len(sys.argv) > 1: + N = int(sys.argv[1]) + else: + N = 5 + +def fact(n): + if n > 1: + return n * fact(n-1) + return 1 +while N > 0: + print(fact(N)) + if N % 4 == 0: + fact = N * (N - 1) / 2 + N = N -1 + diff --git a/chapter_01/examples/raw1.cc b/chapter_01/examples/raw1.cc new file mode 100644 index 0000000000000000000000000000000000000000..0781800a602f8463ce7eba4483e5bf99ccb6738a --- /dev/null +++ b/chapter_01/examples/raw1.cc @@ -0,0 +1,8 @@ +#include <iostream> +#include <string> + +int main() +{ + std::cout << "Use a single backslash character at the end of the line to continue input to the next line, as shown ...\n" + << "OBJ=a.o \\\n\tb.o\\\n\tc.o\n"; +} diff --git a/chapter_01/examples/rawstring.cc b/chapter_01/examples/rawstring.cc new file mode 100644 index 0000000000000000000000000000000000000000..2c57d2dce8aa6781bc8fd2e48e75663bc6b1e1f7 --- /dev/null +++ b/chapter_01/examples/rawstring.cc @@ -0,0 +1,14 @@ +#include <iostream> +#include <string> + +int main() +{ + // clang-format off + std::string s = R"xyz(This is a " raw " C++11 string.)xyz"; + std::cout << s << '\n'; + s = R"(Inside a raw string \n does not create a new line.)"; + std::cout << s << '\n'; + s = R"(The regular expression to match a sequence of up to 3 digits is \d{3})"; + // clang-format on + std::cout << s << '\n'; +} diff --git a/chapter_01/examples/sharedptr.cc b/chapter_01/examples/sharedptr.cc new file mode 100644 index 0000000000000000000000000000000000000000..d6c27a5a7e43c0196ae720dd97a10fbcba483278 --- /dev/null +++ b/chapter_01/examples/sharedptr.cc @@ -0,0 +1,33 @@ +#include <iostream> +#include <memory> + +struct MyStruct { + int vl{ 0 }; + + MyStruct(int i) + : vl{ i } + { + std::cout << "Creating MyStruct at memory address " + << (void*)this << " with data " << vl << "\n"; + } + ~MyStruct() + { + std::cout << "Destroying MyStruct at memory address " + << (void*)this << " with data " << vl << "\n"; + } + MyStruct() + : MyStruct(0) + { + } +}; + +auto main() -> int +{ + auto u1 = std::make_shared<MyStruct>(1); + auto u2 = u1; //ok + auto u3 = std::move(u1); + std::cout << "Data value for u3 is u3->vl = " << u3->vl << "\n"; + std::cout << "Reference count of u1 is " << u1.use_count() << "\n"; + std::cout << "Reference count of u2 is " << u2.use_count() << "\n"; + std::cout << "Reference count of u3 is " << u3.use_count() << "\n"; +} diff --git a/chapter_01/examples/sqrt_error_handling/mysqrt_expected.cc b/chapter_01/examples/sqrt_error_handling/mysqrt_expected.cc new file mode 100644 index 0000000000000000000000000000000000000000..75d10d83bcd922ef4bfcb39dde408f0a5996c2b9 --- /dev/null +++ b/chapter_01/examples/sqrt_error_handling/mysqrt_expected.cc @@ -0,0 +1,35 @@ +#include <cmath> +#include <expected> +#include <iostream> + +auto mysqrt(double x) -> std::expected<double, std::string> +{ + const auto eps = 1.0e-12; + const auto eps2 = eps * eps; + if (x >= 0.) { + auto r0 = 0.5 * (1. + x); + auto r1 = x / r0; + while ((r0 - r1) * (r0 - r1) > eps2) { + r0 = 0.5 * (r0 + r1); + r1 = x / r0; + } + return { r1 }; + } else { + return std::unexpected { "Unexpected input!" }; + } +} + +auto main() -> int +{ + double x {}; + std::cout << "Enter a positive real number: "; + std::cin >> x; + if (auto rm = mysqrt(x); rm) { + auto rs = std::sqrt(x); + std::cout << "Square root with own function = " << rm.value() << "\n"; + std::cout << "Square root with standard function = " << rs << "\n"; + std::cout << "Difference = " << rm.value() - rs << "\n"; + } else { + std::cout << "Square root did not return an expected value. Error: " << rm.error() << "\n"; + } +} diff --git a/chapter_01/examples/sqrt_error_handling/mysqrt_expt0.cc b/chapter_01/examples/sqrt_error_handling/mysqrt_expt0.cc new file mode 100644 index 0000000000000000000000000000000000000000..164f4c3b083816af9cc9028d7601e8a6fac45fa5 --- /dev/null +++ b/chapter_01/examples/sqrt_error_handling/mysqrt_expt0.cc @@ -0,0 +1,36 @@ +#include <iostream> +#include <cmath> + +using error_code = int; + +auto mysqrt(double x) -> double +{ + const auto eps = 1.0e-12; + const auto eps2 = eps * eps; + if (x < 0) throw error_code{-1}; + auto r0 = 0.5 * (1. + x); + auto r1 = x / r0; + while ((r0 - r1) * (r0 - r1) > eps2) { + r0 = 0.5 * (r0 + r1); + r1 = x / r0; + } + return r1; +} + +auto main() -> int +{ + double x{}; + std::cout << "Enter a positive real number: "; + std::cin >> x; + try { + auto rm = mysqrt(x); + auto rs = std::sqrt(x); + std::cout << "Square root with own function = " << rm << "\n"; + std::cout << "Square root with standard function = " << rs << "\n"; + std::cout << "Difference = " << rm - rs << "\n"; + } catch (error_code& error) { + std::cout << "The input number needs to be positive.\n"; + std::cout << "Caught error_code with value " << error << "\n"; + } +} + diff --git a/chapter_01/examples/sqrt_error_handling/mysqrt_expt1.cc b/chapter_01/examples/sqrt_error_handling/mysqrt_expt1.cc new file mode 100644 index 0000000000000000000000000000000000000000..ff969b5a69e95abeedd054a3550935409ae8b3bd --- /dev/null +++ b/chapter_01/examples/sqrt_error_handling/mysqrt_expt1.cc @@ -0,0 +1,36 @@ +#include <iostream> +#include <cmath> + +using error_code = std::string; + +auto mysqrt(double x) -> double +{ + const auto eps = 1.0e-12; + const auto eps2 = eps * eps; + if (x < 0) + throw error_code{"Asking for square root of a negative number, are you alright?" }; + auto r0 = 0.5 * (1. + x); + auto r1 = x / r0; + while ((r0 - r1) * (r0 - r1) > eps2) { + r0 = 0.5 * (r0 + r1); + r1 = x / r0; + } + return r1; +} + +auto main() -> int +{ + double x{}; + std::cout << "Enter a positive real number: "; + std::cin >> x; + try { + auto rm = mysqrt(x); + auto rs = std::sqrt(x); + std::cout << "Square root with own function = " << rm << "\n"; + std::cout << "Square root with standard function = " << rs << "\n"; + std::cout << "Difference = " << rm - rs << "\n"; + } catch (error_code& error) { + std::cout << "Caught error_code with value:\"" << error << "\"\n"; + } +} + diff --git a/chapter_01/examples/sqrt_error_handling/mysqrt_expt2.cc b/chapter_01/examples/sqrt_error_handling/mysqrt_expt2.cc new file mode 100644 index 0000000000000000000000000000000000000000..bf99b1043991ede2b8bee444ddafbaba3f5c0d9c --- /dev/null +++ b/chapter_01/examples/sqrt_error_handling/mysqrt_expt2.cc @@ -0,0 +1,35 @@ +#include <stdexcept> +#include <iostream> +#include <cmath> + +auto mysqrt(double x) -> double +{ + const auto eps = 1.0e-12; + const auto eps2 = eps * eps; + if (x < 0) + throw std::runtime_error{"Asking for square root of a negative number, are you alright?" }; + auto r0 = 0.5 * (1. + x); + auto r1 = x / r0; + while ((r0 - r1) * (r0 - r1) > eps2) { + r0 = 0.5 * (r0 + r1); + r1 = x / r0; + } + return r1; +} + +auto main() -> int +{ + double x{}; + std::cout << "Enter a positive real number: "; + std::cin >> x; + try { + auto rm = mysqrt(x); + auto rs = std::sqrt(x); + std::cout << "Square root with own function = " << rm << "\n"; + std::cout << "Square root with standard function = " << rs << "\n"; + std::cout << "Difference = " << rm - rs << "\n"; + } catch (std::runtime_error& error) { + std::cout << "Caught runtime_error:\"" << error.what() << "\"\n"; + } +} + diff --git a/chapter_01/examples/sqrt_error_handling/mysqrt_expt3.cc b/chapter_01/examples/sqrt_error_handling/mysqrt_expt3.cc new file mode 100644 index 0000000000000000000000000000000000000000..bf99b1043991ede2b8bee444ddafbaba3f5c0d9c --- /dev/null +++ b/chapter_01/examples/sqrt_error_handling/mysqrt_expt3.cc @@ -0,0 +1,35 @@ +#include <stdexcept> +#include <iostream> +#include <cmath> + +auto mysqrt(double x) -> double +{ + const auto eps = 1.0e-12; + const auto eps2 = eps * eps; + if (x < 0) + throw std::runtime_error{"Asking for square root of a negative number, are you alright?" }; + auto r0 = 0.5 * (1. + x); + auto r1 = x / r0; + while ((r0 - r1) * (r0 - r1) > eps2) { + r0 = 0.5 * (r0 + r1); + r1 = x / r0; + } + return r1; +} + +auto main() -> int +{ + double x{}; + std::cout << "Enter a positive real number: "; + std::cin >> x; + try { + auto rm = mysqrt(x); + auto rs = std::sqrt(x); + std::cout << "Square root with own function = " << rm << "\n"; + std::cout << "Square root with standard function = " << rs << "\n"; + std::cout << "Difference = " << rm - rs << "\n"; + } catch (std::runtime_error& error) { + std::cout << "Caught runtime_error:\"" << error.what() << "\"\n"; + } +} + diff --git a/chapter_01/examples/sqrt_error_handling/mysqrt_opt.cc b/chapter_01/examples/sqrt_error_handling/mysqrt_opt.cc new file mode 100644 index 0000000000000000000000000000000000000000..19790a8d38dcd62d8d655b5936e75ebbbf2a7181 --- /dev/null +++ b/chapter_01/examples/sqrt_error_handling/mysqrt_opt.cc @@ -0,0 +1,36 @@ +#include <iostream> +#include <cmath> +#include <optional> + +auto mysqrt(double x) -> std::optional<double> +{ + std::optional<double> ans; + const auto eps = 1.0e-12; + const auto eps2 = eps * eps; + if (x >= 0.) { + auto r0 = 0.5 * (1. + x); + auto r1 = x / r0; + while ((r0 - r1) * (r0 - r1) > eps2) { + r0 = 0.5 * (r0 + r1); + r1 = x / r0; + } + ans = r1; + } + return ans; +} + +auto main() -> int +{ + double x{}; + std::cout << "Enter a positive real number: "; + std::cin >> x; + if (auto rm = mysqrt(x); rm) { + auto rs = std::sqrt(x); + std::cout << "Square root with own function = " << rm.value() << "\n"; + std::cout << "Square root with standard function = " << rs << "\n"; + std::cout << "Difference = " << rm.value() - rs << "\n"; + } else { + std::cout << "Square root does not contain a value. Bad input!\n"; + } +} + diff --git a/chapter_01/examples/uniqueptr.cc b/chapter_01/examples/uniqueptr.cc new file mode 100644 index 0000000000000000000000000000000000000000..b057d6cadfe08a2eb65e8a38bf80ee7d85589b16 --- /dev/null +++ b/chapter_01/examples/uniqueptr.cc @@ -0,0 +1,35 @@ +#include <iostream> +#include <memory> + +struct MyStruct { + MyStruct(int i) + : vl{ i } + { + std::cout << "Creating MyStruct at memory address " + << static_cast<void*>(this) << " with data " << vl << "\n"; + } + ~MyStruct() + { + std::cout << "Destroying MyStruct at memory address " + << static_cast<void*>(this) << " with data " << vl << "\n"; + } + int vl = 0; + MyStruct() + : MyStruct(0) + { + } +}; + +auto main() -> int +{ + auto u1 = std::make_unique<MyStruct>(1); + // The integer passed as argument is forwarded to the constructor of MyStruct + // auto u2 = u1; //won't compile + auto u3 = std::move(u1); + std::cout << "Data value for u3 is u3->vl = " << u3->vl << "\n"; + auto u4 = std::make_unique<MyStruct[]>(4); + // When we want to create an array with make_unique, we have to express + // this wish through the template parameter to make_unique. Here we see + // that u4 becomes an array, even if we are simply passing one integer + // as an argument, like we did for u1. +} diff --git a/chapter_01/examples/uniqueptr2.cc b/chapter_01/examples/uniqueptr2.cc new file mode 100644 index 0000000000000000000000000000000000000000..7b146e8b13a40f85a7194315a23edefbf65440e1 --- /dev/null +++ b/chapter_01/examples/uniqueptr2.cc @@ -0,0 +1,9 @@ +#include <memory> +#include <iostream> + +auto main() -> int +{ + auto u = std::make_unique<double[]>(1024); + for (auto i = 0UL; i < 1024UL; ++i) u[i] = i; + std::cout << u[334] << "\n"; +} diff --git a/chapter_01/solutions/CMakeLists.txt b/chapter_01/solutions/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3e9ef8ec7f522977fe6535f91c7034ee4729d71c --- /dev/null +++ b/chapter_01/solutions/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.28) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +project(cxx_course_solutions CXX) + + +FILE (GLOB sources ./ *.cc) +foreach(source ${sources}) + get_filename_component(withoutext "${source}" NAME_WE) + add_executable("${withoutext}" "${source}") +endforeach() + + diff --git a/chapter_01/solutions/check_prime.cc b/chapter_01/solutions/check_prime.cc new file mode 100644 index 0000000000000000000000000000000000000000..de7bfc26c72ee14c5e65694690ae33cbb1cbf484 --- /dev/null +++ b/chapter_01/solutions/check_prime.cc @@ -0,0 +1,25 @@ +#include <iostream> + +auto is_prime(unsigned int n) -> bool +{ + bool found_divisor = false; + for (auto i = 2U; + (not found_divisor) and i * i <= n; + ++i) { + if (n % i == 0U) found_divisor = true; + } + return (not found_divisor); +} + +auto main() -> int +{ + std::cout << "Number to check: "; + unsigned int inp{}; + std::cin >> inp; + if (is_prime(inp)) + std::cout << "Yes, that's a prime.\n"; + else + std::cout << "Not a prime.\n"; +} + + diff --git a/chapter_01/solutions/fibonacci.cc b/chapter_01/solutions/fibonacci.cc new file mode 100644 index 0000000000000000000000000000000000000000..307d6ac7fd97ff674e1c3832fb3670985bec2535 --- /dev/null +++ b/chapter_01/solutions/fibonacci.cc @@ -0,0 +1,33 @@ +#include <iostream> +#include <limits> + +auto main() -> int +{ + size_t umax{ std::numeric_limits<size_t>::max() }; + unsigned nfib = 0; + size_t f0{ 0 }, f1{ 1 }; + do { + size_t f2 = f0 + f1; + f0 = f1; + f1 = f2; + ++nfib; + } while (f1 < umax - f0); + std::cout << "The largest number in the Fibonacci sequence under " << umax << " is " << f1 << "\n"; + std::cout << "Number of entries in the Fibonacci sequence under " << umax << " is " << nfib << "\n"; +} +#include <iostream> +#include <limits> +#include <format> + +auto main() -> int +{ + using namespace std; + size_t umax{ numeric_limits<size_t>::max() }; + unsigned nfib = 0; + size_t f0{ 0 }, f1{ 1 }; + // Insert your code here + + cout << format(R"(The largest number in the Fibonacci sequence under {0:} is {1:}, +and there are {2:} entries under {0:} in that sequence. +)" , umax, f1, nfib); +} diff --git a/chapter_01/solutions/gcd.cc b/chapter_01/solutions/gcd.cc new file mode 100644 index 0000000000000000000000000000000000000000..153b3e41ef77ebadbcca7cc23a2026bc861f9943 --- /dev/null +++ b/chapter_01/solutions/gcd.cc @@ -0,0 +1,45 @@ +#include <iostream> + +auto euclid_gcd(unsigned long smaller, unsigned long larger) -> unsigned long +{ + if (smaller > larger) + std::swap(smaller, larger); + while (smaller != 0) { + auto rem = larger % smaller; + larger = smaller; + smaller = rem; + } + return larger; +} + +auto main(int argc, char* argv[]) -> int +{ + if (argc != 3) { + std::cout << "Usage:\n" + << argv[0] << " number1 number2\n"; + return 1; + } + unsigned long n1 = std::stoul(argv[1]), n2 = std::stoul(argv[2]); + std::cout << euclid_gcd(n1, n2) << "\n"; +} +#include <iostream> + +auto euclid_gcd(unsigned long smaller, unsigned long larger) -> unsigned long +{ + if (smaller > larger) + std::swap(smaller, larger); + // Fill in your code to implement Euclid's algorithm here. + + return ? ? ? ; +} + +auto main(int argc, char* argv[]) -> int +{ + if (argc != 3) { + std::cout << "Usage:\n" + << argv[0] << " number1 number2\n"; + return 1; + } + unsigned long n1 = std::stoul(argv[1]), n2 = std::stoul(argv[2]); + std::cout << euclid_gcd(n1, n2) << "\n"; +} diff --git a/chapter_01/solutions/midpt.cc b/chapter_01/solutions/midpt.cc new file mode 100644 index 0000000000000000000000000000000000000000..b5b420c27733e045e1f66aad48a2d1125e4dc911 --- /dev/null +++ b/chapter_01/solutions/midpt.cc @@ -0,0 +1,16 @@ +// examples/midpt.cc +#include <iostream> + +auto mid(int a, int b) -> int +{ + return (a + b) / 2; +} +auto main() -> int +{ + int i = 0, j = 0; + std::cout << "Enter i, j: "; + std::cin >> i >> j; + std::cout << "A number half way between " << i << " and " << j + << " is " << mid(i, j) << "\n"; +} + diff --git a/chapter_01/solutions/min_of_three.cc b/chapter_01/solutions/min_of_three.cc new file mode 100644 index 0000000000000000000000000000000000000000..7093015d3a52afb37dbb1626663148d744230b2d --- /dev/null +++ b/chapter_01/solutions/min_of_three.cc @@ -0,0 +1,21 @@ +// examples/min_of_three.cc +#include <iostream> + +auto min_of_three(int a, int b, int c) -> int +{ + if (a <= b) { + if (a <= c) return a; + else return c; + } else { + if (b <= c) return b; + else return c; + } +} +auto main() -> int +{ + int i = 0, j = 0, k = 0; + std::cout << "Enter i, j and k: "; + std::cin >> i >> j >> k; + std::cout << "The smallest of the three is " << min_of_three(i, j, k) << "\n"; +} + diff --git a/chapter_01/solutions/mysqrt.cc b/chapter_01/solutions/mysqrt.cc new file mode 100644 index 0000000000000000000000000000000000000000..ae024aab0c80f5bace12b78040b752f83441ccba --- /dev/null +++ b/chapter_01/solutions/mysqrt.cc @@ -0,0 +1,32 @@ +#include <iostream> +#include <cmath> + +auto mysqrt(double x) -> double +{ + const auto eps = 1.0e-12; + const auto eps2 = eps * eps; + auto r0 = 0.5 * (1. + x); + auto r1 = x / r0; + while ((r0 - r1) * (r0 - r1) > eps2) { + r0 = 0.5 * (r0 + r1); + r1 = x / r0; + } + return r1; +} + +auto main() -> int +{ + double x{}; + std::cout << "Enter a positive real number: "; + std::cin >> x; + if (x > 0.) { + auto rm = mysqrt(x); + auto rs = std::sqrt(x); + std::cout << "Square root with own function = " << rm << "\n"; + std::cout << "Square root with standard function = " << rs << "\n"; + std::cout << "Difference = " << rm - rs << "\n"; + } else { + std::cout << "The input number needs to be positive.\n"; + } +} + diff --git a/chapter_01/solutions/raw1.cc b/chapter_01/solutions/raw1.cc new file mode 100644 index 0000000000000000000000000000000000000000..abe15584291f9d73737da98823bfe7fdf184dc56 --- /dev/null +++ b/chapter_01/solutions/raw1.cc @@ -0,0 +1,12 @@ +#include <iostream> +#include <string> + +auto main() -> int +{ + using namespace std; + cout << "Use a single backslash character at the end of the line to continue input to the next line, as shown ...\n" + << R"(OBJ=a.o \ + b.o\ + c.o +)"; +}