diff --git a/.ccls b/.ccls new file mode 100644 index 0000000..bff1d50 --- /dev/null +++ b/.ccls @@ -0,0 +1,7 @@ +clang +%c -std=c17 +%cpp -std=c++2a +%h %hpp --include=Global.h +-Iinc +-DMACRO + diff --git a/.gitignore b/.gitignore index 547746f..87a02f0 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,12 @@ build .pylintrc .ipynb_checkpoints a.out +ams562_desktop.py + +*.out +lecture_code/*/.ccls-cache/* +lecture_code/*/*/.ccls-cache/* +lecture_code/lecture0/.ccls-cache/@@home@agh@projects@ams562-work@ams562-notes@lecture_code@lecture0/@home@agh@software@clang+llvm-10.0.0@lib@clang@10.0.0@include@__stddef_max_align_t.h +.ccls-cache/* + +*/.ccls-cache/* diff --git a/intro/lec0.rst b/intro/lec0.rst index 43d06fb..6090ddb 100644 --- a/intro/lec0.rst +++ b/intro/lec0.rst @@ -71,7 +71,7 @@ do not make your academic litter brothers/sisters hate you. "I'm so glad that I commented!" +++++++++++++++++++++++++++++++ -Actually, you are the one who benefit the most from making comments. While +You are the one who benefits the most from making comments. While doing research, an important thing that everybody needs to keep in mind is to make the work reproducible. One needs to make sure that his/her results can be reproduced in the future. Therefore, make comments for yourselves in the @@ -81,6 +81,8 @@ Of course, there are better tools, e.g. `Git`_ see :ref:`here `, to help you manage your work. But making comments are the most fundamental requirement that. +Good versus Bad Comments ++++++++++++++++++++++++++++++++ Let's take a look at the following examples: .. code-block:: cpp diff --git a/intro/simple_cpp.rst b/intro/simple_cpp.rst index 1856e5e..25e7983 100644 --- a/intro/simple_cpp.rst +++ b/intro/simple_cpp.rst @@ -4,7 +4,13 @@ .. _intro_simple_cpp: Simple `C++`_ -============= +======================= + +Here, we will present the most basic C++ program that does something. +The purpose of this section is to + +* Give you a chance to use the programming environment +* Give a first feel of how you control the computer using C++. .. contents:: Table of Contents :local: @@ -12,25 +18,43 @@ Simple `C++`_ .. _intro_simple_cpp_main: -The ``main`` functions ----------------------- +The simplest `C++`_ program +------------------------------- + +Here is the simplest `C++`_ program you can write. + +.. code-block:: cpp + + int main() {return 0;} + +Every `C++`_ program must have a function ``main``. +A function is a named sequence of instructions that the computer executes. +Each function has four parts: + +1. A *return* type `int`, specificies the kind of result +2. A *name*, ``main`` +3. A *parameter list* ``()`` +4. A *function body* enclosed in the set of curly braces ``{}``, lists the sequence of statements + +The ``main`` function must return an integer to indicate your system the exit +status of the program. -Each `C++`_ program is written in a ``main`` function in `C++`_, where a -``main`` function must return an integer to indicate your system the exit -status of the program. -.. note:: 0 is used for indicating exiting successfully. -Here is the simplest `C++`_ program, :code:`int main() { return 0; }`, -which does nothing but just returns ``EXIT_SUCCESS`` to your system. + +.. note:: 0 is used for indicating exiting successfully. .. _intro_simple_cpp_compile: -Compile the one-line program ----------------------------- +Compile and link the one-line program +--------------------------------------------- Unlike `Python`_ and `MATLAB`_, where you can directly invoke the scripts, all `C++`_ programs must be first **compiled** into executable binaries. +By compiling a program, we mean translating the human-readable text instructions +into something that the computer can execute. +In this class, we use the g++ compiler to +translate our source code into executable file. .. note:: @@ -71,7 +95,7 @@ You should see ``0`` on the screen. "Hello World!" -------------- - +Here we will introduce the classic "Hello World!" program written in C++. Unfortunately, you cannot write one line code for "Hello World!" in `C++`_. In `Python`_, you can write a ``hello_world.py`` script with: @@ -96,23 +120,47 @@ You should see "Hello World!" on your screen. Or even something like: However, there is no built-in ``print`` method in `C++`_, we have to include the standard input and output library, i.e. ``iostream``. +Here is the classic "Hello World!" program. + .. code-block:: cpp :linenos: - #include + // This program outpouts the message "Hello, World!" to the monitor + #include // #include directive - int main() { - std::cout << "Hello World!" << std::endl; + int main() {// C++ programs start by executing the main function + std::cout << "Hello World!\n";// output "Hello, World!" return 0; + // notice that semicolons terminate statements. } + // quotes delimit a string literal + // \n is notation for new line + +Let's parse some of this program +* ``#include `` is an ``#include`` directive. This is where we included the definition of ``std::cout`` +* ``std::cout`` character output stream +* ``<<`` is the output operator +* ``"Hello World!\n`` String literal that is displayed on screen +* ``// This is a comment`` -Once we include the IO library (line 1), we can use the standard output -streamer, i.e. ``std::out``, to write out messages (line 4). Now, copy the program into ``hello_world.cpp``, and compile and run it. .. note:: - This section is basically to demonstrate some simple codes. There will be - a specific section talking about IO. + It's important you mind the details when writing programs in CPP. + Try making a mistake and see how the compliler responds + + * Forget the header + * Forget to terminate the string + * Misspell returned + * Forget a semicolon + * Forget a { + +The hello world program is crucial because it represents the most basic program that you can write. +Its purpose is to get you familiar with writing programs in C++. +The rest of your programs should include the same basic structure. +In future lectures we will go over more information about I/O in C++ + + diff --git a/lecture_code/lecture0/ex1.cpp b/lecture_code/lecture0/ex1.cpp new file mode 100644 index 0000000..6cc2ca1 --- /dev/null +++ b/lecture_code/lecture0/ex1.cpp @@ -0,0 +1,3 @@ + + +int main() { return 0; } // minimal C++ program diff --git a/lecture_code/lecture0/hello_world.cpp b/lecture_code/lecture0/hello_world.cpp new file mode 100644 index 0000000..9d6ae73 --- /dev/null +++ b/lecture_code/lecture0/hello_world.cpp @@ -0,0 +1,14 @@ +// This is the famous hello world program +//#include + +int main() { + // we print hello world using the + // cout (character output stream) + // defined in iostream + // note "Hello World!\n" is a string literal + // \n is a newline character + // \ is used to specify special characters + std::cout << "Hello World!\n"; + // what happens when we forget to return 0? + return 0; +} diff --git a/lecture_code/lecture1/cin_demo.cpp b/lecture_code/lecture1/cin_demo.cpp new file mode 100644 index 0000000..6d9f0f2 --- /dev/null +++ b/lecture_code/lecture1/cin_demo.cpp @@ -0,0 +1,12 @@ +// This is the famous hello world program +#include + +int main() { + // best practice, always indicate the user what to enter + std::cout << "Please enter your first and last names: "; + std::string fname, lname; + // the program will hang here until receives the user input + std::cin >> fname >> lname; + std::cout << "Hello! " << fname << ' ' << lname << std::endl; + return 0; +} diff --git a/lecture_code/lecture1/declare_test.cpp b/lecture_code/lecture1/declare_test.cpp new file mode 100644 index 0000000..ca11f0a --- /dev/null +++ b/lecture_code/lecture1/declare_test.cpp @@ -0,0 +1,9 @@ + +#include + +int main(void) { + int temp; + std::cout << temp << std::endl; // undefined behaviour + temp = 5; + std::cout << temp << std::endl; +} diff --git a/lecture_code/lecture1/fundamental_types.cpp b/lecture_code/lecture1/fundamental_types.cpp new file mode 100644 index 0000000..dbc08c5 --- /dev/null +++ b/lecture_code/lecture1/fundamental_types.cpp @@ -0,0 +1,26 @@ + +#include + +int main(void) { + bool b; // Boolean, true/false + char c; // character 'a','z','9' + int i; // integer, -265, 32, 29 + double d; // double-precision floating point number + long l; // double-precision floating point number + double *ptr; // pointer to double (address to variable) + unsigned ui; // non-negative integer, for example 0,1,999 + + unsigned short fu = 0b1111111111111111; + short fi = 0b0111111111111111; + + std::cout << "size of bool = " << sizeof(b) << " byte" << std::endl; + std::cout << "size of char = " << sizeof(c) << " byte" << std::endl; + std::cout << "size of double = " << sizeof(d) << " byte" << std::endl; + std::cout << "size of int = " << sizeof(i) << " byte" << std::endl; + std::cout << "size of long = " << sizeof(l) << " byte" << std::endl; + std::cout << "size of pointer = " << sizeof(ptr) << " byte" << std::endl; + std::cout << "size of ui = " << sizeof(ui) << " byte" << std::endl; + + std::cout << "max int = " << fi << std::endl; + std::cout << "max unsigned = " << fu << std::endl; +} diff --git a/lecture_code/lecture1/hello_world.cpp b/lecture_code/lecture1/hello_world.cpp new file mode 100644 index 0000000..a26a11b --- /dev/null +++ b/lecture_code/lecture1/hello_world.cpp @@ -0,0 +1,7 @@ +#include + +int main() { + std::cout << "Hello AMS 562\n"; + + return 0; +} diff --git a/lecture_code/lecture1/initialize.cpp b/lecture_code/lecture1/initialize.cpp new file mode 100644 index 0000000..c893ee8 --- /dev/null +++ b/lecture_code/lecture1/initialize.cpp @@ -0,0 +1,54 @@ +#include +#include +#include +#include + +void print_var(int a) { std::cout << "int " << a << ::std::endl; } +void print_var(long int a) { std::cout << "long int " << a << ::std::endl; } +void print_var(unsigned long int a) { + std::cout << "unsigned long int " << a << ::std::endl; +} +void print_var(unsigned int a) { + std::cout << "unsigned int " << a << ::std::endl; +} +void print_var(float a) { std::cout << "float " << a << ::std::endl; } +void print_var(double a) { std::cout << "double " << a << ::std::endl; } +void print_var(std::string a) { std::cout << "string " << a << ::std::endl; } +void print_var(char a) { std::cout << "char " << a << std::endl; } +void print_var(bool a) { std::cout << "bool " << a << std::endl; } +void print_var(std::complex a) { + std::cout << "complex " << a.real() << " " << a.imag() << std::endl; +} + +int main() { + double d1 = 2.3; // initialize d1 to 2.3 + double d2{2.3}; // initialize d2 to 2.3 + double d3 = {2.3}; // is optional with {} + + std::complex z = 1; // a complex number with double-precision + std::complex z2{d1, d2}; + std::complex z3 = {d1, d2}; + print_var(z); + print_var(z2); + print_var(z3); + + std::vector v{1, 2, 3, 4, 5, 6}; // vector of ints + + int i1 = 7.8; // i1 becomes 7 + // int i2{7.8}; // error: narrowing conversion of double to int + // = allows narrowing conversion + // {} does not + unsigned int wha = -1; // What is the value? + int whaaaa{wha}; + print_var(wha); + print_var(whaaaa); + + auto b = true; // a bool + auto ch = 'x'; // a char + auto i = 124; // a int + auto d = 1.2; // a double + auto z = sqrt(y); // the type retured + auto bb{true}; // a bool + + return 0; +} diff --git a/lecture_code/lecture1/iostreams.cpp b/lecture_code/lecture1/iostreams.cpp new file mode 100644 index 0000000..853646d --- /dev/null +++ b/lecture_code/lecture1/iostreams.cpp @@ -0,0 +1,11 @@ +// This is the famous hello world program +#include + +int main() { + std::cout << "Hello World!\n"; + std::cout << "Hello World!" << std::endl; + std::cout << "1 +1 =" << (1 + 1) << std::end; + std::cout << "Size of double is: " << sizeof(double) << std::endl; + + return 0; +} diff --git a/lecture_code/lecture1/literal.cpp b/lecture_code/lecture1/literal.cpp new file mode 100644 index 0000000..e897922 --- /dev/null +++ b/lecture_code/lecture1/literal.cpp @@ -0,0 +1,52 @@ +#include +#include +// This code depends on function overloading +// Function overloading is defining multiple functions with the same name +// Each function has the same name but differ in their input parameters +// You + +void print_var(int a) { std::cout << "int " << a << ::std::endl; } +void print_var(long int a) { std::cout << "long int " << a << ::std::endl; } +void print_var(unsigned long int a) { + std::cout << "unsigned long int " << a << ::std::endl; +} +void print_var(unsigned int a) { + std::cout << "unsigned int " << a << ::std::endl; +} +void print_var(float a) { std::cout << "float " << a << ::std::endl; } +void print_var(double a) { std::cout << "double " << a << ::std::endl; } +void print_var(std::string a) { std::cout << "string " << a << ::std::endl; } +void print_var(char a) { std::cout << "char " << a << ::std::endl; } + +int main() { + // integer literals + print_var(0b00001); // binary integer literal + print_var(0b01011); + print_var(0xFFFFFu); + print_var(0xFFFF); + print_var(0b00001); // binary + print_var(0x0BF0); // hexadecimal + print_var(-32); + print_var(-32u); + print_var(32ul); + print_var(32l); + print_var(32u); + // floating point literals + print_var(1.0f); + print_var(3.2e-1f); + // doubles + print_var(3.2e2); + print_var(-2.0); + print_var(-5.21); + // String Literlas + print_var("\"A\""); + print_var("\'"); + print_var("\tHello World!\n"); + print_var("\Hello\v World!\n"); + // Char literals + print_var('a'); + // literals + // 32, 1, -2, -100, 30001,... + // 32l // long literal + return 0; +} diff --git a/lecture_code/lecture1/precision.cpp b/lecture_code/lecture1/precision.cpp new file mode 100644 index 0000000..49a0e91 --- /dev/null +++ b/lecture_code/lecture1/precision.cpp @@ -0,0 +1,17 @@ +#include +// floats have 7 digits of precision +// doubles have 15 + +// Question is 1.1 = 1.10000004 + +int main() { + float single_lhs = 1.1; + float single_rhs = 1.10000004; // 10 sig + // == operator tests equality + std::cout << (single_lhs == single_rhs) << std::endl; + // try the same with double + double double_lhs = 1.1; + double double_rhs = 1.10000004; + std::cout << (double_lhs == double_rhs) << std::endl; + return 0; +} diff --git a/lecture_code/lecture1/printmul2.cpp b/lecture_code/lecture1/printmul2.cpp new file mode 100644 index 0000000..e30a3af --- /dev/null +++ b/lecture_code/lecture1/printmul2.cpp @@ -0,0 +1,12 @@ +#include + +double mul2(double x) { return x * 2; } +void printxmul2(double x) { + std::cout << "2 * " << x << " is " << mul2(x) << "\n"; +} + +int main() { + printxmul2(2.234); + + return 0; +} diff --git a/lecture_code/lecture1/read_line.cpp b/lecture_code/lecture1/read_line.cpp new file mode 100644 index 0000000..5e2e473 --- /dev/null +++ b/lecture_code/lecture1/read_line.cpp @@ -0,0 +1,15 @@ +// This is the famous hello world program +#include + +int main() { + std::string word, sent; + std::cout << "Enter a word:"; + std::cin >> word; // read in a word from cin + std::cout << "The word you just entered is:" << word << std::endl; + std::cin.ignore(); // ignore '\n' + std::cout << "Enter a sentence:\n"; + std::getline(std::cin, sent); + std::cout << "The sentence you entered is:\n" << sent << std::endl; + + return 0; +} diff --git a/lecture_code/lecture1/scope_lifetime.cpp b/lecture_code/lecture1/scope_lifetime.cpp new file mode 100644 index 0000000..612d1a8 --- /dev/null +++ b/lecture_code/lecture1/scope_lifetime.cpp @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +// scope and life time +int hello = 2; // global namespace +double square(double a) { + std::cout << "global hello in square function " << hello << std::endl; + return a * a; +} +int main() { + double local_main = 32; + { double local_scope_d = 23; } // local _scope_d gets destroyed here + // std::cout << local_scope_d << std::endl; + std::cout << "global hello in main function" << hello + << std::endl; // print global scope hello + double s3 = square(3); + return 0; +} diff --git a/lecture_code/lecture1/simple.cpp b/lecture_code/lecture1/simple.cpp new file mode 100644 index 0000000..76e8197 --- /dev/null +++ b/lecture_code/lecture1/simple.cpp @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/lecture_code/lecture1/simple_string.cpp b/lecture_code/lecture1/simple_string.cpp new file mode 100644 index 0000000..15221a6 --- /dev/null +++ b/lecture_code/lecture1/simple_string.cpp @@ -0,0 +1,16 @@ +#include +#include + +int main() { + char fname[128] = {"ADRIAN"}; // C-style character array + char lname[128] = { + "HURTADO"}; // automatically appends null termination character \0 + std::string dfname = "Stella"; + std::string dlname = "Luna"; + + std::cout << "My name is " << fname << " " << lname + << std::endl; // reads to null termination charcter + std::cout << "My dog's name " << dfname << " " << dlname << std::endl; + + return 0; +} diff --git a/lecture_code/lecture1/string.cpp b/lecture_code/lecture1/string.cpp new file mode 100644 index 0000000..95616f0 --- /dev/null +++ b/lecture_code/lecture1/string.cpp @@ -0,0 +1,43 @@ +#include +#include + +char *add_char_array(char *first, char *last) { + // copy pointer to first character of first word + char *together = first; + // read up until NULL character + while (*first != '\0') { + first++; + } + // add a space + *first = ' '; + first++; + + // read and append character from last into first + while (*last != '\0') { + *first = *last; + last++; + first++; + } + + // append a NULL termination character + *first = 0; + + std::cout << std::endl; + return together; +} +int main() { + + char fname[128]; // C-style character array + char lname[128]; + // std::string fname; + // std::string lname; + + std::cout << "Give me your name" << std::endl; + std::cin >> fname; + std::cin >> lname; + + char *full = add_char_array(fname, lname); + std::cout << "Your name is " << full << std::endl; + + return 0; +} diff --git a/lecture_code/lecture1/swap_int.cpp b/lecture_code/lecture1/swap_int.cpp new file mode 100644 index 0000000..4f82e7c --- /dev/null +++ b/lecture_code/lecture1/swap_int.cpp @@ -0,0 +1,22 @@ + +#include + +void swap(int &, int &); + +int main(void) { + int a = 2; + int b = 4; + int temp; + std::cout << temp; + std::cout << "a = " << a << " b = " << b << std::endl; + + swap(a, b); + + std::cout << "a = " << a << " b = " << b << std::endl; +} + +void swap(int &a, int &b) { + int temp = b; + b = a; + a = temp; +} diff --git a/lecture_code/tour/ch2_user_defined_types/classes.cpp b/lecture_code/tour/ch2_user_defined_types/classes.cpp new file mode 100644 index 0000000..0865299 --- /dev/null +++ b/lecture_code/tour/ch2_user_defined_types/classes.cpp @@ -0,0 +1,44 @@ +#include + +// Vector object is a "handle" containing pointer to elements +// and number of elements +// The number of elements can vary from Vector object to Vector object +// However, a single vector object always has the same size. +class Vector { +public: + Vector(int s) : elem{new double[s]}, sz{s} {} // construct a Vector + double &operator[](int i) { return elem[i]; } + int size() { return sz; } + +private: + double *elem; // pointer to elements + int sz; // the nubmer of elements +}; +// the members elem and sz are only accessible through +// the interface provided +// Vector(), operator[](), and size() + +double read_and_sum(int s) +// read s integers from cin and return their sum; +// s is assumed to be positive +{ + Vector v(s); // Vector with s elements + for (int i = 0; i != v.size(); ++i) { + std::cin >> v[i]; // write to v[i] through [] operator which returns + // reference to elem[i] + } + double sum = 0; + for (int i = 0; i != v.size(); ++i) { + sum += v[i]; // sum read through [] operator + } + return sum; +} + +int main() { + // + // + int s = 3; + read_and_sum(s); + + return 0; +} diff --git a/lecture_code/tour/ch2_user_defined_types/enum.cpp b/lecture_code/tour/ch2_user_defined_types/enum.cpp new file mode 100644 index 0000000..25ccc03 --- /dev/null +++ b/lecture_code/tour/ch2_user_defined_types/enum.cpp @@ -0,0 +1,66 @@ +#include +#include +#include + +enum class Color { red, blue, green }; +enum class Traffic_light { green, yellow, red }; + +Traffic_light &operator++(Traffic_light &t) { + switch (t) { + case Traffic_light::green: + return t = Traffic_light::yellow; + case Traffic_light::yellow: + return t = Traffic_light::red; + case Traffic_light::red: + return t = Traffic_light::green; + } + return t; +} + +void printLight(const Traffic_light &t) { + if (t == Traffic_light::green) { + std::cout << "Green" << std::endl; + } else if (t == Traffic_light::yellow) { + std::cout << "Yellow" << std::endl; + } else if (t == Traffic_light::red) { + std::cout << "Red" << std::endl; + } else { + std::cout << "Flash Who knows" << std::endl; + } +} + +int main() { + Color col = Color::red; + Traffic_light light = Traffic_light::red; + printLight(light); + ++light; + printLight(light); + ++light; + printLight(light); + + // enumerators are in the scope of their enum class + // The can be used repeatedly in different enum classes + // without confusion + // + // Enumerations are used to represent a small set of integer + // values. They are used to make code more readable + // and less error-prone + // + // The class after enum specifies that an enumeration + // is strongly typed and that its enumerations are scoped + // + // Being seperate types, enum classes help prevent accidental + // misuses of constants...we can't mix Traffic_light and + // Color values: + // + // + // Color x = red; eror which red? + // Color y = Traffic_light::red; red is not a Color + Color z = Color::red; // allowed in c++ 17 + Color x = Color{5}; // allowed in c++ 17 + Color y{0}; + std::cout << (int)x << std::endl; + std::cout << (int)z << std::endl; + + return 0; +} diff --git a/lecture_code/tour/ch2_user_defined_types/structs.cpp b/lecture_code/tour/ch2_user_defined_types/structs.cpp new file mode 100644 index 0000000..84eba94 --- /dev/null +++ b/lecture_code/tour/ch2_user_defined_types/structs.cpp @@ -0,0 +1,70 @@ +#include + +struct Vector { + int sz; // number of elements + double *elem; // pointer to elements +}; + +// we pass v by non const reference +void vector_init(Vector &v, int s) { + v.elem = new double[s]; // allocate an array of s doubles + v.sz = s; +} +// new operator allocates memory from area called the +// free store +// dynamic memory +// heap +// Objects that live in the free store +// are independent of the scope in which +// they are created. +// The "live" until they are destroyed using the delete +// operator +// +double read_and_sum(int s) +// read s integers from cin and return their sum; +// s is assumed to be positive +{ + Vector v; + vector_init(v, s); + + for (int i = 0; i != s; ++i) { + std::cin >> v.elem[i]; + } + double sum = 0; + for (int i = 0; i != s; ++i) { + sum += v.elem[i]; + } + return sum; +} + +// we asume that v is valid (aka) initialized with a value for members +void f(Vector v, Vector &rv, Vector *pv) { + int i1 = v.sz; // access through name + int i2 = rv.sz; // access through reference + int i3 = pv->sz; // access through pointer + std::cout << "Here are the sizes " << i1 << " " << i2 << " " << i3 + << std::endl; +} +// We use .(dot) to access struct members through name (and through reference) +// -> to access struct members through a pointer. + +int main() { + // + if (true) { + + int sz = 5; + Vector v; + vector_init(v, sz); + + Vector *pv = &v; + Vector &rv = v; + f(v, rv, pv); + } else { + + double s = read_and_sum(3); + + std::cout << "sum of 3 numbers " << std::endl; + } + + return 0; +} diff --git a/lecture_code/tour/ch2_user_defined_types/unions.cpp b/lecture_code/tour/ch2_user_defined_types/unions.cpp new file mode 100644 index 0000000..597bbe6 --- /dev/null +++ b/lecture_code/tour/ch2_user_defined_types/unions.cpp @@ -0,0 +1,51 @@ +#include +#include + +// Union is a struct in which all members at the same address +// so taht the union occupies only as much space as its largest +// member. A union can only hold a value for only one member +// at a time. Example, consider a symbol table entry that +// holds a name and a value. The value can either +// be a Node* or an int: +// +enum Type { ptr, num }; // a Type can hold values ptr and num + +struct Entry { + std::string name; // strin is a standsard library type + Type t; + int *p; // use p if t==ptr + int i; + ; // use i if t=num +}; + +// we only use either p or i +void f(Entry *pe) { + if (pe->t == num) + std::cout << pe->i; + else { + std::cout << *pe->p; + } +} + +int main() { + // + Entry ei; + ei.t = num; // set the Type to num + ei.i = 40; + + Entry ep; + ep.t = ptr; // set Type + ep.p = new int; + *ep.p = 20; + // + Entry *p_ei = &ei; + Entry *p_ep = &ep; + + std::cout << "Ei = "; + f(p_ei); + std::cout << std::endl; + std::cout << "Ep = "; + f(p_ep); + + return 0; +} diff --git a/lecture_code/tour/ch2_user_defined_types/unions1.cpp b/lecture_code/tour/ch2_user_defined_types/unions1.cpp new file mode 100644 index 0000000..c66e29f --- /dev/null +++ b/lecture_code/tour/ch2_user_defined_types/unions1.cpp @@ -0,0 +1,67 @@ +#include +#include + +// Union is a struct in which all members at the same address +// so taht the union occupies only as much space as its largest +// member. A union can only hold a value for only one member +// at a time. Example, consider a symbol table entry that +// holds a name and a value. The value can either +// be a Node* or an int: +// +enum Type { ptr, num }; // a Type can hold values ptr and num + +// Since p and i are never used at the same time space is wasted +// You can recover the space by specifyying that both should +// be members of a union like this +union Value { + int *p; + int i; +}; + +struct Entry { + std::string name; // strin is a standsard library type + Type t; + Value v; + ; // use i if t=num +}; + +// we only use either p or i +void f(Entry *pe) { + if (pe->t == num) + std::cout << pe->v.i; + else { + std::cout << *pe->v.p; + } +} + +// maintaining the correspondence between a type field (here t) +// and the type held in a union is error prone. +// To avoid erros we can enfornce that correspondence by encapsulating +// the union and the type field in a class and offer access only +// through member functions that use the union correctly. +// +// At the application level, abstractions relying on such tagged unions +// are common and useful. The use of "naked" unions is best minimized + +int main() { + // + Entry ei; + ei.t = num; // set the Type to num + ei.v.i = 40; + + Entry ep; + ep.t = ptr; // set Type + ep.v.p = new int; + *ep.v.p = 20; + // + Entry *p_ei = &ei; + Entry *p_ep = &ep; + + std::cout << "Ei = "; + f(p_ei); + std::cout << std::endl; + std::cout << "Ep = "; + f(p_ep); + + return 0; +} diff --git a/lecture_code/tour/ch2_user_defined_types/unions2.cpp b/lecture_code/tour/ch2_user_defined_types/unions2.cpp new file mode 100644 index 0000000..6813236 --- /dev/null +++ b/lecture_code/tour/ch2_user_defined_types/unions2.cpp @@ -0,0 +1,76 @@ +#include +#include + +// Union is a struct in which all members at the same address +// so taht the union occupies only as much space as its largest +// member. A union can only hold a value for only one member +// at a time. Example, consider a symbol table entry that +// holds a name and a value. The value can either +// be a Node* or an int: +// +enum Type { ptr, num }; // a Type can hold values ptr and num + +// Since p and i are never used at the same time space is wasted +// You can recover the space by specifyying that both should +// be members of a union like this +union Value { + int *p; + int i; +}; + +class ValueUnion { +private: + Value v; + Type t; + +public: + ValueUnion(Type ti, Value vi) : v{vi}, t{ti} {} +}; + +struct Entry { + std::string name; // strin is a standsard library type + Type t; + Value v; + ; // use i if t=num +}; + +// we only use either p or i +void f(Entry *pe) { + if (pe->t == num) + std::cout << pe->v.i; + else { + std::cout << *pe->v.p; + } +} + +// maintaining the correspondence between a type field (here t) +// and the type held in a union is error prone. +// To avoid erros we can enfornce that correspondence by encapsulating +// the union and the type field in a class and offer access only +// through member functions that use the union correctly. +// +// At the application level, abstractions relying on such tagged unions +// are common and useful. The use of "naked" unions is best minimized + +int main() { + // + Entry ei; + ei.t = num; // set the Type to num + ei.v.i = 40; + + Entry ep; + ep.t = ptr; // set Type + ep.v.p = new int; + *ep.v.p = 20; + // + Entry *p_ei = &ei; + Entry *p_ep = &ep; + + std::cout << "Ei = "; + f(p_ei); + std::cout << std::endl; + std::cout << "Ep = "; + f(p_ep); + + return 0; +} diff --git a/lecture_code/tour/ch2_user_defined_types/variant.cpp b/lecture_code/tour/ch2_user_defined_types/variant.cpp new file mode 100644 index 0000000..593fed3 --- /dev/null +++ b/lecture_code/tour/ch2_user_defined_types/variant.cpp @@ -0,0 +1,47 @@ +#include +#include +#include + +struct Entry { + std::string name; // strin is a standsard library type + std::variant v; +}; + +// we only use either p or i +void f(Entry *pe) { + if (std::holds_alternative(pe->v)) { + std::cout << std::get(pe->v); + } else { + std::cout << *std::get(pe->v); + } +} + +// maintaining the correspondence between a type field (here t) +// and the type held in a union is error prone. +// To avoid erros we can enfornce that correspondence by encapsulating +// the union and the type field in a class and offer access only +// through member functions that use the union correctly. +// +// At the application level, abstractions relying on such tagged unions +// are common and useful. The use of "naked" unions is best minimized + +int main() { + // + Entry ei; + ei.v = 40; + + Entry ep; + ep.v = new int; + ep.v = 20; + // + Entry *p_ei = &ei; + Entry *p_ep = &ep; + + std::cout << "Ei = "; + f(p_ei); + std::cout << std::endl; + std::cout << "Ep = "; + f(p_ep); + + return 0; +} diff --git a/lectures/1/images/MemoryAddressContent.png b/lectures/1/images/MemoryAddressContent.png new file mode 100644 index 0000000..bf2d0fa Binary files /dev/null and b/lectures/1/images/MemoryAddressContent.png differ diff --git a/lectures/1/note.rst b/lectures/1/note.rst index 9c8085e..4433fc3 100644 --- a/lectures/1/note.rst +++ b/lectures/1/note.rst @@ -10,6 +10,8 @@ .. _lec1_types: +.. I want to write a comment here hopefully this doesn't show up + `C++`_ is all about TYPES! ========================== @@ -19,7 +21,7 @@ Unlike `Python`_ (or any other dynamic languages), all `C++`_ variables must be initialized with their types explicitly given. And the variable names cannot be -reused within the same :ref:`cope`. Consider the following +reused within the same :ref:`scope`. Consider the following `Python`_ code .. _lec1_dy_eg: diff --git a/lectures/4/note.rst b/lectures/4/note.rst index 68c5e80..cbba465 100644 --- a/lectures/4/note.rst +++ b/lectures/4/note.rst @@ -10,7 +10,7 @@ .. _lec4_func_basis: -The Basis +The Basics ========= .. contents:: @@ -263,7 +263,7 @@ Let's first look at the following function that returns a pointer: } On return, ``getPointer`` will return a **copy** of ``ptr`` and this behavior -is will defined. Now, let's look at the the *function body* (content inside +is well defined. Now, let's look at the the *function body* (content inside the function scope). A **local** integer ``a`` is created as well as a pointer ``ptr`` that points to it. The memory address of ``a`` is copied whiling returning ``ptr``, but ``a`` is popped out from the stack right after the @@ -607,11 +607,16 @@ following syntax: :code:`return_type(type1, type2, ...)`, for example, the .. note:: Function declaration (prototyping) is actually like any other declarations - thus having type and variable name. The different is that the variable name - is in the middle of the type, i.e. :code:`void Empty()`. In this case, it + thus having type and variable name. The difference is that the variable name + is in the middle of the type, i.e. :code:`void Empty()`. In this case, it is very similar to defining arrays, i.e. :code:`int array2[2]`, where ``array2`` is the variable that has type of :code:`int[2]`. +.. code-block:: cpp + void Empty();// type then name + int array2[2];// type name + + With a type precisely defined, we expect, of course, its pointer and reference defined as well. The syntax is as following: diff --git a/pdf_lectures/Lecture0 _ AMS 562 Jupyter_Desktop, Terminal , Git.pdf b/pdf_lectures/Lecture0 _ AMS 562 Jupyter_Desktop, Terminal , Git.pdf new file mode 100644 index 0000000..17830ce Binary files /dev/null and b/pdf_lectures/Lecture0 _ AMS 562 Jupyter_Desktop, Terminal , Git.pdf differ diff --git a/software/req.rst b/software/req.rst index 9ce102a..2fe50f1 100644 --- a/software/req.rst +++ b/software/req.rst @@ -133,13 +133,13 @@ and helpful, please take a look at it. You may also find using `Git`_ in `Visual Studio Code`_ is handy, see :ref:`here `. -Set up your private repository on `Bitbucket`_ +Set up your private repository on `Github`_ ---------------------------------------------- -We will use one of the popular online git network, `Bitbucket`_, to collect +We will use one of the popular online git network, `Github`_, to collect your homework assignments. Register an account with your **SBU** email address, then create a **private** repository following this -`description `_. +`description `_. Name your repository with ``ams562_``. And initialize your repository with a ``README.md`` that at least includes your SBU ID and name, @@ -159,8 +159,8 @@ Set up an SSH Key (optional) Using `Secure Shell `_ is the preferred way (but not required for this class) for using `Git`_. Follow -`this description `_ -to setup an SSH key for your `Bitbucket`_ account. +`this description `_ +to setup an SSH key for your `Github`_ account. .. note:: Keep your private key and **passphrase** secure!