├── .gitignore ├── Basic C++ ├── Basic Syntax.md ├── File IO │ ├── File IO.md │ └── code snippets │ │ ├── badFileHandling.cpp │ │ ├── integers.txt │ │ ├── payroll.txt │ │ └── readFile.cpp ├── Functions │ ├── Functions.md │ └── code snippets │ │ ├── defaultParameters.cpp │ │ └── parameterPassing.cpp ├── Good Programming.md ├── Strings.md ├── Structs │ ├── Structs.md │ └── code snippets │ │ ├── struct1.cpp │ │ └── struct2.cpp └── Vectors │ ├── Implementing the Vector.md │ ├── Vectors.md │ └── code snippets │ ├── cars.txt │ ├── dogs.txt │ ├── vectorBasics.cpp │ ├── vectorOfClass.cpp │ └── vectorOfObjectsContainingVectors.cpp ├── Classes ├── Class Basics │ ├── Class Basics.md │ └── code snippets │ │ ├── ClassBasics.cpp │ │ ├── Person.cpp │ │ ├── SimpleDate.cpp │ │ └── SimplestClass.cpp ├── Composition and Association │ ├── Composition and Association.md │ └── code snippets │ │ ├── AssociationClass.cpp │ │ ├── AssociationStruct.cpp │ │ └── testAssociationComposition.cpp ├── Copy Control │ ├── Copy Control.md │ └── code snippets │ │ ├── CopyControlBasics.cpp │ │ ├── Vector.cpp │ │ ├── Vector.h │ │ └── testVector.cpp ├── Inheritance │ ├── Inheritance in Copy Control.md │ ├── Inheritance.md │ └── code snippets │ │ ├── Inheritance.cpp │ │ ├── Polymorphism.cpp │ │ ├── abstractClasses.cpp │ │ ├── code in notes │ │ ├── Animals-02.cpp │ │ ├── Animals-03.cpp │ │ ├── Animals-04.cpp │ │ ├── Animals-05.cpp │ │ ├── NoPolymorphismFromBaseConstructor.cpp │ │ └── protected4.cpp │ │ ├── inheritanceInCopyControl.cpp │ │ └── multipleInheritance.cpp └── Operator Overloading │ ├── Operator Overloading.md │ └── code snippets │ ├── SquareBrackets.cpp │ ├── complexWithOverload.cpp │ ├── complexWithOverload.h │ ├── dateWithOverload.cpp │ ├── dateWithOverload.h │ ├── outputOperator.cpp │ ├── testComplexWithOverload.cpp │ └── testDateWithOverload.cpp ├── Exception ├── Exceptions and Assertions.md └── code snippets │ └── Exception.cpp ├── Linked Lists ├── Linked Lists.md └── code snippets │ ├── LinkedList.cpp │ ├── Node.cpp │ ├── Node.h │ └── testNode.cpp ├── OOP Simplified ├── OOP Simplified.md ├── abstraction.md ├── encapsulation.md ├── images │ ├── Screenshot 2021-05-25 171146.png │ ├── car1.png │ ├── car2.png │ ├── car3.png │ ├── chess1.png │ ├── chess2.png │ ├── chess3.png │ ├── chess4.png │ ├── chess5.png │ ├── chess6.png │ ├── fruit1.png │ ├── fruit2.png │ ├── fruit3.png │ ├── weapon1.png │ ├── weapon2.png │ └── weapon3.png ├── inheritance.md └── polymorphism.md ├── Pointers ├── code snippets │ ├── DynamicArray.cpp │ ├── NewDelete.cpp │ ├── PointerBasics.cpp │ ├── pointerWithConst.cpp │ └── vectorOfObjectsOnHeap.cpp ├── pointer arithmetic.md └── pointers.md ├── Python to C++ └── DIfference between Python and C++.md ├── README.md ├── Recursion ├── Recursion.md └── code snippets │ ├── Recursion.cpp │ ├── binserach.cpp │ └── recursiveLinkedList.cpp ├── STL ├── STL - Standard Template Library.md └── code snippets │ └── STL.cpp ├── SampleCode.md ├── Separate Compilation ├── Cyclic Association.md ├── Include Guards.md ├── Namespaces.md ├── Separate Compilation.md └── code snippets │ ├── Date.cpp │ ├── Date.h │ ├── dateWithNamespace.cpp │ ├── dateWithNamespace.h │ ├── testDate.cpp │ └── testDateWithNamespace.cpp ├── Template ├── Convert Vector Class to Template.md └── code snippets │ ├── Vector.cpp │ ├── Vector.h │ └── maximum.h ├── homeworks ├── hw01 │ └── hw01.md ├── hw02 │ └── hw02.md ├── hw03 │ └── hw03.md ├── hw04 │ └── hw04.md ├── hw05 │ └── hw05.md ├── hw06 │ └── hw06.md ├── hw07 │ └── hw07.md └── hw08 │ ├── hw08.md │ ├── outputNew.txt │ └── testPolynomial.cpp └── recitations ├── rec01 ├── Recitation 1 notes on input filesV2.pdf ├── jabberwocky └── rec01.md ├── rec02 ├── Basic SortingPython.pdf └── rec02.md ├── rec03 ├── Rec03.pdf ├── accounts.txt ├── minesweeper.pdf ├── rec03.md └── transactions.txt ├── rec04 ├── Rec04 Additional Info for Xcode.pdf └── rec04.md ├── rec05 ├── rec05-start.cpp └── rec05.md ├── rec06 ├── rec06-origV2.cpp └── rec06.md ├── rec07 ├── output-for-required.txt ├── rec07.cpp └── rec07.md ├── rec08 ├── gcd.cpp ├── rec08.md └── testRational.cpp ├── rec09 ├── rec09.md └── rec09.zip ├── rec10 ├── rec10 19S.zip └── rec10.md ├── rec11 ├── linkedListFuncs.cpp ├── rec11.md └── rec11_ Linked List Basics.pdf ├── rec12 ├── NoSentinels.jpeg ├── TwoSentinels.jpg ├── output.txt ├── rec12-test.cpp └── rec12.md ├── rec13 ├── pooh-nopunc.txt ├── rec13.md └── rec13_test.cpp └── rec14 ├── rec14.md └── tree.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | *.html -------------------------------------------------------------------------------- /Basic C++/Basic Syntax.md: -------------------------------------------------------------------------------- 1 | # Basic Syntax of C++ 2 | 3 | ## Topics 4 | * Main function 5 | * Variables 6 | * Primitive types 7 | * Conditions 8 | * Logical Operators 9 | * Loops 10 | 11 | ## The main function 12 | In C++, every program must have a function called main, which is the program called when we compile and run a C++ program. The main program has to return type `int`. 13 | 14 | Here is a simple working C++ program: 15 | ```C++ 16 | int main() {return 0;} 17 | ``` 18 | 19 | ## Hello World 20 | 21 | ```c++ 22 | #include 23 | using namespace std; 24 | 25 | int main(){ 26 | cout << "Hello World" << endl; 27 | } 28 | ``` 29 | Note: 30 | * `#include` tells compiler to read in the library `iostream` to use the function `cout`. 31 | * `using namespace` will same you having to type the **qualifier** `std` to `cout`. Otherwise, that line will turn to 32 | ```c++ 33 | std::cout << "Hello World" << endl; 34 | ``` 35 | 36 | ## Variables 37 | C++ requires that all variables be defined before they are used and furthermore that every variable must have a type that sticks with the variable until it ceases to exist. 38 | 39 | Suppose we want to modify the previous program to ask the "user" for a name to say hello to: 40 | ```c++ 41 | #include 42 | #include 43 | using namespace std; 44 | 45 | int main() { 46 | string name = "world"; 47 | cout << "Hello " << name << "!\n"; 48 | } 49 | ``` 50 | 51 | However, we should ask the user for their *name*: 52 | ```c++ 53 | #include 54 | #include 55 | using namespace std; 56 | 57 | int main() { 58 | string name; 59 | cout << "What is your name? "; 60 | cin >> name; 61 | cout << "Hello " << name << "!\n"; 62 | } 63 | ``` 64 | 65 | Note: 66 | * `string name` did not define the content of name but did initilize the variable `name` for us to use in `cin >> name;` 67 | 68 | ### Default Types - Also known as *primitive* types 69 | * int: the most common type to represent integers. In most compilers this will be a 32-bit value 70 | * double: used for "floating point" values, like 3.1415926535. 71 | * bool: can hold the values `true` and `false`. 72 | * char: holds a "character". 73 | 74 | ## Conditions 75 | Here are the syntax for if / else if / else statements: 76 | ```c++ 77 | // a simple if statement 78 | if (answer == 42) { 79 | cout << "Now what was the question?"; 80 | } 81 | 82 | // an if-else statement 83 | if (answer == 42) { 84 | cout << "Now what was the question?\n"; 85 | } else { 86 | cout << "The answer wasn't 42\n"; 87 | } 88 | 89 | // an if-else-if-else statement 90 | if (answer == 42) { 91 | cout << "Now what was the question?\n"; 92 | } else if (answer == 17) { 93 | cout << "That's pretty random\n"; 94 | } else { 95 | cout << "Wasn't anything we tested for.\n"; 96 | } 97 | ``` 98 | Note: conditions must be in parentheses in C++, which applies to *for loops*, *while loops*, *if else statements*, etc. 99 | 100 | ### Logical Operators 101 | * `and` is `&&` 102 | * `or` is `||` 103 | * `not` is `!` 104 | 105 | ## Loops 106 | 107 | ### For loop 108 | ```c++ 109 | for (int i = 0; i < 5; ++i) { 110 | cout << "Hello world!\n"; 111 | } 112 | ``` 113 | There are three parts in the for loop: 1) initialization, 2) test and 3) increment. 114 | 1. Initilization defines a counter `i` of type `int`. The variable will *only* exist in this for loop. 115 | 2. Tess is evaluated each time we iterate the loop, which is the condition as to when we should stop. 116 | 3. Increment part is whatever code we want to use after a pass through the loop and before we do the test to decide if we should begin another loop. 117 | 118 | ### While loop 119 | While loop is to continue looping over a block of code so long as some condition it true. 120 | ```c++ 121 | while (i < 5) { 122 | cout << "Hello world!\n"; 123 | ++i; 124 | ``` 125 | 126 | 127 | -------------------------------------------------------------------------------- /Basic C++/File IO/File IO.md: -------------------------------------------------------------------------------- 1 | # File I/O for Text Files 2 | To deal with text files in C++, we need the `` library, which is the input stream class to operate on files. 3 | 4 | ## Reading a File 5 | 1. The first step of reading a file is to create a **stream object** to get input from a file. A stream object has type `ifstream`. 6 | ```c++ 7 | #include 8 | ifstream ifs("data.txt") 9 | ``` 10 | Note: Here we defined a variable `ifs` which is a stream object of the `data.txt` file. 11 | 12 | 2. We should check if the file opened correctly. 13 | ```c++ 14 | if (!ifs) { 15 | cerr << "Could not open the file.\n"; 16 | exit(1); 17 | } 18 | ``` 19 | 3. To read from the file, it depends on what information is in the file and how we want to use it. 20 | 21 | Most common way to read from a file: 22 | ```c++ 23 | ifs >> x; 24 | ``` 25 | C++ would skip over any whitespace, interpret what it sees in the file based on the type of variable x, and read until whitespace. 26 | ### Loop Through a File 27 | Suppose we have a file of integers to read and print, we will need a loop: 28 | ```c++ 29 | int anInt; 30 | while (ifs >> anInt) { 31 | cout << anInt << endl; 32 | } 33 | ``` 34 | Note: the while loop has the condition of whether the read is successful, and if unsuccessful we know there is no more to read. 35 | 36 | ### Reading a Line 37 | If we want to read an entire line with whitespaces: 38 | ```c++ 39 | string line; 40 | getline(cin, line); 41 | ``` 42 | Note: variable `line` will get every character expect the end-of-line character. 43 | 44 | Looping through a file line by line: 45 | ```c++ 46 | while (getline(ifs, line)) { 47 | cout << line << endl; 48 | } 49 | ``` 50 | ### Close a File 51 | Make sure to always close a file whenever you are done with it. 52 | ```c++ 53 | ifs.close(); 54 | ``` 55 | ### Other Useful Methods 56 | If you have attempted to read something and couldn't, either because you came to the end of the file, or something of the type you wanted to read wasn't at that spot in the file, some flags get set inside the stream object. These flags will prevent you from reading anything else from the file. If you still reading the file, you will need to "clear" those flags. 57 | ```c++ 58 | ifs.clear(); 59 | ``` 60 | If we finished reading till the end of a file and want to go back to the start and read the file again, jump to the beginning with: 61 | ```c++ 62 | ifs.seekg(0); 63 | ``` 64 | Note: if you had already read all the way to the end of file, you will nead to call `clear` before you can `seekg`. 65 | 66 | ### Passing Streams 67 | One group of parameter types that need to be treated specialy is the stream classes. Whether you are talking about the standard streams (i.e. `cin`, `cout` and `cerr`) or you are talking about a file stream, the all must be passed-by-reference. 68 | 69 | Why? The point is we never want to make a copy of a stream. We don't want to have two different stream "objects" referring to a single real underlying stream. A stream has a number of attributes that describe the stream's current status. For example, is it still ok to read from? What is the next position in the stream that we will read from or write to? Every time you use a stream, those attributes can change. But if we have to different stream objects referring to the same underlying stream then they can end up disagreeing with each other. And that's not good. 70 | 71 | To prevent such confusion, we always pass streams by reference. That way even when we have passed a stream to a function, the parameter name in the function is really referring to the same stream object as the calling function was using. 72 | 73 | Oh, and you will find that you don't have any choice in this area. If you try to pass a stream by value, or try to make a copy of a stream in any other way, your program will not compile. The folks who wrote the stream classes made sure of that. Later on, when we discuss copy control, we will see how they did it. 74 | 75 | What about making your stream a const parameter? Not likely to be a good idea. After all, think about what a stream object holds. Among other things, it has flags as to whether it is still readable or if we have hit the end of the file. And it has some sort of position marker that keeps track of where the next read will come from or where the next write will go to. All these things need to be free to be modified when we use the stream, so passing a stream by constant reference is not good. -------------------------------------------------------------------------------- /Basic C++/File IO/code snippets/badFileHandling.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Example of how NOT to read a file. 3 | John Sterling 4 | CS1124 5 | Polytechnic University 6 | */ 7 | 8 | // This program has been stripped down to focus on a common 9 | // student programming error when reading files. The part of 10 | // the code to pay attention to is the loop. 11 | 12 | #include // cin, cout, cerr, endl 13 | #include // ifstream 14 | #include // string 15 | 16 | using namespace std; 17 | 18 | int main() { 19 | ifstream payrollStream; 20 | payrollStream.open("payroll.txt"); 21 | 22 | string name; 23 | int money; 24 | // This loop is WRONG!! The only person who would approve is whoever is 25 | // the person at the end of payroll file. WHY does this code fail to work 26 | // properly? 27 | 28 | // The problem happens when you have any additional characters at the end 29 | // of the file 30 | while (!payrollStream.eof()) { 31 | payrollStream >> name >> money; 32 | cout << "Pay to the order of "<< name << " $" << money << endl; 33 | } 34 | 35 | return 0; 36 | } -------------------------------------------------------------------------------- /Basic C++/File IO/code snippets/integers.txt: -------------------------------------------------------------------------------- 1 | 1 2 3 -------------------------------------------------------------------------------- /Basic C++/File IO/code snippets/payroll.txt: -------------------------------------------------------------------------------- 1 | Steele 100 2 | Katz 90 3 | Sterling 75 -------------------------------------------------------------------------------- /Basic C++/File IO/code snippets/readFile.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include // cin, cout, cerr, endl 3 | #include // ifstream 4 | #include // string 5 | 6 | using namespace std; 7 | 8 | // main always has an int return type. 9 | int main() { 10 | 11 | ifstream nameStream; 12 | cout << "What is the name of the file? "; 13 | string fileName; 14 | cin >> fileName; 15 | // We can not pass a string object to the 16 | // method "open". 17 | // We have to pass a "C string". 18 | // (C strings are just arrays of characters 19 | // with a NULL character at the end.) 20 | // The method "c_str()" returns a C string 21 | // version of a string object. 22 | nameStream.open(fileName.c_str()); 23 | 24 | // We do not have to explicitly invoke the 25 | // "fail" method here, though we could if we 26 | // want. When we test the stream object nameStream, 27 | // it returns false if the stream is broken and true otherwise. 28 | // Note that it is perfectly ok to write "nameStream.fail()" instead 29 | // of "!nameStream". 30 | if (!nameStream) { 31 | // Using the stream object cerr since this is an error message. 32 | cerr << "Couldn't open the names file.\n"; 33 | return 1; 34 | } 35 | 36 | string name; 37 | 38 | // if nameStream is already broken before the read or breaks 39 | // during the read then the test for the while will fail. 40 | // What does "broken" mean? That we failed to do something that 41 | // we tried to do with the stream. 42 | while ( nameStream >> name ) { 43 | cout << name << endl; 44 | } 45 | 46 | nameStream.close(); 47 | 48 | // Note that the following line, "return 0;" is optional. 49 | // VC++6 used to give a warning 50 | // but .Net does a better job of conforming to the standard. 51 | return 0; 52 | } -------------------------------------------------------------------------------- /Basic C++/Functions/code snippets/defaultParameters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // Note the "= 5" after the parameter name y. 5 | // This allows us to call the function foo passing it either 6 | // two arguments or just one argument. When the second argument 7 | // is omitted in a call to foo, then the parameter y will have 8 | // the default value, which is specified here to be 5. 9 | void foo(int x, int y = 5) { 10 | cout << "x = " << x << ", y = " << y << endl; 11 | } 12 | 13 | int main () { 14 | foo(17); 15 | foo(17, 0); 16 | return 0; 17 | } 18 | 19 | /* 20 | // We could have achieved almost exactly the same effect by 21 | // defining foo twice. One time we could define it as taking 22 | // two parameters as in: 23 | void foo(int x, int y) { 24 | cout << "x = " << x << ", y = " << y << endl; 25 | } 26 | // and the second time taking only one parameter, but adding 27 | // in a local variable y. 28 | void foo(int x) { 29 | int y = 5; 30 | cout << "x = " << x << ", y = " << y << endl; 31 | } 32 | */ -------------------------------------------------------------------------------- /Basic C++/Functions/code snippets/parameterPassing.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | void pass_by_value(int n){ 8 | n++; 9 | // the actual value n in main() did not change 10 | } 11 | void pass_by_ref(int& n){ 12 | n++; 13 | // & is like the address, the ref to n in main(), so value changes 14 | } 15 | int pass_by_return(int n){ 16 | return n+n; 17 | //return gives new copy of n+n 18 | } 19 | 20 | void pass_by_const_ref(const int& n){ 21 | // n cannot be changed 22 | } 23 | 24 | 25 | void print_vec(vector v){ 26 | for (int n : v){ 27 | cout << n << ' '; 28 | } 29 | cout << endl; 30 | 31 | } 32 | 33 | void print_vec_const(const vector& v){ // doesn't return, doesn't change vector v, doesnt have side effects 34 | for (int n : v){ // int n is a copy 35 | cout << n << ' '; 36 | } 37 | cout << endl; 38 | 39 | } 40 | 41 | void square_vec(const vector& v){ 42 | for (int n : v){ // int n is a copy 43 | cout << (n * n) << ' '; 44 | } 45 | } 46 | 47 | 48 | 49 | int main(int argc, const char * argv[]) { 50 | // Test code here 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /Basic C++/Good Programming.md: -------------------------------------------------------------------------------- 1 | # Good Programming 2 | It's a little scary to start a section on "good programming", especially in an introductory guide to C++. There's a lot to say under this heading, but I want to keep it short and to the point. First off, you should probably check my [C++ Coding Guidelines](https://cse.engineering.nyu.edu/jsterling/cs2124/Notes/CodeGuideline.html) for simple things like naming conventions and the like. 3 | 4 | There are a few other things that you should pay careful attention to as you start your C++ programming career. 5 | 6 | ## Globals 7 | Global variables are variables that are defined outside of any function or type definition. Every variable that we have defined was either local to a function or was a member of a struct. My "advice" on using globals at this stage? 8 | 9 | Don't. 10 | 11 | Overuse of globals is generally viewed as a sign of sloppy code. What's the problem with them? Any piece of code, anywhere in the program can access and even modify their contents. It makes debugging much, much harder. And one of the advantages of using a language like C++ is to make debugging easier. 12 | 13 | For this course, you will **never use global variables**. This is to get you thinking the right way. Later on, you will make up your own mind as to when a global is an improvement to your program. Hopefully by then you will recognize the danger of globals and use them sparingly. 14 | 15 | Global constants, on the other hand, are ok, in fact we encourage you to use them! Here is an example: 16 | ```c++ 17 | const int THE_ANSWER = 42; 18 | ``` 19 | 20 | ## Scope 21 | Define your variables using the smallest scope possible. This is in a sense an extension of what I said about globals. You want to define a variable so that ideally it can only be used where it makes sense. We saw an example of this earlier when I talked about the for loop and how you can limit the scope of the loop's index to just the for loop itself. That's a good thing. 22 | 23 | In general, define a variable as close to the place where it is first used as possible. In some languages, like earlier versions of C, you have to define all local variables at the beginning of a function. That's not true in C++. In fact, it is considered poor programming style in C++ to define them all at the beginning of the function. (Old time C programmers will tend to disagree with me on this.) 24 | 25 | So, if a variable is only going to be used inside a block of code (i.e. within a pair of curly-braces) such as in an if statement or a loop, then put the definition for that variable *inside* that block. -------------------------------------------------------------------------------- /Basic C++/Strings.md: -------------------------------------------------------------------------------- 1 | # Strings 2 | Strings are like vectors and `string` in Python, and can be used like a vector of characters. The methods and operators used for vectors all works for strings. 3 | 4 | ```c++ 5 | string s = "abc"; // Note the double quotes around a string. 6 | s.push_back('z'); // Note the single quotes around a character. 7 | ``` 8 | We can also access the characters in a string using the square-bracket operator. And if the string hasn't been marked as *constant*, we can change the value of a character inside it, the same way we would change any of the values inside a vector. 9 | ## String Concatenation 10 | Two string objects can be concatenated together using the + operator, to form a new string. Similarly, we can use += to add one string onto another string (i.e. to append one string to another). 11 | ```c++ 12 | string a = "The"; 13 | string b = "Cat"; 14 | cout << a + " " + b << endl; 15 | ``` 16 | or 17 | ```c++ 18 | string a = "The"; 19 | string b = "Cat"; 20 | a += " "; 21 | a += b; 22 | cout << a << endl; 23 | ``` 24 | 25 | Note: these `+` and `+=` operators only support *string* objects, not string literals 26 | Ex: 27 | ```c++ 28 | cout << "The" + " " + "Cat" << endl; // Does NOT compile! 29 | ``` 30 | `"The"` is a string literal, not a string object. -------------------------------------------------------------------------------- /Basic C++/Structs/Structs.md: -------------------------------------------------------------------------------- 1 | # Structs in C++ 2 | A common way to make our own types is by using *structs* 3 | ```c++ 4 | struct Cat { 5 | string color; 6 | string name; 7 | double weight; 8 | }; // Don't forget semi-colon at the end 9 | ``` 10 | `Cat` has three attributes: `color`, `name` and `weight`. Attributes are also known as fields or member variables. 11 | 12 | We can then create a cat, provide values for its various attributes and finally access those values to print them with the following code: 13 | ```c++ 14 | Cat myCat; 15 | myCat.name = "Felix"; 16 | myCat.color = "grey"; 17 | myCat.weight = 3.14; 18 | cout << myCat.name << '\t' << myCat.color << '\t' << myCat.weight << endl; 19 | ``` 20 | ## Assigning Structs to another 21 | ```c++ 22 | Cat b; 23 | b = myCat; 24 | ``` 25 | same as 26 | ```c++ 27 | b.color = myCat.color; 28 | b.name = myCat.name; 29 | b.weight = myCat.weight; 30 | ``` 31 | 32 | Note that currently `Cat` cannot perform operators like equality or printing. 33 | ```c++ 34 | // COMPILATION ERROR!!! 35 | if (b == myCat) {/* We want to do something if they are equal*/} 36 | 37 | cout << myCat << endl; // COMPILATION ERROR!!! 38 | ``` 39 | To solve this, we use operator overloading. 40 | 41 | ## Filling a vector of structs 42 | Above we defined a Cat struct. How would we fill a vector of cats from a file holding the cat information? Below is a function that is passed a stream to read from and a vector to fill with Cats. We assume that the file has one cat per line. 43 | ```c++ 44 | void fillCatVector (ifstream& ifs, vector& vc) { 45 | Cat c; 46 | while (ifs >> c.name >> c.color >> c.weight) { 47 | vc.push_back(c); 48 | } 49 | } 50 | ``` -------------------------------------------------------------------------------- /Basic C++/Structs/code snippets/struct1.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | struct Point 8 | { 9 | int x, y, z; 10 | }; 11 | 12 | Point point{1, 2, 3}; // simple assignment of a struct in one line 13 | 14 | int main() 15 | { 16 | vector points; 17 | ifstream pfile("data.txt"); 18 | Point new_pt; 19 | while (pfile >> new_pt.x >> new_pt.y >> new_pt.z) 20 | { 21 | 22 | points.push_back(new_pt); 23 | } 24 | for (Point p : points) 25 | { 26 | cout << p.x << ' ' << p.y << ' ' << p.z << endl; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Basic C++/Structs/code snippets/struct2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | /* 5 | Demostrating some interesting behaviors of pass-by-const-reference using structs 6 | 7 | Note these behaviors also apply to Classes 8 | 9 | display() is called a method of Person object 10 | */ 11 | 12 | struct Person 13 | { 14 | void display() const 15 | { // if not const, displayPerson() function will get an error 16 | cout << name << endl; 17 | } 18 | string name; 19 | }; 20 | 21 | void displayPerson(const Person &aPerson) 22 | { // That's because there's a const in this function, 23 | // The compiler can't tell if aPerson.display() would modify the object or not. 24 | aPerson.display(); 25 | } 26 | 27 | int main() 28 | { 29 | Person john; 30 | john.name = "John"; 31 | john.display(); 32 | displayPerson(john); 33 | } -------------------------------------------------------------------------------- /Basic C++/Vectors/code snippets/cars.txt: -------------------------------------------------------------------------------- 1 | 2 | Ford Mustang 1968 3 | Mazda RX7 1975 4 | Cadillac DeVille 1980 -------------------------------------------------------------------------------- /Basic C++/Vectors/code snippets/dogs.txt: -------------------------------------------------------------------------------- 1 | ben 3 terrier 2 | chris 2 shepherd 3 | aslan 5 shepherd -------------------------------------------------------------------------------- /Basic C++/Vectors/code snippets/vectorBasics.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | textVectorBasics.cpp 3 | 1) read a file of integers into a vector 4 | 2) display the values in the vector 5 | */ 6 | 7 | #include // cout, cerr, endl 8 | #include // ifstream 9 | #include // vector 10 | using namespace std; 11 | 12 | int main() { 13 | cout << "Program: textVectorBasics.cpp\n\n"; 14 | 15 | // Open the data file 16 | ifstream ifs("integers.txt"); 17 | if (!ifs) { 18 | cerr << "Couldn't open 'intergers.txt'\n"; 19 | exit(1); 20 | } 21 | 22 | // Create a vector to put the data into. 23 | // Note that it is a vector of ints. 24 | // It is initially empty. 25 | vector alfred; 26 | 27 | int x; // Temporary variable to read the data into 28 | // Usual loop for reading all the items from a file 29 | while (ifs >> x) 30 | // push_back increase the length of the vector by one 31 | // and copies x into this new last slot in the vector. 32 | alfred.push_back(x); 33 | 34 | // Loop over the vector printing out the values. 35 | // size_t: Note the use of size_t for the index variable. 36 | // Even if you don't usually use size_t, it's a good idea here, 37 | // because that's what the method size() returns. 38 | // If you don't use size_t you will get a warning. 39 | // size(): returns the count of how many items there are in 40 | // the vector. 41 | for (size_t i = 0; i < alfred.size(); ++i) 42 | // Isn't it nice that we can access the elements in the vector 43 | // the same way we would an array? 44 | cout << alfred[i] << ' '; 45 | 46 | cout << endl; 47 | 48 | } -------------------------------------------------------------------------------- /Basic C++/Vectors/code snippets/vectorOfClass.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | vectorOfClass.cpp 3 | 1) read a file into a vector of class objects. 4 | 2) display the values in the vector 5 | 6 | */ 7 | 8 | #include // cout, cerr, endl 9 | #include // ifstream 10 | #include 11 | #include 12 | using namespace std; 13 | 14 | class Car { 15 | public: 16 | Car(const string& theMake, const string& theModel, int theYear) 17 | : make(theMake), model(theModel), year(theYear) 18 | {} 19 | void display() const { 20 | cout << "Make: " << make 21 | << "; Model: " << model 22 | << "; Year: " << year << endl; 23 | } 24 | private: 25 | string make; 26 | string model; 27 | int year; 28 | }; // Remember the semi-colon. I forgot it. Again. 29 | 30 | int main() { 31 | cout << "Program: vectorOfClass.cpp\n\n"; 32 | 33 | // Open the data file 34 | ifstream ifs("cars.txt"); 35 | if (!ifs) { 36 | cerr << "Couldn't open 'cars.txt'\n"; 37 | exit(1); 38 | } 39 | 40 | // Create a vector to put the data into. 41 | // The vector is initially empty. 42 | vector myCars; 43 | 44 | string make; // Temporary variable to read the make into 45 | string model; // Temporary variable to read the model into 46 | int year; // Temporary variable to read the year into 47 | // Usual loop for reading all the items from a file 48 | while (ifs >> make >> model >> year) { 49 | // Create a car 50 | Car aCar(make, model, year); 51 | // Push a COPY of aCar onto the end of the vector 52 | myCars.push_back(aCar); 53 | } 54 | 55 | // Loop over the vector printing out the values. 56 | for (size_t i = 0; i < myCars.size(); ++i) { 57 | myCars[i].display(); 58 | } 59 | } -------------------------------------------------------------------------------- /Basic C++/Vectors/code snippets/vectorOfObjectsContainingVectors.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | vectorOfStructsContainingVectors.cpp 3 | 4 | Demonstrate the use of arrays that hold 5 | struct objects that hold arrays 6 | 7 | John Sterling 8 | CS1124 9 | Polytechnic University 10 | */ 11 | 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | using namespace std; 19 | 20 | //const int BREED_MAX = 20; // Maximum number of breeds that can be stored for a Dog. 21 | // // This should be a static const int inside the Dog struct, 22 | // // but we haven't covered that. 23 | // 24 | struct Dog { 25 | string name; // The name of the dog 26 | vector breed; // A dog may be a combination of several breeds 27 | // int countOfBreeds; // How many breeds for this dog? 28 | int age; // Age of the dog. (Probably better to use date of birth). 29 | 30 | }; 31 | void displayDog(const Dog&); 32 | 33 | void fillKennel(ifstream&, vector&); 34 | 35 | int main() { 36 | //const int KENNEL_SIZE = 10; 37 | vector kennel; 38 | ifstream ifs; 39 | ifs.open("dogs.txt"); 40 | if (!ifs) { // equivalent to: if (ifs.fail()) { 41 | cerr << "Idiot! I can't open the file!\n"; 42 | exit(17); 43 | } 44 | 45 | fillKennel(ifs, kennel); 46 | 47 | // Note that we use the method size here. 48 | cout << "Total number of dogs read in: " << static_cast(kennel.size()) << endl; 49 | 50 | // Display the dogs that were read in 51 | for (size_t i = 0; i < kennel.size(); ++i) displayDog(kennel[i]); 52 | } 53 | 54 | // fillKennel is passed a stream to read descriptions of dogs from, 55 | // a vector of dogs to fill 56 | // Each line of the file describes a single dog. 57 | // Each line consists of: 58 | // name age breed1 breed2 ... 59 | void fillKennel(ifstream& dogStream, vector& myDogs) { 60 | // Fill the array. 61 | // Use the && operator's "short circuiting" 62 | // to prevent more than sizeOfDogs number of Dogs to be read 63 | string name; 64 | while (dogStream >> name) { 65 | Dog aDog; 66 | aDog.name = name; 67 | dogStream >> aDog.age; 68 | 69 | string breeds; 70 | getline(dogStream, breeds); // Get the remainder of the line containing thebreeds 71 | istringstream iss(breeds); // Set up a stream to read the breeds from 72 | 73 | string aBreed; 74 | //aDog.breed.clear(); // Need this if aDog is defined outside the loop 75 | // Fill the Dog's vector of breeds. 76 | while( iss >> aBreed ) aDog.breed.push_back(aBreed); 77 | 78 | myDogs.push_back(aDog); 79 | } 80 | } 81 | 82 | // Display a dog 83 | void displayDog(const Dog& d) { 84 | cout << "Name: " << d.name 85 | << "; Age: " << d.age 86 | << "; Breeds: "; 87 | // Display all but the last breed followed by ", ". 88 | for (size_t i = 0; i < d.breed.size()-1; ++i) cout << d.breed[i] << ", "; 89 | // Display the last breed followed by a newline. 90 | if (d.breed.size()> 0) cout << d.breed.back() << endl; 91 | } -------------------------------------------------------------------------------- /Classes/Class Basics/code snippets/ClassBasics.cpp: -------------------------------------------------------------------------------- 1 | //Object Oriented Programming 2 | //Classes 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | /* 9 | Struct are usually identified as only data without behavior 10 | Only big difference between Classes and Structs is that methods are all public in struct 11 | */ 12 | 13 | 14 | class Person { 15 | public: 16 | Person(const string& theName, const int& theAge) // contructor with arguments, can't just initilize empty Person object 17 | : name(theName), age(theAge) // initilization list (initilize non-primitive fields) . More effcient 18 | { 19 | //name = theName; this is also okie. But the initilization list will call default constructor for non-primitive fields. This is extra work. 20 | } 21 | 22 | // Person() {} default constructer syntax. In the initlization list it calls the default constructor for non-primitive fields 23 | // Same as Person() : name() {} 24 | 25 | 26 | void display() const { // if not const, displayPerson() function will get an error 27 | // const makes all the attributes in the function unchangable 28 | cout << name << endl; 29 | } 30 | // void setName(const string& theName){name = theName;} // extra work 31 | 32 | 33 | private: // ALL MEMBER FIELDS MUST BE PRIVATE. This is encapsulation in play 34 | string name; 35 | int age; 36 | }; 37 | 38 | void displayPerson(const Person& aPerson) { 39 | // The compiler can't tell if aPerson.display() would modify the object or not. if Person.display() doesn't have const keyword 40 | aPerson.display(); 41 | } 42 | 43 | int main() { 44 | Person john("John", 20); // use constructer 45 | // Person george; this is an error now, no arguments added. Constructer defined, so default constructer disappears 46 | // john.setName("John"); This is very extra 47 | // john.name = "John"; This doesn't work anymore cuz .name is private 48 | john.display(); 49 | } 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /Classes/Class Basics/code snippets/Person.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | class Date { 6 | public: 7 | Date(int month, int day, int year) : month(month), day(day), year(year) {} 8 | void display() const { cout << month << '/' << day << '/' << year; } 9 | private: 10 | int month, day, year; 11 | }; 12 | 13 | class Person { 14 | public: 15 | Person(const string& aName, int m, int d, int y) 16 | : myName(aName), bday(m, d, y) { } 17 | void display() const { 18 | cout << "Displaying a Person named " << myName << " whose birthday is "; 19 | bday.display(); 20 | cout << endl; 21 | } 22 | private: 23 | string myName; 24 | Date bday; 25 | }; 26 | 27 | int main() { 28 | Person will("Will", 3, 14, 1592); // Don't know how old Will is. March 14, 1592 is just a guess. 29 | will.display(); 30 | } -------------------------------------------------------------------------------- /Classes/Class Basics/code snippets/SimpleDate.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Example of a simple class. 3 | (This has three compilation errors. Can you explain why?) 4 | John Sterling 5 | CS1124 6 | Polytechnic University 7 | */ 8 | 9 | #include 10 | #include 11 | using namespace std; 12 | 13 | // The Date class demonstrates 14 | // the use of constructors, accessors and mutators. 15 | // private vs. public 16 | // const methods 17 | // default arguments 18 | 19 | class Date { 20 | public: 21 | // CONSTRUCTORS 22 | 23 | // date is assumed to be in the form mm/dd/yyyy 24 | Date(const string& date) { 25 | month = atoi(date.substr(0,2).c_str()); 26 | day = atoi(date.substr(3,2).c_str()); 27 | year = atoi(date.substr(6,4).c_str()); 28 | } 29 | 30 | // Getters (aka Accessors) 31 | // Remember to make every function const 32 | // that doesn't change the member variables. 33 | int getDay() const { return day; } 34 | int getMonth() const { return month; } 35 | int getYear() const { return year; } 36 | 37 | // Setters (aka Mutators) 38 | void setMonth(int m) { 39 | if (m > 0 && m <= 12) 40 | month = m; 41 | else { 42 | cerr << "Date::setMonth: Invalid month: " << m << endl; 43 | exit(1); 44 | } 45 | } 46 | 47 | // display method for printing dates as month/day/year. 48 | // Note that we used a default argument for the stream 49 | // so that way we can print to the screen if no argument 50 | // is provided, or print to a file stream if we like. 51 | // Note that there is one little thing wrong here that 52 | // will cause a problem elsewhere. Try compiling and see. 53 | void display(ostream& os = cout) { 54 | os << month << '/' << day << '/' << year; 55 | } 56 | 57 | // earlierThan is a feature we might like to add later. 58 | // So long as we don't use it, there is no harm in 59 | // providing a prototype here. 60 | bool earlierThan(Date) const; 61 | 62 | private: 63 | int day, month, year; 64 | }; 65 | 66 | // This does not compile. Why? 67 | // How do we fix the display function so that this can compile. 68 | void notMuchofaFunction (const Date& sometime) { 69 | sometime.display(); 70 | } 71 | 72 | int main() { 73 | Date d1; // Compilation error. Why? No "default constructor" 74 | 75 | Date independenceDay("07/04/1776"); 76 | independenceDay.display(); 77 | independenceDay.month = 17; // Won't compile because month is private. 78 | independenceDay.setMonth(17); // What will happen? 79 | 80 | Date whatIsThis(); // What is this? 81 | } 82 | 83 | -------------------------------------------------------------------------------- /Classes/Class Basics/code snippets/SimplestClass.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Example of simplest class. 3 | John Sterling 4 | CS1124 5 | Polytechnic University 6 | */ 7 | 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | // The class NothingHere is a valid class. It doesn't have anything 13 | // in it. 14 | 15 | class NothingHere { 16 | }; // Remember to put the semi-colon here or you will get strange errors. 17 | 18 | int main() { 19 | NothingHere x; 20 | 21 | // Not much we can do with the NothingHere class, 22 | // except create an instance of one. 23 | // Hm, let's see, how big is our NothingHere? 24 | // Even an empty class like this takes up a single byte. 25 | // (Can you guess why?) 26 | // Ans: 27 | // an object of one empty class will take at least one byte to ensure that the two different objects will have different addresses. 28 | cout << "sizeof(x) = " << sizeof(x) << endl; 29 | } -------------------------------------------------------------------------------- /Classes/Composition and Association/Composition and Association.md: -------------------------------------------------------------------------------- 1 | # Composition and its Issues 2 | Suppose we have two classes, `Foo` and `Bar` and we would like every `Foo` to have a `Bar`. We can represent that with the following class definitions: 3 | ```c++ 4 | class Bar {}; // Not interested in what Bar consists of right now. 5 | 6 | class Foo { 7 | public: 8 | private: 9 | Bar myBar; // Every Foo has a Bar. 10 | int someOtherData; 11 | }; 12 | ``` 13 | This is referred to as *composition*. It is also called *containment*. What is implied by this arrangement? 14 | 15 | * When we create a `Foo`, we automatically create a `Bar` at the same time. When our `Foo` object is destroyed, the `Bar` is destroyed with it. 16 | * What if I want to use a different `Bar` from the one we started with? Sure I might be able to change the values stored inside the `Bar`, but I couldn't put a *different* `Bar` there. 17 | * Every `Foo` has a `Bar`. It can't get rid of it. 18 | * The `Bar` belongs to the `Foo` and can't be shared equally with other `Foos`. 19 | * The `Bar` is stored inside the `Foo`. `Foo` has to be big enough to hold `Bar` and anything else it wants to hold. 20 | 21 | So, when might we want a different design? 22 | 23 | * What if we don't want every `Foo` to start out with a `Bar`, but instead to get one later. 24 | * Or what if we want to be able to throw away the `Bar` after a while? 25 | * Or replace it with a different one? 26 | * What if I want to share a single `Bar` among several `Foos`? 27 | * What if `Bar` is actually the same class as `Foo`? 28 | 29 | Any of these would require that we use a different arrangement. For example, if `Bar` is actually the same class a `Foo`, then we are proposing the following class: 30 | 31 | ```c++ 32 | class Foo { 33 | public: 34 | private: 35 | Foo myFoo; // Every Foo has a Foo. 36 | int someOtherData; 37 | }; 38 | ``` 39 | 40 | But this says that inside a `Foo` is another `Foo`. Not only that but it has `someOtherData`, which is an `int`. How can I fit a `Foo` inside another `Foo`. Every `Foo` is the same size, but if one was inside another wouldn't the second one have to be bigger than the one that's inside of it??? Definitely a problem. 41 | 42 | How could we come up with such a problem? Consider a `Person` class, in which we want to store the possibilty that a `Person` has a spouse (i.e., a husband or a wife). The class might look like: 43 | 44 | ```c++ 45 | class Person { 46 | private: 47 | string name; 48 | Person spouse; 49 | }; 50 | ``` 51 | 52 | It should be clear that a `Person` can't have space to have another `Person` inside of him/her. Also, most people are not born with a spouse. And sadly, sometimes we may have to allow for losing a spouse or even acquiring another. (We are not trying to handle multiple simultaneous spouses.) 53 | 54 | How can we handle these issues in C++? 55 | 56 | ## Solution: Association by using Pointers 57 | 58 | We can make our **member variable into a pointer**. In the case of the `Person` with a spouse, the class could be written as: 59 | 60 | ```c++ 61 | class Person { 62 | private: 63 | string name; 64 | Person* spouse; 65 | }; 66 | ``` 67 | 68 | The only difference is that now spouse is a pointer to a `Person`, instead of a `Person`. Since a pointer variable just holds an address, there is not difficulty in storing a pointer to a `Person` inside of a `Person`. 69 | 70 | Now we are **associating** one `Person` with another, and not **containing** one `Person` in another. 71 | 72 | How does this approach help us with the other problems mentioned earlier? What value could we store in spouse if a `Person` is not currently married? In other words, what value can we use to say that the variable spouse is not actually pointing to another Person? `nullptr`. The value `nullptr` for a pointer variable always means the variable is not pointi*ng at anything. That makes pointers ideal when you might need a variable that *sometimes* refers to an object and other times doesn't refer to anything at all. 73 | 74 | ## Conclusion 75 | 76 | ### *Composition* refers to containing an `object` of one class in an `object` of another class. Composition has several issues. We can solve the issues of composition by not storing the entire `object` of one class in an `object` of another class but rather just use a pointer. This is called *Association*. -------------------------------------------------------------------------------- /Classes/Composition and Association/code snippets/AssociationClass.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | William's Notes 3 | 4 | Demonstrate how to create an "association" 5 | between two classes objects using pointers. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | using namespace std; 13 | 14 | 15 | class Person { 16 | friend ostream& operator<<(ostream& os, const Person& thePerson){ 17 | os << "Person: " << thePerson.name << ", bday: " << thePerson.bday; 18 | if (thePerson.spouse == nullptr){ 19 | os << " single"; 20 | } 21 | else { // use pointer to get the other person's name 22 | // os << "married to: " << *thePerson.spouse.name; this doesn't work. Dot operator has more precedence than * 23 | // os << "married to: " << (*thePerson.spouse).name; works but ugly 24 | os << " married to: " << thePerson.spouse -> name; // same as (*thePerson.spouse).name 25 | } 26 | return os; 27 | } 28 | // it is possible to modify data using pointer 29 | friend void modify_ptr(Person& rhs){ 30 | Person* p = &rhs; 31 | p -> name = "Mathilda"; 32 | // if don't want p to modify the content of the thing it is pointing too 33 | const Person* p2 = &rhs; 34 | // p2 -> name = "Cant change"; doesn't work 35 | // if don't want p to get changed and point to another object 36 | Person* const p3 = &rhs; 37 | } 38 | 39 | public: 40 | //Person(const string& theName, int m, int d, int y) : name(theName), bday(m, d, y) {} 41 | //same as: 42 | Person(const string& theName, const Date& aDate) : name(theName), bday(aDate), spouse(nullptr) {} 43 | 44 | bool marries(Person& betrothed){ 45 | if (spouse == nullptr && betrothed.spouse == nullptr){ 46 | spouse = &betrothed; // point the pointer spouse to the address of Person object betrothed 47 | betrothed.spouse = this; // this is a person pointer. It holds the address of this object. 48 | // private can be accessed by the same class, so betrothed.spouse is not private since betrothed is also a Person 49 | return true; 50 | } 51 | return false; 52 | } 53 | 54 | private: 55 | string name; 56 | Date bday; 57 | // Person spouse; Cannot have another person field in Person class. Occupy too much memory (same memory as the class's object memory) 58 | // string spouse; only know the name 59 | Person* spouse; // only 8 bits of memory for pointer 60 | }; 61 | 62 | 63 | class Date{ 64 | friend ostream& operator << (ostream& os, const Date& rhs); 65 | public: 66 | Date(int m, int d, int y) : month(m), day(d), year(y) {} 67 | private: 68 | int month, day, year; 69 | }; 70 | 71 | 72 | ostream& operator << (ostream& os, const Date& rhs){ 73 | os << rhs.month << '/' << rhs.day << '/' << rhs.year; 74 | return os; 75 | } 76 | 77 | 78 | int main() { 79 | Person john("John", Date(7,1,1999)); 80 | Person mary("Mary", Date(7,1,1200)); 81 | 82 | vector people; 83 | people.push_back(&john); 84 | people.push_back(&mary); 85 | for (Person* p : people){ 86 | cout << *p << endl; 87 | } 88 | people.clear(); 89 | } 90 | -------------------------------------------------------------------------------- /Classes/Composition and Association/code snippets/AssociationStruct.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | John Sterling 3 | 4 | Demonstrate how to create an "association" 5 | between two struct objects using pointers. 6 | */ 7 | 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | /* 13 | We want a "spouse" member in our Person struct 14 | to represent who our person is married to. 15 | It is not possible for the type of the spouse 16 | field to be Person. Why? (There's not enough 17 | room in one Person object to contain another 18 | Person object.) 19 | */ 20 | struct Person { 21 | string name; 22 | string bday; 23 | int height; 24 | Person* spouse; 25 | }; 26 | 27 | // makes the two people be married. 28 | bool marry(Person&, Person&); 29 | 30 | int main() { 31 | Person john; 32 | john.name = "John"; 33 | john.bday = "May 29, 1917"; 34 | john.height = 72; 35 | // Important to initalize the spouse pointer to NULL! 36 | // Otherwise we don't know if the person is married. 37 | john.spouse = NULL; 38 | 39 | Person marilyn; 40 | marilyn.name = "Marilyn"; 41 | marilyn.bday = "06/01/1926"; 42 | marilyn.height = 64; 43 | marilyn.spouse = NULL; 44 | 45 | marry(john, marilyn); 46 | 47 | cout << "John is married to " << john.spouse->name << endl; 48 | 49 | } 50 | 51 | // marry returns false if one of the two arguments 52 | // is already married. Otherwise it "marries" them 53 | // together by setting their spouse pointers to point 54 | // to each other, and returns true. 55 | bool marry(Person& p1, Person& p2) { 56 | if (p1.spouse || p2.spouse) return false; 57 | p1.spouse = &p2; 58 | p2.spouse = &p1; 59 | return true; 60 | } -------------------------------------------------------------------------------- /Classes/Copy Control/code snippets/CopyControlBasics.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Important Note: 4 | Shallow copy works only for primitive 5 | non primitive uses delegation to their own associated copy constructor 6 | 7 | 8 | Copy Control: The Big 3 9 | 1. Destructor 10 | 2. Copy Constructor 11 | 3. Assignment Operator 12 | 13 | Why do we need a Destructor? 14 | If an instance is responsible for resource in the heap and is about to cease to exist which leads to memory leak 15 | 16 | Why do we need Copy Constructor? 17 | When a shallow copy of an instance is going to go through the desructor and pointer is lost 18 | deep copy -> own copy constructor 19 | 20 | Why do we need Assignment Operator 21 | When we want to reassign an existing object will another object of the same type. We have to do the copy, and free up the object unused. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | using namespace std; 29 | 30 | 31 | class Thing{ 32 | friend ostream& operator << (ostream& os, const Thing& rhs); 33 | public: 34 | Thing(int x) {p = new int(x);} 35 | 36 | Thing(Thing& thing){p = new int(*thing.p);} // called whenever initilizing the same instance as a copy of something 37 | 38 | Thing operator = (const Thing& rhs){ // x = (y = z), y = z should return a Thing object 39 | // What if x = x? That's gonna crash 40 | if(rhs.p != p){ // if we are not doing self assignment 41 | // 1. freeup self's resource 42 | delete p; // calling destructor is not smart 43 | // 2. allocate new resource (u dont want to point to the same thing as rhs 44 | // 3. copy the resources from the rhs 45 | p = new int(*rhs.p); // deep copy 46 | } 47 | 48 | return *this; // 4. return self. if x = (y = z), y is self so return y. 49 | } 50 | 51 | void setValue(int val){*p = val;} 52 | int getValue() const {return *p;} 53 | 54 | void cleanUp(){ 55 | delete p; // p will be pointed to a invalid address. It releases the memory, but it does not modify the value of p. 56 | p = nullptr; 57 | // If u do p = nullptr and then delete p later, nothing happens. 58 | // The source code for delete says if p = nullptr, return; 59 | } 60 | 61 | ~Thing(){ // This is a destructor. 62 | // Whenever, an object is out of scope and when we delete an object, destructor is called 63 | // So we dont need cleanup() 64 | delete p; 65 | p = nullptr; 66 | } 67 | private: 68 | int* p; 69 | }; 70 | /* 71 | Parameter "something" is pass-by-value but without Copy Constructor, the default copy constructor made by C++ itself 72 | does a shallow copy. something did not create its own p, its p is connected to the p of aThing, 73 | and the destructor will be called to something which will delete the shared p. 74 | */ 75 | void doNothing(Thing something){} 76 | 77 | void simpleFunc(){ 78 | // Demonstrating Purpose of Copy Constructor 79 | Thing aThing(17); // creates a pointer on the heap 80 | cout << aThing << endl; 81 | // delete aThing.p; 82 | 83 | // aThing.cleanUp(); 84 | // however, we want cleanup() to run in every situation that heap gets memory 85 | doNothing(aThing);// here aThing's destructor is called but p is already deleted 86 | // WE NEED A DEEP COPY, a copy constructor 87 | 88 | Thing anotherThing(aThing); // the copy constructor is called 89 | Thing anotherThing2 = aThing; // same thing different syntax 90 | // return creates a copy 91 | 92 | // Demonstrating Purpose of Assignment Operators 93 | Thing somethingElse(28); 94 | aThing = somethingElse; // reassigning 95 | // if we don't have copy control, now aThing.p -> 28 and its original 17 is memory leaked, so we need assignment operator 96 | // operator = (aThing, somethingElse); doesn't work since operator=() is a method 97 | aThing.operator = (somethingElse); 98 | 99 | } 100 | 101 | ostream& operator << (ostream& os, const Thing& rhs){ 102 | os << *rhs.p; 103 | return os; 104 | } 105 | 106 | int main() { 107 | simpleFunc(); 108 | } 109 | 110 | -------------------------------------------------------------------------------- /Classes/Copy Control/code snippets/Vector.cpp: -------------------------------------------------------------------------------- 1 | #include "Vector.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace CS1124 { 6 | 7 | Vector::Vector(int s) : size(s), data (new int[size]){ 8 | } 9 | 10 | // Copy Constructor 11 | // Note the type of the parameter. 12 | Vector::Vector(const Vector& v) { 13 | size = v.size; 14 | data = new int[size]; 15 | for (int i = 0; i < size; i++) 16 | data[i] = v.data[i]; 17 | } 18 | 19 | // Destructor 20 | Vector::~Vector() { 21 | delete [] data; 22 | } 23 | 24 | // Change the size of the Vector. 25 | // If newSize is not larger than the current size, 26 | // we will not do anything. 27 | // Note that we did not initialize the new array elements. 28 | // Should we? 29 | void Vector::resize(int newSize) { 30 | if (newSize > size) { 31 | int* newData = new int[newSize]; 32 | for (int i = 0; i < size; ++i) 33 | newData[i] = data[i]; 34 | delete [] data; 35 | data = newData; 36 | size = newSize; 37 | } 38 | } 39 | 40 | 41 | // Assignment operator. 42 | // MUST BE defined as a member function. 43 | // The text chooses to return void, however it is 44 | // the usual practice to return a reference to the 45 | // class. 46 | Vector& Vector::operator=(const Vector& right) { 47 | // Assignment operators should begin 48 | // with a check that you're not being 49 | // asked to do a "self-assignment" as in: 50 | // x = x; 51 | // Here we look to see if the "this" pointer 52 | // contains the same address as the address 53 | // of the argument. 54 | if (this != &right) { 55 | if (size != right.size) { 56 | // if our target array isn't the same size 57 | // as the target's, then we delete ours and 58 | // get one that is the correct size. 59 | delete [] data; 60 | size = right.size; 61 | data = new int[size]; 62 | } 63 | for (int i = 0; i < size; i++) 64 | data[i] = right.data[i]; 65 | } 66 | return *this; 67 | } 68 | 69 | // operator<< is printing a space after each element in 70 | // the Vector. Note that this did not need to be a friend. 71 | ostream& operator<< (ostream& os, const Vector& v) { 72 | for (int i = 0; i < v.getSize(); i++) 73 | os << v[i] << ' '; 74 | return os; 75 | } 76 | 77 | // operator[]. Simple version that does not do range checking 78 | // Two versions. The first is when we are using a const vector 79 | // The second is when we want to be able to change the value 80 | // inside the vector. 81 | int Vector::operator[] (int index) const { 82 | return data[index]; 83 | } 84 | int& Vector::operator[] (int index) { 85 | return data[index]; 86 | } 87 | } -------------------------------------------------------------------------------- /Classes/Copy Control/code snippets/Vector.h: -------------------------------------------------------------------------------- 1 | #ifndef VECTOR_H 2 | #define VECTOR_H 3 | #include 4 | 5 | namespace CS1124 { 6 | 7 | class Vector { 8 | public: 9 | //CONSTRUCTORS 10 | Vector(const Vector&); // Copy Constructor 11 | Vector(int size = 4); // Create a vector of a particular size defaulting to 4. 12 | 13 | // DESTRUCTOR 14 | ~Vector(); 15 | 16 | // Accessor 17 | int getSize() const {return size;} 18 | 19 | // Change the size of the Vector. 20 | // If newSize is smaller than the current size, 21 | // we will not do anything. 22 | void resize(int newSize); 23 | 24 | // Assignment operator 25 | // C++ requires that it be a member function. 26 | Vector& operator=(const Vector&); 27 | 28 | // [] operator. 29 | // C++ requires that it be a member function. 30 | // The reference return type is to allow us to assign to it. 31 | int& operator[](int i); 32 | // Need a second version, for the times that we 33 | // are using a const vector. 34 | int operator[](int i) const; 35 | 36 | private: 37 | int size; 38 | int* data; 39 | }; 40 | // The output operator can't be a member of the Vector class 41 | // and it doesn't need to be a friend so long as we have an 42 | // accessor for the size and the [] operator to access the items 43 | // in the array. 44 | std::ostream& operator<< (std::ostream&, const Vector&); 45 | } 46 | #endif -------------------------------------------------------------------------------- /Classes/Copy Control/code snippets/testVector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Vector.h" 3 | using namespace std; 4 | using namespace CS1124; 5 | 6 | int main() { 7 | // Define a vector of five elements. 8 | Vector v(5); 9 | 10 | cout << "Setting v to a sequence of squares." << endl; 11 | 12 | for (int i = 0; i < 5; i++) 13 | v[i] = i * i; 14 | cout << "v = " << v << endl; 15 | 16 | cout << "Initializing w with the copy constructor" << endl; 17 | Vector w = v; 18 | 19 | cout << "v = " << v << endl; 20 | cout << "w = " << w << endl; 21 | cout << endl; 22 | 23 | cout << "v[0] = 17;" << endl; 24 | v[0] = 17; 25 | cout << "v = " << v << endl; 26 | cout << "w = " << w << endl; 27 | cout << endl; 28 | 29 | cout << "w = v;" << endl; 30 | w = v; 31 | cout << "v = " << v << endl; 32 | cout << "w = " << w << endl; 33 | cout << endl; 34 | 35 | // We'll make w a little larger and see what happens. We should get "garbage" 36 | // in the new entries. 37 | w.resize(6); 38 | cout << "w.resize(6)\n" << w << endl; 39 | // Trying to resize v a smaller size should have no effect. 40 | v.resize(2); 41 | cout << "v.resize(2)\nWe hope nothing changes because we don't support resizing 'down'.\n" << v << endl; 42 | 43 | return 0; 44 | } -------------------------------------------------------------------------------- /Classes/Inheritance/code snippets/Inheritance.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | File: Inheritance1.cpp 3 | John Sterling -- jsterling@poly.edu 4 | CS1124 5 | Polytechnic University 6 | 7 | 1) The class Cat "inherits" from the class Pet. Pet is called 8 | the "base" class and Cat is called the "derived" class. 9 | 2) The function display only needs to be implemented in Pet, 10 | but it can still be used from Cat. 11 | 3) Constructors for the 12 | 4) Cats can do things that Pets can't. 13 | */ 14 | 15 | #include 16 | #include 17 | using namespace std; 18 | 19 | // A class to represent pets. 20 | class Pet { 21 | public: 22 | 23 | // We want a constructor that initializes the pet's name. 24 | Pet(const string& s) : name(s) { } 25 | 26 | // Notice that we define "display" in Pet but don't in Cat. 27 | void display() const { cout << name << endl; } 28 | 29 | protected: 30 | string name; 31 | }; 32 | 33 | // Cats are Pets, at least for the purpose of our program. To let C++ 34 | // know that, we put the " : public Pet" in between "class Cat" and the 35 | // curly brace. 36 | class Cat : public Pet { 37 | public: 38 | // The Cat constructor shown in the comment below didn't work. 39 | // We got acompilation error 40 | // saying that there was no default constructor for the Pet 41 | // class. That was true, but we didn't try calling the 42 | // Pet default constructor. At least not that we knew about. But C++ 43 | // tried to call it for us. Where? In the initialization list. We 44 | // didn't write an initialization list! C++ pretends that we 45 | // wrote "Cat (string s) : Pet() {". If we want to avoid it, we 46 | // *have to* invoke some other Pet constructor in the intialization 47 | // list. 48 | // Cat (const string& s) { name = s; } 49 | 50 | // Here is a working version of the Cat constructor. By calling the 51 | // Pet constructor, it will initialize the cat's name. 52 | Cat (const string& s) : Pet(s) { } 53 | 54 | void meow() {} 55 | }; 56 | 57 | int main() { 58 | Pet p("Felix"); 59 | p.display(); 60 | // If we try to make a pet "meow", then we will get a compilation error: 61 | //p.meow(); 62 | 63 | Cat c("Heathcliffe"); 64 | // We are using a member function that we never explicitly defined, 65 | // the "display" member function for a Cat. Code reuse in action! 66 | c.display(); 67 | // Cats can do something that other Pets cannot, the can meow. 68 | c.meow(); 69 | return 0; 70 | } -------------------------------------------------------------------------------- /Classes/Inheritance/code snippets/Polymorphism.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | File: Inheritance2.cpp 3 | John Sterling -- jsterling@poly.edu 4 | CS1124 5 | Polytechnic University 6 | 7 | 1) Builds on the project Inheritance1. Look there for the basics. Some 8 | comments from Inheritance1 have been removed for clarity. 9 | 2) Cat redefines the displayDetailed function from the Pet class. 10 | 3) The test program explores what happens when we call displayDetailed 11 | with different Pets and in different ways. What do we have to do 12 | in order to use the "right" definition of the function? 13 | 4) Note the way the array myPets is initialized. Which constructor is 14 | used? 15 | */ 16 | 17 | #include 18 | #include 19 | using namespace std; 20 | 21 | // A class to hold pets. 22 | class Pet { 23 | public: 24 | 25 | // CONSTRUCTORS 26 | Pet(const string& s) { name = s; } 27 | 28 | // displayDetailed does a little more than just display the name. 29 | // Try running with and without the word "virtual". 30 | //virtual 31 | void displayDetailed() const { 32 | cout << "Pet: " << name << endl; 33 | } 34 | protected: 35 | string name; 36 | }; 37 | 38 | // Cats are Pets, at least for the purpose of our program. 39 | class Cat : public Pet { 40 | public: 41 | Cat (const string& s) : Pet(s) { } 42 | 43 | // displayDetailed does things a little differently for Cats than 44 | // for other Pets in general, so we redefine it here. 45 | void displayDetailed() const { 46 | cout << "Cat: " << name << endl; 47 | } 48 | }; 49 | 50 | int main() { 51 | Pet p("Felix"); 52 | p.displayDetailed(); 53 | Cat c("Heathcliffe"); 54 | c.displayDetailed(); 55 | 56 | cout << endl << "Playing with containers of Pets\n\n"; 57 | // Here we've created an array holding two Pets. 58 | // What happens when we call displayDetails? Look closely. 59 | // An aside, what constructor is being used here for the elements 60 | // of the array? 61 | Pet myPets[2] = {p, c}; 62 | for (int i = 0; i < 2; i++) 63 | myPets[i].displayDetailed(); 64 | 65 | // Here we've created an array holding two pointers to Pets. 66 | // What happens now when we call displayDetails? 67 | // Try this without the word "virtual" in the declaration for 68 | // displayDetailed in the Pet class. 69 | Pet* myPetPtrs[2]; 70 | myPetPtrs[0] = &p; 71 | myPetPtrs[1] = &c; 72 | for (int j = 0; j < 2; j++) 73 | myPetPtrs[j]->displayDetailed(); 74 | return 0; 75 | } -------------------------------------------------------------------------------- /Classes/Inheritance/code snippets/abstractClasses.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | File: TestAbstract.cpp 3 | John Sterling -- jsterling@poly.edu 4 | CS1124 5 | Polytechnic University 6 | 7 | Demonstrates use of Pure Virtual methods and Abstract Classes. 8 | */ 9 | 10 | #include 11 | #include 12 | using namespace std; 13 | 14 | // We are developing a class hierarchy of shapes. 15 | // Every shape needs to be able to "draw" itself. 16 | // We may have Circles, rectangles, triangles, etc. 17 | // But first a couple of issues: 18 | // 19 | // 1) Each type of Shape will need to know how to draw 20 | // itself. So every Shape must have a draw method. 21 | // We can make sure that every type of Shape has a draw 22 | // method by putting the prototype for draw() in the 23 | // Shape class definition. 24 | 25 | // 2) But how do we draw a "Shape", if it's not 26 | // some particular kind of Shape, like a Circle. We can't. 27 | // In fact it doesn't even make any sense to create a Shape 28 | // if we don't know what kind it is. 29 | // 30 | // We can handle both issues by declaring the draw method 31 | // as "pure virtual". The class Shape is then said to be 32 | // an "abstract class". Any class that has at least one pure 33 | // virtual method is an abstract class. 34 | // A method is made to be pure virtual by writing its 35 | // declaration in the Shape class as: 36 | // virtual void draw() = 0; 37 | // This declaration forces the class that inherit from Shape 38 | // into providing an implementation for draw(). 39 | // It also prevents anyone from trying to create a Shape object 40 | // that isn't something more specific. That is, you cannot: 41 | // Shape s; // error 42 | // That would cause a compilation error. 43 | // You *can* however create a pointer to a Shape: 44 | // Shape* shapePtr; 45 | 46 | // All Shape classes will need a Point object to keep track of 47 | // their location. 48 | class Point { 49 | public: 50 | Point() : x(0), y(0) {} 51 | Point(int newX, int newY) : x(newX), y(newY) {} 52 | void display() const {cout << "x = " << x << "; y = " << y << endl;} 53 | // other methods omitted for now. 54 | private: 55 | int x, y; 56 | }; 57 | 58 | class Shape { 59 | public: 60 | // draw method is "pure virtual". Note the " = 0". 61 | virtual void draw() const = 0; 62 | // It is always good to declare the destructor in any 63 | // base class to be virtual. 64 | virtual ~Shape() {} 65 | // Abstract classes *can* have constructors. With no arguments 66 | // this constructor initializes the location to x=10, y=20; 67 | Shape(int x = 10, int y = 20) : location(x, y) {} 68 | protected: 69 | // Abstract classes can have members. 70 | Point location; 71 | }; 72 | 73 | class Circle : public Shape { 74 | public: 75 | // Circle constructor would automatically (implicitly) call 76 | // the Shape constructor in its initialization list, but it is 77 | // a good idea to write it in yourself, if only to remind you. 78 | Circle() : Shape(), radius(5) {}; 79 | void draw() const { 80 | cout << "I'm drawing a circle with radius = " << radius 81 | << " and location: "; 82 | location.display(); 83 | } 84 | private: 85 | int radius; 86 | }; 87 | 88 | class Square : public Shape { 89 | public: 90 | // The Square constructor will invoke the Shape constructor 91 | // even though we didn't say to. This has the same effect as 92 | // in the default Circle constructor above. 93 | Square() : side(1) {}; 94 | void draw() const { 95 | cout << "I'm drawing a square with side = " << side 96 | << " and location: "; 97 | location.display(); 98 | } 99 | private: 100 | int side; 101 | }; 102 | 103 | 104 | int main() { 105 | 106 | Shape* sp = new Circle; 107 | sp->draw(); 108 | delete sp; 109 | sp = new Square; 110 | sp->draw(); 111 | delete sp; 112 | // Either of the following two lines would cause compilation errors. 113 | //Shape sp; 114 | //sp = new Shape(); 115 | 116 | return 0; 117 | } -------------------------------------------------------------------------------- /Classes/Inheritance/code snippets/code in notes/Animals-02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | class Animal { 5 | public: 6 | void eat() { cout << "Animal eating\n"; } 7 | private: 8 | }; 9 | 10 | class Lion : public Animal { 11 | public: 12 | private: 13 | }; 14 | 15 | class Tiger : public Animal { 16 | public: 17 | void eat() { cout << "Tiger eating\n"; } 18 | private: 19 | }; 20 | 21 | class Bear : public Animal { 22 | public: 23 | private: 24 | }; 25 | 26 | int main() { 27 | Bear yogi; 28 | yogi.eat(); 29 | Tiger tigger; 30 | tigger.eat(); 31 | } -------------------------------------------------------------------------------- /Classes/Inheritance/code snippets/code in notes/Animals-03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | class Animal { 6 | public: 7 | Animal(const string& name) : name(name) {} 8 | void eat() { cout << "Animal eating\n"; } 9 | private: 10 | string name; 11 | }; 12 | 13 | class Lion : public Animal { 14 | public: 15 | private: 16 | }; 17 | 18 | class Tiger : public Animal { 19 | public: 20 | void eat() { cout << "Tiger eating\n"; } 21 | private: 22 | }; 23 | 24 | class Bear : public Animal { 25 | public: 26 | private: 27 | }; 28 | 29 | int main() { 30 | Bear yogi("Yogi"); 31 | yogi.eat(); 32 | Tiger tigger("Tigger"); 33 | tigger.eat(); 34 | } -------------------------------------------------------------------------------- /Classes/Inheritance/code snippets/code in notes/Animals-04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | class Animal { 6 | public: 7 | Animal(const string& name) : name(name) {} 8 | void eat() { cout << "Animal eating\n"; } 9 | private: 10 | string name; 11 | }; 12 | 13 | class Lion : public Animal { 14 | public: 15 | private: 16 | }; 17 | 18 | class Tiger : public Animal { 19 | public: 20 | Tiger(const string& name) : Animal(name) {} 21 | void eat() { cout << "Tiger eating\n"; } 22 | private: 23 | }; 24 | 25 | class Bear : public Animal { 26 | public: 27 | Bear(const string& name) : Animal(name) {} 28 | private: 29 | }; 30 | 31 | int main() { 32 | Bear yogi("Yogi"); 33 | yogi.eat(); 34 | Tiger tigger("Tigger"); 35 | tigger.eat(); 36 | } -------------------------------------------------------------------------------- /Classes/Inheritance/code snippets/code in notes/Animals-05.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Call a method from the base class on an instance of the derived 3 | class. 4 | */ 5 | 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | class Animal { 11 | public: 12 | Animal(const string& name) : name(name) {} 13 | void eat() { cout << "Animal eating\n"; } 14 | private: 15 | string name; 16 | }; 17 | 18 | class Lion : public Animal { 19 | public: 20 | Lion(const string& name) : Animal(name) {} 21 | void eat() { 22 | cout << "Lion!!!!! "; 23 | Animal::eat(); 24 | } 25 | private: 26 | }; 27 | 28 | class Tiger : public Animal { 29 | public: 30 | Tiger(const string& name) : Animal(name) {} 31 | void eat() { cout << "Tiger eating\n"; } 32 | private: 33 | }; 34 | 35 | class Bear : public Animal { 36 | public: 37 | Bear(const string& name) : Animal(name) {} 38 | private: 39 | }; 40 | 41 | int main() { 42 | Tiger tigger("Tigger"); 43 | tigger.eat(); // tigger eating like a proper Tiger. 44 | tigger.Animal::eat(); // tigger eating like an Animal. 45 | Lion coward("Cowardly"); 46 | coward.eat(); 47 | } -------------------------------------------------------------------------------- /Classes/Inheritance/code snippets/code in notes/NoPolymorphismFromBaseConstructor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | NoPolymorphismFromBaseConstructor.cpp 3 | CS1124 4 | John Sterling 5 | 6 | Demonstrates that in C++, function calls from a constructor do not 7 | use polymorphism 8 | */ 9 | 10 | #include 11 | using namespace std; 12 | 13 | class Base { 14 | public: 15 | Base() { 16 | foo(); 17 | } 18 | virtual void foo() const { cout << "Base::foo()\n"; } 19 | }; 20 | 21 | class Derived : public Base { 22 | public: 23 | Derived() : n(42) { } 24 | virtual void foo() const { cout << "Derived::foo() " << n << "\n"; } 25 | private: 26 | int n; 27 | }; 28 | 29 | int main() { 30 | Derived der; 31 | der.foo(); 32 | } -------------------------------------------------------------------------------- /Classes/Inheritance/code snippets/code in notes/protected4.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | protected4.cpp 3 | CS1124 4 | John Sterling 5 | 6 | Demonstrates that within a derived class we can access a protected 7 | member on an instance of our own class, but not on an instance of a 8 | different derived class. 9 | */ 10 | 11 | #include 12 | using namespace std; 13 | 14 | class Base { 15 | protected: 16 | int getValue() const { return value; } 17 | private: 18 | int value; 19 | }; 20 | 21 | class Derived : public Base { 22 | public: 23 | void display() { cout << "Value: " << getValue() << endl; } 24 | }; 25 | 26 | class DerivedTwo : public Base { 27 | public: 28 | void display() { cout << "Value: " << getValue() << endl; } 29 | 30 | // fails to compile 31 | int getDerivedValue(const Derived& der) { return der.getValue(); } 32 | 33 | // compiles fine. 34 | int getDerivedTwoValue(const DerivedTwo& der2) { return der2.getValue(); } 35 | }; 36 | 37 | int main() { 38 | Derived der; 39 | DerivedTwo derTwo, derTwoB; 40 | cout << derTwo.getDerivedValue(der) << endl; 41 | cout << derTwo.getDerivedTwoValue(derTwoB) << endl; 42 | } -------------------------------------------------------------------------------- /Classes/Inheritance/code snippets/inheritanceInCopyControl.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | File: TestConstructorDestructorOrder.cpp 3 | John Sterling -- jsterling@poly.edu 4 | CS1124 5 | Polytechnic University 6 | */ 7 | 8 | #include 9 | using namespace std; 10 | 11 | // The purpose of this code is to see the order in which the 12 | // bodies of the constructors and destructors get called 13 | // even when we don't tell C++ what to do. 14 | // We can't change the order of those calls, though we can 15 | // tell C++ which constructor for a class to use, if we prefer 16 | // not to use the default ones. 17 | 18 | class A { 19 | public: 20 | A() {cout << "In A's constructor\n";} 21 | ~A() {cout << "In A's destructor\n";} 22 | private: 23 | }; 24 | 25 | class C { 26 | public: 27 | C() {cout << "In C's constructor\n";} 28 | ~C() {cout << "In C's destructor\n";} 29 | private: 30 | }; 31 | 32 | class B : public A { 33 | public: 34 | B() {cout << "In B's constructor\n";} 35 | ~B() {cout << "In B's destructor\n";} 36 | private: 37 | C c; 38 | }; 39 | 40 | 41 | 42 | 43 | int main() { 44 | B* bPtr = new B; 45 | delete bPtr; 46 | cout << "------------------------------\n"; 47 | A* aPtr = new B; 48 | delete aPtr; // Hm, something odd happens here. 49 | // What? What do we do to fix it? 50 | // Answer below. 51 | 52 | return 0; 53 | } 54 | 55 | 56 | 57 | /* 58 | The problem above is that the destructor for the class B did 59 | not get called when the line: 60 | delete aPtr; 61 | was executed. Even though the object that is being deleted *is* 62 | an object of type B. That also kept C's destructor from being called. 63 | 64 | The reason is that aPtr is a variable of type 65 | "pointer to A". Only methods for class A will be called, unless 66 | they were marked as virtual. What method do we want to call? B's 67 | destructor. What to we have to do? Mark the destructor "virtual". 68 | Where? In class A. 69 | 70 | Got all that? 71 | */ -------------------------------------------------------------------------------- /Classes/Inheritance/code snippets/multipleInheritance.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Multiple Inheritance 3 | */ 4 | 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | // A simple Person class. 10 | class Person { 11 | public: 12 | Person(const string& aName): name(aName) {} 13 | protected: 14 | string name; 15 | }; 16 | 17 | // Instructor derived from Person. 18 | // Note the use of "virtual" here. 19 | // Try commenting it out here and in Student. 20 | // (I placed "class Instructor : virtual public Person" on three lines 21 | // just to make it easy for you to comment out "virtual" 22 | class Instructor : 23 | //virtual 24 | public Person { 25 | public: 26 | Instructor(const string& aName): Person(aName) {} 27 | }; 28 | 29 | // Student derived from Person. 30 | // Again note the use of "virtual" here. 31 | class Student: 32 | //virtual 33 | public Person { 34 | public: 35 | Student(const string& aName): Person(aName) {} 36 | }; 37 | 38 | // a TA is both an Instructor and a Student 39 | // Note that THREE constructors are invoked in the initialization list 40 | class TA : public Instructor, public Student { 41 | public: 42 | TA(const string& myName) : 43 | Person(myName), 44 | Instructor(myName), Student(myName) {} 45 | void display(ostream& os = cout) const { 46 | os << Person::name << endl; 47 | os << Student::Person::name << endl; 48 | os << Instructor::Person::name << endl; 49 | } 50 | private: 51 | }; 52 | 53 | int main() { 54 | TA chirag("Chirag Chhatriwala"); 55 | chirag.display(); 56 | } -------------------------------------------------------------------------------- /Classes/Operator Overloading/code snippets/SquareBrackets.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SquareBrackets.cpp 3 | CS1124 Sample Code 4 | John Sterling 5 | Brooklyn Polytech 6 | 7 | Demonstrate the use of the "square bracket" operator. 8 | */ 9 | 10 | #include 11 | using namespace std; 12 | 13 | // Calling this class "Vector" is certainly an overstatement right now. 14 | // In fact, it's not even as general as a basic array. 15 | // But it does serve the purpose of demonstrating the [] operator. 16 | // Later we can build on it to add some of the functionality that we 17 | // would expect of a vector class. 18 | class Vector { 19 | 20 | // It's not the point of this project, but it's hard to resist 21 | // overloading the output operator, once you know how. 22 | friend ostream& operator<< (ostream& os, const Vector& vec) { 23 | for (int i = 0; i < Vector::MAX; ++i) os << vec[i] << ' '; 24 | return os; 25 | } 26 | 27 | public: 28 | static const int MAX = 10; 29 | // Not all compilers accept static constant ints, initialized this way. 30 | // An alternative is to use an enum, as in the next line. 31 | // enum {MAX = 10}; 32 | 33 | // Seems a shame to leave the data in the vector uninitialized. 34 | Vector() { for (int i = 0; i < Vector::MAX; ++i) data[i] = 0; } 35 | 36 | // Here is the focus of this project. 37 | // Two simple lines of code. 38 | // The compiler will use this one when the vector is constant. 39 | int operator[](size_t i) const {return data[i];} 40 | int& operator[](size_t i) {return data[i];} 41 | 42 | private: 43 | int data[MAX]; 44 | }; 45 | 46 | // Try putting "const" before "Vector" in the parameter list. 47 | // Why does the compiler complain? 48 | void f( Vector& v) {int &x = v[7];} 49 | 50 | int main() { 51 | 52 | // Create an instance of a Vector. 53 | // Unfortunately, we can't say how big the vector is 54 | // or pick what kind of thing it holds. Later. 55 | Vector v; 56 | 57 | // Put some interesting data in the vector 58 | for (int i = 0; i < Vector::MAX; ++i) v[i] = i*i; 59 | 60 | // Display the vector. 61 | // Of course this only works because we overloaded the output operator. 62 | // (Otherwise known as the "insertion" operator for those who like such words.) 63 | cout << v << endl; 64 | 65 | } -------------------------------------------------------------------------------- /Classes/Operator Overloading/code snippets/complexWithOverload.h: -------------------------------------------------------------------------------- 1 | // File: Complex.h 2 | // John Sterling -- jsterling@poly.edu 3 | // CS1124 4 | // Polytechnic University 5 | // Brooklyn, NY 6 | 7 | #ifndef COMPLEX_H 8 | #define COMPLEX_H 9 | #include 10 | 11 | namespace CS1124 { 12 | 13 | class Complex { 14 | public: 15 | // Constructors. 16 | Complex(double r = 0, double imag = 0); 17 | 18 | // ACCESSORS 19 | // The "getter" functions are declared as "const". You 20 | // might want to try taking off the const modifier and 21 | // see what happens when you compile. Where do you think 22 | // a problem might occur?? 23 | double getReal() const {return real;} 24 | double getImaginary() const {return imaginary;} 25 | 26 | // "Setters" 27 | void setReal(double r) {real = r;} 28 | void setImaginary(double i) {imaginary = i;} 29 | 30 | // Pre- and pos- increment and decrement operators 31 | // The decrement operators will be defined as friends 32 | // and the increment operators will be defined as 33 | // members. 34 | // ================================================ 35 | // Pre-decrement operator. Allows us to write: 36 | // Complex c; 37 | // --c; 38 | // What do we want it to mean? I assume we would like to 39 | // subtract one to the real part of the number. The value 40 | // of the expression is the same as the new value of c. 41 | // Note that overloading operator-- this way does not allow 42 | // "c--". We have to declare that separately. 43 | // Defined as a non-member function. The prototype 44 | // is here inside the class definition because we have 45 | // chosen to make it a friend. 46 | // Note that the return type should be a reference. 47 | friend Complex& operator-- (Complex&); 48 | 49 | // Post-decrement operator. Allows us to write: 50 | // Complex c: 51 | // c--; 52 | // This is similar to --c in that one is subtracted from 53 | // the real part of c. However, the value of the expression 54 | // is the same as what c was before subtracting one. 55 | // The post-decrement function must take a dummy second 56 | // argument. The purpose of this dummy argument is 57 | // simply to distinguish the definition of the post-decrement 58 | // operator from that of the pre-increment operator. 59 | // Note also that the return type is not a reference!!!! 60 | // (Good test question as to why it isn't.) 61 | friend Complex operator-- (Complex&, int); 62 | 63 | // Pre-increment operator. Allows us to write: 64 | // Complex c; 65 | // ++c; 66 | // What do we want it to mean? I assume we would like to 67 | // add one to the real part of the number. Note that 68 | // overloading operator++ this way does not allow "c++". 69 | // Since are implementing this as a member function, 70 | // we don't need to pass an argument. 71 | Complex& operator++ (); 72 | 73 | // Post-increment operator. Allows us to write: 74 | // Complex c: 75 | // c++; 76 | // This is similar to ++c. Its value is whatever c 77 | // was, but then it changes c by adding one to it. 78 | // The function shows one argument, an int. This 79 | // is a "dummy" argument, used by C++ to distinguish 80 | // between the pre- and post- increment operators. 81 | // Note that the return type is NOT a reference!!!! 82 | Complex operator++ (int); 83 | 84 | Complex& operator+=(const Complex&); 85 | 86 | private: 87 | double real; 88 | double imaginary; 89 | }; // end of Complex class definition. 90 | 91 | // These operators are not defined inside the class but the 92 | // Complex.h header file is still a good place for their 93 | // prototypes. 94 | // All paramaters are passed by constant reference for efficiency 95 | // and because we do not need to modify them. 96 | Complex operator+ (const Complex& left, const Complex& right); 97 | Complex operator- (const Complex& left, const Complex& right); 98 | 99 | // NB: ostream must be qualified here by the namespace std. 100 | // Why didn't I just have a "using namespace std" line above? 101 | // Also note that the ostream and istream parameters are 102 | // NOT const. 103 | std::ostream& operator<<(std::ostream& os, const Complex& c); 104 | std::istream& operator>>(std::istream& is, Complex& c); 105 | 106 | } // end of namespace CS1124 definition 107 | 108 | #endif -------------------------------------------------------------------------------- /Classes/Operator Overloading/code snippets/dateWithOverload.cpp: -------------------------------------------------------------------------------- 1 | #include "Date.h" 2 | #include 3 | // When we're not in a header file, it is ok to 4 | // have "using namespace std" 5 | using namespace std; 6 | 7 | namespace CS1124 { 8 | Date::Date(const string& date) { 9 | month = atoi(date.substr(0,2).c_str()); 10 | day = atoi(date.substr(3,2).c_str()); 11 | year = atoi(date.substr(6,4).c_str()); 12 | } 13 | 14 | int Date::getYear() const { return year; } 15 | int Date::getMonth() const { return month; } 16 | int Date::getDay() const { return day; } 17 | 18 | void Date::setYear(int x) { year = x; } 19 | 20 | // operator< implemented as a member. 21 | bool Date::operator<(const Date& rhs) const { 22 | if (year > rhs.year) return false; 23 | else if (year < rhs.year) return true; 24 | else if (month > rhs.month) return false; 25 | else if (month < rhs.month) return true; 26 | else if (day >= rhs.day) return false; 27 | else return true; 28 | } 29 | 30 | // operator==. Implemented as a friend, so we don't have to use accessor functions. 31 | bool operator==(const Date& lhs, const Date& rhs) { 32 | return (rhs.year == lhs.year && rhs.month == lhs.month && rhs.day == lhs.day); 33 | } 34 | // operator>. Implemented as a non-member, non-friend. Using other operators 35 | // that were already implemented makes this one easy. 36 | bool operator>(const Date& lhs, const Date& rhs) { 37 | return (!(lhs < rhs) && !(lhs == rhs)); 38 | } 39 | // operator<<. Since we didn't make it a friend, we had to add some accessors. 40 | ostream& operator<<(ostream& os, const Date& rhs) { 41 | os << "Month: " << rhs.getMonth() 42 | << "; Day: " << rhs.getDay() 43 | << "; Year: " << rhs.getYear(); 44 | return os; 45 | } 46 | } -------------------------------------------------------------------------------- /Classes/Operator Overloading/code snippets/dateWithOverload.h: -------------------------------------------------------------------------------- 1 | #ifndef DATE_H 2 | #define DATE_H 3 | #include 4 | #include 5 | 6 | namespace CS1124 { 7 | class Date { 8 | // Equality test operator implemented as a friend function. 9 | // Remember that friend functions are non-member functions, 10 | // however we have to place their prototype in the class definition. 11 | // It doesn't matter where in the class definition we place it. 12 | // I like to put them here, right at the beginning. 13 | friend bool operator==(const Date& lhs, const Date& rhs); 14 | public: 15 | Date(const std::string& date); 16 | void setYear(int y); 17 | int getYear() const; 18 | int getMonth() const; 19 | int getDay() const; 20 | // Less than operator implemented as a member function. 21 | bool operator<(const Date& rhs) const; 22 | 23 | private: 24 | int day, month, year; 25 | }; 26 | 27 | // Greater than operator implemented as a non-member function. 28 | bool operator>(const Date& lhs, const Date& rhs); 29 | // Output operator implemented, of course, as a non-member function. 30 | std::ostream& operator<< (std::ostream& os, const Date& d); 31 | } 32 | #endif -------------------------------------------------------------------------------- /Classes/Operator Overloading/code snippets/outputOperator.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | class Person { 7 | // not a method so we use friend to let it access private fields. 8 | friend ostream& operator<<(ostream& os, const Person& thePerson); 9 | public: 10 | Person(const string& theName, const int& theAge) : name(theName), age(theAge){} 11 | 12 | void display() const {cout << name << endl;} 13 | 14 | const string& getName() const {return name;} //return type string& means the thing returned is a reference that can be modified which we dont want, so we add const. 15 | 16 | private: 17 | string name; 18 | int age; 19 | }; 20 | void displayPerson(const Person& aPerson) { 21 | aPerson.display(); 22 | } 23 | /* 24 | Why return type ostream&? 25 | Ex: (cout << "fred") << 17 operates cout << "fred" first 26 | cout << "fred" has to return cout to do cout << 17 27 | */ 28 | ostream& operator<<(ostream& os, const Person& thePerson){ // ostream always has to referred 29 | // os << "Person: " << thePersn.name << endl; Person is private ):. Need getName function 30 | //os << "Person: " << thePerson.getName(); Or 31 | os << "Person: " << thePerson.name; // define this function as friend in Person class. 32 | return os; 33 | } 34 | 35 | int main() { 36 | Person john("John", 20); 37 | john.display(); 38 | cout << john; // Overload cout.operator<<(john) 39 | } 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Classes/Operator Overloading/code snippets/testComplexWithOverload.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | File: testComplex.cpp 3 | John Sterling -- jsterling@poly.edu 4 | CS1124 5 | Polytechnic University 6 | Demonstrates the use of overloaded operators for 7 | a complex number class. Focus is on arithmetic 8 | operators, including the pre/post increment and 9 | decrement operators. 10 | */ 11 | 12 | #include 13 | #include "Complex.h" 14 | #include 15 | using namespace std; 16 | using namespace CS1124; 17 | 18 | 19 | int main() { 20 | 21 | // create a default complex number and print it. 22 | Complex a; 23 | cout << "A default complex number: " << a << endl; 24 | 25 | // create a complex number representing "1+2i". 26 | Complex b(1,2); 27 | 28 | // create a complex number representing "42+0i". 29 | Complex theAnswer(42); 30 | 31 | // Ask for a complex number of the form a+bi and print it. 32 | // Use the overloded >> operaor to read it and the overloaded 33 | // << operator to print it. 34 | cout << "Please enter a complex number of the form: a+bi\n"; 35 | Complex x; 36 | cin >> x; 37 | cout << "You entered: " << x << endl; 38 | 39 | // Use the overloaded operators + and << to output the 40 | // sum of two complex numbers. 41 | cout << "The sum of (" << x << ") and (1+2i): " << x + b << endl; 42 | 43 | // Create a complex number representing "4+4i". 44 | Complex c(4, 4); 45 | 46 | // Use the overloaded operators + and << to output the 47 | // difference of two complex numbers. 48 | cout << "The difference of (" << c << ") and (1+2i): " << c - b << endl; 49 | 50 | // Why does this work??? Hm... Good test question. 51 | cout << "The sum of (" << c << ") and 5: " << c + 5 << endl; 52 | 53 | // Show the result of incrementing b 54 | cout << "If b == " << b << endl; 55 | cout << "then ++b == " << ++b << endl; 56 | 57 | cout << "If c == " << c << endl; 58 | --c; 59 | cout << "then --c == " << c << endl; 60 | 61 | } 62 | -------------------------------------------------------------------------------- /Classes/Operator Overloading/code snippets/testDateWithOverload.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Example of very basic class using separate compilation. 3 | John Sterling 4 | CS1124 5 | Polytechnic University 6 | */ 7 | 8 | // This program uses essentially the same Date class as used in the example of 9 | // separate compilation, with the addition ofcomparison and output operators. 10 | // The display and earlierThan methods were removed as they are no longer needed. 11 | 12 | #include "Date.h" 13 | #include 14 | #include 15 | using namespace std; 16 | using namespace CS1124; 17 | 18 | 19 | int main() { 20 | 21 | Date d1("03/14/1592"); 22 | cout << "Displaying d1: "; 23 | cout << d1 << endl; 24 | 25 | Date d2("11/23/5813"); 26 | cout << "Displaying d2: "; 27 | cout << d2 << endl; 28 | 29 | cout << "Is date d1 earlier than date d2?\n"; 30 | if (d1 < d2) 31 | cout << "Yes\n"; 32 | else 33 | cout << "No\n"; 34 | cout << "Is date d1 later than date d2?\n"; 35 | if (d1 > d2) 36 | cout << "Yes\n"; 37 | else 38 | cout << "No\n"; 39 | cout << "Is date d1 the same as date d2?\n"; 40 | if (d1 == d2) 41 | cout << "Yes\n"; 42 | else 43 | cout << "No\n"; 44 | cout << "Is date d1 the same as date d1?\n"; 45 | if (d1 == d1) 46 | cout << "Yes\n"; 47 | else 48 | cout << "No\n"; 49 | 50 | } 51 | -------------------------------------------------------------------------------- /Exception/code snippets/Exception.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | File: TestException.cpp 3 | John Sterling 4 | Demonstrates how to throw / catch exceptions. 5 | */ 6 | 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | /* 12 | Issues covered in this code. 13 | 1) throw-list (aka exception specification). 14 | a) Purpose: lists all the things a function can throw. 15 | b) If it is used, it should appear in both the function 16 | prototype and the function definition. 17 | 2) Using a class to represent an exception. 18 | Here an object of the class IAmAnException might be 19 | spoken of as a "IAmAnException exception". 20 | 3) Creating an "exception object" to throw. 21 | "throw IAmAnException()" 22 | When creating an object to throw using the default constructor 23 | you use parentheses after the default constructor name. 24 | */ 25 | 26 | void first(); 27 | void second(); 28 | 29 | // Sometimes the best sort of thing 30 | class IAmAnException {}; 31 | 32 | int main() { 33 | first(); 34 | } 35 | 36 | void first () { 37 | cout << "Before\n"; 38 | try { 39 | second(); 40 | } catch (string s) { 41 | cout << "Caught a string: " << s << endl; 42 | } catch (int n) { 43 | if (n!=7) 44 | cout << "Caught an integer: " << n << endl; 45 | else 46 | throw; // pass exception "up" -- local objects get extended lifetime. 47 | } catch (IAmAnException) { 48 | cout << "Caught an exception object\n"; 49 | } catch (char s[]) { 50 | cout << "Caught a character array: " << s << endl; 51 | } catch (...) {} 52 | cout << "AFTER\n"; 53 | } 54 | 55 | void second () 56 | { 57 | int q; // Consider the lifetimes of q. 58 | cin >> q; 59 | if (q==0) return; 60 | else if (q == 1) throw 7; 61 | else if (q == 2) throw "I'm a message"; 62 | else if (q == 3) throw 72.6; 63 | else if (q == 4) throw q; // Now what happens to q... 64 | else if (q == 5) throw IAmAnException(); 65 | else if (q == 6) throw 17; 66 | } 67 | -------------------------------------------------------------------------------- /Linked Lists/code snippets/Node.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | File: Node.cpp 3 | John Sterling 4 | This implementation makes use of a constructor for Node. 5 | If you want detailed comments see the original version. 6 | This version takes additional "shortcuts": 7 | Temporary pointers are ONLY created where necessary: 8 | e.g., a pointer parameter is (re)used for walking 9 | down the list. 10 | We use "while(p)" instead of "while(p != NULL)" 11 | */ 12 | 13 | #include "Node.h" 14 | using namespace std; 15 | 16 | namespace CS1124 { 17 | 18 | void listDisplay(const Node* p, ostream& os) { 19 | while (p) { 20 | os << p->data << ' '; 21 | p = p->link; 22 | } 23 | os << endl; 24 | } 25 | 26 | int listLength(const Node* p) { 27 | int length = 0; 28 | while (p != NULL) { 29 | length++; 30 | p = p->link; 31 | } 32 | return length; 33 | } 34 | 35 | void listInsertHead(int data, Node*& headPtr) { 36 | // Create a new node, holding data and pointing to headPtr. 37 | // Put the address of this new node back into headPtr. 38 | headPtr = new Node(data, headPtr); 39 | } 40 | 41 | void listRemoveHead(Node*& headPtr) { 42 | if (headPtr) { 43 | Node* second = headPtr->link; 44 | delete headPtr; 45 | headPtr = second; 46 | } 47 | } 48 | 49 | void listInsertAfter(int entry, Node* previousPtr) { 50 | // Create a new node, holding data and pointing to the node 51 | // that comes after the node pointed to by previousPtr. 52 | // Store the address of the new Node back into that same link. 53 | previousPtr->link = new Node(entry, previousPtr->link); 54 | } 55 | 56 | void listRemoveAfter(Node* previousPtr) { 57 | Node* removePtr = previousPtr->link; 58 | previousPtr->link = removePtr->link; 59 | delete removePtr; 60 | } 61 | 62 | Node* listFindLast(Node* p) { 63 | if (p) 64 | while (p->link) p = p->link; 65 | return p; 66 | } 67 | 68 | void listAppend(Node*& listOne, Node* listTwo) { 69 | if (listOne) { 70 | Node* p = listFindLast(listOne); 71 | p->link = listTwo; 72 | } else 73 | listOne = listTwo; 74 | } 75 | 76 | Node* listDuplicate(const Node* sourcePtr) { 77 | if (sourcePtr == NULL) 78 | return NULL; 79 | 80 | Node* newHead = new Node(sourcePtr->data); 81 | Node* newTail = newHead; 82 | 83 | const Node* p = sourcePtr->link; 84 | while (p) { 85 | listInsertAfter(p->data, newTail); 86 | newTail = newTail->link; 87 | p = p->link; 88 | } 89 | return newHead; 90 | } 91 | 92 | void listClear(Node*& p) { 93 | while (p) { 94 | Node *temp = p->link; 95 | delete p; 96 | p = temp; 97 | } 98 | } 99 | 100 | // As far as understanding pointer manipulation, 101 | // it is better that you understand the code 102 | // above for listClear. 103 | // But this certainly is a tidier way to do the job. 104 | void listClear2(Node*& p) { 105 | while (p) listRemoveHead(p); 106 | } 107 | 108 | Node* listSearch(int target, Node* p) { 109 | while (p && p->data != target) 110 | p = p->link; 111 | return p; 112 | } 113 | 114 | Node* listNodeAtIndex(int index, Node* p) { 115 | int count = 0; 116 | while (count < index && p != NULL) { 117 | count++; 118 | p = p->link; 119 | } 120 | return p; 121 | } 122 | } -------------------------------------------------------------------------------- /Linked Lists/code snippets/Node.h: -------------------------------------------------------------------------------- 1 | /* 2 | File: Node.h 3 | The header file for the linked list toolkit 4 | */ 5 | 6 | #include 7 | #ifndef NODE_H 8 | #define NODE_H 9 | namespace CS1124 { 10 | 11 | // This version of Node provides a constructor which allows some functions 12 | // to be written more simply. Notice that default arguments are provided 13 | // for both fields, NULL for the link and zero for the data. 14 | struct Node { 15 | Node(int x = 0, Node* l = NULL) : data(x), link(l) {} 16 | int data; 17 | Node* link; 18 | }; 19 | 20 | // listDisplay displays the data values in the list. 21 | void listDisplay(const Node* headPtr, std::ostream& = std::cout) ; 22 | 23 | // listLength returns the length of the list pointed to by headPtr. 24 | int listLength(const Node* headPtr) ; 25 | 26 | // listInsertHead adds a new node to the list in front of the original head. 27 | void listInsertHead(int entry, Node*& headPtr) ; 28 | 29 | // listRemoveHead removes the first node from a list. 30 | void listRemoveHead(Node*& headPtr) ; 31 | 32 | // listInsert adds a new node to the list, immediately after the 33 | // node that previousPtr is pointing to. 34 | void listInsertAfter(int entry, Node* previousPtr) ; 35 | 36 | // listRemove removes from the list the node immediately after previousPtr 37 | void listRemoveAfter(Node* previousPtr) ; 38 | 39 | // listFindLast returns a pointer to the last node in the list. 40 | // If the list is empty then NULL is returned. 41 | Node* listFindLast(Node* headPtr) ; 42 | 43 | // listAppend assumes that listOne has at least one node. 44 | // listOne is changed so that it's last node now points to listTwo. 45 | // If listOne was NULL, it now points at listTwo 46 | void listAppend(Node*& listOne, Node* listTwo); 47 | 48 | // listDuplicate creates a new list that is a copy of the original. 49 | // It creates a new node for every node in the original list. 50 | // listDuplicate returns the head pointer of the new list. 51 | Node* listDuplicate(const Node* sourcePtr) ; 52 | 53 | // listClear frees up all the nodes in a list, setting the head pointer to NULL. 54 | void listClear(Node*& headPtr) ; 55 | 56 | // listSearch returns a pointer to the first node in the list "headPtr" 57 | // that has the value "target". 58 | // If the target value is not found then NULL is returned. 59 | Node* listSearch(int target, Node* headPtr) ; 60 | 61 | // listNodeAtIndex returns a pointer to the node in the list at position "index". 62 | // To be consistent with arrays, the first node in the list has index zero. 63 | Node* listNodeAtIndex(int index, Node* headPtr) ; 64 | } 65 | #endif -------------------------------------------------------------------------------- /Linked Lists/code snippets/testNode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | FILE: testLinkedList.cpp 3 | CS 1124 4 | John Sterling 5 | 6 | Test code for the basic linked list toolkit. 7 | 8 | */ 9 | 10 | #include 11 | #include "Node.h" 12 | using namespace std; 13 | using namespace CS1124; 14 | 15 | int main() { 16 | Node* listOne = NULL; 17 | cout << "listOne is empty. It's length is: " << listLength(listOne) << endl; 18 | 19 | listInsertHead(1, listOne); 20 | listInsertHead(2, listOne); 21 | listInsertHead(3, listOne); 22 | listInsertHead(5, listOne); 23 | cout << "Use listInsertHead to insert the values: 1, 2, 3 & 5\n"; 24 | cout << "listOne: "; 25 | listDisplay(listOne); 26 | Node* listTwo = listDuplicate(listOne); 27 | cout << "Use listDuplicate on listOne to create listTwo\n"; 28 | cout << "listTwo: "; 29 | listDisplay(listTwo); 30 | 31 | listRemoveHead(listOne); 32 | cout << "Remove listOne's head\n"; 33 | cout << "listOne: "; 34 | listDisplay(listOne); 35 | cout << "listTwo: "; 36 | listDisplay(listTwo); 37 | cout << "Note that listTwo is unchanged\n"; 38 | 39 | Node* p = listSearch(2, listOne); 40 | cout << "The list starting with the value 2\n"; 41 | listDisplay(p); 42 | listInsertAfter(17, p); 43 | cout << "Add 17 following 2\n"; 44 | cout << "listOne: "; 45 | listDisplay(listOne); 46 | 47 | Node* q = listNodeAtIndex(2, listOne); 48 | cout << "The list that starts at index 2 of listOne: "; 49 | listDisplay(q); 50 | listRemoveAfter(q); 51 | cout << "Removing the node following listOne's node with an index of 2\n"; 52 | cout << "listOne: "; 53 | listDisplay(listOne); 54 | cout << "listOne's length is: " << listLength(listOne) << endl; 55 | listClear(listOne); 56 | cout << "Clear listOne\n"; 57 | cout << "listOne: "; 58 | listDisplay(listOne); 59 | cout << "listOne's length is: " << listLength(listOne) << endl; 60 | listClear(listOne); 61 | 62 | Node* listThree = listDuplicate(listTwo); 63 | cout << "Create listThree as a duplicate of listTwo.\n"; 64 | cout << "listThree: "; 65 | listDisplay(listThree); 66 | listAppend(listTwo, listThree); 67 | cout << "Append listThree onto listTwo.\n"; 68 | cout << "listTwo: "; 69 | listDisplay(listTwo); 70 | cout << "listThree: "; 71 | listDisplay(listThree); 72 | } 73 | -------------------------------------------------------------------------------- /OOP Simplified/OOP Simplified.md: -------------------------------------------------------------------------------- 1 | ## Object Oriented Programming in a Nutshell 2 | We will talk about what Oject Oriented Programming means, and the four main principles of Object Oriented Programming, using a chess game as an example. 3 | 4 | ## What is Object Oriented Programming 5 | In order to understand what object oriented programming is, it's best to first understand what `objects` are. Additionally, to understand `objects`, it's best to first understand what *primitive data types* are. 6 | ### Primitive Data 7 | *Primitive data types* store *single* and *simple* values. Examples include: `char`, `int`, `float`, `double`, `boolean`, etc. In the earlier stages of programming, these *primitive* data types are enough for the programs. However, as programs became large and more complex, only using primitive data types wasn't sufficient anymore. Programmers began to need to *group* pieces of data together to represent a specific `object`. 8 | ## Chess Example 9 | For instance, if we want to program a chess game, we need to program a **knight** piece. There are plenty of variables with different types that we need in order to represent a **knight**, including but not limited to: 10 | * A `position` variable to keep track of where the knight is 11 | * A `color` variable to represent whether the knight is white or black 12 | * A `captured` boolean variable to remove the knight from the chess board if captured 13 | 14 | 15 | 16 | Note that we have several more chess pieces other than **knights** which also need several variables to represent, so it is best if there was a way to *group* these variables together. In essence, Grouping related variables together is almost necessary when it comes to complex programs. 17 | 18 | ### The Structure 19 | The `struct` or the structure data type introduced a way of grouping related variables. In C, `struct` is similar to an array in that it stores many pieces of data together, but `struct` can store data of different types where as the arrays cannot. A `struct` can also store other `struct`. In the chess example, we can now store all the variables that represent a **knight** in a `struct`. 20 | 21 | 22 | 23 | We can also store both knights into another `struct`. 24 | 25 | 26 | 27 | The `struct` is the precursor to the object, or so we call **class objects.** 28 | 29 | ### Downside of structs 30 | The issue that the `struct` had and an issue that objects would come to remedy was that you could not define functions within a `struct`. Thinking about the chess example, we have all the data to represent a **knight**, but we cannot define a function *specific* to the behaviors of a **knight**, such as their move function, within a knight `struct`. 31 | 32 | ### Object Oriented Programming 33 | When object oriented programming came along, objects can do everything a `struct` can do, and also define functions *specific* to the object, called member functions or member methods. For the chess example, we can define member variables and member methods to represent a knight. 34 | 35 | 36 | 37 | 38 | ___ 39 | 40 | #### What are Objects? 41 | Objects are **instances of a class** 42 | ___ 43 | #### What are Classes? 44 | Classes are **templates for objects** 45 | ___ 46 | #### Difference between Objects and Classes 47 | Let's use the chess example to clarify the difference. The knight `class` represents *any given* knight, and a knight `object` represents *only one* singular knight. 48 | 49 | ### Conclusion 50 | Object oriented programming helps programmers create complex programs by grouping together relate data and functions. We will continue explaining what object oriented programming is by diving into the details of its four main principles. 51 | 52 | ## [1. Encapsulation](./encapsulation.md) 53 | 54 | ## [2. Abstraction](./abstraction.md) 55 | 56 | ## [3. Inheritance](./inheritance.md) 57 | 58 | ## [4. Polymorphism](polymorphism.md) 59 | 60 | ___ 61 | Source: [Link](https://www.youtube.com/watch?v=SiBw7os-_zI) -------------------------------------------------------------------------------- /OOP Simplified/abstraction.md: -------------------------------------------------------------------------------- 1 | # Abstraction 2 | ## Definition: Abstraction refers to **only showing essential details** (having a set interface) and keeping everything else hidden. 3 | ___ 4 | ## Car Example 5 | Let's take driving a car as an example. In order to drive a car, we need to know how to steer the steering wheel to turn the car, and how to press on the gas and brake pedals to move or stop the car. We are not concerned with how the car functions internally. Let's break down this examples into three parts: input, process, and output. 6 | ``` 7 | Input - Steer the sterring wheel, Press on Gas Pedal 8 | 9 | Process - the inner workings of the car 10 | 11 | Output - The car turns, the car moves 12 | ``` 13 | As you can see, we only need to understand the input and output, and the process is not imporotant to us. 14 | 15 | This idea demostrated by the car example should extend to `objects`. 16 | 17 | ## Abstraction in Classes 18 | Users of you classes should not worry about the inner details of those classes. Abstraction is similar to Encapsulation in that because we want to prevent bugs when the program gets complicated. 19 | 20 | If we want to work on a big program incrementally, or work with multiple other programmers, we need to have every section function correctly with only requiring knowledge of the **Input** and **Output** and not the inner workings on that section. How do we achieve this? 21 | 22 | ## Interface and Implementation 23 | We can thinkg of our program in turns of **Interface** and **Implementation**. 24 | 25 | Interface - the way sections of code can communicate with one another. This is typically done through methods that each class is able to access. 26 | 27 | Implementation - the implementation of these methods, or how these methods are coded, should be hidden within the class and not accessible on the outside. 28 | 29 | ## Chess Example 30 | Let's say you are working on the `knight` class, and your friend is working on the `king` class. In order to effectively work together, we need to agree on an **interface** for which these pieces can communicate with each other. 31 | 32 | For the `knight`'s `move()` method, we need to check if the `king` is checked, so we access the `getter()` to check the `status` of the `king`. If we can put the `king` out of check with the `knight`, we need to access the `setter()` to change the `status` of the `king`. Note that how to determine whether the `king` is checked is the **implementation** of the `king`'s class, and we only need the `king`'s **interface** for the `knight` to move. 33 | 34 | 35 | 36 | ## Conclusion 37 | Abstraction prevents entanglement between sections of the program. If classes are entangled, then one change in one section creates a *ripple effect* that requires many more changes in other sections to maintain the functionality of the program. 38 | 39 | Creating an **interface** through which classes can interact ensures that each class can be **individually developed** without creating ripple effects. 40 | -------------------------------------------------------------------------------- /OOP Simplified/encapsulation.md: -------------------------------------------------------------------------------- 1 | # Encapsulation 2 | ## Definition: Encapsulation refers to the **bundling of data with methods** that can operate on that data within a class. Essentially, it is the idea of **hiding data** within a class, preventing anything outside that class from *directly* interacting with it. 3 | ___ 4 | To interact with the attributes (member variables) of an object, we have to do that through the object's methods. In practice, we usually do this by implementing **getting** and **setting** methods for object attributes. 5 | 6 | ## Getter Method - Retrieve information 7 | 8 | In the chess example, to determine if I could capture another chess piece, I would need the other chess piece's color. So we define a getter method `getColor()` to retrieve the color of the other piece of chess. This way, we can check the color of any chess piece anything in the program without risking to alter the internal attributes of said pieces. 9 | 10 | ## Setter Method - Change information 11 | 12 | The setter methods provides the rules of changing attribute information. It will make sure the change to the attributes is within the bounds of what is allowed, so people won't have worry about breaking an object's behavior should could happen if they can alter that information of attributes *directly*. 13 | 14 | For instance, in the `move()` method of a knight, we should provide *validation* checks to look for conditions like, a piece of the same color is in that position, or our king piece is *checked* and that move doesn't save us out of *check*, etc. 15 | 16 | ## Read Only Attributes 17 | 18 | Some attributes should not be change by other parts of the program, so we want to keep it **read only** from the outside. To do this, we will define a **getter** method and not a **setter** method so that the variable could only be *referenced*, but not *changed*. 19 | 20 | ## How to achieve encapsulation 21 | Always use `private` access modifiers for attributes. 22 | 23 | ## Conclusion 24 | It's generally best not to allow the external program to *directly* edit an object's attributes. This is very important whne working on large and complex programs, since we want an `object` to work well without requiring them to rely on other parts of the program to not have errors. **Information hiding** helps you keep control of your program. -------------------------------------------------------------------------------- /OOP Simplified/images/Screenshot 2021-05-25 171146.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/OOP Simplified/images/Screenshot 2021-05-25 171146.png -------------------------------------------------------------------------------- /OOP Simplified/images/car1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/OOP Simplified/images/car1.png -------------------------------------------------------------------------------- /OOP Simplified/images/car2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/OOP Simplified/images/car2.png -------------------------------------------------------------------------------- /OOP Simplified/images/car3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/OOP Simplified/images/car3.png -------------------------------------------------------------------------------- /OOP Simplified/images/chess1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/OOP Simplified/images/chess1.png -------------------------------------------------------------------------------- /OOP Simplified/images/chess2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/OOP Simplified/images/chess2.png -------------------------------------------------------------------------------- /OOP Simplified/images/chess3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/OOP Simplified/images/chess3.png -------------------------------------------------------------------------------- /OOP Simplified/images/chess4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/OOP Simplified/images/chess4.png -------------------------------------------------------------------------------- /OOP Simplified/images/chess5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/OOP Simplified/images/chess5.png -------------------------------------------------------------------------------- /OOP Simplified/images/chess6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/OOP Simplified/images/chess6.png -------------------------------------------------------------------------------- /OOP Simplified/images/fruit1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/OOP Simplified/images/fruit1.png -------------------------------------------------------------------------------- /OOP Simplified/images/fruit2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/OOP Simplified/images/fruit2.png -------------------------------------------------------------------------------- /OOP Simplified/images/fruit3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/OOP Simplified/images/fruit3.png -------------------------------------------------------------------------------- /OOP Simplified/images/weapon1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/OOP Simplified/images/weapon1.png -------------------------------------------------------------------------------- /OOP Simplified/images/weapon2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/OOP Simplified/images/weapon2.png -------------------------------------------------------------------------------- /OOP Simplified/images/weapon3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/OOP Simplified/images/weapon3.png -------------------------------------------------------------------------------- /OOP Simplified/inheritance.md: -------------------------------------------------------------------------------- 1 | # Inheritance 2 | ## Definition: Inheritance is the principle that allows classes to derive from other classes. Classes can *inherit* methods and attributes from another class. 3 | ___ 4 | ## Weapon Example 5 | Let's say we are programming a medieval RPG game where our player can collect different weapons. To utilize inheritance, we first implement a class called `Weapon`, which contains pertinent methods and attributes that are common to all weapons, like an attribute `damage` representing how much damage the weapon does, and a method `attack()` that uses a weapon to attack enemies. 6 | 7 | We then want to implement seperate classes for the different type of weapons like a `Sword` or `Club` class. Swords and Clubs will have different values for the same attribute, like a `Sword` is `sharp` but the `Club` is `blunt`. Additionally, `Sword` might have attributes that `Club` doesn't have and vice versa. However, both `Sword` and `Club` are regarded as weapons, so they should inherit the `Weapon` class. 8 | 9 | 10 | 11 | In this example, the `Weapon` class is the **Superclass**, the **Base class**, or the **Parent Class**. The `Sword` and `Club` class are the **Subclass**, the **Derived Class**, or the **Child Class**. 12 | 13 | The methods and attributes of the **superclass** could also be present in its **subclasses** depending on the *access modifiers* (more on that later). 14 | 15 | 16 | 17 | ## Class Hierarchy 18 | Class Hierarchy refers to the tree of relationship between superclasses and subclasses. Class hierarchy can have many layers with many classes in each layer. The class hierarchy acts as a web of classes with different relationships to one another. Back to the weapon example, the `Weapon` class can also inherit from a class `Item`, which can have more subclasses like `Tool`. 19 | 20 | 21 | 22 | ## Access Modifiers 23 | ___ 24 | ### Definition: Access modifiers change which classes have access to other classes, methods, or attributes. To sound more professional, it defines the scope of accessibility. 25 | ___ 26 | ### The three access modifiers that would be covered are: 27 | ### * Public 28 | ### * Private 29 | ### * Protected 30 | 31 | ### Public - `public` members can be accessed from anywhere in the program by anyone. To sound nerdy, there is no limit to the scope of accessibility. 32 | This includes anywhere both inside of the class hierarchy it is defined as well as outside in the rest of the program. 33 | 34 | If we have a food hierarchy and an attribute defined in the `Fruit` class, everyone can access that attribute if the access modifier is `public`. 35 | 36 | 37 | 38 | ### Private - `private` members can only be accessed from within the same class that the member is defined in. To sound nerdy, the scope of accessibility is limited to the `namespace` of that class. 39 | This allows us to create multiple private members of the same name in different locations in the class hierarchy so that they do no conflict with one another. 40 | 41 | Again, for an attribute defined in the `Fruit` class, the attribute can only be accessed in the `Fruit` class 42 | 43 | 44 | 45 | ### Protected - `protected` members can be accessed within the class it is defined, as well as any subclasses of that class. To sound nerdy, the scope of accessibility is limited to the `namespace` of that class and its subclasses. 46 | This makes `protected` members private to the hierarchy in which they are defined. 47 | 48 | 49 | Again, for an attribute defined in the `Fruit` class, the attribute can be accessed in the `Fruit` class and also the `Apple` and `Orange` class. 50 | 51 | 52 | 53 | ## Conclusion 54 | Inheritance allows us to create a class hierarchy to emphasize the network between similar classes and also reduces redundancy. -------------------------------------------------------------------------------- /OOP Simplified/polymorphism.md: -------------------------------------------------------------------------------- 1 | # Polymorphism 2 | ## Definition: Polymorphism describes methods with the *same name* that are able to take on many forms 3 | ___ 4 | ## Two Types of Polymorphism 5 | ### Dynamic Polymorphism - Occurs during **runtime** 6 | ### Static Polumorphism - Occurs during **compile time** 7 | ___ 8 | ## Dynamic Polymorphism 9 | Dynamic polymorphism occurs when the program is executed. This type of polymorphism describes when a **method** signature is in both a *subclass* and a *superclass*. 10 | 11 | The method shares the same *name*, same *parameters*, just with different *implementation*. 12 | 13 | ### Which method will be called? 14 | This will depend on which class the `object` belongs to. If an `object` of subclass is called, the method implemented by the *subclass* will **override** that of the *superclass*. The implementation of a method signature that will be used is determined dynamically as the program is run. 15 | 16 | ### Car Example 17 | We have a *superclass* called `Car` and a *subclass* `SportsCar`. Both classes has a `drive(double miles)` method which the same parameters just different implementations. 18 | 19 | 20 | 21 | If we have a `SportsCar` object `mySportsCar`, calling `mySportsCar.drive(miles)` will call the `SportsCar`'s implementation of the `drive()` method since it overrides the implementation of its *superclass*. 22 | 23 | 24 | 25 | ### Other Names for Dynamic Polymorphism 26 | * Method Overriding 27 | * Runtime Binding 28 | * Dynamic Binding 29 | 30 | ### Benefits of Dynamic Polymorphism 31 | This allows us to have a generic implementation of a method in the *superclass* and if we want more specific behavior we can override it in the *subclass*. 32 | 33 | ## Static Polymorphism 34 | Static polymorphism occurs during compile time rather than during runtime. This refers to when multiple methods with the same *name* but different *arguments* are defined in the same class. This also refers to when multiple functions (not methods) with same *name* and different *arguments*. 35 | 36 | ### Ways to Differentiate Methods of the Same Name 37 | * Different number of parameters 38 | * Different types of parameters 39 | * Different order of parameters 40 | * Different qualifiers (`const` or `volatile`) 41 | 42 | ### Ways to Differentiate Functions of the Same Name 43 | * Different number of parameters 44 | * Different types of parameters 45 | * Different order of parameters 46 | 47 | Note the different between methods and functions. 48 | 49 | ### Car Example 50 | If we have a `Car` class, the `Car` class can have three methods all called `drive()` with different parameters. Depending on the parameters when `drive()` is called, the `drive()` implementation that has the matching parameters will be called. 51 | 52 | 53 | 54 | ### Other Names for Static Polymorphism 55 | * Method Overloading 56 | * Function Overloading 57 | * Compile Time Binding 58 | * Dynamic Binding 59 | 60 | Note: Method/Function overloading can cause trouble if you do not keep straight which parameters you need for which implementation. Using the incorrect arguments **may not** cause an error if it matches that of another form of the method, which can cause issues that can hard to detect. 61 | 62 | ## Overview 63 | Overall, polymorphism can be useful since it allows methods with the same name to take on many different forms. When utilizing polymorphism, be sure that you are calling the correct form of the method/function. -------------------------------------------------------------------------------- /Pointers/code snippets/DynamicArray.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | testIncreasingArraySize.cpp 3 | John Sterling 4 | CS1124 5 | Demonstrate how to "Expand" the array, as needed, 6 | in order to hold the contents of a file. . 7 | */ 8 | 9 | 10 | #include 11 | #include 12 | using namespace std; 13 | 14 | const size_t INITIAL_SIZE = 3; 15 | 16 | void fillArray(int*& arr, size_t& count, size_t& size, ifstream& ifs); 17 | 18 | int main() { 19 | 20 | size_t size = INITIAL_SIZE; 21 | size_t count = 0; // index for next entry. Also count of entries. 22 | int* arr = new int[size]; // Initial array. 23 | 24 | ifstream ifs("data.txt"); // We should check if the file opened correctly. 25 | 26 | fillArray(arr, count, size, ifs); 27 | 28 | // Let's just see what's in the array, to make sure the code worked. 29 | for (size_t i = 0; i < count; ++i) 30 | cout << arr[i] << endl; 31 | 32 | } 33 | 34 | // Pass the array and the size by reference because they are both going to change. 35 | void expandArray(int*& arr, size_t& size) { 36 | size_t newSize = 2 * size; // The size for the new array. 37 | int* temp = new int[newSize]; // This is the new array. 38 | // Loop to copy the data from the old array to the new one 39 | for (size_t i = 0; i < size; ++i) 40 | temp[i] = arr[i]; 41 | delete [] arr; // Now we can get rid of the old array. 42 | arr = temp; // Our array pointer needs to point to the new array 43 | size = newSize; // and our size needs the expanded size. 44 | } 45 | 46 | // fillArray fill the array arr from the stream ifs. 47 | // count is how many entries in the array are already used. 48 | // size is the size of the array. 49 | // The array may have to be resized, so it and the size are passed by reference. 50 | // The count will also change as we add entries so it is also passed by reference. 51 | // We already know that streams are always passed by reference, because they 52 | // change whenever we read or write them. 53 | void fillArray(int*& arr, size_t& count, size_t& size, ifstream& ifs) { 54 | int x; // Some place to read the information into 55 | while (ifs >> x) { // Get the next item from the file 56 | if (count == size) // Is our array already full? 57 | expandArray(arr, size); // then "expand" it. 58 | arr[count++] = x; // Put the item into the array since we now have room. 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /Pointers/code snippets/NewDelete.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | 6 | // Defining an array of ints. We have to know how 7 | // many ints there will be when we write the program. 8 | int arr[5] = {1, 4, 9, 16, 25}; 9 | 10 | // What if we want to ask the user how big an array to use? 11 | cout << "How big an array do you want? "; 12 | int arraySize; 13 | cin >> arraySize; 14 | 15 | // We might like to write: 16 | // int anotherArray[arraySize]; 17 | // But that would result in a compilation error, complaining that 18 | // we should use a constant expression for the size of the array. 19 | // Instead if we want to create an array with a size that we get 20 | // from the user, then we have to write: 21 | int* myIntPtr = new int[arraySize]; 22 | 23 | // How do we use the pointer called myIntPtr? 24 | for (int i = 0; i < arraySize; i++) 25 | myIntPtr[i] = i * i; 26 | 27 | // Let's loop again, this time using pointer arithmetic 28 | for (int i = 0; i < arraySize; i++) 29 | cout << *(myIntPtr + i) << ", "; 30 | cout << endl; 31 | 32 | // Now let's "free up" the memory we used for the array. 33 | delete [] myIntPtr; 34 | 35 | // We no longer have official permission to use the memory 36 | // where that array was. And soon it might get reused for 37 | // something else. But let's just see if it still has our 38 | // values there for now. Our program could crash now... 39 | cout << "We freed up the memory, let's see what's there now\n"; 40 | for (int i = 0; i < arraySize; i++) 41 | cout << *(myIntPtr + i) << ", "; 42 | cout << endl; 43 | 44 | // Of course we could be using array notation in that loop above: 45 | cout << "Printing it again using array notation\n" 46 | << "Should look the same.\n"; 47 | for (int i = 0; i < arraySize; i++) 48 | cout << myIntPtr[i] << ", "; 49 | cout << endl; 50 | 51 | 52 | } -------------------------------------------------------------------------------- /Pointers/code snippets/PointerBasics.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Example of addresses, pointers and pointer arithmetic. 3 | Also the use of pointers as array names. 4 | John Sterling 5 | CS1124 6 | Polytechnic University 7 | */ 8 | 9 | #include 10 | using namespace std; 11 | 12 | int main() { 13 | 14 | int x = 6; 15 | cout << "x = " << x << endl; 16 | // The address of x is writte &x 17 | cout << "&x = " << &x << endl; 18 | 19 | // declaring a pointer to an int and initializing it to the address 20 | // of an int variable. Note that pointers always have a type! 21 | int* px = &x; 22 | // Print out the contents of a pointer variable. 23 | cout << "px = " << px << endl; 24 | // Print out the value that the pointer points to. 25 | // When you use the * character on the left side of a pointer 26 | // variable it is called the "dereferencing operator". 27 | cout << "*px = " << *px << endl; 28 | 29 | int f[] = { 8, 13, 21, 34, 55, 89 }; 30 | int* pf; 31 | // We will print out the contents of the array f[] 32 | cout << "f[] = { "; 33 | // Looping over an array using pointers. 34 | // Note that the name of an array is the array's address 35 | for (pf = f; pf < f + 6; pf++) cout << *pf << ", "; 36 | cout << "}\n"; 37 | 38 | // Here is a second way of getting the address of an array. 39 | pf = &f[0]; 40 | cout << "*pf = " << *pf << endl; 41 | // What is "*pf + 2" ? In other words, which has higher precedence, 42 | // the dereferencing operator or the addition operator? 43 | cout << "*pf + 2 = " << *pf + 2 << endl; 44 | cout << "*(pf + 2) = " << *(pf + 2) << endl; 45 | // What is the effect of using dereferencing and pre-increment? 46 | cout << "*++pf = " << *++pf << endl; 47 | // What is the effect of using dereferencing and post-increment? 48 | cout << "*pf++ = " << *pf++ << endl; 49 | cout << "*(pf + 2) = " << *(pf + 2) << endl; 50 | // See that f has not changed, even though pf has. 51 | cout << "*(f + 2) = " << *(f + 2) << endl; 52 | cout << "f[2] = " << f[2] << endl; 53 | // Could we do the same with f as we did with pf above? 54 | // That is, can we use f++? No. VC++ complains that "++ needs and l-value". 55 | // That means we have to be able to assign to f. But we can't write "f = 5" 56 | // or any other such assignment expression. Another way to view it is that 57 | // f is const. It may represent an address, but we can't change what that 58 | // address is. 59 | // f++; 60 | 61 | // If the name of an array is really just the address of the array 62 | // and if a pointer to the array holds the address of the array, 63 | // is there some easy way to use a pointer AS an array? Yes! 64 | pf = f; 65 | cout << "pf[2] = " << pf[2] << endl; 66 | 67 | 68 | // What is the type of a and of b? 69 | int* a, b; 70 | 71 | // How do we define a pointer to a pointer? 72 | // See the use of two asterisks? Note that we use an int** to hold the 73 | // address of an int*. 74 | int** pp = &px; 75 | cout << "**pp = " << **pp << endl; 76 | 77 | } -------------------------------------------------------------------------------- /Pointers/code snippets/pointerWithConst.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // Memory and pointer 5 | 6 | int main(){ 7 | 8 | // POINTER HOLDS ADDRESS 9 | int x = 17; 10 | cout << &x << endl; // prints the memory address of x 11 | 12 | // If u want to store the address: 13 | int* p = &x; // int* means an int pointer 14 | // int *p = &x same thing 15 | // int * p = &x 16 | cout << p << endl; 17 | 18 | // how to use p to get value of x? 19 | cout << *p << endl; // *p = x and p = &x 20 | 21 | // Different pointers 22 | // This is a pointer pointing to a constant int, 23 | // meaning p1 cannot modify the integer x 24 | const int* p1 = &x; 25 | // This is a constant pointer pointing to an int, 26 | // meaning p2 can modufy the integer x, but p2 cannot point to something else 27 | int* const p2 = &x; 28 | // This a constant pointer pointing to a constant int, 29 | // meaning p3 can modify neither x nor point to something else 30 | const int* const p3 = &x; 31 | } -------------------------------------------------------------------------------- /Pointers/code snippets/vectorOfObjectsOnHeap.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This program demonstrates the use of heaps 3 | Important information about virtual addresss memory space for a program 4 | 5 | Lowest place of memory: where your code is 6 | Above it, we have data, which are the global variables 7 | Above the globals there's the heaps where we can allocate and store new objects 8 | At the very top. u have the call stack: main (inside the main there's local variables) 9 | 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | using namespace std; 17 | 18 | 19 | class Person { 20 | friend ostream& operator<<(ostream& os, const Person& thePerson){ 21 | os << "Person: " << thePerson.name << ", bday: " << thePerson.bday; 22 | if (thePerson.spouse == nullptr){ 23 | os << " single"; 24 | } 25 | else { 26 | os << " married to: " << thePerson.spouse -> name; 27 | } 28 | return os; 29 | } 30 | friend void modify_ptr(Person& rhs){ 31 | Person* p = &rhs; 32 | p -> name = "Mathilda"; 33 | const Person* p2 = &rhs; 34 | Person* const p3 = &rhs; 35 | } 36 | public: 37 | Person(const string& theName, const Date& aDate) : name(theName), bday(aDate), spouse(nullptr) {} 38 | bool marries(Person& betrothed){ 39 | if (spouse == nullptr && betrothed.spouse == nullptr){ 40 | spouse = &betrothed; 41 | betrothed.spouse = this; 42 | return true; 43 | } 44 | return false; 45 | } 46 | private: 47 | string name; 48 | Date bday; 49 | Person* spouse; 50 | }; 51 | 52 | class Date{ 53 | friend ostream& operator << (ostream& os, const Date& rhs); 54 | public: 55 | Date(int m, int d, int y) : month(m), day(d), year(y) {} 56 | private: 57 | int month, day, year; 58 | }; 59 | 60 | 61 | ostream& operator << (ostream& os, const Date& rhs){ 62 | os << rhs.month << '/' << rhs.day << '/' << rhs.year; 63 | return os; 64 | } 65 | 66 | int main() { 67 | // Vector of Person objects 68 | vector people; 69 | ifstream file("people.txt"); // assumming we have a people.txt file 70 | string name; 71 | int m, d, y; 72 | while (file >> name){ 73 | file >> m >> d >> y; 74 | Person myPerson(name, Date(m,d,y)); 75 | people.push_back(&myPerson); // This is bad 76 | // &myPerson will always be the same. WHY? 77 | // because the address of myPerson did not change 78 | // we need a new person object every thing 79 | } 80 | 81 | people.clear(); // set the size to zero. If you have a vector of pointers, nothing happens to the objects it is pointing at. 82 | 83 | while (file >> name){ // Correct way 84 | file >> m >> d >> y; 85 | Person* p = new Person(name, Date(m,d,y)); // new Person returns the memory address 86 | people.push_back(p); // All the perosn objects are stored in the heaps area 87 | } 88 | /* 89 | The difference between heap and global objects is that globals are accessible to the entire program but heap is only 90 | accessible if the address is given. It is hidden without the address. 91 | */ 92 | 93 | new Person("fred", Date(1,2,3)); // This is called memory leak. 94 | // You create an object in the heap but is inaccessible because the addresss is not stored. This cause the program to run slower over time. 95 | 96 | // In order to get rid of old memory stored in the heap in people vector: 97 | for (Person* p : people){ 98 | delete p; // release the memory in the heap 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /Python to C++/DIfference between Python and C++.md: -------------------------------------------------------------------------------- 1 | # Python to C++ (the Differences) 2 | 3 | ## C++ is a Compiled language 4 | Python is a interpreted langauge, where you type a line into IDE and the code execute immediately. C++ has to be **builded** in order to be executable, which includes two steps: complication and linking. The word **build** and **compile** are used interchangeably. 5 | 6 | ## C++ is a static type language 7 | Python is a dynamically typed language where a variable can change from an integer to a string. In C++, we have to define a type for the variable and assigning a value with the **wrong** type to a variable will result in a complication error. 8 | 9 | Remember, we have to define the types for variables, parameters of functions, and return values for fucntions. 10 | 11 | ## Indentation vs. Blocks 12 | In Python, we use indentation to define structures. In C++ we use a pair of curly braces to define structures. Of course, for human readability, it is important in C++ that we still use consistent indentation. 13 | 14 | In Python: 15 | ```python 16 | def func(): 17 | print("CS 2124") 18 | ``` 19 | In C++: 20 | ```c++ 21 | void func(void): 22 | cout << "CS 2124" << endl; 23 | ``` 24 | ## Statements End in Semicolon 25 | In Python, each line is a statment by default, but C++ allows a statement to take multiple lines so we use the semicolon `;` to tell the compiler when a statement is finished. 26 | 27 | ## Console I/O 28 | C++ does not have a `print()` function like Python. Instead, the simple input (from the keyboard) and output (to the screen) uses the input and output operator. 29 | 30 | Print variable x to screen: 31 | ```c++ 32 | cout << x << endl; 33 | // endl means to print a new line character, which is the same as 34 | cout << x << '\n'; 35 | ``` 36 | 37 | Read from keyboard into variable x: 38 | ```c++ 39 | cin >> x; 40 | ``` 41 | 42 | Note: 43 | * `cout` stands for *standard output*, which represents the screen. 44 | * `<<` is the *output operator*, which directs variable `x` to `cout` 45 | * `cin` stands for *standard input*, which represents our keyboard. 46 | * `>>` is the *input operator*, which directs the input from keyboard to variable `x`. 47 | 48 | ## String and Character Literals 49 | In Python, we can use single and double quotes to represent a string or character. In C++, double quotes are used to represent string literals and single quotes are used to represent a character literal. 50 | 51 | ## Syntax Differences 52 | There are lots of syntax differences between Python and C++, which will be shown to you in the following semester. 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /Recursion/Recursion.md: -------------------------------------------------------------------------------- 1 | # Recursion 2 | *To understand recursion, first you must understand recursion.* 3 | 4 | A function that calls itself is a **recursive function**. This programming technique is called **recursion**. Some uses of recursion may lead to very inefficient code, while others are perfectly reasonable and make the implementation of an algorithm easier to understand. 5 | 6 | ## Design 7 | 1. Think about how you can solve the problem by using the *same* function on a smaller version of the problem. 8 | 1. Do some *small* piece of the task at each call to the function. 9 | Know when to stop. 10 | 1. Be sure to get the right ordering between items 1 & 2. 11 | 12 | Always try your solution out on a small test case. Employing such sanity checks should be an ingrained habit. 13 | 14 | Recursive solutions are often a little surprising the first time you see them. **Practice** helps. 15 | 16 | ## Simple Examples 17 | * Basic Printing 18 | * Print 1 to n [in reverse] 19 | * Print n of one character followed by n of another. 20 | * Print n to 1 followed by 1 to n. 21 | * Print digits of an int [in reverse] 22 | * Arrays 23 | * Print an array [in reverse]. Note: requires passing in the array’s size. 24 | * Sum/max/min of an array. 25 | * Reverse an array 26 | * Check for palindrome 27 | * c-string. No size needed. Example of using a sentinel. 28 | * print [in reverse]. 29 | * length. 30 | * Factorial 31 | * Count the number of 1’s in the binary representation of a non-negative int. 32 | * Exponention: pow(x, n). Both brute force and “smart”. The smart solution saves a lot * of multiplies for large values of n. 33 | * `gcd( x, y ) = ( y == 0 ? x : gcd( y, x%y ) )`. 34 | * Linked list* 35 | * Display [in reverse] 36 | * Find a specified value 37 | * Find last element 38 | * Clear 39 | * Copy 40 | * Size [or length] of the list. 41 | * Sum/max/min 42 | 43 | ## Harder Examples 44 | * Fibonnaci 45 | * Binary Search 46 | * Towers of Hanoi (also try an iterative solution) -------------------------------------------------------------------------------- /Recursion/code snippets/Recursion.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // Recursion 5 | // A recursive function must: 6 | // 1) call itself on a reduced task 7 | // 2) know when to stop 8 | // 3) do something SMALL in each call 9 | // 4) Pay attention to the order of 1 and 3. 10 | 11 | int factorial (int n); 12 | void printOnetoN(int n); 13 | void printNtoOne(int n); 14 | void printDigits(int n); 15 | void printDigitsInReverse(int n); 16 | void printOctal(int n); 17 | // How many 1's in the binary representation of n? 18 | int parity(unsigned n); 19 | // same as above but as a single line of code 20 | int parity2(unsigned n); 21 | // print n a's followed by n b's. 22 | void printAB(int n); 23 | int sumArray(int arr[], int n); 24 | // same as above but as a single line of code 25 | int sumArray2(int arr[], int n); 26 | int maxArray(int arr[], int n); 27 | bool checkPalindrome(char arr[], int n); 28 | // same as above but as a single line of code 29 | bool checkPalindrome2(char arr[], int n); 30 | 31 | int main() { 32 | cout << "Print 1 to 11: "; 33 | printOnetoN(11); 34 | cout << endl; 35 | cout << "Print 11 to 1: "; 36 | printNtoOne(11); 37 | cout << endl; 38 | cout << "6! = " << factorial(6) << endl; 39 | cout << "256 in reverse: "; 40 | printDigitsInReverse(256); 41 | cout << endl; 42 | cout << "256 in octal: "; 43 | printOctal(256); 44 | cout << endl; 45 | cout << "5 in binary has " << parity(5) << " ones\n"; 46 | cout << "7 in binary has " << parity(7) << " ones\n"; 47 | cout << "Print 5 a's followed by 5 b's: "; 48 | printAB(5); 49 | cout << endl; 50 | int myArray[] = { 13, 1, 34, 8}; 51 | cout << "myArray[] = { 13, 1, 34, 8}\n"; 52 | cout << "max of myArray = " << maxArray(myArray, 4) << endl; 53 | cout << "sum of myArray = " << sumArray(myArray, 4) << endl; 54 | char charArray1[] = "Able was I ere I saw elbA"; 55 | char charArray2[] = "Nothing special"; 56 | cout << "charArray1: " << charArray1 << endl; 57 | cout << "is" << (checkPalindrome(charArray1, strlen(charArray1)) ? "" : " not") << " a palindrome\n"; 58 | cout << "charArray2: " << charArray2 << endl; 59 | cout << "is" << (checkPalindrome(charArray2, strlen(charArray2)) ? "" : " not") << " a palindrome\n"; 60 | 61 | } 62 | 63 | // 5! = 5 * 4 * 3 * 2 * 1 64 | // = 5 * 4! 65 | // n! = n * (n-1)! 66 | // factorial(5) = 5 * factorial(4) 67 | int factorial (int n) { 68 | if (n == 1) 69 | return 1; 70 | else 71 | return n * factorial(n-1); 72 | } 73 | void printOnetoN(int n) { 74 | if ( n > 0 ) { 75 | printOnetoN( n - 1 ); 76 | cout << n << " "; 77 | } 78 | } 79 | void printNtoOne(int n) { 80 | if ( n > 0 ) { 81 | cout << n << " "; 82 | printNtoOne( n - 1 ); 83 | } 84 | } 85 | 86 | void printDigits(int n) { 87 | if ( n < 10 ) { 88 | cout << n; 89 | } else { 90 | printDigits( n / 10); 91 | cout << n % 10; 92 | } 93 | } 94 | void printDigits2(int n) { 95 | if (n >= 10) 96 | printDigits2(n / 10); 97 | cout << n % 10; 98 | } 99 | 100 | void printDigitsInReverse(int n) { 101 | if ( n < 10 ) { 102 | cout << n; 103 | } else { 104 | cout << n % 10; 105 | printDigitsInReverse( n / 10); 106 | } 107 | } 108 | void printDigitsInReverse2(int n) { 109 | cout << n % 10; 110 | if ( n >= 10 ) 111 | printDigitsInReverse( n / 10); 112 | } 113 | void printOctal(int n) { 114 | if ( n < 8 ) { 115 | cout << n; 116 | } else { 117 | printOctal( n / 8); 118 | cout << n % 8; 119 | } 120 | } 121 | void printOctalReverse(int n) { 122 | cout << n % 8; 123 | if ( n >= 8 ) 124 | printOctal( n / 8); 125 | } 126 | 127 | int parity(unsigned n) { 128 | if (n) 129 | return (n % 2) + parity(n / 2); 130 | else 131 | return 0; 132 | } 133 | int parity2(unsigned n) { 134 | return (n==0) ? 0 : (n % 2) + parity2(n / 2); 135 | } 136 | void printAB(int n) { 137 | if (n) { 138 | cout << "a"; 139 | printAB(n-1); 140 | cout << "b"; 141 | } 142 | } 143 | int sumArray(int arr[], int n) { 144 | if (n == 0) 145 | return 0; 146 | else 147 | return arr[0] + sumArray(arr+1, n-1); 148 | } 149 | int sumArray2(int arr[], int n) { 150 | return (n == 0) ? 0 :(arr[0] + sumArray(arr+1, n-1)); 151 | } 152 | int maxArray(int arr[], int n) { 153 | if (n == 1) 154 | return arr[0]; 155 | else 156 | return max(arr[0], maxArray(arr+1, n-1)); 157 | } 158 | bool checkPalindrome(char arr[], int n) { 159 | if (n < 2) 160 | return true; 161 | else if (arr[0] != arr[n-1]) 162 | return false; 163 | else 164 | return checkPalindrome(arr+1, n-2); 165 | } 166 | bool checkPalindrome2(char arr[], int n) { 167 | return (n < 2) ? true : (arr[0] == arr[n-1]) && checkPalindrome2(arr+1, n-2); 168 | } -------------------------------------------------------------------------------- /Recursion/code snippets/binserach.cpp: -------------------------------------------------------------------------------- 1 | //Program to demonstrate the recursive function for binary search. 2 | #include 3 | using namespace std; 4 | 5 | 6 | // binarySearch takes four arguments: 7 | // searchfor is the thing we are looking for 8 | // a[] is the array to search in. It must be already sorted (i.e., in order) 9 | // left is the index in the array that we are startting at. 10 | // right is the index of the array that we are ending at. 11 | // This version of binarySearch returns array index if the number was found 12 | // and -1 otherwise. 13 | 14 | int binarySearch(int searchfor, int a[], int left, int right) { 15 | // we'll need the midpoint, so let's figure it out now. 16 | int mid = (left + right) / 2; 17 | // Did we miss it? 18 | // If the index "on the left" has gone passed the index "on the right" then 19 | // the number we want just isn't in the array. 20 | if (left > right) return -1; 21 | // check to see if our target is at the index mid. 22 | // If it is, then we have success! 23 | else if (searchfor == a[mid]) return mid; 24 | // If our target is bigger than the value at mid then we need to search 25 | // to the right in the array. and return that result. 26 | else if (searchfor > a[mid]) 27 | return binarySearch(searchfor, a, mid + 1, right); 28 | // The only other possibility is that it is to the left, so we return 29 | // the result of searching there. 30 | else 31 | return binarySearch(searchfor, a, left, mid - 1); 32 | } 33 | 34 | int main( ) { 35 | const int ARRAY_SIZE = 14; 36 | int a[] = {1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610}; 37 | int key = 0; 38 | cout << "a[] == {1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610}\n"; 39 | while (true) { 40 | cout << "Enter number to be located or -1 to exit: "; 41 | int key; 42 | cin >> key; 43 | if (key == -1) 44 | break; 45 | else { 46 | int found = binarySearch(key, a, 0, ARRAY_SIZE - 1); 47 | if (found >= 0) 48 | cout << key << " is in index location " 49 | << found << endl; 50 | else 51 | cout << key << " is not in the array." << endl; 52 | } 53 | } 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /Recursion/code snippets/recursiveLinkedList.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | FILE: testRecursiveLinkedList.cpp 3 | CS 1124 4 | John Sterling 5 | 6 | Recursive versions of some of the linked list functions 7 | */ 8 | 9 | #include 10 | using namespace std; 11 | 12 | struct Node { 13 | Node(int d = 0, Node* l = NULL) : data(d), link(l) {} 14 | int data; 15 | Node* link; 16 | }; 17 | 18 | // No this one's not recursive. Used to create lists to play with. 19 | void listInsertHead(int entry, Node*& headPtr) { 20 | headPtr = new Node(entry, headPtr); 21 | } 22 | 23 | // This one's not recursive, either. Used for "listClear2". 24 | void listRemoveHead(Node*& headPtr) { 25 | if (headPtr) { 26 | Node* second = headPtr->link; 27 | delete headPtr; 28 | headPtr = second; 29 | } 30 | } 31 | 32 | // ===========Start of recursive function definitions================== 33 | 34 | int listLength(const Node* headPtr) { 35 | if (headPtr) return 1 + listLength(headPtr->link); 36 | else return 0; 37 | } 38 | 39 | void listDisplay(const Node* headPtr) { 40 | if (headPtr) { 41 | cout << headPtr->data << ' '; 42 | listDisplay(headPtr->link); 43 | } 44 | else cout << endl; 45 | } 46 | 47 | Node* listFindLast(Node* headPtr) { 48 | if (!headPtr) return NULL; // Be nice if they pass in an empty list. 49 | else if (!headPtr->link) return headPtr; 50 | else return listFindLast(headPtr->link); 51 | } 52 | 53 | // A good choice for recursion, but we do this in recitation, so I won't solve it here. 54 | Node* listDuplicate(const Node* sourcePtr); 55 | 56 | void listClear(Node*& headPtr) { 57 | if (headPtr) listClear(headPtr->link); 58 | delete headPtr; 59 | headPtr = NULL; 60 | } 61 | 62 | // another version of listClear. 63 | void listClear2(Node*& headPtr) { 64 | listRemoveHead(headPtr); 65 | if (headPtr) listClear2(headPtr); 66 | } 67 | 68 | Node* listSearch(int target, Node* headPtr) { 69 | if (!headPtr) return NULL; 70 | else if (headPtr->data == target) return headPtr; 71 | else return listSearch(target, headPtr->link); 72 | } 73 | 74 | Node* listNodeAtIndex(int index, Node* headPtr) { 75 | // if they ask for an index beyond the end of the list, return NULL 76 | if (!headPtr) return NULL; 77 | else if (index) return listNodeAtIndex(index-1, headPtr->link); 78 | else return headPtr; 79 | } 80 | 81 | int main() { 82 | Node* listOne = NULL; 83 | cout << "listOne is empty. It's length is: " << listLength(listOne) << endl; 84 | 85 | listInsertHead(1, listOne); 86 | listInsertHead(2, listOne); 87 | listInsertHead(3, listOne); 88 | listInsertHead(5, listOne); 89 | cout << "Use listInsertHead to insert the values: 1, 2, 3 & 5\n"; 90 | cout << "listOne: "; 91 | listDisplay(listOne); 92 | cout << "listOne's length: " << listLength(listOne) << endl; 93 | 94 | Node* p = listSearch(2, listOne); 95 | cout << "The list starting with the value 2\n"; 96 | listDisplay(p); 97 | 98 | Node* q = listNodeAtIndex(1, listOne); 99 | cout << "The list that starts at index 1 of listOne: "; 100 | listDisplay(q); 101 | 102 | cout << "Clear listOne\n"; 103 | listClear(listOne); 104 | cout << "listOne: "; 105 | listDisplay(listOne); 106 | cout << "listOne's length is: " << listLength(listOne) << endl; 107 | } 108 | -------------------------------------------------------------------------------- /STL/code snippets/STL.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | template 8 | void displayContainer(const T& x) { 9 | for (T::const_iterator iter = x.begin(); iter != x.end(); iter++) 10 | cout << *iter << " "; 11 | cout << endl; 12 | } 13 | 14 | int main() { 15 | // create an array to use later. 16 | int myArray[] = {2, 3, 5, 7, 11, 13, 17}; 17 | cout << "int myArray[] = {2, 3, 5, 7, 11, 13, 17};\n"; 18 | 19 | // create an empty list of integers. 20 | list li; 21 | 22 | // create a list of integers that contains 23 | // six entries all with the value 17. 24 | list li2(6, 17); 25 | cout << "Creating: list li2(6, 17)\n"; 26 | // Display the list. 27 | cout << "Displaying li2\n"; 28 | for (list::iterator iter = li2.begin(); iter != li2.end(); iter++) 29 | cout << *iter << " "; 30 | cout << endl; 31 | 32 | // create a list of integers that contains 33 | // the entries (3, 5, 7, 11) from myArray. 34 | // Note that we are using the address of the first 35 | // element and the address of the element just past 36 | // the last one that we want. 37 | list li3(myArray+1, myArray+5); 38 | cout << "Creating: list li3(myArray+1, myArray+5)\n"; 39 | cout << "Displaying li3\n"; 40 | for (list::iterator iter = li3.begin(); iter != li3.end(); iter++) 41 | cout << *iter << " "; 42 | cout << endl; 43 | 44 | li3.push_front(28); 45 | cout << "Pushing 28 on the front of li3\n"; 46 | cout << "Displaying li3\n"; 47 | for (list::iterator iter = li3.begin(); iter != li3.end(); iter++) 48 | cout << *iter << " "; 49 | cout << endl; 50 | 51 | cout << "Reversing the first six elements of myArray\n"; 52 | reverse(myArray, myArray+6); 53 | for (int i = 0; i < 7; i++) 54 | cout << myArray[i] << " "; 55 | cout << endl; 56 | cout << "Sorting the last six elements of myArray\n"; 57 | sort(myArray+1, myArray+7); 58 | for (int i = 0; i < 7; i++) 59 | cout << myArray[i] << " "; 60 | cout << endl; 61 | 62 | cout << "Creating a vector to contain a copy of the elements in li2\n"; 63 | vector vi(li3.begin(), li3.end()); 64 | cout << "Sorting the vector\n"; 65 | sort(vi.begin(), vi.end()); 66 | for (int i = 0; i < vi.size(); i++) 67 | cout << vi[i] << " "; 68 | cout << endl; 69 | 70 | 71 | // We would like to sort our list the same way, but iterators 72 | // for lists don't behave quite the same way as pointers do or 73 | // as iterators for vectors do. So instead of the generic function call: 74 | // sort(li3.begin(), li3.end()); 75 | // we have to call a member function: 76 | cout << "Sorting list li3:\n"; 77 | li3.sort(); 78 | for (list::iterator iter = li3.begin(); iter != li3.end(); iter++) 79 | cout << *iter << " "; 80 | cout << endl; 81 | 82 | cout << "Reversing list li3:\n"; 83 | li3.reverse(); 84 | for (list::iterator iter = li3.begin(); iter != li3.end(); iter++) 85 | cout << *iter << " "; 86 | cout << endl; 87 | 88 | cout << "Using 'find'. The number 11 is in li3: "; 89 | cout << boolalpha << (find(li3.begin(), li3.end(), 11) != li3.end()) << endl; 90 | cout << "Using 'find'. The number 14 is in li3: "; 91 | cout << boolalpha << (find(li3.begin(), li3.end(), 14) != li3.end())<< endl; 92 | 93 | 94 | 95 | } 96 | -------------------------------------------------------------------------------- /Separate Compilation/Cyclic Association.md: -------------------------------------------------------------------------------- 1 | # Forward Declarations and Cyclic Association for Classes 2 | 3 | ## Forward Declarations 4 | Suppose we wrote a class A as follows: 5 | ```c++ 6 | class A { 7 | private: 8 | B x; 9 | }; 10 | ``` 11 | 12 | What does the compiler need to know about `class B` when it reads this definition of class A? Since the member variable x is of type B, then we *have to know* **how big an object of type B is**. In C++, that means that we have to **define** `class B` first, before we **define** `class A`. 13 | 14 | What about the very similar looking case below: 15 | ```c++ 16 | class C { 17 | private: 18 | D* y; 19 | }; 20 | ``` 21 | What does the compiler need to know here about `class D`? What is the type of member variable y? It is a pointer to D. All pointers are the same size. We don't need to actually know anything about `class D` to know how much space to allow for the member variable y. All we need to know is that D is a *valid type*, not *how* it is defined. How can we say that D is a valid type without actually giving its full definition? 22 | ```c++ 23 | class D; 24 | 25 | class C { 26 | private: 27 | D* y; 28 | }; 29 | ``` 30 | Notice the line: `class D;`. That is a **forward declaration** for a class. It promises that we will define the class D later, but meanwhile the compiler can accept that D is a valid type. This is good enough when all we need to do is declare a pointer to D, but not when we want to create an object of type D. To have an actual object we will have to define D. 31 | 32 | Why bother with all this? Why not just give D's definition, instead of a "forward declaration"? 33 | 34 | ## Cyclic Association 35 | What if the two classes look like: 36 | ```c++ 37 | class D { 38 | private: 39 | C* z; 40 | }; 41 | 42 | 43 | class C { 44 | private: 45 | D* y; 46 | }; 47 | ``` 48 | Now we have a problem. C needs to know something about D and at the same time D needs to know something about C. The solution is to use the forward declaration: 49 | 50 | ```c++ 51 | class C; 52 | 53 | 54 | class D { 55 | private: 56 | C* z; 57 | }; 58 | 59 | 60 | class C { 61 | private: 62 | D* y; 63 | }; 64 | ``` 65 | 66 | Remember, the forward delaration does not tell us anything more than the fact that the name *will* be defined as a type. It does not tell us how big an object would be. And it does not tell us what members (variables or functions), the class has. 67 | 68 | How will that make a difference? Suppose we add a couple of functions to these classes: 69 | 70 | ```c++ 71 | class C; 72 | 73 | 74 | class D { 75 | public: 76 | void dFunc() { z->cFunc(); } 77 | private: 78 | C* z; 79 | }; 80 | 81 | 82 | class C { 83 | public: 84 | void cFunc() { } 85 | private: 86 | D* y; 87 | }; 88 | ``` 89 | Now the compiler is going to be unhappy again. Why? Because the function definition for `dFunc` is calling the member function `cFunc`. But no one has told the compiler yet that there even is such a member function! The compiler won't know that until it sees the actual class definition for the class C. How can we fix this? Well, it would fix itself if we were already using separate compilation. How? Let's move the *definition* of the member function `dfunc` till *after* we the defintion for the class C. 90 | 91 | ```c++ 92 | class C; 93 | 94 | 95 | class D { 96 | public: 97 | void dFunc(); 98 | private: 99 | C* z; 100 | }; 101 | 102 | 103 | class C { 104 | public: 105 | void cFunc() { } 106 | private: 107 | D* y; 108 | }; 109 | 110 | 111 | void D::dFunc() { z->cFunc(); } 112 | ``` 113 | 114 | How does this fix anything? Now when the compiler reads the definition of the class D, it sees a *prototype* for `dFunc`, not the whole definition. In particular, it does not see that function call to `cFunc`. We have moved `dFunc`'s definition with the call to `cFunc` till *after* Class C's definition. Finally the compiler is happy. And we can go do something more entertaining than worrying about keeping compilers happy. 115 | -------------------------------------------------------------------------------- /Separate Compilation/Include Guards.md: -------------------------------------------------------------------------------- 1 | # Include Guard 2 | Include Guards (also sometimes called macroguards) are used to prevent functions, classes and other symbols from being declared more than once. Remember that if C++ comes across a symbol being declared a second time then it will flag that second declaration as an error. Classes are usually declared in header files and sometimes a header file gets included more than once. The second time you include the header file, the class that is declared inside it will be declared again. 3 | 4 | Suppose you have a class, Person, that you have declared in a file called Person.h. You would like to be able to include Person.h in your code without having to think if it has already been included. That's where the include guard comes in. An include guard consists of three lines: 5 | 6 | ```c++ 7 | #ifndef ... 8 | #define ... 9 | #endif 10 | ``` 11 | I have used "..." to refer to some identifier name that we will fill in later. 12 | 13 | The command "#ifndef" means "if ... is not defined". If it is already defined then every line of code up till the line "#endif" will be completely ignored by the compiler. 14 | 15 | The command "#define ..." defines the identifier that we use instead of "...". What does it define it as? In this case we are only saying that the identifier *exists*, or in other words that it has been defined. The value doesn't matter and since we never intend to refer to its value, we don't bother to specify one. I figure if I did specify a value then someone might become confused and wonder why we picked that value instead of some other value. 16 | 17 | The third line, which would come at the end of your file, is used to end the "if" that was used in the "#ifndef" line. 18 | 19 | The next question is, what should be put in place of "..." in lines 1 & 2? Any symbol name at all could be used. But it should be a symbol that `isn't being used anywhere else`. What could we use? Well, a name based on the file name would seem a good choice. For example, we might choose `PERSON_H`. We used the underscore character ("_") instead of the period (".") since identifiers can't have a period in them. We used capital letters just because that's the accepted tradition when declaring any constant symbol. 20 | 21 | Therefore the header file Person.h, might look something like this: 22 | ```c++ 23 | #ifndef PERSON_H 24 | #define PERSON_H 25 | class Person { 26 | // The rest of the definition of the Person class would go here. 27 | }; 28 | #endif 29 | ``` 30 | A common programming error is to use the same symbol in more than one file. Be careful and don't do it. What kind of error would be caused? Suppose we already included in a *different* file that also started with the lines: 31 | ```c++ 32 | #ifndef PERSON_H 33 | #define PERSON_H 34 | ``` 35 | and then we try to include our Person.h header file. This time the class Person will not get defined. Any code in the ".cpp" file which refers to the Person class will get an error indicating that the Person class is undefined. 36 | -------------------------------------------------------------------------------- /Separate Compilation/code snippets/Date.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | file: Date.cpp 3 | */ 4 | 5 | #include "Date.h" 6 | #include 7 | #include // atoi. Note we also get it from string. 8 | 9 | // When we're not in a header file, it is ok to 10 | // have "using namespace std" 11 | using namespace std; 12 | 13 | Date::Date(const string& date) { 14 | // atoi comes 15 | month = atoi(date.substr(0,2).c_str()); 16 | day = atoi(date.substr(3,2).c_str()); 17 | year = atoi(date.substr(6,4).c_str()); 18 | } 19 | void Date::display(std::ostream& os) const { 20 | os << month << '/' << day << '/' << year; 21 | } 22 | bool Date::earlierThan(Date d) const { 23 | if (year > d.year) return false; 24 | else if (year < d.year) return true; 25 | else if (month > d.month) return false; 26 | else if (month < d.month) return true; 27 | else if (day >= d.day) return false; 28 | else return true; 29 | } 30 | int Date::getYear() const { return year; } 31 | 32 | void Date::setYear(int x) { year = x; } -------------------------------------------------------------------------------- /Separate Compilation/code snippets/Date.h: -------------------------------------------------------------------------------- 1 | #ifndef DATE_H 2 | #define DATE_H 3 | // This use of #ifndef, #define and #endif is called "an include 4 | // guard". It avoids problems with people including header files 5 | // more than once and then having symbols defined more than once. 6 | #include 7 | #include 8 | // Note that in header files its considered bad form to have 9 | // "using namespace std;" 10 | 11 | class Date { 12 | public: 13 | // Since we don't have "using namespace std;" 14 | // we have to qualify the symbol "string" to show 15 | // that it comes from the std namespace. 16 | Date(const std::string& date); 17 | void setYear(int y); 18 | 19 | int getYear() const; 20 | 21 | void display(std::ostream& = std::cout) const; 22 | bool earlierThan(Date) const; 23 | int daysBetween(Date) const; // We haven't implemented this yet 24 | void addDays(int days); // We haven't implemented this yet 25 | 26 | private: 27 | int day, month, year; 28 | }; 29 | 30 | // This endif matches up with the ifndef above. 31 | #endif -------------------------------------------------------------------------------- /Separate Compilation/code snippets/dateWithNamespace.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/Separate Compilation/code snippets/dateWithNamespace.cpp -------------------------------------------------------------------------------- /Separate Compilation/code snippets/dateWithNamespace.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/Separate Compilation/code snippets/dateWithNamespace.h -------------------------------------------------------------------------------- /Separate Compilation/code snippets/testDate.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Example of very basic class using separate compilation. 3 | John Sterling 4 | CS1124 5 | Polytechnic University 6 | */ 7 | 8 | // This is the same code as was used in the earlier program to implement 9 | // and test the Date class, except that the class definition was moved 10 | // to the header file Date.h and the implementations of Date's member 11 | // functions have been moved to Date.cpp. 12 | 13 | // Comments have generally been removed these files if they don't relate 14 | // to separate compilation. 15 | 16 | #include "Date.h" 17 | #include 18 | #include 19 | using namespace std; 20 | 21 | 22 | int main() { 23 | 24 | Date d1("03/14/1592"); 25 | cout << "d1's year is: " << d1.getYear() << endl; 26 | cout << "Change d1's year to 17\n"; 27 | d1.setYear(17); 28 | cout << "Checking d1's year: " << d1.getYear() << endl; 29 | cout << "Displaying d1: "; 30 | d1.display(); 31 | cout << endl; 32 | cout << "Displaying d2: "; 33 | Date d2("11/23/5813"); 34 | d2.display(); 35 | cout << endl; 36 | cout << "Is date d1 earlier than date d2?\n"; 37 | if (d1.earlierThan(d2)) 38 | cout << "Yes\n"; 39 | else 40 | cout << "No\n"; 41 | } 42 | -------------------------------------------------------------------------------- /Separate Compilation/code snippets/testDateWithNamespace.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/Separate Compilation/code snippets/testDateWithNamespace.cpp -------------------------------------------------------------------------------- /Template/Convert Vector Class to Template.md: -------------------------------------------------------------------------------- 1 | # Converting the Vector class to a Vector Template class. 2 | 3 | 1. Add the template header: 4 | ```c++ 5 | template 6 | ``` 7 | just before the class definition. The word "template" is a keyword and so is "class". Instead of "class", the language allows you to use "typename", so you may come across either one when reading code. "T" is a totally arbitrary choice for the name of the type that we are using. It is very common for people to use "T", but you could use "SLUG" or "slug" just as well. 8 | 2. Change the type of the member data from `int*` to `T*`. This is the data type that the Vector depends on and the main point of converting to a template class. 9 | 3. Look for other uses of int to replace them with `T`. 10 | * Change the return types in the two versions of operator[] from `int&` to `T&` 11 | 4. Copy and paste *all* the function definitions from Vector.cpp to the end of Vector.h. 12 | 13 | 14 | Every function needs to be examined for changes. Here I have described the kinds of changes that have to be made and which functions they apply to. 15 | 16 | 1. Add the template header. 17 | ```c++ 18 | template 19 | ``` 20 | in front of every function definition. (Sorry for being boring and using "T". Not everyone likes SLUGs.) 21 | 22 | 2. Replace "`Vector::`" with "`Vector::`" throughout the file. 23 | 3. You do not have to change parameter types passed to member functions, because the use of `Vector::` already tells the compiler that we will be using a parameterized type for Vector throughout the *rest* of the function. 24 | 4. However, non-member functions need to have their parameter types qualified: 25 | * In the input/output operators change the parameter from `Vector` to `Vector`. 26 | 5. Also the *return type* for the assignment operator must be qualified as it is not 6. within the scope of the qulified function name. 27 | 1. Look for other uses of "int" that need to change to "T". 28 | 1. Check any use of `int*` 29 | * the `resize` function. 30 | 1. Check any use of `new int` for functions where an array of ints is being created 31 | * constructors 32 | * resize function 33 | * assignment operator 34 | 1. Change the return type for the const `operator[]` from `int` to `T`. 35 | 1. Change the return type for the non-const `operator[]` and `int&` to `T&`. 36 | 1. Be careful *not* to change any use of int that is used for other purposes such as an index for an array or the size of the Vector. (It would have been better if we'd used size_t for all these, but we haven't been. Oh, well.) 37 | 38 | ### In TestVector.cpp 39 | 40 | Change "`Vector`" to "`Vector`" when defining the vectors `v` and `w`. 41 | 42 | ### Finally 43 | 44 | 1. ReBuild the project. You will get several errors for the compilation of Vector.cpp. That's ok, we'll get rid of them right now: 45 | * In the VC++'s Solution Explorer select the file Vector.cpp and hit the delete key because we do not want it in the project anymore. Don't worry the file wasn't deleted, in case you still want it for some reason. It's just been removed from the project. 46 | 47 | That completes all the changes necessary. We can now create Vectors of any type we wish without any further changes. -------------------------------------------------------------------------------- /Template/code snippets/Vector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Vector.h" 3 | using namespace std; 4 | using namespace CS1124; 5 | 6 | int main() { 7 | // Define a vector of five elements. 8 | Vector v(5); 9 | 10 | cout << "Setting v to a sequence of squares." << endl; 11 | 12 | for (int i = 0; i < 5; i++) 13 | v[i] = i * i; 14 | cout << "v = " << v << endl; 15 | 16 | cout << "Initializing w with the copy constructor" << endl; 17 | Vector w = v; 18 | 19 | cout << "v = " << v << endl; 20 | cout << "w = " << w << endl; 21 | cout << endl; 22 | 23 | cout << "v[0] = 17;" << endl; 24 | v[0] = 17; 25 | cout << "v = " << v << endl; 26 | cout << "w = " << w << endl; 27 | cout << endl; 28 | 29 | cout << "w = v;" << endl; 30 | w = v; 31 | cout << "v = " << v << endl; 32 | cout << "w = " << w << endl; 33 | cout << endl; 34 | 35 | // We'll make w a little larger and see what happens. We should get "garbage" 36 | // in the new entries. 37 | w.resize(6); 38 | cout << "w.resize(6)\n" << w << endl; 39 | // Trying to resize v a smaller size should have no effect. 40 | v.resize(2); 41 | cout << "v.resize(2)\nWe hope nothing changes because we don't support resizing 'down'.\n" << v << endl; 42 | 43 | return 0; 44 | } -------------------------------------------------------------------------------- /Template/code snippets/Vector.h: -------------------------------------------------------------------------------- 1 | #ifndef VECTOR_H 2 | #define VECTOR_H 3 | #include 4 | 5 | namespace CS1124 { 6 | 7 | template 8 | class Vector { 9 | 10 | // Within the class definition, any use of "Vector" as a class 11 | // will be understood by the compiler to mean "Vector". 12 | // Examples are the second parameter to the << operator 13 | // and the parameter to the copy constructor. In any such case 14 | // you can write "Vector" or "Vector" -- both are correct. 15 | 16 | template 17 | friend std::ostream& operator<< (std::ostream&, const Vector&); 18 | public: 19 | //CONSTRUCTORS 20 | Vector(); // Default Constructor 21 | Vector(const Vector&); // Copy Constructor 22 | Vector(int); // Create a vector of a particular size 23 | 24 | // DESTRUCTOR 25 | ~Vector(); 26 | 27 | // Change the size of the Vector. 28 | // If newSize is smaller than the current size, 29 | // we will not do anything. 30 | void resize(int newSize); 31 | 32 | // Assignment operator 33 | // C++ requires that it be a member function. 34 | Vector& operator=(const Vector&); 35 | // [] operator. 36 | // C++ requires that it be a member function. 37 | // The reference return type is to allow us to assign to it. 38 | T& operator[](int i); 39 | T operator[] (int i) const; 40 | private: 41 | int size; 42 | T * data; 43 | }; 44 | 45 | // Note the use of the member initialization list. 46 | template 47 | Vector::Vector() : size (4), data (new T[size]) { 48 | } 49 | 50 | template 51 | Vector::Vector(int s) : size (s), data (new T[size]){ 52 | } 53 | 54 | // Copy Constructor 55 | // Note the type of the parameter. 56 | // Any use of Vector with the scope of the 57 | // function name (qualified with Vector) 58 | // is assumed to mean Vector 59 | template 60 | Vector::Vector(const Vector& v) { 61 | size = v.size; 62 | data = new T[size]; 63 | for (int i = 0; i < size; i++) 64 | data[i] = v.data[i]; 65 | } 66 | 67 | // Destructor 68 | template 69 | Vector::~Vector() { 70 | delete [] data; 71 | } 72 | 73 | // Change the size of the Vector. 74 | // If newSize is not larger than the current size, 75 | // we will not do anything. 76 | template 77 | void Vector::resize(int newSize) { 78 | if (newSize > size) { 79 | T* newData = new T[newSize]; 80 | for (int i = 0; i < size; ++i) 81 | newData[i] = data[i]; 82 | delete [] data; 83 | data = newData; 84 | size = newSize; 85 | } 86 | } 87 | 88 | 89 | // Assignment operator. 90 | // MUST BE defined as a member function. 91 | // The text chooses to return void, however it is 92 | // the usual practice to return a reference to the 93 | // class. 94 | template 95 | // Note that the return type is NOT IN THE SCOPE of the function name, 96 | // so we have to put Vector instead of just Vector. 97 | Vector& Vector::operator=(const Vector& right) { 98 | // Assignment operators should begin 99 | // with a check that you're not being 100 | // asked to do a "self-assignment" as in: 101 | // x = x; 102 | // Here we look to see if the "this" pointer 103 | // contains the same address as the address 104 | // of the argument. 105 | if (this != &right) { 106 | if (size != right.size) { 107 | // if our target array isn't the same size 108 | // as the target's, then we delete ours and 109 | // get one that is the correct size. 110 | delete [] data; 111 | size = right.size; 112 | data = new T[size]; 113 | } 114 | for (int i = 0; i < size; i++) 115 | data[i] = right.data[i]; 116 | } 117 | return *this; 118 | } 119 | 120 | // operator<< is printing a ", " after each element in 121 | // the Vector except for the last. 122 | template 123 | std::ostream& operator<< (std::ostream& os, const Vector& v) { 124 | for (int i = 0; i < v.size; i++) { 125 | os << v.data[i]; 126 | if (i < v.size - 1) os << ", "; 127 | } 128 | return os; 129 | } 130 | 131 | template 132 | T& Vector::operator[] (int index) { 133 | return data[index]; 134 | } 135 | template 136 | T Vector::operator[] (int index) const { 137 | return data[index]; 138 | } 139 | } 140 | #endif -------------------------------------------------------------------------------- /Template/code snippets/maximum.h: -------------------------------------------------------------------------------- 1 | // File: maximum.h 2 | 3 | // We need the template header immediately before every 4 | // template function. 5 | template 6 | // For the function maximum, the return type and the types 7 | // for both the parameters are the same. 8 | // Note that the "greater than" operator (i.e., operator>) *must* be 9 | // overloaded in any class that you want to use the maximum function on. 10 | T maximum(const T& a, const T& b) { 11 | if (a > b) 12 | return a; 13 | else 14 | return b; 15 | } -------------------------------------------------------------------------------- /homeworks/hw03/hw03.md: -------------------------------------------------------------------------------- 1 | # Homework 3: Encapsulation, Data Hiding, Delegation. Operator Overloading 2 | ## Focus: 3 | * Object-oriented programming 4 | * Data Hiding 5 | * Encapsulation 6 | * Delegation 7 | * Operator Overloading 8 | ## Problem: 9 | We will expand our Warrior a little. Each Warrior will have a weapon. He is "born" with it, i.e. the weapon is created together with the warrior. It can only be accessed by him. It provides him with his strength. In battle, weapons lose their edge and weaken. When a Warrior's weapon loses all of its strength, the Warrior himself dies. 10 | 11 | ## Implementation 12 | * Remember that we are using *data hiding*. Therefore, every field, aka member variable, must be private. 13 | * What are the types of things in the problem? We will need a class for each type. 14 | * What do the things / types *do*? These "behaviors" should be represented as *methods*. 15 | * Weapons have both a name and a strength. The weapon is created together with the Warrior and cannot be accessed by anyone else. 16 | * Note that the input file changed a little, compared to the previous assignment. When a Warrior is created, instead of simply specifying his name and strength, the Warrior command specifies the Warrior's name as well as his Weapon's name and *its* strength. 17 | * The Status report will is also modified to show the name of the Warrior's Weapon. 18 | * No one can access a warrior's weapon except the warrior himself. But the weapon is what actually holds the warrior's strength. How does this effect the programming? Any time the code needs to know or change the warrior's strength, the warrior then "asks" the weapon what the strength is or tells the weapon that the strength needs to be changed. This represents the idea of *delegation*. We will see this concept frequently, where one object requests that another object do some task. 19 | * It is in fact unnecessary for any code other than a Warrior to even know about the Weapon. We will enforce this by *nesting* the definition of the Weapon class inside the Warrior class. To make sure that no code other than Warrior's makes use of Weapon, we need to make the class private. 20 | * One last implementation detail. to display the information about an object, whether it is a warrior or a weapon, we will use that object's output operator. 21 | 22 | ## Input 23 | Our sample input file might now look like: 24 | ``` 25 | Warrior Jim Glamdring 42 26 | Warrior Lancelot Naegling 15 27 | Warrior Arthur Excalibur 15 28 | Warrior Torvalds Narsil 20 29 | Warrior Gates Orcrist 8 30 | Status 31 | Battle Arthur Lancelot 32 | Battle Jim Lancelot 33 | Battle Torvalds Gates 34 | Battle Gates Lancelot 35 | Status 36 | ``` 37 | ## Output 38 | The corresponding output would be: 39 | ``` 40 | There are: 5 warriors 41 | Warrior: Jim, weapon: Glamdring, 42 42 | Warrior: Lancelot, weapon: Naegling, 15 43 | Warrior: Arthur, weapon: Excalibur, 15 44 | Warrior: Torvalds, weapon: Narsil, 20 45 | Warrior: Gates, weapon: Orcrist, 8 46 | Arthur battles Lancelot 47 | Mutual Annihilation: Arthur and Lancelot die at each other's hands 48 | Jim battles Lancelot 49 | He's dead, Jim 50 | Torvalds battles Gates 51 | Torvalds defeats Gates 52 | Gates battles Lancelot 53 | Oh, NO! They're both dead! Yuck! 54 | There are: 5 warriors 55 | Warrior: Jim, weapon: Glamdring, 42 56 | Warrior: Lancelot, weapon: Naegling, 0 57 | Warrior: Arthur, weapon: Excalibur, 0 58 | Warrior: Torvalds, weapon: Narsil, 12 59 | Warrior: Gates, weapon: Orcrist, 0 60 | ``` 61 | ## Notes 62 | Remember this program is *significantly* different than the prior assignment, which did not use any OOP techniques. Some functions that existed in the previous assignment may now be methods. And displaying information about an object will now be done through its class's output operator. 63 | 64 | ## Turn in 65 | Hand in a single cpp file, hw02.cpp, containing your program. -------------------------------------------------------------------------------- /homeworks/hw04/hw04.md: -------------------------------------------------------------------------------- 1 | # Homework 4 2 | ## Focus 3 | * Classes 4 | * Association 5 | * As always: good coding 6 | ## Problem: 7 | We will [continue to] model a game of medieval times. Our world is filled with not only warriors but also nobles. Nobles don't have much to do except do battle with each other. (We'll leave the feasting and other entertainments for add-ons.) Warriors don't have much to do except hire out to a noble and fight in his behalf. Of course the nobles are pretty wimpy themselves and will lose if they don't have warriors to defend them. How does all this work? 8 | 9 | * Warriors start out with a specified strength. 10 | * A battle between nobles is won by the noble who commands the stronger army. 11 | * The army's strength is simply the combined strengths of all its warriors. 12 | * A battle is to the death. The losing noble dies as does his warriors. 13 | * The winner does not usually walk away unscarred. All his men lose a portion of their strength equal to the ratio of the enemy army's combined strenth to their army's. If the losing army had a combined strength that was 1/4 the size of the winning army's, then each soldier in the winning army will have their own strength reduced by 1/4. 14 | 15 | ### Hiring and Firing 16 | 17 | * Warriors are hired and fired by Nobles. Lack of adequate labor laws, have left the Warriors without the ability to quit, nor even to have a say on whether or not a Noble can hire them. 18 | * However it is possible that an attempt to hire or fire may fail. Naturally the methods should not "fail silently". Instead, they will return true or false depending on whether they succeed or not. 19 | * A Warrior can only be employed by one Noble at a time and cannot be hired away if he is already employed. 20 | * As noted below, Nobles who are dead can neither hire nor fire anyone. (Note this will implicitly prevent dead Warriors from being hired.) 21 | * When a warrior is fired, he is no longer part of the army of the Noble that hired him. He is then free to be hired by another Noble. 22 | * How do you remove something from a vector. 23 | * While there are techniques that make use of iterators, we have not yet discussed iterators so you will not use them here. (As a heads up, if you see a technique that requires you to call a vector's begin() method, that is using iterators. Don't use it.) 24 | * While it may seem a slight burden, certainly it does not require more than a simple loop to remove an item from a vector. No do not do something silly like create a whole new vector. 25 | * Soon we will cover iterators and then you will be freed from these constraints. Patience, please. 26 | 27 | ## Death 28 | It's a sad topic, but one we do have to address. 29 | 30 | * People die when they lose a battle, whether they are a Nobles or Warriors. 31 | * Nobles who are dead are in no position to hire or fire anyone. Any attempt by a dead Lord to hire someone will simply fail and the Warrior will remain unhired. 32 | * However curiously, as has been seen before, Nobles can declare battle even though they are dead. 33 | * Note that when a Noble is created he does not have any strength. At the same time he is obviously alive. So lack of strength and being dead are clearly not equivalent. 34 | 35 | A test program and output are attached. Note that the output shown is what you are **expected** to generate. Pardon us, we don't like limiting your creativity, but having your output consistent with ours makes the first step of grading a bit easier. And also helps you to be more confident that your code works. 36 | 37 | ## Programming Constraints 38 | What would a homework assignment be without unnecessary and unreasonable constraints? 39 | 40 | Your classes must satisfy the following: 41 | 42 | * The battle method will announce who is battling whom, and the result (as shown in the example output). 43 | * If one or both of the nobles is already dead, just report that. 44 | * The "winner" doesn't win anything for kicking around a dead guy. And his warriors don't use up any strength. 45 | * Look at the output for the sample test program to see what you should be displaying. 46 | * A noble's army is a **vector of pointers to warriors**. Warriors will be ordered in the army by the order in which they were hired. That affects how you remove a Warrior thatgets fired. 47 | 48 | ## And some things to make life easier 49 | Just in case you are confused, let me point out that this problem does not involve the use of the heap. That means your program will not make use of the operator `new` or the operator `delete`. 50 | 51 | ## Turn in 52 | Hand in the file named hw04.cpp. -------------------------------------------------------------------------------- /homeworks/hw06/hw06.md: -------------------------------------------------------------------------------- 1 | # Homework 6: Cyclic Association and Separate Compilation 2 | ## Focus 3 | * Cyclic Association 4 | * Operator overloading 5 | * Separate compilation 6 | * Namespace 7 | ## Problem: 8 | We are revisiting the world of Nobles and Warriors (hoping you aren't sick of it...), now adding one new feature: not only can warriors be fired, they can also runaway!!! Of course, when a warrior runs away, he has to inform his noble. Which means the warrior has to know who hired him and be able to communicate with him. Which means, obviously, that he will need a pointer to his noble. Good thing we learned about forward class declarations! 9 | 10 | You will also: 11 | 12 | * Place all method definition outside of the their classes 13 | * Use separate compilation for all methods, giving each class its own header and implementation files. 14 | * Yes, this item implies the first. But if you haven't covered separate compilation yet, you can do most of the work but just handling the first bullet for now. The rest should get covered sufficiently before the due date. 15 | * Place the code in the WarriorCraft namespace. 16 | 17 | ## Test Code and Output 18 | Below is a test program and its output. The only change in the test program from the one in hw04 is that cheetah runs away, rather than getting fired. (Yes, a noble should still be able to fire a warrior.) The output should also only be different in the one line of output corresoponding to cheetal running away. 19 | ```c++ 20 | #include "Noble.h" 21 | #include "Warrior.h" 22 | #include 23 | #include 24 | #include 25 | using namespace std; 26 | using namespace WarriorCraft; 27 | 28 | int main() { 29 | Noble art("King Arthur"); 30 | Noble lance("Lancelot du Lac"); 31 | Noble jim("Jim"); 32 | Noble linus("Linus Torvalds"); 33 | Noble billie("Bill Gates"); 34 | 35 | Warrior cheetah("Tarzan", 10); 36 | Warrior wizard("Merlin", 15); 37 | Warrior theGovernator("Conan", 12); 38 | Warrior nimoy("Spock", 15); 39 | Warrior lawless("Xena", 20); 40 | Warrior mrGreen("Hulk", 8); 41 | Warrior dylan("Hercules", 3); 42 | 43 | jim.hire(nimoy); 44 | lance.hire(theGovernator); 45 | art.hire(wizard); 46 | lance.hire(dylan); 47 | linus.hire(lawless); 48 | billie.hire(mrGreen); 49 | art.hire(cheetah); 50 | 51 | cout << jim << endl; 52 | cout << lance << endl; 53 | cout << art << endl; 54 | cout << linus << endl; 55 | cout << billie << endl; 56 | 57 | cheetah.runaway(); 58 | cout << art << endl; 59 | 60 | art.battle(lance); 61 | jim.battle(lance); 62 | linus.battle(billie); 63 | billie.battle(lance); 64 | } 65 | ``` 66 | ### Output 67 | ``` 68 | Jim has an army of 1 69 | Spock: 15 70 | Lancelot du Lac has an army of 2 71 | Conan: 12 72 | Hercules: 3 73 | King Arthur has an army of 2 74 | Merlin: 15 75 | Tarzan: 10 76 | Linus Torvalds has an army of 1 77 | Xena: 20 78 | Bill Gates has an army of 1 79 | Hulk: 8 80 | Tarzan flees in terror, abandoning his lord, King Arthur 81 | King Arthur has an army of 1 82 | Merlin: 15 83 | King Arthur battles Lancelot du Lac 84 | Mutual Annihalation: King Arthur and Lancelot du Lac die at each other's hands 85 | Jim battles Lancelot du Lac 86 | He's dead, Jim 87 | Linus Torvalds battles Bill Gates 88 | Linus Torvalds defeats Bill Gates 89 | Bill Gates battles Lancelot du Lac 90 | Oh, NO! They're both dead! Yuck! 91 | ``` 92 | ## Turn in 93 | Five files: Noble.h, Noble.cpp, Warrior.h, and Warrior.cpp and also (for the grader's convenience) the above test program as hw05.cpp. No don't zip them, NYU Classes handles multiple-file submissions just fine. -------------------------------------------------------------------------------- /homeworks/hw08/hw08.md: -------------------------------------------------------------------------------- 1 | # Homework 8: Linked lists 2 | ## Focus: 3 | * Linked Lists 4 | * Operator Overloading 5 | * Copy control 6 | * Separate compilation 7 | 8 | ## Problem: 9 | You will implement a class `Polynomial` for storing and manipulating polynomial expressions. A polynomial is an expression of the form 10 | 11 | ## akxk + ... + a2x2 + a1x + a0 12 | 13 | The number k is called the **degree of the polynomial** and the numbers a0, ..., ak are called the **coefficients**. 14 | 15 | Store each polynomial as a degree and a **singly linked list** of its coefficients, but "backwards", i.e. with the lowest degree coefficient first. (Backwards makes your program easier!) **Do NOT use a doubly linked list in this assignment**! 16 | 17 | For example, the polynomial 4x3 + x + 7 would be stored as: 18 | ``` 19 | head_ptr --> 7 --> 1 --> 0 --> 4 20 | degree: 3 21 | ``` 22 | Here the constant term, 7, is first, then the linear (x) term, 1, then the quadratic (x2) term, 0, and finally the highest degree term with a coefficient of 4. In addition, the degree of the polynomial, 3, is stored in the member variable degree. 23 | 24 | Storing the polynomials in this order, rather than in the order in which we normally write them, will make it easier to perform arithmetic operations. 25 | 26 | The class *invariant* (i.e., the thing that must be true about the class whenever a member function is *finished* making changes) is: 27 | 28 | 1. The coefficients are stored in a linked list with the constant term at the front of the list and the highest order term at the end of the list. 29 | 1. The zero polynomial is represented by a list with a single item, zero. The degree of the zero polynomial is 0. 30 | 1. The list for a non-zero polynomial does not end with a zero coefficient. (In other words, the highest degree coefficient is only zero if this is the zero polynomial.) 31 | 1. The value of the degree member variable is one less than the length of the list. 32 | 33 | ### What you have to handle: 34 | 35 | * constructor that takes a vector of its coefficients in order from highest degree term to lowest 36 | * `+=` 37 | * `+` 38 | * copy control, i.e. destructor, copy constructor and assignment operator 39 | * `==` 40 | * `!=` 41 | * `<<` Use the caret ^ for exponentiation. So: 5x3 represents five times the term with an exponent of three. 42 | * evaluation. Takes a single argument and evaluates the polynomial for that value of "X". 43 | 44 | ## Notes 45 | * Coefficients can be either ints or doubles, as you prefer. 46 | * Feel free to make your life easier by using the linked list code that we developed. Include the Node struct definition and function prototypes in your polynomial.h and the function implementations in polynomial.cpp. 47 | 48 | **Test program**: attached is a test program. Feel free to expand on it. You may not be familiar with all of the syntax used in this program. 49 | 50 | * boolalpha. This manipulator tells the output stream that when it is printing a bool value, true or false, to print it that way, i.e. as the strings "true" and "false". Without this manipulator, C++ will print true as 1 and false as 0. 51 | * {2, 4, 8}. The use of braces around a comma-delimited sequence of values can be used to initialize a vector to hold that sequence of values. Please note that this use of braces requires C++11. 52 | 53 | **What to hand in:** 54 | 55 | Header and implementation files for polynomial (polynomial.h and polynomial.cpp). 56 | 57 | ### Additional resources for assignment 58 | * [outputNew.txt](./outputNew.txt) 59 | * [testPolynomial.cpp](./testPolynomial.cpp) -------------------------------------------------------------------------------- /homeworks/hw08/outputNew.txt: -------------------------------------------------------------------------------- 1 | p1: 17 2 | p2: x + 2 3 | p3: -1x + 5 4 | p4: 5x^4 + 4x^3 + 3x^2 + 2x + 1 5 | has_a_zero: 4x^3 + x + 7 6 | p2 + p3: 7 7 | p2 + p4: 5x^4 + 4x^3 + 3x^2 + 3x + 3 8 | p4 + p2: 5x^4 + 4x^3 + 3x^2 + 3x + 3 9 | Polynomial p5(p4); 10 | p5 += p3; 11 | p4: 5x^4 + 4x^3 + 3x^2 + 2x + 1 12 | p5: 5x^4 + 4x^3 + 3x^2 + x + 6 13 | Calling doNothing(p5) 14 | p5: 5x^4 + 4x^3 + 3x^2 + x + 6 15 | p6: 0 16 | (p4 == p6) is false 17 | p6: 5x^4 + 4x^3 + 3x^2 + 2x + 1 18 | (p4 == p6) is true 19 | Evaluating p1 at 5 yields: 17 20 | Evaluating p2 at 5 yields: 7 21 | p7: 3x^2 + 2x + 1 22 | Evaluating p7 at 5 yields: 86 23 | (p1 == p2) is false 24 | (p1 != p2) is true 25 | ((p8 + p9) == p10) is true -------------------------------------------------------------------------------- /homeworks/hw08/testPolynomial.cpp: -------------------------------------------------------------------------------- 1 | #include "polynomial.h" 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | void doNothing(Polynomial temp) {} 7 | 8 | int main() { 9 | 10 | //test constructor 11 | Polynomial p1({17}); // 17 12 | Polynomial p2({1, 2}); // x + 2 13 | Polynomial p3({-1, 5}); // -1x + 5 14 | Polynomial p4({5, 4, 3, 2, 1}); // 5x^4 + 4x^3 + 3x^2 + 2x + 1 15 | Polynomial has_a_zero({4, 0, 1, 7}); // 4x^3 + x + 7 16 | 17 | cout << "p1: " << p1 << endl; 18 | cout << "p2: " << p2 << endl; 19 | cout << "p3: " << p3 << endl; 20 | cout << "p4: " << p4 << endl; 21 | cout << "has_a_zero: " << has_a_zero << endl; 22 | cout << "p2 + p3: " << (p2+p3) << endl; 23 | cout << "p2 + p4: " << (p2+p4) << endl; 24 | cout << "p4 + p2: " << (p4+p2) << endl; 25 | 26 | 27 | //test copy constructor - the statement below uses the copy constructor 28 | //to initialize poly3 with the same values as poly4 29 | Polynomial p5(p4); 30 | p5 += p3; 31 | cout << "Polynomial p5(p4);\n" 32 | << "p5 += p3;\n"; 33 | 34 | cout << "p4: " << p4 << endl; 35 | cout << "p5: " << p5 << endl; 36 | 37 | cout << "Calling doNothing(p5)\n"; 38 | doNothing(p5); 39 | cout << "p5: " << p5 << endl; 40 | 41 | //tests the assignment operator 42 | Polynomial p6; 43 | cout << "p6: " << p6 << endl; 44 | cout << boolalpha; // Causes bools true and false to be printed that way. 45 | cout << "(p4 == p6) is " << (p4 == p6) << endl; 46 | p6 = p4; 47 | cout << "p6: " << p6 << endl; 48 | cout << boolalpha; 49 | cout << "(p4 == p6) is " << (p4 == p6) << endl; 50 | 51 | //test the evaluaton 52 | int x = 5; 53 | cout << "Evaluating p1 at " << x << " yields: " << p1.evaluate(5) << endl; 54 | cout << "Evaluating p2 at " << x << " yields: " << p2.evaluate(5) << endl; 55 | 56 | Polynomial p7({3, 2, 1}); // 3x^2 + 2x + 1 57 | cout << "p7: " << p7 << endl; 58 | cout << "Evaluating p7 at " << x << " yields: " << p7.evaluate(5) << endl; 59 | 60 | cout << boolalpha; 61 | cout << "(p1 == p2) is " << (p1 == p2) << endl; 62 | cout << "(p1 != p2) is " << (p1 != p2) << endl; 63 | 64 | /*================================================================= 65 | NEW TEST CODE - test if cleaning the leading 0s 66 | ===================================================================*/ 67 | 68 | Polynomial p8({ 1, 1 }); 69 | Polynomial p9({ -1, 1 }); 70 | Polynomial p10({ 0, 0, 2 }); 71 | //p8 + p9 tests if += does the cleanup() 72 | //p10 tests if constructor does the cleanup() 73 | cout << "((p8 + p9) == p10) is " << ((p8 + p9) == p10) << endl; 74 | 75 | 76 | } 77 | 78 | 79 | -------------------------------------------------------------------------------- /recitations/rec01/Recitation 1 notes on input filesV2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/recitations/rec01/Recitation 1 notes on input filesV2.pdf -------------------------------------------------------------------------------- /recitations/rec01/jabberwocky: -------------------------------------------------------------------------------- 1 | Twas brillig and the slithey toves 2 | did gyre and gymble in the wabe. 3 | All mimsy were the borogroves 4 | and the momeraths outgrabe. 5 | 6 | Beware the Jabberwock, my son! 7 | The jaws that bite, the claws that catch! 8 | Beware the JubJub bird and shun 9 | The furmious Bandersnatch! 10 | 11 | He took his vorpal sword in hand. 12 | Long time the manxome foe he sought 13 | So, rested he by the TumTum tree 14 | And stood a while in thought. 15 | 16 | And as in uffish thought he stood, 17 | The Jabberwock with eyes of flame 18 | Came whiffling through the tulgey wood 19 | And burbled as it came. 20 | 21 | One two, one two, and through and through 22 | His vorpal blade went snicker snack. 23 | He left it dead and with its head 24 | He went gallumphing back. 25 | 26 | And hast thou slain the Jabberwock? 27 | Come to my arms, my beamish boy 28 | Callou, Callay, oh frabjous day 29 | He chortled in his joy. 30 | 31 | Twas brillig and the slithey toves 32 | did gyre and gymble in the wabe. 33 | All mimsy were the borogroves 34 | and the momeraths outgrabe. 35 | -------------------------------------------------------------------------------- /recitations/rec01/rec01.md: -------------------------------------------------------------------------------- 1 | # Recitation 01 - C++ Basics 2 | ## Topics 3 | * strings, vectors, I/O 4 | ## Task 5 | Some recitations, aka *labs*, will follow a "tutorial" style. Others, such as this one, will present you with a program to write. Regardless of the style of the assignment: 6 | 7 | * Feel free to ask questions! Check the course notes! Even talk to your classmates! The purpose of the labs is for you to get hands on experience and produce good working code. 8 | * If you are done before the end of the lab, ask a lab instructor to check over your code. It is very possible that even if your code works, the instructor may point out areas where your code could be improved, either to make it more readable, or because your code might have failed for input cases. 9 | * When you are done, either because you have shown it to a lab instructor and had it "checked off" or if you needed to finish it up at home, submit it on NYU Classes. 10 | 11 | And now on to the description of today's task. 12 | 13 | * We want to read a file, display it to the screen and report how many "words" there are. 14 | * There are several ways to do this. Here's one way: 15 | * Read the file line-by-line, printing each line to the screen. 16 | * Read the file again, word-by-word, keeping a count of the words read and displaying the count when you are done. 17 | 18 | If you have time and know how (we didn't get to cover this in the fall, but again, *if* you know how...), break the problem into functions. What are good ways to do that? What parameters should you pass to the function? More time? Try counting each distinct "word". 19 | 20 | * Good programming style: 21 | * Naming 22 | * Length of lines 23 | * Comments are not required for labs except be sure there is a comment at the top of the file identifying the author (you, hopefully), the name of the program file, and a *very* brief description of the program. 24 | * Note that all of your submissions both labs and homeworks for the semester should have such a comment at the beginning of each code file. 25 | ## Submit 26 | * Whether or not you have been "checked off" during the recitation, submit a single source file, `rec01.cpp`, on NYU Classes. If you do not, your grade may be penalized. Do not submit any other files, such as those generated for your development environment (IDE). 27 | 28 | ## What you need to know 29 | Since you are just starting out with C++ and with this course, I thought it might be handy to have links back to the course lecture notes on the necessary material. It is possible for this recitation that some item(s) may not have been covered in your lecture section. Hopefully, given your prior programming experience, none of these issues will seem complicated, but please feel free, as always, to ask for help from your lab instructors or your fellow students. 30 | 31 | * [Defining variables](../../Basic%20C%2B%2B/Basic%20Syntax.md#variables), using [conditions and looping](../../Basic%20C%2B%2B/Basic%20Syntax.md#conditions) 32 | * [How to open a file, check that it opened correctly, read and close it](Basic%20C%2B%2B/File%20IO/File%20IO.md) 33 | * Note we probably did not cover all the details of how to read files. In particular note that 34 | * to read a single "token", use the input operator and read into a string variable 35 | * to read a line, use the function getline. 36 | * To read a file token by token or line by line, do either of the above, as part of a while loop, e.g.: 37 | * `while (ifs >> token) { /* code to do things with the token */ }` 38 | * `while ( getline(ifs, line) ) { /* code to do things with the line */ }` 39 | * There's a lot more explanation at the above link. 40 | * [How to use strings](../../Basic%20C%2B%2B/Strings.md) 41 | * Ideally [writing functions](../../Basic%20C%2B%2B/Functions/Functions.md). If you have covered this, then certainly break the problem up into appropriate functions. However, if you haven't gotten to that in lecture, as certainly happens in the fall semester, don't do it. 42 | 43 | ### Additional resources for assignment 44 | * [Recitation 1 notes on input filesV2.pdf](./Recitation%201%20notes%20on%20input%20filesV2.pdf) 45 | * [jabberwocky](./jabberwocky) -------------------------------------------------------------------------------- /recitations/rec02/Basic SortingPython.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/recitations/rec02/Basic SortingPython.pdf -------------------------------------------------------------------------------- /recitations/rec03/Rec03.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/recitations/rec03/Rec03.pdf -------------------------------------------------------------------------------- /recitations/rec03/accounts.txt: -------------------------------------------------------------------------------- 1 | moe 6 2 | larry 28 3 | curly 42 4 | -------------------------------------------------------------------------------- /recitations/rec03/minesweeper.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/recitations/rec03/minesweeper.pdf -------------------------------------------------------------------------------- /recitations/rec03/rec03.md: -------------------------------------------------------------------------------- 1 | # Recitation 3 - Classes - encapsulation and data hiding 2 | 3 | ## Topics 4 | * Classes 5 | 6 | The first is a [tutorial](./Rec03.pdf) on the basics of C++'s syntax for using classes. 7 | 8 | The second choice is to define a class for the game [Minesweeper](minesweeper.pdf). Please note this is more difficult, for example it involves doing a depth-first search on a two-dimensional grid. 9 | 10 | Either choice is fine and earns the same amount of credit. Realistically, all students are more likely to complete the first choice during the lab. 11 | 12 | ### Additional resources for assignment 13 | * [minesweeper.pdf](./minesweeper.pdf) 14 | * [transactions.txt](./transactions.txt) 15 | * [Rec03.pdf](./Rec03.pdf) 16 | * [accounts.txt](./accounts.txt) -------------------------------------------------------------------------------- /recitations/rec03/transactions.txt: -------------------------------------------------------------------------------- 1 | Account moe 6 2 | Deposit 6 10 3 | Withdraw 6 100 4 | 5 | Account larry 28 6 | Withdraw 6 100 7 | Deposit 6 10 8 | Deposit 6 10 9 | Withdraw 6 5 10 | 11 | Account curly 42 12 | -------------------------------------------------------------------------------- /recitations/rec04/Rec04 Additional Info for Xcode.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/recitations/rec04/Rec04 Additional Info for Xcode.pdf -------------------------------------------------------------------------------- /recitations/rec05/rec05-start.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | rec05.cpp 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | 11 | // Test code 12 | void doNothing(Section sec) { cout << sec << endl; } 13 | 14 | int main() { 15 | 16 | cout << "Test 1: Defining a section\n"; 17 | // Section secA2("A2", "Tuesday", 16); 18 | // cout << secA2 << endl; 19 | 20 | cout << "\nTest 2: Adding students to a section\n"; 21 | // secA2.addStudent("John"); 22 | // secA2.addStudent("George"); 23 | // secA2.addStudent("Paul"); 24 | // secA2.addStudent("Ringo"); 25 | // cout << secA2 << endl; 26 | 27 | cout << "\nTest 3: Defining a lab worker.\n"; 28 | // LabWorker moe( "Moe" ); 29 | // cout << moe << endl; 30 | 31 | cout << "\nTest 4: Adding a section to a lab worker.\n"; 32 | // moe.addSection( secA2 ); 33 | // cout << moe << endl; 34 | 35 | cout << "\nTest 5: Adding a second section and lab worker.\n"; 36 | // LabWorker jane( "Jane" ); 37 | // Section secB3( "B3", "Thursday", 11 ); 38 | // secB3.addStudent("Thorin"); 39 | // secB3.addStudent("Dwalin"); 40 | // secB3.addStudent("Balin"); 41 | // secB3.addStudent("Kili"); 42 | // secB3.addStudent("Fili"); 43 | // secB3.addStudent("Dori"); 44 | // secB3.addStudent("Nori"); 45 | // secB3.addStudent("Ori"); 46 | // secB3.addStudent("Oin"); 47 | // secB3.addStudent("Gloin"); 48 | // secB3.addStudent("Bifur"); 49 | // secB3.addStudent("Bofur"); 50 | // secB3.addStudent("Bombur"); 51 | // jane.addSection( secB3 ); 52 | // cout << jane << endl; 53 | 54 | cout << "\nTest 6: Adding some grades for week one\n"; 55 | // moe.addGrade("John", 17, 1); 56 | // moe.addGrade("Paul", 19, 1); 57 | // moe.addGrade("George", 16, 1); 58 | // moe.addGrade("Ringo", 7, 1); 59 | // cout << moe << endl; 60 | 61 | cout << "\nTest 7: Adding some grades for week three (skipping week 2)\n"; 62 | // moe.addGrade("John", 15, 3); 63 | // moe.addGrade("Paul", 20, 3); 64 | // moe.addGrade("Ringo", 0, 3); 65 | // moe.addGrade("George", 16, 3); 66 | // cout << moe << endl; 67 | 68 | cout << "\nTest 8: We're done (almost)! \nWhat should happen to all " 69 | << "those students (or rather their records?)\n"; 70 | 71 | cout << "\nTest 9: Oh, IF you have covered copy constructors in lecture, " 72 | << "then make sure the following call works:\n"; 73 | // doNothing(secA2); 74 | // cout << "Back from doNothing\n\n"; 75 | 76 | } // main 77 | -------------------------------------------------------------------------------- /recitations/rec06/rec06-origV2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Recitation 06 3 | CS2124 4 | 5 | Focus: Dynamic arrays and copy control 6 | */ 7 | 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | class Position { 13 | friend ostream& operator<<(ostream& os, const Position& rhs) { 14 | os << '[' << rhs.title << ',' << rhs.salary << ']'; 15 | return os; 16 | } 17 | public: 18 | Position(const string& aTitle, double aSalary) 19 | : title(aTitle), salary(aSalary) {} 20 | const string& getTitle() const { return title; } 21 | double getSalary() const { return salary; } 22 | void changeSalaryTo(double d) { salary = d; } 23 | private: 24 | string title; 25 | double salary; 26 | }; // class Position 27 | 28 | class Entry { 29 | friend ostream& operator<<(ostream& os, const Entry& rhs) { 30 | os << rhs.name << ' ' << rhs.room 31 | << ' ' << rhs.phone << ", " << *rhs.pos; 32 | return os; 33 | } 34 | public: 35 | Entry(const string& name, unsigned room, unsigned phone, Position& position) 36 | : name(name), room(room), phone(phone), pos(&position) { 37 | } 38 | const string& getName() const { return name; } 39 | unsigned getPhone() const { return phone; } 40 | private: 41 | string name; 42 | unsigned room; 43 | unsigned phone; 44 | Position* pos; 45 | }; // class Entry 46 | 47 | class Directory { 48 | // Overload output operator 49 | public: 50 | // Of course the first function you need to write for this (or 51 | // any) class is... 52 | // ??? 53 | // ... 54 | 55 | 56 | // We'll get you started with the add method, but obviously you 57 | // have a lot of work to do here. 58 | void add(const string& name, unsigned room, unsigned ph, Position& pos) { 59 | if (size == capacity) { 60 | // something is missing!!! Add it! 61 | 62 | } // if 63 | entries[size] = new Entry(name, room, ph, pos); 64 | ++size; 65 | } // add 66 | 67 | private: 68 | Entry** entries; 69 | size_t size; 70 | size_t capacity; 71 | }; // class Directory 72 | 73 | void doNothing(Directory dir) { cout << dir << endl; } 74 | 75 | int main() { 76 | 77 | // Note that the Postion objects are NOT on the heap. 78 | Position boss("Boss", 3141.59); 79 | Position pointyHair("Pointy Hair", 271.83); 80 | Position techie("Techie", 14142.13); 81 | Position peon("Peonissimo", 34.79); 82 | 83 | // Create a Directory 84 | Directory d; 85 | d.add("Marilyn", 123, 4567, boss); 86 | cout << d << endl; 87 | 88 | Directory d2 = d; // What function is being used?? 89 | d2.add("Gallagher", 111, 2222, techie); 90 | d2.add("Carmack", 314, 1592, techie); 91 | cout << d << endl; 92 | 93 | cout << "Calling doNothing\n"; 94 | doNothing(d2); 95 | cout << "Back from doNothing\n"; 96 | 97 | Directory d3; 98 | d3 = d2; 99 | 100 | // Should display 1592 101 | cout << d2["Carmack"] << endl; 102 | 103 | } // main 104 | -------------------------------------------------------------------------------- /recitations/rec06/rec06.md: -------------------------------------------------------------------------------- 1 | # Recitation 6: Dynamic Arrays and Copy Control 2 | ## Topics 3 | * Copy Control (aka Big 3) 4 | * operator[] 5 | ## Task 6 | You will develop a class to represent a directory or employees. 7 | 8 | We provide you with some code to start with in the attached file rec06-orig.cpp. 9 | 10 | It provides the basic class definitions that we will need for modeling a directory of employees in a company. In particular, it provides the code you will need for the classes Entry and Position, along with a start for the Directory class. 11 | ___ 12 | Your job is to: 13 | 14 | * Read and understand the given code. 15 | * Fill in the missing code for the Directory add method. 16 | * Overload Directory's output operator. Test your code now! 17 | * Implement the Big 3 (i.e., destructor, copy constructor and assignment operator) for the Directory class. At the beginning of each of these functions, add a print statement to show when you have entered them. This will help you understand when / where they are each being used. 18 | * Overload Directory's [] operator to allow looking up a person's phone number, by passing in their name. 19 | * You should (as always) consider if there is any way to further expand the code in main() to test your new features. 20 | ## Dynamic Array? 21 | Some might ask, "Why are we using a *dynamic array* of Entry pointers for our Directory?" Sure, you are [much] more likely to use a vector or other container type (e.g. map), but this provides you with a good exercise in implementing copy control, which is the point of this exercise. 22 | 23 | Note that the Directory is *responsible* for both the Entries and the dynamic array itself. 24 | 25 | You should *think* about how using a vector of pointers would change your code. 26 | 27 | ### Additional resources for assignment 28 | * [rec06-origV2.cpp](./rec06-origV2.cpp) -------------------------------------------------------------------------------- /recitations/rec07/output-for-required.txt: -------------------------------------------------------------------------------- 1 | No courses or students added yet 2 | Registrar's Report 3 | Courses: 4 | Students: 5 | 6 | AddCourse CS101.001 7 | Registrar's Report 8 | Courses: 9 | CS101.001: No Students 10 | Students: 11 | 12 | AddStudent FritzTheCat 13 | Registrar's Report 14 | Courses: 15 | CS101.001: No Students 16 | Students: 17 | FritzTheCat: No Courses 18 | 19 | AddCourse CS102.001 20 | Registrar's Report 21 | Courses: 22 | CS101.001: No Students 23 | CS102.001: No Students 24 | Students: 25 | FritzTheCat: No Courses 26 | 27 | EnrollStudentInCourse FritzTheCat CS102.001 28 | EnrollStudentInCourse FritzTheCat CS101.001 29 | Registrar's Report 30 | Courses: 31 | CS101.001: FritzTheCat 32 | CS102.001: FritzTheCat 33 | Students: 34 | FritzTheCat: CS102.001 CS101.001 35 | 36 | EnrollStudentInCourse Bullwinkle CS101.001 37 | Should fail, i.e. do nothing, since Bullwinkle is not a student. 38 | Registrar's Report 39 | Courses: 40 | CS101.001: FritzTheCat 41 | CS102.001: FritzTheCat 42 | Students: 43 | FritzTheCat: CS102.001 CS101.001 44 | 45 | CancelCourse CS102.001 46 | Registrar's Report 47 | Courses: 48 | CS101.001: FritzTheCat 49 | Students: 50 | FritzTheCat: CS101.001 51 | 52 | Purge for start of next semester 53 | Registrar's Report 54 | Courses: 55 | Students: 56 | 57 | -------------------------------------------------------------------------------- /recitations/rec07/rec07.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | rec07 3 | Starter Code for required functionality 4 | Yes, you may add other methods. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | class Student; 13 | 14 | class Course { 15 | friend ostream& operator<<(ostream& os, const Course& rhs); 16 | public: 17 | // Course methods needed by Registrar 18 | Course(const string& courseName); 19 | const string& getName() const; 20 | bool addStudent(Student*); 21 | void removeStudentsFromCourse(); 22 | 23 | private: 24 | string name; 25 | vector students; 26 | }; 27 | 28 | class Student { 29 | friend ostream& operator<<(ostream& os, const Student& rhs); 30 | public: 31 | // Student methods needed by Registrar 32 | Student(const string& name); 33 | const string& getName() const; 34 | bool addCourse(Course*); 35 | 36 | // Student method needed by Course 37 | void removedFromCourse(Course*); 38 | 39 | private: 40 | string name; 41 | vector courses; 42 | }; 43 | 44 | class Registrar { 45 | friend ostream& operator<<(ostream& os, const Registrar& rhs); 46 | public: 47 | Registrar(); 48 | bool addCourse(const string&); 49 | bool addStudent(const string&); 50 | bool enrollStudentInCourse(const string& studentName, 51 | const string& courseName); 52 | bool cancelCourse(const string& courseName); 53 | void purge(); 54 | 55 | private: 56 | size_t findStudent(const string&) const; 57 | size_t findCourse(const string&) const; 58 | 59 | vector courses; 60 | vector students; 61 | }; 62 | 63 | int main() { 64 | 65 | Registrar registrar; 66 | 67 | cout << "No courses or students added yet\n"; 68 | cout << registrar << endl; 69 | 70 | cout << "AddCourse CS101.001\n"; 71 | registrar.addCourse("CS101.001"); 72 | cout << registrar << endl; 73 | 74 | cout << "AddStudent FritzTheCat\n"; 75 | registrar.addStudent("FritzTheCat"); 76 | cout << registrar << endl; 77 | 78 | cout << "AddCourse CS102.001\n"; 79 | registrar.addCourse("CS102.001"); 80 | cout << registrar << endl; 81 | 82 | cout << "EnrollStudentInCourse FritzTheCat CS102.001\n"; 83 | registrar.enrollStudentInCourse("FritzTheCat", "CS102.001"); 84 | cout << "EnrollStudentInCourse FritzTheCat CS101.001\n"; 85 | registrar.enrollStudentInCourse("FritzTheCat", "CS101.001"); 86 | cout << registrar << endl; 87 | 88 | cout << "EnrollStudentInCourse Bullwinkle CS101.001\n"; 89 | cout << "Should fail, i.e. do nothing, " 90 | << "since Bullwinkle is not a student.\n"; 91 | registrar.enrollStudentInCourse("Bullwinkle", "CS101.001"); 92 | cout << registrar << endl; 93 | 94 | cout << "CancelCourse CS102.001\n"; 95 | registrar.cancelCourse("CS102.001"); 96 | cout << registrar << endl; 97 | 98 | /* 99 | // [OPTIONAL - do later if time] 100 | cout << "ChangeStudentName FritzTheCat MightyMouse\n"; 101 | registrar.changeStudentName("FritzTheCat", "MightyMouse"); 102 | cout << registrar << endl; 103 | 104 | cout << "DropStudentFromCourse MightyMouse CS101.001\n"; 105 | registrar.dropStudentFromCourse("MightyMouse", "CS101.001"); 106 | cout << registrar << endl; 107 | 108 | cout << "RemoveStudent FritzTheCat\n"; 109 | registrar.removeStudent("FritzTheCat"); 110 | cout << registrar << endl; 111 | */ 112 | 113 | cout << "Purge for start of next semester\n"; 114 | registrar.purge(); 115 | cout << registrar << endl; 116 | } 117 | 118 | -------------------------------------------------------------------------------- /recitations/rec08/gcd.cpp: -------------------------------------------------------------------------------- 1 | int greatestCommonDivisor(int x, int y) { 2 | while (y != 0) { 3 | int temp = x % y; 4 | x = y; 5 | y = temp; 6 | } 7 | return x; 8 | } 9 | -------------------------------------------------------------------------------- /recitations/rec08/rec08.md: -------------------------------------------------------------------------------- 1 | # Recitation 08: Operator Overloading 2 | ## Topics 3 | * Overloading Operators 4 | ## Recitation Project 5 | * Design, implement and test a C++ class to work with real numbers as rational numbers. 6 | * The data members are the numerator and denominator, stored as integers. 7 | * We have no need for setters or getters (aka mutators or accessors) in the Rational class. All of our operations on rational numbers involve the entired number, not just the numerator or denominator. 8 | * Implement the operators: 9 | * `<<` and `>>` (i.e., input and output). 10 | * Rational numbers are read and written as an integer, followed by a slash, followed by an integer. 11 | * Either (or both) of the numerator and the denominator may be input as negative integers. The following are all possible inputs: 1/2, -1/-2, -1/2 and 1/-2. 12 | * It's a design decision as to when to "normalize" a rational number. Should it always be normalized? Or is that only a choice to be made when we dispaly it? 13 | * We will maintain the numbers in their normalized form at all times. 14 | * Thus when they are first created, they must be stored as normalized and any operation that might change a number must also normalize it. 15 | * What does "normalize" mean? The numerator and denominator will be in "lowest terms" and only the numerator may be negative. For example, if we were given as input 4/-8, we would store and display it as -1/2. Simililarly -8/-6 would turn into 4/3. 16 | * `+=` Implement as a member function, aka *method*. 17 | * `+` Implement (i.e., addition) as a non-member function that calls the `+=` operator. Do not make `+` a friend. (There is no reason to.) 18 | * `==` Implement as a non-member. 19 | * `!=` Implement as a non-member, but not as a friend. 20 | * `++` and `--` 21 | * Both pre- and post-. 22 | * Member for `++` 23 | * Non-member, non-friend for `--` 24 | * `<` non-member 25 | * `<=`, > and `>=` Implement as **non-member and non-friend**. 26 | * Make it possible to write `if (r) {}`, where `r` is a Rational number. The test will evaluate to `false` if the numerator is zero and `true` otherwise. 27 | * We provide two files 28 | * testRational.cpp to test your class. Can you think of additional tests to write? 29 | * gcd.cpp: to compute the greatest common divisor of two non-negative integers, that should be useful for writing the normalize function. If you're clever, try to write this function yourself before looking at ours. 30 | ## If time allows in lab: 31 | * Use separate compilation, writing the files Rational.h and Rational.cpp, satisfying the above requirements. 32 | * Place the class in the CS2124 namespace. 33 | 34 | ### Additional resources for assignment 35 | * [testRational.cpp](./testRational.cpp) 36 | * [gcd.cpp](./gcd.cpp) -------------------------------------------------------------------------------- /recitations/rec08/testRational.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | testRational.cpp 3 | CS2124 4 | Implement the class Rational, so that the following program works. 5 | */ 6 | 7 | #include 8 | 9 | // If time allows use separate compilation, otherwise just define the class below 10 | #include "Rational.h" 11 | 12 | using namespace std; 13 | 14 | // If time allows after implementing separate compilation, then wrap the class in a namespace. 15 | using namespace CS2124; 16 | 17 | int main() { 18 | Rational twoThirds(2,3); 19 | cout << twoThirds << endl; 20 | 21 | Rational a, b; 22 | cout << "Input a rational number, e.g. 6/9.\n"; 23 | cout << "a: "; 24 | cin >> a; 25 | cout << "Input a rational number, e.g. 6/9.\n"; 26 | cout << "b: "; 27 | cin >> b; 28 | const Rational one = 1; 29 | 30 | cout << "a = " << a << endl; 31 | cout << "b = " << b << endl; 32 | cout << "one = " << one << endl; 33 | cout << "a += b: " << (a += b) << endl; // Implement as member 34 | cout << "a = " << a << endl; 35 | 36 | // Implement as non-member, but not a friend 37 | cout << "a + one: " << (a + one) << endl; 38 | cout << "a == one: " << boolalpha << (a == one) << endl; 39 | 40 | // How does this manage to work? 41 | // It does NOT require writing another == operator. 42 | cout << "1 == one: " << boolalpha << (1 == one) << endl; 43 | 44 | // Do not implement as friend. 45 | cout << "a != one: " << boolalpha << (a != one) << endl; 46 | 47 | cout << "a = " << a << endl; 48 | cout << "++a = " << (++a) << endl; 49 | cout << "a = " << a << endl; 50 | cout << "a++ = " << (a++) << endl; 51 | cout << "a = " << a << endl; 52 | cout << "--a = " << (--a) << endl; 53 | cout << "a = " << a << endl; 54 | cout << "a-- = " << (a--) << endl; 55 | cout << "a = " << a << endl; 56 | 57 | cout << "++ ++a = " << (++ ++a) << endl; 58 | cout << "a = " << a << endl; 59 | cout << "-- --a = " << (-- --a) << endl; 60 | cout << "a = " << a << endl; 61 | 62 | cout << "a++ ++ = " << (a++ ++) << endl; 63 | cout << "a = " << a << endl; 64 | 65 | // Even though the above example, (a++ ++), compiled, the 66 | // following shouldn't. 67 | // But some compiler vendors might let it... Is your compiler 68 | // doing the right thing? 69 | cout << "a-- -- = " << (a-- --) << endl; 70 | cout << "a = " << a << endl; 71 | 72 | 73 | // Should report that 1 is true 74 | if (Rational(1)) { 75 | cout << "1 is true" << endl; 76 | } else { 77 | cout << "1 is false" << endl; 78 | } 79 | 80 | // Should report that 0 is false 81 | if (Rational(0)) { 82 | cout << "0 is true" << endl; 83 | } else { 84 | cout << "0 is false" << endl; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /recitations/rec09/rec09.md: -------------------------------------------------------------------------------- 1 | # Recitation 9: Intro to Inheritance 2 | ## Instructions 3 | See attached zip file. 4 | 5 | Note that there is a file rec09.html. Just open that. All other files are linked to from there. 6 | 7 | ### Additional resources for assignment 8 | * [rec09.zip](./rec09.zip) -------------------------------------------------------------------------------- /recitations/rec09/rec09.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/recitations/rec09/rec09.zip -------------------------------------------------------------------------------- /recitations/rec10/rec10 19S.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/recitations/rec10/rec10 19S.zip -------------------------------------------------------------------------------- /recitations/rec10/rec10.md: -------------------------------------------------------------------------------- 1 | # Recitation - More Inheritance 2 | ## Focus 3 | * Inheritance 4 | * Polymorphism 5 | ## Details 6 | See attached. Note that there are two parts. In the first part you will develop a class hierarchy for musical instruments, together with a Musical Instrument Lending Library that stores them, lends them and tests them out. You are provided with a musician 7 | 8 | In the second, you develop an Orchestra class and extend your instrument classes with new method(s). 9 | 10 | The purpose of this exercise is to practice you skills at implementing and using inheritance. And part of that is the design of your hierarchies. 11 | 12 | What methods should be abstract? Is there any "common" behavior that can be captured in a base class, and then extended in a derived class. An example might be the "make a sound" behavior. All instruments have to do that, but how they do it varies by type. Note that all instruments start off the same way when they make a sound. There's some "common code" you could call from the methods actually make the sound. Where should that common code go? 13 | 14 | ### Additional resources for assignment 15 | * [rec10 19S.zip](./rec10%2019S.zip) -------------------------------------------------------------------------------- /recitations/rec11/linkedListFuncs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | functions for use with CS2124 rec11 3 | -jbs 4 | */ 5 | 6 | // Node to be used a part of linked list 7 | struct Node { 8 | Node(int data = 0, Node* next = nullptr) : data(data), next(next) {} 9 | int data; 10 | Node* next; 11 | }; 12 | 13 | // listAddHead: adds a data item to the beginning of a [possibly empty] list 14 | void listAddHead(Node*& headPtr, int entry) { 15 | headPtr = new Node(entry, headPtr); 16 | } 17 | 18 | // listClear: frees up all the nodes in a list 19 | void listClear(Node*& headPtr) { 20 | while (headPtr) { 21 | Node* next = headPtr->next; 22 | delete headPtr; 23 | headPtr = next; 24 | } 25 | } 26 | 27 | // listBuild: constructs a list from a vector of data items. Note that 28 | // you can use a curly-braced sequence. 29 | // This may be useful for setting up test cases. Feel free to use it 30 | // or not as you like. 31 | // Example of using would be: 32 | // Node* myList = listBuild({1, 4, 9, 16}); // builds a list of: 1 4 9 16 33 | Node* listBuild(const vector& vals) { 34 | Node* result = nullptr; 35 | for (size_t index = vals.size(); index > 0; --index) { 36 | listAddHead(result, vals[index-1]); 37 | } 38 | return result; 39 | } 40 | -------------------------------------------------------------------------------- /recitations/rec11/rec11.md: -------------------------------------------------------------------------------- 1 | # Recitation 11 - Linked List Basics 2 | ## Topic 3 | * linked lists 4 | ## Details 5 | See attached for detailed instructions. 6 | 7 | ### Additional resources for assignment 8 | * [rec11_ Linked List Basics.pdf](./rec11_%20Linked%20List%20Basics.pdf) 9 | * [linkedListFuncs.cpp](./linkedListFuncs.cpp) -------------------------------------------------------------------------------- /recitations/rec11/rec11_ Linked List Basics.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/recitations/rec11/rec11_ Linked List Basics.pdf -------------------------------------------------------------------------------- /recitations/rec12/NoSentinels.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/recitations/rec12/NoSentinels.jpeg -------------------------------------------------------------------------------- /recitations/rec12/TwoSentinels.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/william1357chen/Object-Oriented-Programming-in-CPP-CS2124/4348bda49431c96682c7b5b6da89cf11a3df9bd8/recitations/rec12/TwoSentinels.jpg -------------------------------------------------------------------------------- /recitations/rec13/rec13_test.cpp: -------------------------------------------------------------------------------- 1 | // rec13_test.cpp 2 | 3 | #include 4 | #include 5 | #include // task 1 6 | #include // task 2 7 | #include // task 3 8 | #include // task 21 9 | #include // task 22 10 | #include // task 23 11 | using namespace std; 12 | 13 | int main() { 14 | // 1. Create a vector with some values and display using ranged for 15 | cout << "Task 1:\n"; 16 | 17 | cout << "\n=======\n"; 18 | 19 | // 2. Initalize a list as a copy of values from the vector 20 | cout << "Task 2:\n"; 21 | 22 | cout << "\n=======\n"; 23 | 24 | // 3. Sort the original vector. Display both the vector and the list 25 | cout << "Task 3:\n"; 26 | 27 | cout << "\n=======\n"; 28 | 29 | // 4. print every other element of the vector. 30 | cout << "Task 4:\n"; 31 | 32 | cout << "\n=======\n"; 33 | 34 | // 5. Attempt to print every other element of the list using the 35 | // same technique. 36 | cout << "Task 5:\n"; 37 | 38 | cout << "\n=======\n"; 39 | 40 | // 41 | // Iterators 42 | // 43 | 44 | // 6. Repeat task 4 using iterators. Do not use auto; 45 | cout << "Task 6:\n"; 46 | 47 | cout << "\n=======\n"; 48 | 49 | // 7. Repeat the previous task using the list. Again, do not use auto. 50 | // Note that you cannot use the same simple mechanism to bump 51 | // the iterator as in task 6. 52 | cout << "Task 7:\n"; 53 | 54 | cout << "\n=======\n"; 55 | 56 | // 8. Sorting a list 57 | cout << "Task 8:\n"; 58 | 59 | cout << "\n=======\n"; 60 | 61 | // 9. Calling the function to print the list 62 | cout << "Task 9:\n"; 63 | 64 | cout << "=======\n"; 65 | 66 | // 10. Calling the function that prints the list, using ranged-for 67 | cout << "Task 10:\n"; 68 | 69 | cout << "=======\n"; 70 | 71 | // 72 | // Auto 73 | // 74 | 75 | // 11. Calling the function that, using auto, prints alterate 76 | // items in the list 77 | cout << "Task 11:\n"; 78 | 79 | cout << "=======\n"; 80 | 81 | 82 | // 12. Write a function find that takes a list and value to search for. 83 | // What should we return if not found 84 | cout << "Task 12:\n"; 85 | 86 | cout << "=======\n"; 87 | 88 | // 13. Write a function find that takes a list and value to search for. 89 | // What should we return if not found 90 | cout << "Task 13:\n"; 91 | 92 | cout << "=======\n"; 93 | 94 | // 95 | // Generic Algorithms 96 | // 97 | 98 | // 14. Generic algorithms: find 99 | cout << "Task 14:\n"; 100 | 101 | cout << "=======\n"; 102 | 103 | // 15. Generic algorithms: find_if 104 | cout << "Task 15:\n"; 105 | 106 | cout << "=======\n"; 107 | 108 | // 16. Functor 109 | cout << "Task 16:\n"; 110 | 111 | cout << "=======\n"; 112 | 113 | // 17. Lambda 114 | cout << "Task 17:\n"; 115 | 116 | cout << "=======\n"; 117 | 118 | // 18. Generic algorithms: copy to an array 119 | cout << "Task 18:\n"; 120 | 121 | cout << "=======\n"; 122 | 123 | // 124 | // Templated Functions 125 | // 126 | 127 | // 19. Implement find as a function for lists 128 | cout << "Task 19:\n"; 129 | 130 | cout << "=======\n"; 131 | 132 | // 20. Implement find as a templated function 133 | cout << "Task 20:\n"; 134 | 135 | cout << "=======\n"; 136 | 137 | // 138 | // Associative collections 139 | // 140 | 141 | // 21. Using a vector of strings, print a line showing the number 142 | // of distinct words and the words themselves. 143 | cout << "Task 21:\n"; 144 | 145 | cout << "\n=======\n"; 146 | 147 | // 22. Repeating previous step, but using the set 148 | cout << "Task 22:\n"; 149 | 150 | cout << "=======\n"; 151 | 152 | // 23. Word co-occurence using map 153 | cout << "Task 23:\n"; 154 | 155 | cout << "=======\n"; 156 | } 157 | -------------------------------------------------------------------------------- /recitations/rec14/tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | struct TNode { 5 | TNode(int data = 0, TNode *left = nullptr, TNode *right = nullptr) 6 | : data(data), left(left), right(right) {} 7 | int data; 8 | TNode *left, *right; 9 | }; 10 | 11 | int max(TNode* root) { 12 | // Provide this code 13 | } 14 | 15 | int main() { 16 | 17 | TNode a(1), b(2), c(4), d(8, &a, &b), e(16, &c), f(32, &d, &e); 18 | cout << max(&f) << endl; 19 | 20 | } 21 | 22 | 23 | 24 | --------------------------------------------------------------------------------