# cpp
## resources
- [Assembly Code Breakdown of your code](https://godbolt.org/)
- [cplusplus.com](http://cplusplus.com/reference/)
- [Cherno C++ Tutorial Series](https://www.youtube.com/playlist?list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb)
## Data Types
### Auto
The `auto` specifier is a way of detecting the data type based on assignment value.
```cpp
auto i = 5; // causes i to be of type int
// and
auto j = 5.0; // causes j to be of type double.
```
### Character
_Character are a single character only, and in the assignment the character must be wrapped in single quotes._
```cpp
char arrowBody = '-'
```
### conversion
If you do not want to make a new variable or refactor an existing variable due to the need for it to be a `double` and not an `int` any longer.
Like when finding the average of integers and the returned value is floating point
this will work like `cast()` in SQL
```cpp
#include <iostream>
using namespace std;
int main() {
int kidsInFamily1 = 3; // Should be int, not double
int kidsInFamily2 = 4; // (know anyone with 2.3 kids?)
int numFamilies = 2; // Should be int, not double
double avgKidsPerFamily = 0.0; // Expect fraction, so double
avgKidsPerFamily = static_cast<double>(kidsInFamily1 + kidsInFamily2)
/ static_cast<double>(numFamilies);
cout << "Average kids per family: " << avgKidsPerFamily << endl;
return 0;
}
```
### Double / Float
_Floating point numbers "They have a decimal point", can be 1.0 like an integer but can also be 1.1._
```cpp
double heightInCentimeters = 198.7;
```
#### 'Good Enough' Equality
> Floating-point numbers should not be compared using `==`. Ex: Avoid float1 `==` float2.
> .
> Reason: Some floating-point numbers cannot be exactly represented in the limited available memory bits like 64 bits. Floating-point numbers expected to be equal may be close but not exactly equal.
> .
> Floating-point numbers should be compared for _"close enough"_ rather than exact equality.
> Ex: If `( x - y ) < 0.0001`, x and y are deemed equal.
> Because the difference may be negative, the absolute value is used: `fabs(x - y) < 0.0001`.
> .
> The difference threshold indicating that floating-point numbers are equal is often called the `epsilon`. Epsilon's value depends on the program's expected values, but 0.0001 is common.
### Integer
_Whole numbers only._
```cpp
int age = 28;
```
#### Other types of Integers
| Declaration | Size | Supported number range | Standard-defined minimum size |
| ------------------ | ------- | ------------------------------------------------------- | ----------------------------- |
| `char myVar;` | 8 bits | -128 to 127 | 8 bits |
| `short myVar;` | 16 bits | -32,768 to 32,767 | 16 bits |
| `long myVar;` | 32 bits | -2,147,483,648 to 2,147,483,647 | 32 bits |
| `long long myVar;` | 64 bits | -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 | 64 bits |
| `int myVar;` | 32 bits | -2,147,483,648 to 2,147,483,647 | 16 bits |
#### Unsigned Integers
If you know an integer will always be positive then you can double the range of the positive value limit as the negative value limit will be reduced to zero in favor of expanding the positive limit.
| Declaration | Size | Supported number range | Standard-defined minimum size |
| --------------------------- | ------- | -------------------------------- | ----------------------------- |
| `unsigned char myVar;` | 8 bits | 0 to 255 | 8 bits |
| `unsigned short myVar;` | 16 bits | 0 to 65,535 | 16 bits |
| `unsigned long myVar;` | 32 bits | 0 to 4,294,967,295 | 32 bits |
| `unsigned long long myVar;` | 64 bits | 0 to 184,467,440,737,095,551,615 | 64 bits |
| `unsigned int myVar;` | 32 bits | 0 to 4,294,967,295 | 16 bits |
### Mutability
`const` variables are traditionally upper snake case `LIKE_THIS`
To declare something as `const` is to make it immutable and unable to be reassigned to a new value.
```cpp
const int CENTIMETERS_PER_INCH = 3; // will forever be 3
```
### Strings
_Strings make use of the [[#Strings]] library to represent an array of characters (a word or more) in a single datatype with minimal headache on management and more options and functionality than C-style strings_
```cpp
string firstName = "bryan";
```
If you are reading in^\[[[#basic input output]]] a string value into a variable, any spaces will be considered the termination of the string.
To get the entire input string you need to use `getline()`
```cpp
string firstName;
string lastName;
cout << "Enter first name:" << endl;
getline(cin, firstName); // Gets entire line up to ENTER
cout << "Enter last name:" << endl;
getline(cin, lastName); // Gets entire line up to ENTER
cout << endl;
cout << "Welcome " << firstName << " " << lastName << "!" << endl;
cout << "May I call you " << firstName << "?" << endl;
```
#### C Strings
char arrays were the only type of strings that existed in `C` such as:
```cpp
char movieTitle[20] = "Star Wars";
```
> Because a string can be shorter than the character array, a string in a char array must end with a special character known as a null character, written as '\\0'. Given a string literal like "Star Wars", the compiler automatically appends a null character.
> .
> A char array of size 20 can store strings of lengths 0 to 19. The longest string is 19, not 20, since the null character must be stored.
`C` strings can be in legacy code and are included with:
```cpp
#include <cstring>
```
## Data Structures
### Vectors are Array++
A vector is an ordered list of items of a given data type.
Each item in a vector is called an **element**.
```cpp
#include <vector>
// vector<dataType> identifier(numElements);
vector<int> myVector(5); // an integer vector with 5 elements
/*
Though if you assign a vector a size of 5 the true size is still using the 0..n array indexing. so if you say:
*/
vector<int> myVector(5);
/*
and then try to access element 5:
*/
myVector.at(5); // <-- ERROR! 5 elements at index 0..4
```
#### Iterating Through a Vector
Using [[#For Loop Syntax]] on a vector can be a little irritating at first with the size declaration but usage of array indexing:
```cpp
// These give a variable to reference the size of the vector
const int NUM_ELEMENTS = 3;
vector<int> userVals(NUM_ELEMENTS);
// test case
userVals.at(0) = 2;
userVals.at(1) = 7;
userVals.at(2) = 4;
/*
where i < NUM_ELEMENTS is to say it quits if it is larger than 2
i.e. 3. NUM_ELEMENTS goes up to 3, but because of the array indexing
the true values are 0, 1, & 2 as shown above in the test case
*/
for (int i = 0; i < NUM_ELEMENTS; ++i) {
cout << userVals.at(i) << endl;
}
//#> 2, 7, 4
```
An even easier way of doing the same thing without an unnecessary `const` variable is to use `.size()`
```cpp
vector<int> userVals(3);
// test case
userVals.at(0) = 2;
userVals.at(1) = 7;
userVals.at(2) = 4;
/*
the size is 3 so if i < 3 which is what the prior example also showed
*/
for (int i = 0; i < userVals.size(); ++i) {
cout << userVals.at(i) << endl;
}
//#> 2, 7, 4
```
#### Reversing a vector
```cpp
const int NUM_ELEMENTS = 8; // Number of elements
vector<int> revVctr(NUM_ELEMENTS); // User values
unsigned int i; // Loop index
int tmpValue; // Placeholder
// User populates the vector
cout << "Enter " << NUM_ELEMENTS << " integer values..." << endl;
for (i = 0; i < revVctr.size(); ++i) {
cout << "Value: ";
cin >> revVctr.at(i);
}
// Reverse the vector (this doesnt take into account an odd # of vals)
// Size returns the amount of values in a vector, the exact number of
// indexes is really -1 but to rever a vector we really only need to
// pivot around a mid point or in this case a middle value or half of
// the vector's size hence .size() / 2 below
for (i = 0; i < (revVctr.size() / 2); ++i) {
// temp value holds the values one by one starting from the left i=1
tmpValue = revVctr.at(i);
// .size() - 1 as that is the true last index of the vector and -i
// so we can begin to move towards the center values right to left
// i starts off at 0 so the first iteration is in reality swapping
// the first and last elements of a vector
revVctr.at(i) = revVctr.at(revVctr.size() - 1 - i);
// Referring again to the true last element of the vector receiving
// the true last index of the vector receiving the value of the first
// this is the end of the swap
revVctr.at(revVctr.size() - 1 - i) = tmpValue;
}
```
### enumerations
enums are basically just numbers. In this instance
`FICTION = 0` and `NONFICTION = 1`
```cpp
enum BookType {FICTION,NONFICTION};
```
`bookTypeStrings` are really just [[#Strings]] labels for the `BookType` enum as the enum in really is just numbers.
```cpp
static const std::string bookTypeStrings[] = {"FICTION","NONFICTION"};
```
The enumumerated values are being used as an index for the label values:
```cpp
bookTypeStrings[FICTION] // returns the string: "FICTION"
bookTypeStrings[NONFICTION] // returns the string: "NONFICTION"
```
The order of the strings does matter in this instance as the values default to a normal 0..1..n indexing unless manually set to specific values:
```cpp
enum light { RED = 2, YELLOW = 5, GREEN = 7 };
```
### Structs
> a **struct** is nearly identical to a class. The difference is that if a Class Member Function appears before a label of private or public, then by default, in a struct the member is public while in a class the member is private. Some programmers suggest a good practice is to use struct for simple data grouping with that data being public, while using class for objects (having data and functions, with data private).
> .
> However, some C++ programmers argue that good practice is to only use class, abandoning struct entirely
<https://www.guru99.com/cpp-structures.html>
```cpp
// Declaration
struct Person
{
char name[30];
int citizenship;
int age;
}
// Instantiation
Person p;
```
## libs
### cassert for Unit Testing
`assert.h` defines one macro function that can be used as a standard debugging tool:
### The C Character Type Library
> This header declares a set of functions to classify and transform individual characters.
#### isalpha( c )
true if alphabetic: a-z or A-Z
```cpp
isalpha('x') // true
isalpha('6') // false
isalpha('!') // false
```
#### isdigit( c )
true if digit: 0-9.
```cpp
isdigit('x') // false
isdigit('6') // true
```
#### isalnum( c )
Returns true if c is alphabetic or a numeric digit. Thus, returns true if either [[#isalpha( c )]] or [[#isdigit( c )]] would return true.
#### isspace( c )
true if whitespace.
```cpp
isspace(' ') // true
isspace('\n') // true
isspace('x') // false
```
#### toupper( c )
Uppercase version
```cpp
toupper('a') // A
toupper('A') // A
toupper('3') // 3
```
#### tolower( c )
Lowercase version
```cpp
tolower('A') // a
tolower('a') // a
tolower('3') // 3
```
#### isblank()
Returns true if character c is a blank character. Blank characters include spaces and tabs.
```cpp
isblank(myString[5]); // Returns true because that character is a space ' '.
isblank(myString[0]); // Returns false because 'H' is not blank.
```
#### isxdigit()
Returns true if c is a hexadecimal digit: 0-9, a-f, A-F.
```cpp
isxdigit(myString[3]); // Returns true because '9' is a hexadecimal digit.
isxdigit(myString[1]); // Returns true because 'e' is a hexadecimal digit.
isxdigit(myString[6]); // Returns false because 'G' is not a hexadecimal digit.
```
#### ispunct()
Returns true if c is a punctuation character. Punctuation characters include: `!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`
```cpp
ispunct(myString[4]); // Returns true because '!' is a punctuation character.
ispunct(myString[6]); // Returns false because 'G' is not a punctuation character.
```
#### isprint()
Returns true if c is a printable character. Printable characters include alphanumeric, punctuation, and space characters.
#### iscntrl()
Returns true if c is a control character. Control characters are all characters that are not printable.
### cmath
#### fabs()
```cpp
double bodyTemp = 0.0;
cout << "Enter body temperature in Fahrenheit: ";
cin >> bodyTemp;
if (fabs(bodyTemp - 98.6) < 0.0001) {
cout << "Temperature is exactly normal." << endl;
} else if (bodyTemp > 98.6) {
cout << "Temperature is above normal." << endl;
} else {
cout << "Temperature is below normal." << endl;
}
```
### C Standard Library
The [C Standard Library](http://cplusplus.com/reference/cstdlib/) contains many standard general utilities for `C`.
```cpp
#include <cstdlib>
```
#### rand
Returns a pseudo-random integral number in the range between 0 and `RAND_MAX`.
This number is generated by an algorithm that returns a sequence of apparently non-related numbers each time it is called. This algorithm uses a seed to generate the series, which should be initialized to some distinctive value using function `srand`.
`RAND_MAX` is a constant defined in `<cstdlib>`.
A typical way to generate trivial pseudo-random numbers in a determined range using rand is to use the modulo of the returned value by the range span and add the initial value of the range:
```cpp
v1 = rand() % 100; // v1 in the range 0 to 99
v2 = rand() % 100 + 1; // v2 in the range 1 to 100
v3 = rand() % 30 + 1985; // v3 in the range 1985-2014
```
#### srand
The pseudo-random number generator is initialized using the argument passed as seed.
For every different seed value used in a call to `srand`, the pseudo-random number generator can be expected to generate a different succession of results in the subsequent calls to `rand`.
Two different initializations with the same seed will generate the same succession of results in subsequent calls to `rand`.
If seed is set to 1, the generator is reinitialized to its initial value and produces the same values as before any call to rand or `srand`.
In order to generate random-like numbers, `srand` is usually initialized to some distinctive runtime value, like the value returned by function time (declared in header `<ctime>`). This is distinctive enough for most trivial randomization needs.
```cpp
#include <iostream>
#include <cstdlib>
#include <ctime>
int main(int argc, const char * argv[]) {
printf ("First number: %d\n", rand()%100);
srand (time(0));
printf ("Random number: %d\n", rand()%100);
srand (1);
printf ("Again the first number: %d\n", rand()%100);
return 0;
}
```
### cstring
#### comparison
##### strcmp()
`strchr(sourceStr, searchChar)`
Returns `NULL` if `searchChar` does not exist in `sourceStr`. (Else, returns address of first occurrence, discussed elsewhere).
`NULL` is defined in the cstring library.
```cpp
// Given:
char orgName[100] = "United Nations";
char userText[20] = "UNICEF";
char targetText[10];
if (strchr(orgName, 'U') != NULL) { // 'U' exists in orgName?
... // 'U' exists in "United Nations", branch taken
}
if (strchr(orgName, 'u') != NULL) { // 'u' exists in orgName?
... // 'u' doesn't exist (case matters), branch not taken
}
```
#### concatenation
##### strcat()
`strcat(destStr, sourceStr)`
> Copies sourceStr (up to and including null character) to end of destStr (starting at destStr's null character).
```cpp
strcat(orgName, userText); // orgName is "United NationsUNICEF"
```
##### strncat()
`strncat(destStr, sourceStr, numChars)`
> Copies up to numChars characters to destStr's end, then appends null character.
```cpp
strcpy(targetText, "abc"); // targetText is "abc"
strncat(targetText, "123456789", 3); // targetText is "abc123"
```
#### copying
##### strcpy()
`strcpy(destStr, sourceStr)`
> Copies sourceStr (up to and including null character) to destStr.
```cpp
strcpy(targetText, userText); // Copies "UNICEF" + null char
// to targetText
strcpy(targetText, orgName); // Error: "United Nations"
// has > 10 chars
targetText = orgName; // Error: Strings can't be
// copied this way
```
##### strncpy()
`strncpy(destStr, sourceStr, numChars)`
> Copies up to numChars characters.
```cpp
strncpy(orgName, userText, 6); // orgName is "UNICEF Nations"
```
#### Other
##### strlen()
`int strcmp(str1, str2)`
Returns 0 if `str1` and `str2` are equal, non-zero if they differ.
```cpp
// Given:
char orgName[100] = "United Nations";
char userText[20] = "UNICEF";
char targetText[10];
if (strcmp(orgName, "United Nations") == 0) {
... // Equal, branch taken
}
if (strcmp(orgName, userText) == 0) {
... // Not equal, branch not taken
}
```
#### searching
##### strchr()
`size_t strlen(sourceStr)`
Returns number of characters in `sourceStr` up to, but not including, first null character. `size_t` is integer type.
```cpp
// Given:
char orgName[100] = "United Nations";
char userText[20] = "UNICEF";
char targetText[10];
x = strlen(orgName); // Assigns 14 to x
x = strlen(userText); // Assigns 6 to x
x = strlen(targetText); // Error: targetText may lack null char
```
### Streams
- Refer to: [[#streams]]
- And Also: [[#files]]
### The String Library
[\<string\>](http://cplusplus.com/reference/string/string/)
> Strings are objects that represent sequences of characters.
This library include the `string` class and this class has various methods that allow us to perform string manipulation.
#### capacity
##### clear()
Deletes characters, sets size to 0.
```cpp
// userText is "Help me!"
userText.clear(); // Clears string
userText.size(); // Returns 0
userText.at(0); // Generates exception
```
##### empty()
True is length is 0
```cpp
// userText is "Help me!"
userText.empty() // Returns false
// userText is ""
userText.empty() // Returns true
```
##### length() & size()
Same idea as `len()`
```cpp
// userText is "Help me!"
userText.length() // Returns 8
userText.size() // Returns 8
// userText is ""
userText.length() // Returns 0
```
##### resize( num )
Resize string to have num characters.
If decrease, drops extra chars.
If increase, sets new chars to null ('\\0', ASCII value 0).
```cpp
// userText is "Help me!"
userText.resize(4); // Now "Help"
userText.size(); // Returns 4
```
#### element-access
##### at
> C++ also supports C-style access of a string using brackets \[] rather than .at(), as in: someString[0]. However, such C-style access does not provide such error checking. Good practice is to use .at() rather than brackets for accessing a string's characters, due to .at()'s error checking.
>
> \-- zybooks
```cpp
string name = "bryan";
cout << name.at(1) << endl;
//#> r
```
#### modifiers
##### append( moreString )
Appends a copy of string `moreString`.
```cpp
// userText is "Hi"
userText.append(" friend"); // Now "Hi friend"
userText.length(); // Returns 9
```
##### insert( index, subStr )
Inserts string `subStr` starting at `index`.
```cpp
// userText is "Goodbye"
userText.insert(0, "Well "); // Now "Well Goodbye"
// userText is "Goodbye"
userText.insert(4, "---"); // Now "Good---bye"
```
##### push-back
Appends `newChar` to the end.
_NOTE_ that the char has to be wrapped in single quotes as mentioned in [[#Character]]
```cpp
// userText is "Hello"
userText.push_back('?'); // Now "Hello?"
userText.length(); // Returns 6
```
##### replace( index, num, subStr )
Replaces characters at indices `index` to `index + num - 1` with a copy of `subStr`.
```cpp
// userText is "You have many gifts"
userText.replace(9, 4, "a plethora of");
// Now "You have a plethora of gifts"
```
#### string-operations
##### find( item, index )
Starts at a 0 index and returns index position of your input. Optional 2nd argument can tell you which index to start at so as to skip the first occurrence of something.
```cpp
// userText is "Help me!"
userText.find('p') // Returns 3
userText.find('e') // Returns 1 (first occurrence of e only)
userText.find('z') // Returns string::npos
userText.find("me") // Returns 5
userText.find('e', 2) // Returns 6 (starts at index 2)
```
##### substr( index, len )
Returns substring starting at index and having len characters.
```cpp
// userText is "http://google.com"
userText.substr(0, 7) // Returns "http://"
userText.substr(13, 4) // Returns ".com"
userText.substr(userText.length() - 4, 4) // Last 4: ".com"
```
### C Time Library
[\\<ctime>](http://cplusplus.com/reference/ctime/)
#### Time Manipulation
##### time
[time()](http://cplusplus.com/reference/ctime/time/)
> The value returned generally represents the number of seconds since 00:00 hours, Jan 1, 1970 UTC (i.e., the current unix timestamp). Although libraries may use a different representation of time: Portable programs should not use the value returned by this function directly, but always rely on calls to other elements of the standard library to translate them to portable types (such as `localtime`, `gmtime` or `difftime`).
```cpp
time(0)
```
### Site Definition
[vector](http://cplusplus.com/reference/vector/vector/)
> Vectors are sequence containers representing arrays that can change in size.
> .
> Just like arrays, vectors use contiguous storage locations for their elements, which means that their elements can also be accessed using offsets on regular pointers to its elements, and just as efficiently as in arrays. But unlike arrays, their size can change dynamically, with their storage being handled automatically by the container.
#### Vector Member Functions
##### Capacity
###### resize()
To dynamically resize a vector while program is executing and size is not known during compile time.
```cpp
vctr.resize(N); // Allocates N elements for vector vctr.
```
resize is now adding new slots on top of existing elements, rather it just states that _"THIS is how many elements are in this vector"_. If the resize value is smaller than the vectors current size, all elements in indexes larger than `N` are destroyed and `N` is now the size of the vector.
##### element-access
###### at()
Returns the value at the index number given like the traditional array syntax:
```cpp
vector.at(1) == array[1]; // True
```
you can even use the array syntax on the vector although `.at()` is recommended due to superior error checking just like strings:
###### back()
Basically asks _"Hey, whats the item at the end? i don't know the index but that's the last value??"_
```cpp
// playersList initially 55, 99, 44
cout << playersList.back(); // Prints 44
// playersList is still 55, 99, 44
```
##### modifiers
###### pop_back()
Just like `pop()` in Javascript, this removes the last element from the vector.
```cpp
// playersList is 55, 99, 44 (size 3)
playersList.pop_back(); // Removes last element
// playersList now 55, 99 (size 2)
cout << playersList.back(); // Common combination of back()
playersList.pop_back(); // followed by pop_back()
// Prints 99. playersList becomes just 55
cout << playersList.pop_back(); // Common error
// pop_back() returns void
```
###### push_back()
just like `push()` in Javascript for vectors you are adding a new element to the vector and therefore creating a single new index.
```cpp
// playersList initially 55, 99, 44 (size is 3)
playersList.push_back(77); // Appends new element, sets value to 77
// playersList is now 55, 99, 44, 77 (size is 4)
```
#### modification
##### Vector copying
In this example `salePrices = origPrices;`
```cpp
const int NUM_ELEMENTS = 4; // Number of elements
vector<int> origPrices(NUM_ELEMENTS); // Original prices
vector<int> salePrices(NUM_ELEMENTS); // Sale prices
int i = 0; // Loop index
// Assign original prices
origPrices.at(0) = 10;
origPrices.at(1) = 20;
origPrices.at(2) = 30;
origPrices.at(3) = 40;
// Copy original prices to sales prices
salePrices = origPrices;
```
vector `salePrices` is empty and of size 0 until it copies every element in `origPrices`. This is a complete duplication and takes up twice the memory.
##### Vector Equality
in the above example in [[#Vector copying]], if one were to change the values in some of the elements in `salePrices` and then perform an equality check `==` then the vector will compare element to element through the whole vector and return a boolean result.
```cpp
// Update salePrices. Note: does not affect origPrices
salePrices.at(2) = 27;
salePrices.at(3) = 35;
salePrices == origPrices; // because of above they are no longer equal
// or identical, result is false
```
## files
### Extraction Before Getline
> The `getline()` function and the extraction operator `>>` handle a trailing newline differently, which can lead to a problem.
>
> - The `getline()` function reads a line of text from a buffer, **discarding the ending newline character**.
> - The extraction operator `>>` skips <u>whitespace</u>, then reads the next item such as an integer or string which is said to end at the next <u>whitespace</u>, leaving that ending whitespace character in the buffer (an exception being for reading a single character).
> The problem is that code like `cin >> myInt;` and `getline(cin, nextLine);` may not behave as expected if the integer is ended with a newline. The `getline()` function will read that single remaining newline character, returning an empty string, rather than proceeding to the next line.
> .
> A simple solution is to not mix the two approaches to reading an input buffer, either only using extraction, or only using `getline()`.
> .
> If one must mix the two approaches, then after an extraction operation, the trailing newline should be discarded from the buffer before calling the `getline()`, by inserting some statement in between. One possible solution inserts `cin.ignore()`, which discards the next character in the input buffer. Another possible approach inserts another `getline()` call, ignoring its blank string.
### Input
> Sometimes a program should get input from a file rather than from a user typing on a keyboard. To achieve this, a programmer can create a new input stream that comes from a file, rather than the predefined input stream `cin` that comes from the standard input (keyboard). That new input stream can then be used just like `cin`, as the following program illustrates. Assume a text file exists named _myfile.txt_ with the contents shown (created for example using Notepad on a Windows computer or using TextEdit on a Mac computer).
```
myfile.txt with two integers:
5
10
```
```cpp
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ifstream inFS; // Input file stream
int fileNum1 = 0; // Data value from file
int fileNum2 = 0; // Data value from file
// Try to open file
cout << "Opening file myfile.txt." << endl;
inFS.open("myfile.txt");
if (!inFS.is_open()) {
cout << "Could not open file myfile.txt." << endl;
return 1; // 1 indicates error
}
// Can now use inFS stream like cin stream
// myfile.txt should contain two integers, else problems
cout << "Reading two integers." << endl;
inFS >> fileNum1;
inFS >> fileNum2;
cout << "Closing file myfile.txt." << endl;
inFS.close(); // Done with file, so close it
// Ouput values read from file
cout << "num1: " << fileNum1 << endl;
cout << "num2: " << fileNum2 << endl;
cout << "num1 + num2: " << (fileNum1 + fileNum2) << endl;
return 0;
}
```
> **Five** lines are needed for the new input stream, highlighted above.
> .
>
> - The `#include <fstream>` (for "_file stream_") enables use of the file stream class.
> - A new stream variable has been declared: `ifstream inFS;`. `ifstream` is short for _input file stream_, and is derived from `istream`.
> - The line `inFS.open("myfile.txt");` opens the file for reading and associates the file with the `inFS` stream. Because of the high likelihood that the open fails, usually because the file does not exist or is in use by another program, the program checks whether the open was successful using `if (!inFS.is_open())`.
> - The successfully opened input stream can then be used just like the `cin` stream, e.g., using `inFS >> num1;` to read an integer into `num1`.
> - Finally, when done using the stream, the program closes the file using `inFS.close()`.
> - A common error is to type `cin >> num1;` when actually intending to get data from a file as in `inFS >> num1`. Another common error is a mismatch between the variable data type and the file data, e.g., if the data type is int but the file data is "Hello".
> The `inFS.open(str)` function has a string parameter str, which can be a C++ string or a null-terminated C string. A program often uses a user-entered string as the filename, such as using `cin >> filename;`.
```cpp
/* Given
datafile.txt with two integers:
72
68
*/
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
ifstream inFS; // Input file stream
int fileNum1 = 0; // File data
int fileNum2 = 0; // File data
string filename = ""; // Input filename
// Prompt user for filename
cout << "Enter filename: " << endl;
cin >> filename;
// Try to open file
inFS.open(filename);
if (!inFS.is_open()) {
cout << "Could not open file " << filename << endl;
return 1;
}
// Get numbers. If too few, may encounter problems
inFS >> fileNum1;
inFS >> fileNum2;
// Done with file, close it
inFS.close();
// Ouput values read from file
cout << "num1: " << fileNum1 << endl;
cout << "num2: " << fileNum2 << endl;
cout << "num1 + num2: " << (fileNum1 + fileNum2) << endl;
return 0;
}
/*
Enter filename:
datafile.txt
num1: 72
num2: 68
num1 + num2: 140
*/
```
> A program can read varying amounts of data in a file by using a loop that reads until the end of the file has been reached, as follows.
> .
> The `eof()` function returns true if the previous stream operation reached the end of the file. Errors may be encountered while attempting to read from a file, including end-of-file, corrupt data, etc. So, a program should check that each read was successful before using the variable to which the data read was assigned. The `good()` function returns true if the previous stream operation had no problems. Ex: `if( inFS.good() ) {...} `checks that the previous read operation was successful.
```cpp
/* Given:
myfile.txt with variable number of integers:
111
222
333
444
555
*/
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ifstream inFS; // Input file stream
int fileNum = 0; // File data
// Open file
cout << "Opening file myfile.txt." << endl;
inFS.open("myfile.txt");
if (!inFS.is_open()) {
cout << "Could not open file myfile.txt." << endl;
return 1;
}
// Print read numbers to output
cout << "Reading and printing numbers." << endl;
while (!inFS.eof()) {
inFS >> fileNum;
if( inFS.good() ) {
cout << "num: " << fileNum << endl;
}
}
cout << "Closing file myfile.txt." << endl;
// Done with file, so close it
inFS.close();
return 0;
}
/*
Opening file myfile.txt.
Reading and printing numbers.
num: 111
num: 222
num: 333
num: 444
num: 555
Closing file myfile.txt.
*/
```
### Output
`ofstream` = Output File Stream
```cpp
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ofstream outFS; // Output file stream
// Open file
outFS.open("myoutfile.txt");
if (!outFS.is_open()) {
cout << "Could not open file myoutfile.txt." << endl;
return 1;
}
// Write to file
outFS << "Hello" << endl;
outFS << "1 2 3" << endl;
// Done with file, so close it
outFS.close();
return 0;
}
```
### Stream Errors
> A **stream error** occurs when insertion or extraction fails, causing the stream to enter an error state.
```cpp
#include <iostream>
using namespace std;
int main() {
int num1 = -1; // Initial value -1 for demo purposes.
int num2 = -1;
cout << "Enter a number: " << endl;
cin >> num1; // Stream error state entered here.
cout << "Enter a second number:" << endl;
cin >> num2; // Stream already in error state, so extraction skipped.
cout << "num1: " << num1 << endl;
cout << "num2: " << num2 << endl;
return 0;
}
/*
Enter a number:
six
Enter a second number:
num1: 0
num2: -1
*/
```
> A stream's error state can be checked with a function. Ex: `cin.good() `returns true if `cin` is not in an error state. Otherwise, false is returned. A stream internally uses several 1-bit error flags to track the state of the stream.
| Flag | Meaning | Function |
| :-------- | :---------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------- |
| `goodbit` | Indicates no error flags are set and the stream is good. | `good()` returns true if no stream errors have occurred. |
| `eofbit` | Indicates if end-of-file reached on extraction. | `eof()` returns value of eofbit, if end-of-file reached on extraction. |
| `failbit` | Indicates a logical error for the previous extraction or insertion operation. | `fail()` returns true if either failbit or badbit is set, indicating an error for the previous stream operation. |
| `badbit` | Indicates an error occurred reading or writing the stream, and the stream is bad. Further operations on the stream will fail. | `bad()` returns true if badbit is set, indicating the stream is bad. |
> A stream's error state is cleared using `clear()`. Ex: `cin.clear()` clears the error state from `cin`.
> .
> The function `ignore(maxToIgnore, stopChar)` ignores characters in the stream buffer. Ex: `cin.ignore(10, '\n') `ignores up to 10 characters in the stream buffer, or until a '`\n`' character is encountered.
> .
> Commonly, a program needs to wait until a '`\n`' character is found, in which case set `maxToIgnore` to the maximum size of a stream: `numeric_limits<streamsize>::max()`.
```cpp
// Read user input until a number is entered
#include <iostream>
#include <limits>
using namespace std;
int main() {
int number = 0;
cout << "Enter a number: " << endl;
cin >> number;
while (cin.fail()) {
// Clear error state
cin.clear();
// Ignore characters in stream until newline
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Try again: " << endl;
cin >> number;
}
cout << "You entered: " << number << endl;
return 0;
}
```
> A program may need to check for errors during file reading.
> One approach is to check whether end-of-file was reached after the file reading ends. If end-of-file was not reached, then an error in file reading occurred.
```cpp
/* Given:
myfile.txt:
5
8
six
4
6
*/
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ifstream inFS;
int fileNumber = 0; // Number in file
inFS.open("myfile.txt");
if (!inFS.is_open()) {
cout << "Could not open file myfile.txt." << endl;
return 1;
}
// Read file until end-of-file or an error
while (inFS.good()) {
inFS >> fileNumber;
cout << "File number: " << fileNumber << endl;
}
// If end-of-file not reached, then an error occurred
if (!inFS.eof()) {
cout << "Error reading myfile.txt" << endl;
return 1;
}
inFS.close();
return 0;
}
/*
File number: 5
File number: 8
File number: 0
Error reading myfile.txt
*/
```
## flow
### case statements
#### Syntax
```cpp
int main() {
int num = 0;
cout << "Enter a number (1,2, or 3: ";
cin >> num;
switch (num) {
case 1:
cout << "You Chose 1!" << endl;
break;
case 2:
cout << "You Chose 2!" << endl;
break;
case 3:
cout << "You Chose 3!" << endl;
break;
default:
cout << "WUT" << endl;
break;
}
return 0;
}
```
#### Multi-Case Flows
If you line up a bunch of cases like this:
```cpp
int main() {
int dogAgeYears = 0;
int dogAgeMonths = 0;
cout << "Enter dog's age (in years): ";
cin >> dogAgeYears;
if (dogAgeYears == 0) {
cout << "Enter dog's age in months: ";
cin >> dogAgeMonths;
switch (dogAgeMonths) {
case 0:
case 1:
case 2:
cout << "That's 0..14 human months." << endl;
break;
case 3:
case 4:
case 5:
case 6:
cout << "That's 1..5 human years." << endl;
break;
case 7:
case 8:
cout << "That's 5..9 human years." << endl;
break;
case 9:
case 10:
case 11:
case 12:
cout << "That's 9..15 human years." << endl;
break;
default:
cout << "Invalid input." << endl;
break;
}
}
else {
cout << "FIXME: Do earlier dog year cases." << endl;
switch (dogAgeYears) {
}
}
return 0;
}
```
The cases for 3,4,5, and 6 will all cause the same result, i.e. the result for case 6. The other cases will hit and then flow down executing all code until they finally hit a `break;` statement. This can be useful shorthand for grouping multiple inputs to the same output code. 723541
### if-else
#### Single-Branch
```cpp
// Statements that execute before the branches
if (expression) {
// Statements to execute when the expression is true (first branch)
} else {
// Statements to execute when the expression is false (second branch)
}
// Statements that execute after the branches
```
#### Multi-Branch
The more branches you add to an If-Statement the more it becomes advantageous to just use a case statement^\[[[#case statements]]]
```cpp
if (expr1) {
} else if (expr2) {
} else if (exprN) {
} else {
}
```
#### Short Circuit Evaluation
> A logical operator evaluates operands from left to right. **Short circuit evaluation** skips evaluating later operands if the result of the logical operator can already be determined.
| Operator | Example | Short Circuit Evaluation |
| ---------------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------- |
| operand1 && operand2 | true && operand2 | If the first operand evaluates to true, operand2 is evaluated. |
| operand1 && operand2 | false && operand2 | If the first operand evaluates to false, the result of the AND operation is always false, so operand2 is not evaluated. |
| operand1 \|\| operand2 | true \|\| operand2 | If the first operand evaluates to true, the result of the OR operation is always true, so operand2 is not evaluated. |
| operand1 \|\| operand2 | false \|\|operand2 | If the first operand evaluates to false, operand2 is evaluated. |
### loops
#### for
For Loops Are Cleaner Than [[#While Loops]]
A real benefit of For loops is that they can clean up a lot of the syntax of while loops when while loops are used for iterations that can be calculated before the initiation of the loop, rather than _"Run this while loop until a condition is met sometime at some point"_.
##### The break statement
Just like [[#case statements]] the `break;` keyword will cause the loop to end, just like the case statement will run, executing all code on the flow down until it hits a `break;` statement
##### The continue Statement
```cpp
for ( int i = 0; i <= 19; i++ ) {
if ( ( i % 10 ) == 0 ) {
continue;
}
cout << i << endl;
}
```
The `continue;` statement will skip everything else in the loop and go to the next iteration of the loop.
In this case it will not send 10 to cout because it was told to continue on.
when the if condition found that the 10 was divisible by 10 with modulus division: `%`, it then ran `continue;` and said _"skip the printing of this value"_.
##### For Loop Syntax
```cpp
for (initialExpression; conditionExpression; updateExpression) {
// Loop body: Sub-statements to execute if the
// conditionExpression evaluates to true
}
// Statements to execute after the expression evaluates to false
```
##### When to use For loops v.s. While Loops
| Loop | Usage |
| :-------: | :------------------------------------------------------------------------------------------------------------------------------------------------ |
| **For** | _Use when the number of iterations is computable before entering the loop, as when counting down from X to 0, printing a character N times, etc._ |
| **While** | _Use when the number of iterations is not computable before entering the loop, as when iterating until a user enters a particular character._ |
#### While Loops
##### Eval First While Loop
The condition is **evaluated first** before running any body code of the loop.
```cpp
while (expression) { // <-- Loop expression
// Loop body: Sub-statements that execute if the
// expression evaluats to true
}
// Statements that execute after the expression evaluates to false
// Or loop concludes
```
##### Execute Then Eval Do-While Loop
This condition will always **execute the body** code once before testing the expression for `true`. You can use this if you want the code executed at least once before the loop has a chance to break itself on its tested condition.
```cpp
do {
// Loop body
} while (loopExpression);
```
## funcs
### Declaration
> A **function declaration** specifies the function's return type, name, and parameters, ending with a semicolon where the opening brace would have gone
```cpp
void Hello( string firstName, string lastName );
```
### Definition
The meat of your function. This is where all the body code goes and where you actually perform your coded actions. These are the fleshed out versions of function [[#Declaration]]'s.
```cpp
void Hello( string firstName, string lastName ) {
cout << "Hello " << firstName << " " << lastName << endl;
}
```
### header file
[[#preprocessor directives]]
### Parameters
Parameters passed to a function need to have their data types explicitly declared as well so the function knows what type of data it is receiving:
```cpp
#include <string>
void SayHello ( string name, int age ) {
std::cout << "Hello " << name
<< " you are: " << age << " years old!" << std::endl;
}
int main () {
string myName = "Bryan";
int myAge = 28;
SayHello( myName, myAge );
}
//#> "Hello Bryan you are: 28 years old!"
```
#### Default Parameters
> Sometimes a function's last parameter (or last few) should be optional. A function call could then omit the last argument, and instead the program would use a default value for that parameter. A function can have a **default parameter value** for the last parameter(s), meaning a call can optionally omit a corresponding argument.
```cpp
#include <iostream>
using namespace std;
// Function prints date in two styles (0: American (default), 1: European)
void DatePrint(int currDay, int currMonth, int currYear, int printStyle = 0) {
if (printStyle == 0) { // American
cout << currMonth << "/" << currDay << "/" << currYear;
}
else if (printStyle == 1) { // European
cout << currDay << "/" << currMonth << "/" << currYear;
}
else {
cout << "(invalid style)";
}
return;
}
int main() {
// Print dates given various style settings
DatePrint(30, 7, 2012, 0);
cout << endl;
DatePrint(30, 7, 2012, 1);
cout << endl;
DatePrint(30, 7, 2012); // Uses default value for printStyle
cout << endl;
return 0;
}
```
### pass by reference vs pass by value
#### Pass By References
> A **pass by reference** parameter does not create a local copy of the argument, but rather the parameter refers directly to the argument variable's memory location. Appending & to a parameter's data type makes the parameter pass by reference type.
```cpp
void MyFunction( vector<int>& inputVector ) {
// References my vector but doesnt copy it into the function
// body scope taking up an identical amount of memory.
cout << inputVector.at(16345) << endl;
}
int main() {
vector<int> myVector(785746353);
MyFunction(myVector);
}
```
##### Pass By References with Const
In [[#Pass By References]] the `inputVector` was passed by reference which means any changes made to the vector inside the function body would result in mutation of the original vector as we referred to the original vector.
To prevent mutation of the original vector but take advantage of a pass by reference for efficiency we can prepend `const` to our input parameter so that we wont accidentally be able to mutate that pass by reference value.
```cpp
void MyFunction( const vector<int>& inputVector ) {
// References my vector but doesnt copy it into the function
// body scope taking up an identical amount of memory.
cout << inputVector.at(16345) << endl;
}
int main() {
vector<int> myVector(785746353);
MyFunction(myVector);
}
```
#### Pass By Value
[[#Parameters]] are pass by value, meaning the argument's value is copied into a local variable for the parameter. This duplication is expensive with large items like [[#Vectors are Array++]].
### Return Statement
A function can only return one item, no more. The return statement is what value you want the function to return to you.
If your function [[#Return type]] is `void` then you are returning nothing and you will just use the keyword by itself: `return;`
```cpp
int Square ( int num1, int num2 ) {
return num1 * num2;
}
int main() {
int myNum = 7;
std::cout << Square(myNum) << std::endl;
}
//#> 49
```
### Return type
Before each function [[#Declaration]] you must have a return type for that function. The return type is the data type for what is returned by the function. Most of the data types you will use are in [[#Variables]] but one you will also use is `void` this is when the function will return nothing to you, but it may perform actions such as mutate data, or log things to the console, but no value is returned.
```cpp
void SayHello() {
std::cout << "hello world!" << std::endl;
}
int main() {
SayHello();
}
//#> "hello world!"
```
## mem mgmt
### Static Memory
> The region where global variables (_variables declared outside any function_) as well as static local variables (_variables declared inside functions starting with the keyword "static"_) are allocated. The name "static" comes from these variables not changing (_static means not changing_); they are allocated once and last for the duration of a program's execution, their addresses staying the same.
#### The Stack
> The region where a function's local variables are allocated <u>during a function call</u>. A function call adds local variables to the stack, and a return removes them, like adding and removing dishes from a pile; hence the term "_stack_." Because this memory is automatically allocated and deallocated, it is also called **automatic memory**.
#### The Heap
> The region where the "_new_" operator allocates memory, and where the "_delete_" operator deallocates memory. The region is also called **free store**.
### Pointers
> A **pointer** is a variable that contains a memory address, rather than containing data like most variables
#### Example
```cpp
#include <iostream>
using namespace std;
int main() {
int usrInt = 0; // User defined int value
int* myPtr = nullptr; // Pointer to the user defined int value
// Prompt user for input
cout << "Enter any number: ";
cin >> usrInt;
// Output int value and address
cout << "We wrote your number into variable usrInt." << endl;
cout << "The content of usrInt is: " << usrInt << "." << endl;
cout << "usrInt's memory address is: " << &usrInt << "." << endl;
cout << endl << "We can store that address into pointer variable myPtr."
<< endl;
// Grab address storing user value
myPtr = &usrInt;
// Output pointer value and value at pointer address
cout << "The content of myPtr is: " << myPtr << "." << endl;
cout << "The content of what myPtr points to is: "
<< *myPtr << "." << endl;
return 0;
}
```
#### operators
##### The 'delete' Operator
> The **delete** operator does the opposite of the new operator. The statement `delete pointerVariable`; deallocates a memory block pointed to by pointerVariable, which must have been previously allocated by new. If pointerVariable is null, delete has no effect.
```cpp
new pointerVariable;
delete pointerVariable;
```
##### The 'New' Operator
> Sometimes memory should be allocated while a program is running and should persist independently of any particular function. The **new** operator allocates memory for the given type and returns a pointer (i.e., the address) to that allocated memory.
```cpp
#include <iostream>
using namespace std;
int main() {
int* myPtr = nullptr;
cout << "myPtr: " << myPtr << endl;
// Next line would cause error because myPtr is null
// cout << "*myPtr: " << *myPtr << endl; // ERROR
// new allocates int, returns pointer
myPtr = new int;
cout << "myPtr: " << myPtr << endl;
cout << "*myPtr: " << *myPtr << endl;
*myPtr = 555;
cout << "*myPtr: " << *myPtr << endl;
return 0;
}
```
> The new operator is commonly used with class types, as in `new SimpleItem;` where `SimpleItem` is a class name. After new allocates memory for a class object, the object's constructor is called. Arguments may be provided after the class name to call a non-default constructor.
```cpp
#include <iostream>
using namespace std;
class SimpleItem {
public:
void PrintNums();
SimpleItem(int initVa1 = -1, int initVal2 = -1);
private:
int num1;
int num2;
};
SimpleItem::SimpleItem(int initVal1, int initVal2) {
num1 = initVal1;
num2 = initVal2;
return;
}
void SimpleItem::PrintNums() {
cout << "num1: " << num1 << endl;
cout << "num2: " << num2 << endl;
return;
}
int main() {
SimpleItem* myItemPtr1 = nullptr;
SimpleItem* myItemPtr2 = nullptr;
myItemPtr1 = new SimpleItem;
(*myItemPtr1).PrintNums();
cout << endl;
myItemPtr2 = new SimpleItem(8, 9);
(*myItemPtr2).PrintNums();
return 0;
}
```
#### symbol usage
##### Dereferencing a Pointer
> Prepending `*` to a pointer variable's name in an expression gets the data to which the variable points, as in `*myPtr1`, an act known as **dereferencing** a pointer variable. `*` is the dereference operator that allows the program to access the value pointed to by the pointer using the form:
```cpp
*myInt;
```
##### Get Memory Address
> Prepending `&` to any variable's name gets the variable's address. `&` is the reference operator that returns a pointer to a variable using the following form:
```cpp
&myInt;
```
##### Null Pointer
> The pointer was initialized to **`nullptr`**. The `nullptr` keyword is a literal indicating a pointer points to nothing. A pointer assigned with `nullptr` is said to be null.
##### Pointer Variables
> Appending `*` after a data type in a variable declaration declares a pointer variable, as in `int* myPtr`. One might imagine that the programming language would have a type like address in addition to types like int, char, etc., but instead the language requires each pointer variable to indicate the type of data to which the address points. So valid pointer variable declarations are `int* myPtr1`, `char* myPtr2`, `double* myPtr3`, and even `Seat* myPtr4;` (where Seat is a class type); all such variables will contain memory addresses.
```cpp
int* myInt;
```
#### Using Pointers Example
```cpp
#include <iostream>
using namespace std;
int main() {
double vehicleMpg = 0.0;
double* valPtr = nullptr;
valPtr = &vehicleMpg;
*valPtr = 29.6; // Assigns the number to the variable
// POINTED TO by valPtr.
// vehicleMpg = 40; // Uncomment this later
cout << "Vehicle MPG = " << vehicleMpg << endl;
cout << "Vehicle MPG = " << *valPtr << endl;
return 0;
}
```
## Object Oriented Programming
> The **class** construct defines a new type that can group data and functions to form an object
### Classes with vectors
#### Example
```cpp
#include <iostream>
#include <vector>
#include <string>
using namespace std;
/*** Seat class definition ***/
class Seat {
public:
void Reserve(string resfirstName, string resLastName, int resAmountPaid);
void MakeEmpty();
bool IsEmpty() const;
void Print() const;
private:
string firstName;
string lastName;
int amountPaid;
};
void Seat::Reserve(string resfirstName, string resLastName, int resAmountPaid) {
firstName = resfirstName;
lastName = resLastName;
amountPaid = resAmountPaid;
return;
}
void Seat::MakeEmpty() {
firstName = "empty";
lastName = "empty";
amountPaid = 0;
return;
}
bool Seat::IsEmpty() const {
return(firstName == "empty");
}
void Seat::Print() const {
cout << firstName << " " << lastName << ", ";
cout << "Paid: " << amountPaid << endl;
return;
}
/*** End definitions for Seat class ***/
/*** Functions for vector of Seat objects ***/
void SeatsMakeEmpty(vector<Seat>& seats) {
unsigned int i = 0;
for (i = 0; i < seats.size(); ++i) {
seats.at(i).MakeEmpty();
}
return;
}
void SeatsPrint(vector<Seat> seats) {
unsigned int i = 0;
for (i = 0; i < seats.size(); ++i) {
cout << i << ": ";
seats.at(i).Print();
}
return;
}
void SeatsCreateReservation(vector<Seat>& seats) {
string firstName, lastName;
int amountPaid = 0;
unsigned int seatNum = 0;
Seat seat;
cout << "Enter seat number (0..";
cout << seats.size() - 1 << "): ";
cin >> seatNum;
if (seatNum > (seats.size() - 1)) {
cout << "Seat number too large." << endl;
}
else if ( !(seats.at(seatNum).IsEmpty()) ) {
cout << "Seat already occupied." << endl;
}
else {
cout << "Enter first name: ";
cin >> firstName;
cout << "Enter last name: ";
cin >> lastName;
cout << "Enter amount paid: ";
cin >> amountPaid;
seat.Reserve(firstName, lastName, amountPaid);
seats.at(seatNum) = seat;
cout << "Completed." << endl;
}
return;
}
/*** End functions for vector of Seat objs ***/
int main() {
char userKey = '-';
vector<Seat> seats(5);
SeatsMakeEmpty(seats);
while (userKey != 'q') {
cout << endl << "Enter command (p/r/q): ";
cin >> userKey;
if (userKey == 'p') { // Print seats
SeatsPrint(seats);
}
else if (userKey == 'r') { // Reserve seat
SeatsCreateReservation(seats);
}
else if (userKey == 'q') { // Quit
cout << "Quitting." << endl;
}
else {
cout << "Invalid command." << endl;
}
}
return 0;
}
```
### constructors
Constructors initialize instances of a class. A best practice is to initialize all variables when declared (likely to keep them in the same memory location on the stack).
Constructors share the same name as the class name:
```cpp
#include <iostream>
#include <string>
using namespace std;
/*** ShopItem class definition ***/
class ShopItem {
public:
void SetNameAndPrice(string itemName, int itemPrice);
void Print() const;
ShopItem(); // Default constructor
private:
string name; // Ex: "Bag of salad"
int price; // Price in cents. Ex: 199
};
ShopItem::ShopItem() { // Default constructor
name = "NoName"; // Default name
price = -1; // Default price
return;
}
void ShopItem::SetNameAndPrice(string itemName, int itemPrice) {
name = itemName;
price = itemPrice;
return;
}
void ShopItem::Print() const {
cout << "Name: " << name << ", ";
cout << "Price: " << price << endl;
return;
}
/*** End definitions for ShopItem class ***/
int main() {
ShopItem item1; // Auto-calls default constructor
item1.Print();
item1.SetNameAndPrice("Soap", 385);
item1.Print();
return 0;
}
```
#### Constructor Overloading
Just like with [[#Operator Overloading]] you can overload a constructor to instantiate the same object (class) with different initialization values based on the parameters passed to the constructor:
```cpp
class Seat {
public:
...
Seat(); // Default constructor
Seat(string resfirstName, string resLastName, int resAmountPaid); // Second constructor
...
};
Seat::Seat() { // Default constructor
firstName = "none";
lastName = "none";
amountPaid = -1;
}
Seat::Seat(string resfirstName, string resLastName, int resAmountPaid) { // Second constructor
firstName = resfirstName;
lastName = resLastName;
amountPaid = resAmountPaid;
}
```
#### Constructor Member Initialization
```cpp
// Given
class SampleClass {
public:
SampleClass();
void Print() const;
private:
int field1;
int field2;
};
// Instead of this:
SampleClass::SampleClass() {
field1 = 100;
field2 = 200;
return;
}
// You can do this:
SampleClass::SampleClass() : field1(100), field2(200) {
return;
}
```
This is not particularly useful for members of basic types, but for data members like [[#Vectors are Array++]] that need to be explicitly constructed with a size, this can be very useful:
```cpp
class SampleClass {
public:
SampleClass();
void Print() const;
private:
vector<int> itemList;
// vector<int> itemList(2); not allowed
};
SampleClass::SampleClass() : itemList(2) {
// itemList gets constructed with size 2
return;
}
```
### Data management
The best practice is to make all data members in a class private.
if a data member is declared but is not under a specific label of `public:` or `private:` then the default is **private**. The opposite is true in [[#Structs]].
### derived classes
> Commonly, one class is similar to another class but with some additions or variations. For example, a store inventory system might use a class called GenericItem having itemName and itemQuantity members. But for produce (fruits and vegetables), a class ProduceItem having itemName, itemQuantity, and expirationDate members may be desired. Note that ProduceItem is really a GenericItem with an additional feature, so ideally a program could define the ProduceItem class as being the same as the GenericItem class but with the addition of an expirationDate member.
### Example
```cpp
#include <iostream>
using namespace std;
class RunnerInfo {
public: // The class' public functions
void SetTime(int timeRunSecs); // Time run in seconds
void SetDist(double distRunMiles); // Distance run in miles
double GetSpeedMph() const; // Speed in miles/hour
private: // The class' private internal data members
int timeRun;
double distRun;
};
// "RunnerInfo::" means SetTime is a RunnerInfo member function
void RunnerInfo::SetTime(int timeRunSecs) {
timeRun = timeRunSecs; // timeRun refers to data member
return;
}
void RunnerInfo::SetDist(double distRunMiles) {
distRun = distRunMiles;
return;
}
double RunnerInfo::GetSpeedMph() const {
return distRun / (timeRun / 3600.0); // miles / (secs / (hrs / 3600 secs))
}
int main() {
RunnerInfo runner1; // User-created object of class type RunnerInfo
RunnerInfo runner2; // A second object
runner1.SetTime(360);
runner1.SetDist(1.2);
runner2.SetTime(200);
runner2.SetDist(0.5);
cout << "Runner1's speed in MPH: " << runner1.GetSpeedMph() << endl;
cout << "Runner2's speed in MPH: " << runner2.GetSpeedMph() << endl;
return 0;
}
```
```cpp
class ClassName {
public:
// Public member functions
private:
// Private data members
};
```
### member functions
A member function is a funcs that is a _member_ of a class.
Typically these are `public` functions so that the user can call them as methods of the class instances. There are however private member functions that do some work in the background that the user doesn't even know exist.
#### Inline Member Functions
Unlike the example you can put all the code for a member function in the class declaration. this is called an Inline Member Function, because the function is in the class declaration.
```cpp
class RunnerInfo {
public:
void SetTime(int timeRunSecs) { // Here is the inline function
timeRun = timeRunSecs;
}
void SetDist(double distRunMiles);
double GetSpeedMph() const;
private:
int timeRun;
double distRun;
};
void RunnerInfo::SetDist(double distRunMiles) {
distRun = distRunMiles;
return;
}
```
#### Member Access Operator
These function use the `.` operator known as the `Member Access Operator` which is typical dot notation of `class.method();`
Typically the class will have `getter` and `setter` functions some to set the values of the private data members to the value of inputted data, and others to output that data for the user to use.
#### Mutators, Accessors, and Private Helpers
> Commonly, a data member has a pair of associated functions: a mutator for setting its value, and an accessor for getting its value, as above. Those functions are also known as a **setter** and **getter** functions, respectively, and typically have names that start with set or get.
##### Accessors
Accessors can let the user access the values of the private data members:
> Accessor functions usually are defined as const, to enforce that they do not change data members. The keyword **const** after a member function's declaration and definition causes the compiler to report an error if the function modifies a data member. **<u>If a const member function calls another member function, that function must also be const.</u>**
```cpp
int GetPlayer1PlayA() const; // Accessor
int GameInfo::GetPlayer1PlayA() const {
return player1PlayA;
}
```
##### Example
```cpp
#include <iostream>
using namespace std;
class GameInfo {
public:
void SetPlayer1PlayA(int playScore); // Mutator
void SetPlayer1PlayB(int playScore); // Mutator
void SetPlayer2PlayA(int playScore); // Mutator
void SetPlayer2PlayB(int playScore); // Mutator
int GetPlayer1PlayA() const; // Accessor
int GetPlayer1PlayB() const; // Accessor
int GetPlayer2PlayA() const; // Accessor
int GetPlayer2PlayB() const; // Accessor
int GetPlayer1HighScore() const; // Accessor
int GetPlayer2HighScore() const; // Accessor
private:
int player1PlayA;
int player1PlayB;
int player2PlayA;
int player2PlayB;
int MaxOfPair(int num1, int num2) const; // Private helper fct
};
void GameInfo::SetPlayer1PlayA(int playScore) {
player1PlayA = playScore;
}
void GameInfo::SetPlayer1PlayB(int playScore) {
player1PlayB = playScore;
}
void GameInfo::SetPlayer2PlayA(int playScore) {
player2PlayA = playScore;
}
void GameInfo::SetPlayer2PlayB(int playScore) {
player2PlayB = playScore;
}
int GameInfo::GetPlayer1PlayA() const {
return player1PlayA;
}
int GameInfo::GetPlayer1PlayB() const {
return player1PlayB;
}
int GameInfo::GetPlayer2PlayA() const {
return player2PlayA;
}
int GameInfo::GetPlayer2PlayB() const {
return player2PlayB;
}
int GameInfo::GetPlayer1HighScore() const {
return MaxOfPair(player1PlayA, player1PlayB);
}
int GameInfo::GetPlayer2HighScore() const {
return MaxOfPair(player2PlayA, player2PlayB);
}
int GameInfo::MaxOfPair(int num1, int num2) const {
if (num1 > num2) {
return num1;
}
else {
return num2;
}
}
int main() {
GameInfo funGame;
funGame.SetPlayer1PlayA(88);
funGame.SetPlayer1PlayB(97);
funGame.SetPlayer2PlayA(74);
funGame.SetPlayer2PlayB(40);
cout << "Player1 playA: " << funGame.GetPlayer1PlayA() << endl;
cout << "Player1 max: " << funGame.GetPlayer1HighScore() << endl;
cout << "Player2 max: " << funGame.GetPlayer2HighScore() << endl;
return 0;
}
```
##### Mutators
Modify / 'Mutate' the data members of a class (a setter, it sets the value of a data member by changing it)
```cpp
// Public member function. Setter / Mutator
public:
void SetPlayer1PlayA(int playScore); // Mutator
// Private data member that users cant access
private:
int player1PlayA;
// Function definition, get input value and set private data member
// value equal to that input
void GameInfo::SetPlayer1PlayA(int playScore) {
player1PlayA = playScore;
}
```
##### Private Helpers
These are private functions that are used in the background to carry out tasks. The user will not be able access the functions at all, to the users these functions do not exist.
```cpp
private:
int MaxOfPair(int num1, int num2) const; // Private helper fct
```
#### Scope Resolution Operator
in the class we may declare member functions but if there is a lot of logic we don't want to crowd the class so we may take advantage of the `Scope Resolution Operator`: `::`. Similar to how `R` code uses `::` to access functions from specific packages. We do this by putting a Functions in the class declaration and then the Functions below which houses all the logic:
```cpp
void SetTime(int timeRunSecs); // Time run in seconds
}; // end of the class declaration
// "RunnerInfo::" means SetTime is a RunnerInfo member function
void RunnerInfo::SetTime(int timeRunSecs) {
timeRun = timeRunSecs; // timeRun refers to data member
return;
}
```
If a member function has the word `const` after its declaration like:
```cpp
double GetSpeedMph() const; // Speed in miles/hour
```
from the Example above, then this means that this member function cannot change the value of any data member or else an error is thrown.
### Operator Overloading
Related:
- polymorphism
If you have 2 integers and you add them with `+` then you used the `+` operator. If you want to add 2 private data members that are part of a class that are comprised of multiple parts, the `+` operator is not able to handle this unless we overload it:
```cpp
TimeHrMn time1(3, 22);
TimeHrMn time2(2, 50);
TimeHrMn timeTot;
timeTot = time1 + time2;
timeTot.Print();
//#> H:5, M:72
```
> The + operator was somehow redefined to add TimeHrMn objects' hours and minutes fields separately (3 + 2 is 5, 22 + 50 is 72), leading to simple readable code.
> .
> Although `+` requires left and right operands as in `time1 + time2`, the member function only requires the <u>right operand</u> (rhs: right-hand-side) as the parameter, <u>because the left operand is the calling object</u>. In other words, `time1 + time2` is equivalent to the function call `time1.operator+(time2)`, which is valid syntax but almost never used.
```cpp
#include <iostream>
using namespace std;
class TimeHrMn {
public:
TimeHrMn(int timeHours = 0, int timeMinutes = 0);
void Print() const;
TimeHrMn operator+(TimeHrMn rhs) ; // Overloaded `+` operator
private:
int hours;
int minutes;
};
// Overload + operator for TimeHrMn
TimeHrMn TimeHrMn::operator+(TimeHrMn rhs) { // Definition of overload
TimeHrMn timeTotal;
timeTotal.hours = hours + rhs.hours;
timeTotal.minutes = minutes + rhs.minutes;
return timeTotal;
}
TimeHrMn::TimeHrMn(int timeHours, int timeMinutes) {
hours = timeHours;
minutes = timeMinutes;
return;
}
void TimeHrMn::Print() const {
cout << "H:" << hours << ", " << "M:" << minutes << endl;
return;
}
int main() {
TimeHrMn time1(3, 22);
TimeHrMn time2(2, 50);
TimeHrMn timeTot;
timeTot = time1 + time2; // Implementation of overloaded operator
timeTot.Print();
return 0;
}
```
> When an operator like `+` has been overloaded, the compiler determines which `+` operation to invoke based on the operand types. In `4 + 9`, the compiler sees two integer operands and thus applies the built-in `+` operation. In `time1 + time2`, where `time1` and `time2` are `TimeHrMn` objects, the compiler sees two `TimeHrMn` operands and thus invokes the programmer-defined function.
> .
> A programmer can define several functions that overload the same operator, as long as each involves different types so that the compiler can determine which to invoke.
```cpp
#include <iostream>
using namespace std;
class TimeHrMn {
public:
TimeHrMn(int timeHours = 0, int timeMinutes = 0);
void Print() const;
TimeHrMn operator+(TimeHrMn rhs);
TimeHrMn operator+(int rhsHours);
private:
int hours;
int minutes;
};
// Operands: TimeHrMn, TimeHrMn. Call this "A"
TimeHrMn TimeHrMn::operator+(TimeHrMn rhs) {
TimeHrMn timeTotal;
timeTotal.hours = hours + rhs.hours;
timeTotal.minutes = minutes + rhs.minutes;
return timeTotal;
}
// Operands: TimeHrMn, int. Call this "B"
TimeHrMn TimeHrMn::operator+(int rhsHours) {
TimeHrMn timeTotal;
timeTotal.hours = hours + rhsHours;
timeTotal.minutes = minutes; // Stays same
return timeTotal;
}
TimeHrMn::TimeHrMn(int timeHours, int timeMinutes) {
hours = timeHours;
minutes = timeMinutes;
return;
}
void TimeHrMn::Print() const {
cout << "H:" << hours << ", " << "M:" << minutes << endl;
return;
}
int main() {
TimeHrMn time1(3, 22);
TimeHrMn time2(2, 50);
TimeHrMn timeTot;
int num = 91;
timeTot = time1 + time2; // Invokes "A"
timeTot.Print();
timeTot = time1 + 10; // Invokes "B"
timeTot.Print();
cout << num + 8 << endl; // Invokes built-in add
// timeTot = 10 + time1; // ERROR: No (int, TimeHrMn)
return 0;
}
```
### Class Code Separation of Concerns
Typically 2 files are used to separate class code:
`ClassName.h` **--** _Contains the class definition, including data members and member function declarations._
`ClassName.cpp` **--** _Contains member function definitions._
> Sometimes multiple small related classes are grouped into a single file, to avoid a proliferation of files. But for typical classes, good practice is to create a unique `.cpp` and `.h` file for each class.
#### Classes Within Classes
`TeamPerson.h`
```cpp
#ifndef TEAMPERSON_H
#define TEAMPERSON_H
#include <string>
using namespace std;
class TeamPerson {
public:
void SetFullName(string firstAndLastName);
void SetAgeYears(int ageInYears);
string GetFullName() const;
int GetAgeYears() const;
void Print() const;
private:
string fullName;
int ageYears;
};
#endif
```
`TeamPerson.cpp`
```cpp
#include <iostream>
#include <string>
using namespace std;
#include "TeamPerson.h"
void TeamPerson::SetFullName(string firstAndLastName) {
fullName = firstAndLastName;
return;
}
void TeamPerson::SetAgeYears(int ageInYears) {
ageYears = ageInYears;
return;
}
string TeamPerson::GetFullName() const {
return fullName;
}
int TeamPerson::GetAgeYears() const {
return ageYears;
}
void TeamPerson::Print() const {
cout << "Full name: " << fullName << endl;
cout << "Age (years): " << ageYears << endl;
}
```
`SoccerTeam.h`
```cpp
#ifndef SOCCERTEAM_H
#define SOCCERTEAM_H
#include "TeamPerson.h"
class SoccerTeam {
public:
void SetHeadCoach(TeamPerson teamPerson);
void SetAssistantCoach (TeamPerson teamPerson);
TeamPerson GetHeadCoach() const;
TeamPerson GetAssistantCoach() const;
void Print() const;
private:
TeamPerson headCoach;
TeamPerson assistantCoach;
// Players omitted for brevity
};
#endif
```
`SoccerTeam.cpp`
```cpp
#include <iostream>
using namespace std;
#include "TeamPerson.h"
#include "SoccerTeam.h"
void SoccerTeam::SetHeadCoach(TeamPerson teamPerson) {
headCoach = teamPerson;
return;
}
void SoccerTeam::SetAssistantCoach(TeamPerson teamPerson) {
assistantCoach = teamPerson;
return;
}
TeamPerson SoccerTeam::GetHeadCoach() const {
return headCoach;
}
TeamPerson SoccerTeam::GetAssistantCoach() const {
return assistantCoach;
}
void SoccerTeam::Print() const {
cout << "HEAD COACH: " << endl;
headCoach.Print();
cout << endl;
cout << "ASSISTANT COACH: " << endl;
assistantCoach.Print();
cout << endl;
return;
}
```
`main.cpp`
```cpp
#include <iostream>
using namespace std;
#include "SoccerTeam.h"
#include "TeamPerson.h"
int main() {
SoccerTeam teamCalifornia;
TeamPerson headCoach;
TeamPerson asstCoach;
headCoach.SetFullName("Mark Miwerds");
headCoach.SetAgeYears(42);
teamCalifornia.SetHeadCoach(headCoach);
asstCoach.SetFullName("Stanley Lee");
asstCoach.SetAgeYears(30);
teamCalifornia.SetAssistantCoach(asstCoach);
teamCalifornia.Print();
return 0;
}
```
#### Example
`StoreItem.h`
```cpp
#ifndef STOREITEM_H
#define STOREITEM_H
class StoreItem {
public:
void SetWeightOunces(int ounces);
void Print() const;
private:
int weightOunces;
};
#endif
```
`StoreItem.cpp`
```cpp
#include <iostream>
using namespace std;
#include "StoreItem.h"
void StoreItem::SetWeightOunces(int ounces) {
weightOunces = ounces;
return;
}
void StoreItem::Print() const {
cout << "Weight (ounces): " << weightOunces << endl;
return;
}
```
`main.cpp`
```cpp
#include <iostream>
using namespace std;
#include "StoreItem.h"
int main() {
StoreItem item1;
item1.SetWeightOunces(16);
item1.Print();
return 0;
}
```
### the big three
> The **rule of three** describes a practice that if a programmer explicitly defines any one of those three special member functions (destructor, copy constructor, copy assignment operator), then the programmer should explicitly define all three. For this reason, those three special member functions are sometimes called the **big three**.
> .
> A <u>good practice</u> is to always follow the rule of three and define the big three (_destructor, copy constructor, copy assignment operator_) if any one of these functions are defined.
#### Class Copy Constructors
If a class has a constructor that allocates memory for a variable with a pointer:
```cpp
class MyClass {
public:
MyClass();
~MyClass();
// Set member value dataObj
void SetDataObj(const int setVal) {
*dataObj = setVal;
}
// Return member value dataObj
int GetDataObj() const {
return *dataObj;
}
private:
int* dataObj;// Data member
};
```
And a new class is instantiated, and then passed by **value** to a function:
```cpp
void SomeFunction(MyClass localObj) {
// Do something with localObj
}
int main() {
MyClass tempClassObj; // Create object of type MyClass
// Set and print data member value
tempClassObj.SetDataObj(9);
cout << "Before: " << tempClassObj.GetDataObj() << endl;
// Calls SomeFunction(), tempClassObj is passed by value
SomeFunction(tempClassObj);
// Print data member value
cout << "After: " << tempClassObj.GetDataObj() << endl; // ERROR
return 0;
}
```
You get an error because the pass by value acts as a member wise copy.:
- newA = oldA
- newB = oldB
If your class doesn't have pointers then you wont have this issue. But with pointers we need to take a special approach. We need a copy constructor so that when passed by value to a function, when the class is copied locally we don't mess with the pointers. This copy constructor creates a new copy of the original class called a **deep copy**.
> The **copy constructor** can be called with a single pass by reference argument of the class type, representing an original object to be copied to the newly-created object:
```cpp
class MyClass {
public:
...
MyClass(const MyClass& origClass);
...
};
```
```cpp
/*
A class's copy constructor will be called automatically when an object of the class type
is passed by value to a function, and also when an object is initialized by copying another
object during declaration, as in:
*/
MyClass classObj2 = classObj1;
// or
obj2Ptr = new MyClass(classObj1);.
```
##### Implementation
```cpp
#include <iostream>
using namespace std;
class MyClass {
public:
MyClass();
MyClass(const MyClass& origClass); // Copy constructor
~MyClass();
// Set member value dataObj
void SetDataObj(const int setVal) {
*dataObj = setVal;
}
// Return member value dataObj
int GetDataObj() const {
return *dataObj;
}
private:
int* dataObj;// Data member
};
// Default constructor
MyClass::MyClass() {
cout << "Constructor called." << endl;
dataObj = new int; // Allocate mem for data
*dataObj = 0;
return;
}
// Copy constructor
MyClass::MyClass(const MyClass& origClass) {
cout << "Copy constructor called." << endl;
dataObj = new int; // Allocate sub-object
*dataObj = *(origClass.dataObj);
return;
}
// Destructor
MyClass::~MyClass() {
cout << "Destructor called." << endl;
delete dataObj;
return;
}
void SomeFunction(MyClass localObj) {
// Do something with localObj
return;
}
int main() {
MyClass tempClassObj; // Create object of type MyClass
// Set and print data member value
tempClassObj.SetDataObj(9);
cout << "Before: " << tempClassObj.GetDataObj() << endl;
// Calls SomeFunction(), tempClassObj is passed by value
SomeFunction(tempClassObj);
// Print data member value
cout << "After: " << tempClassObj.GetDataObj() << endl;
return 0;
}
```
#### Copy Assignment Operator
> The problem is that the assignment of `classObj2 = classObj1;` merely copied the pointer for `dataObj`, resulting in `classObj1's dataObj` and `classObj2's dataObj` members both pointing to the same memory location. Printing `classObj2` prints 9 but for the wrong reason, and if `classObj1's dataObj` value was later changed, `classObj2's dataObj` value would seemingly magically change too. Additionally, destroying `classObj1` frees that `dataObj's` memory; destroying `classObj2` then tries to free that same memory, causing a program crash. Furthermore, a memory leak has occurred because neither `dataObj` is pointing at location 81.
> .
> The solution is to overload the "` = `" operator by defining a new function, known as the `copy assignment operator` or sometimes just the `assignment operator`, that copies one class object to another. Such a function is typically defined as:
```cpp
class MyClass {
public:
...
MyClass& operator=(const MyClass& objToCopy);
...
};
```
##### Implementation
```cpp
#include <iostream>
using namespace std;
class MyClass {
public:
MyClass();
~MyClass();
MyClass& operator=(const MyClass& objToCopy);
// Set member value dataObj
void SetDataObj(const int setVal) {
*dataObj = setVal;
}
// Return member value dataObj
int GetDataObj() const {
return *dataObj;
}
private:
int* dataObj;// Data member
};
// Default constructor
MyClass::MyClass() {
cout << "Constructor called." << endl;
dataObj = new int; // Allocate mem for data
*dataObj = 0;
return;
}
// Destructor
MyClass::~MyClass() {
cout << "Destructor called." << endl;
delete dataObj;
return;
}
MyClass& MyClass::operator=(const MyClass& objToCopy) {
cout << "Assignment op called." << endl;
if (this != &objToCopy) { // 1. Don't self-assign
delete dataObj; // 2. Delete old dataObj
dataObj = new int; // 3. Allocate new dataObj
*dataObj = *(objToCopy.dataObj); // 4. Copy dataObj
}
return *this;
}
int main() {
MyClass tempClassObj1; // Create object of type MyClass
MyClass tempClassObj2; // Create object of type MyClass
// Set and print object 1 data member value
tempClassObj1.SetDataObj(9);
// Copy class object using copy assignment operator
tempClassObj2 = tempClassObj1;
// Set object 1 data member value
tempClassObj1.SetDataObj(1);
// Print data values for each object
cout << "obj1:" << tempClassObj1.GetDataObj() << endl;
cout << "obj2:" << tempClassObj2.GetDataObj() << endl;
return 0;
}
```
#### Deconstructors
> A destructor has no parameters and no return value (_not even void_)
Just like [[#constructors]] Deconstructors share the same name as the class albeit prepended with a tilde `~` so this is a class with its constructor and destructor:
```cpp
class SampleClass {
public:
SampleClass(); // Constructor
~SampleClass(); // Destructor
private:
};
```
##### Implementation
```cpp
#include <iostream>
using namespace std;
class MyClass {
public:
MyClass();
~MyClass();
private:
int* subObj;
};
MyClass::MyClass() {
cout << "Constructor called." << endl;
subObj = new int; // Allocate mem for data
*subObj = 0;
return;
}
MyClass::~MyClass() {
cout << "Destructor called." << endl;
delete subObj;
return;
}
int main() {
MyClass* tempClassObj; // Create object of type MyClass
tempClassObj = new MyClass; // Allocate mem for object
delete tempClassObj; // No more memory leak
// Freed obj's mem, including subObj
// Rest of program ...
return 0;
}
```
### this implicit parameter
> Within a member function, the implicitly-passed object pointer is accessible via the name this. In particular, a member can be accessed as `this->member`. The `->` is the member access operator for a pointer, similar to the `.` operator for non-pointers.
```cpp
#include <iostream>
using namespace std;
class ShapeSquare {
public:
void SetSideLength(double sideLength);
double GetArea() const;
private:
double sideLength;
};
void ShapeSquare::SetSideLength(double sideLength) {
this->sideLength = sideLength; // Refer to data member with same
// Data member Parameter // name as the passed in parameter
return;
}
double ShapeSquare::GetArea() const{
return sideLength * sideLength; // Both refer to data member
}
int main() {
ShapeSquare square1;
square1.SetSideLength(1.2);
cout << "Square's area: " << square1.GetArea() << endl;
return 0;
}
```
### unit testing
> A goal of testing is to achieve complete **code coverage**, meaning all code is executed at least once. Minimally for a class, that means every public function is called at least once. Of course, the programmer of a class knows about a class' implementation and thus will want to also ensure that every private helper function is called, and that every line of code within every function is executed at least once, which may require multiple calls with different input values for a function with branches.
#### Class to Test
```cpp
#include <iostream>
using namespace std;
// Note: This class intentionally has errors
class StatsInfo {
public:
void SetNum1(int numVal);
void SetNum2(int numVal);
int GetNum1() const;
int GetNum2() const;
int GetAverage() const;
void PrintNums() const;
private:
int num1;
int num2;
};
void StatsInfo::SetNum1(int numVal) {
num1 = numVal;
}
void StatsInfo::SetNum2(int numVal) {
num2 = numVal;
}
int StatsInfo::GetNum1() const {
return num1;
}
int StatsInfo::GetNum2() const {
return num1;
}
int StatsInfo::GetAverage() const {
return num1 + num2 / 2;
}
```
#### Test Bench
```cpp
int main() {
StatsInfo testData;
// Typical testbench tests more thoroughly
cout << "Beginning tests." << endl;
// Check set/get num1
testData.SetNum1(100);
if (testData.GetNum1() != 100) {
cout << " FAILED set/get num1" << endl;
}
// Check set/get num2
testData.SetNum2(50);
if (testData.GetNum2() != 50) {
cout << " FAILED set/get num2" << endl;
}
// Check GetAverage()
testData.SetNum1(10);
testData.SetNum2(20);
if (testData.GetAverage() != 15) {
cout << " FAILED GetAverage for 10, 20" << endl;
}
testData.SetNum1(-10);
testData.SetNum2(0);
if (testData.GetAverage() != -5) {
cout << " FAILED GetAverage for -10, 0" << endl;
}
cout << "Tests complete." << endl;
return 0;
}
```
## Polymorphism
> Sometimes a program has two functions with the same name but differing in the number or types of parameters, known as **function name overloading** or just **function overloading**.
```cpp
#include <iostream>
#include <string>
using namespace std;
// int int int
void DatePrint(int currDay, int currMonth, int currYear) {
cout << currMonth << "/" << currDay << "/" << currYear;
return;
}
// int string int
void DatePrint(int currDay, string currMonth, int currYear) {
cout << currMonth << " " << currDay << ", " << currYear;
return;
}
int main() {
DatePrint(30, 7, 2012);
cout << endl;
DatePrint(30, "July", 2012);
cout << endl;
return 0;
}
```
## precedence rules for logical and relational operators
| Convention | Description | Explanation |
| ----------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `( )` | Items within parentheses are evaluated first. | In !(age > 16), age > 16 is evaluated first, then the logical NOT. |
| `!` | Next to be evaluated is !. | |
| `* / % + -` | Arithmetic operator are then evaluated using the precedence rules for those operators. | z - 45 < 53 is evaluated as (z - 45) < 53. |
| `< <= > >=` | Then, relational operators < <= > >= are evaluated. | x < 2 \|\| x >= 10 is evaluated as (x < 2) \|\| (x >= 10) because < and >= have precedence over \|\|. |
| `== !=` | Then, the equality and inequality operators == != are evaluated. | x == 0 && x >= 10 is evaluated as (x == 0) && (x >= 10) because < and >= have precedence over &<. |
| `&` | Then, the bitwise AND operator is evaluated. | x == 5 \| y == 10 & z != 10 is evaluated as (x == 5) \| ((y == 10) & (z != 10)) because & has precedence over \|. |
| \| | Then, the bitwise OR operator is evaluated. | x == 5 \| y == 10 && z != 10 is evaluated as ((x == 5) \| (y == 10)) && (z != 10)) because \| has precedence over &&. |
| `&&` | Then, the logical AND operator is evaluated. | x == 5 \|\| y == 10 && z != 10 is evaluated as (x == 5) \|\| ((y == 10) && (z != 10)) because && has precedence over \|\|. |
| \|\| | Finally, the logical OR operator is evaluated. | |
## preprocessor directives
> The **preprocessor** is a tool that scans the file from top to bottom looking for any lines that begin with #, known as a **hash symbol**. Each such line is not a program statement, but rather directs the **preprocessor** to modify the file in some way before compilation continues, each such line being known as a **preprocessor directive**. The directive ends at the end of the line, no semicolon is used at the end of the line.
### Include
> Perhaps the most commonly-used preprocessor directive is **\#include**, known as an include directive. **\#include** directs the compiler to replace that line by the contents of the given filename.
```cpp
#include "filename"
#include <filename>
```
### Header Files
Header files are included through Pre-Processor Directives.
Header files contain code such as groups of related functions & their [[#Declaration]]'s and [[#Definition]]'s', as well as classes.
When you input a header file with an `#include` statement its basically like copy/pasting all the code where the file is included. sometimes this can lead to duplication and errors if included multiple times so to prevent this we use [[#Header File Guards]].
#### Header File Guards
These guards look like this:
```cpp
#ifndef FILENAME_H
#define FILENAME_H
// Header file contents
#endif
```
> `#define FILENAME_H` defines the symbol `FILENAME_H` to the preprocessor. The `#ifndef FILENAME_H` and `#endif` form a pair that instructs the preprocessor to process the code between the pair only if FILENAME_H is not defined ("ifndef" is short for "if not defined"). Thus, if the preprocessor includes encounter the header more than once, the code in the file during the second and any subsequent encounters will be skipped because `FILENAME_H` was already defined.
> .
> <u>Good practice</u> is to guard every header file. The following shows the `threeintsfcts.h` file with the guarding code added:
```cpp
#ifndef THREEINTSFCT_H
#define THREEINTSFCT_H
int ThreeIntsSum(int num1, int num2, int num3);
int ThreeIntsAvg(int num1, int num2, int num3);
#endif
```
Another example from [This video by The Cherno](https://youtu.be/9RJTQmK0YPI?list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb) is instead of `ifndef` and all that, using instead `#pragma once` which says to include the file only once per translation unit.
To be safe and make sure all compilers will support portability and the use the fastest option you can use both:
```cpp
#pragma once
#ifndef _HEADER_H_
#define _HEADER_H_
...
#endif
```
## streams
### basic input output
```cpp
/*
Basic input output
Send to STDOUT
endl is like "\n" but better
*/
std::cout << "What are you ending to the terminal?" << std::endl;
//#> What are you ending to the terminal?
std::cin >> myVariable; // "Hello World"
std::cout << "this goes to terminal: " << myVariable << std::endl;
//#> this goes to terminal: Hello World
```
### Input / Output
#### Output Stream
or `ostream` for short is a class that supports output. It is included from [[#iostream]]
`<iostream>` provides the `<<` operator known as the **insertion operator**.
`cout` is a predefined `ostream` object (e.g., you can think of it as declared as `ostream cout;`
> The `<<` operator is overloaded with functions to support the various standard data types, such as int, bool, float, etc., each function converting that data type to a sequence of characters. The operator may be further overloaded by the string library from `#include <string>` or by the programmer for programmer-created classes.
> .
> The `<<` operator returns a reference to the `ostream` that called it, and is evaluated from left to right like most operators, so `<<` operators can appear in series.
```cpp
cout << "Num" << myInt;
// can be thought of as:
( cout.operator<<("Num") ).operator<<(myInt);
```
#### Input Stream
Or `istream`, provides the `>>` operator known as the **extraction operator**. To extract data from a data buffer and write the data into different types of variables.
> `cin` is a predefined istream pre-associated with a system's standard input, usually a computer keyboard. The system automatically puts the standard input into a data buffer associated with `cin`. The `>>` operator <u>skips leading whitespace</u>, extracts as many characters as possible consistent with the target variable's type and <u>stopping at the next whitespace</u>, converts the extracted characters to the target variable's type, and stores the result into the variable.
### output fotmatting
#### Number Formatting
> A programmer can adjust the way that output appears, a task known as output formatting. The main formatting approach uses manipulators. A manipulator is an item designed to be used with the insertion operator `<<` or extraction operator `>>` to adjust the way output appears, and is available via `#include <iomanip>; `or `#include <ios>;` in namespace std. For example, `cout << setprecision(3) << myFloat;` causes the floating-point variable `myFloat` to be output with only 3 digits; if `myFloat` was 12.34, the output would be 12.3.
> .
> <u>Most manipulators change the state of the stream such that the manipulation affects all subsequent output, not just the next output.</u>
| Manipulator | Description | Example |
| :-------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------- |
| fixed | Use fixed-point notation. `From <ios>` | 12.34 |
| scientific | Use scientific notation. `From <ios>` | 12.3E+01 |
| setprecision(p) | If stream has not been manipulated to fixed or scientific: Sets max number of digits in number | p=3 yields 12.3 p=5 yields 12.34 |
| | If stream has been manipulated to fixed or scientific: Sets max number of digits in fraction only (after the decimal point). From `<iomanip>` | fixed: p=1 yields 12.3 scientific: p=1 yields 1.2e+01 |
| showpoint | Even if fraction is 0, show decimal point and trailing 0s. Opposite is noshowpoint. `From <ios>` | For 99.0 with precision=2 and fixed: 99 (default or noshowpoint) 99.00 (showpoint) |
```cpp
#include <iostream>
#include <ios>
#include <iomanip>
using namespace std;
int main() {
double milesTrvld = 765.4321;
cout << "setprecision(p) -- Sets # digits" << endl;
cout << milesTrvld << " (default p is 6)" << endl;
cout << setprecision(8) << milesTrvld << " (p = 8)" << endl;
cout << setprecision(5) << milesTrvld << " (p = 5)" << endl;
cout << setprecision(2) << milesTrvld << " (p = 2)"
<< " (note rounding)" << endl;
cout << milesTrvld << " (manipulator persists)" << endl << endl;
cout << setprecision(2);
cout << "(For following, p = 2 applies to fraction only)" << endl;
// fixed -- uses fixed point notation
cout << fixed;
cout << "fixed: " << milesTrvld << endl;
// scientific -- uses scientific notation
cout << scientific;
cout << "scientific: " << milesTrvld << endl;
return 0;
}
```
#### Text Formatting
| Manipulator | Description | Example (for item "Amy") | |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------- | - |
| setw(n) | Sets the number of characters for the next output item only (does not persist, in contrast to other manipulators). By default, the item will be right-aligned, and filled with spaces. From `<iomanip>` | For n=7: "Amy" | |
| setfill(c) | Sets the fill to character c. From `<iomanip>` | For c='\*': ""\*\*\*\*Amy"" | " |
| left | Changes to left alignment. From `<ios>` | "Amy " | |
| right | Changes to right alignment. From `<ios>` | " Amy" | |
```cpp
#include <iostream>
#include <ios>
#include <iomanip>
using namespace std;
int main() {
cout << "Dog age in human years (dogyears.com)" << endl << endl;
// set num char for each column, set alignment
cout << setw(10) << left << "Dog age" << "|";
cout << setw(12) << right << "Human age" << endl;
cout << "------------------------------" << endl;
cout << setw(10) << left << "2 months" << "|";
cout << setw(12) << right << "14 months" << endl;
cout << setw(10) << left << "6 months" << "|";
cout << setw(12) << right << "5 years" << endl;
// set fill character, num char for each column, set alignment
cout << setfill('-');
cout << setw(10) << left << "8 months" << "|";
cout << setw(12) << right << "9 years" << endl;
cout << setw(10) << left << "1 year" << "|";
// change fill character, num char for each column, set alignment
cout << setfill('.');
cout << setw(12) << right << "15 years" << endl;
// change fill character, num char for each column
cout << setfill('*') << setw(30) << "" << endl;
return 0;
}
```
> Of particular interest is how the `setw()` and `setfill()` manipulators are used in the last few lines. Note how they are used to create a line of 30 asterisks, without having to type 30 asterisks.
> .
> Most manipulators are persistent, meaning they change the state of the stream for all subsequent output. The exception is `setw()`, which <u>only affects the next output item</u>, defined that way likely because programmers usually only want to set the width of the next item and not all subsequent items.
| Manipulator | Description | |
| :---------: | :---------------------------------------------------------------------------------------------------- | ----------------- |
| `endl` | Inserts a newline character '\\n' into the output buffer, and informs the system to flush the buffer. | From `<iostream>` |
| `flush` | Informs the system to flush the buffer. From `<iostream>` | |
### String Streams
#### Input Stream
> Sometimes a programmer wishes to read input data from a string rather than from the keyboard (standard input). A new input string stream variable of type `istringstream` can be created that is associated with a string rather than with the keyboard (standard input). `istringstream` is derived from `istream`. Such a stream can be used just like the `cin` stream. The following program illustrates.
```cpp
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main() {
string userInfo = "Amy Smith 19"; // Input string
istringstream inSS(userInfo); // Input string stream
string firstName; // First name
string lastName; // Last name
int userAge = 0; // Age
// Parse name and age values from input string
inSS >> firstName;
inSS >> lastName;
inSS >> userAge;
// Output parsed values
cout << "First name: " << firstName << endl;
cout << "Last name: " << lastName << endl;
cout << "Age: " << userAge << endl;
return 0;
}
//#> First name: Amy
//#> Last name: Smith
//#> Age: 19
```
> The program uses `#include <sstream>` for access to the string stream class, which is in `namespace std`. The line `istringstream inSS(userInfo);` declares a new stream variable and initializes its buffer to a copy of `userInfo`. Then, the program can extract data from stream `inSS` using `>>` similar to extracting from `cin`.
> .
> A common use of string streams is to process user input line-by-line. The following program reads in the line as a string, and then extracts individual data items from that string.
```cpp
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main() {
istringstream inSS; // Input string stream
string lineString; // Holds line of text
string firstName; // First name
string lastName; // Last name
int userAge = 0; // Age
bool inputDone = false; // Flag to indicate next iteration
// Prompt user for input
cout << "Enter \"firstname lastname age\" on each line" << endl;
cout << "(\"Exit\" as firstname exits)." << endl << endl;
// Grab data as long as "Exit" is not entered
while (!inputDone) {
// Entire line into lineString
getline(cin, lineString);
// Copies to inSS's string buffer
inSS.clear();
inSS.str(lineString);
// Now process the line
inSS >> firstName;
// Output parsed values
if (firstName == "Exit") {
cout << " Exiting." << endl;
inputDone = true;
}
else {
inSS >> lastName;
inSS >> userAge;
cout << " First name: " << firstName << endl;
cout << " Last name: " << lastName << endl;
cout << " Age: " << userAge << endl;
cout << endl;
}
}
return 0;
}
//#> Enter "firstname lastname age" on each line
//#> ("Exit" as firstname exits).
//#>
//#> Mary Jones 22
//#> First name: Mary
//#> Last name: Jones
//#> Age: 22
//#>
//#> Sally Smith 14
//#> First name: Sally
//#> Last name: Smith
//#> Age: 14
//#>
//#> Exit
//#> Exiting.
```
#### Output Stream
> The program uses `getline` to read an input line into a string. The line `inSS.str(lineString);` uses the `str(s)` function to initialize the stream's buffer to string `s`. Afterwards, the program extracts input from that stream using `>>.` The statement `inSS.clear();` is necessary to reset the state of the stream so that subsequent extractions start from the beginning; the clear resets the stream's state.
> .
> Similarly, a new output string stream variable of type **ostringstream** can be created that is associated with a string rather than with the screen (standard output). **ostringstream** is a special kind of (i.e., is derived from) `ostream`. Once created, a program can insert characters into that stream using `<<`, as follows.
```cpp
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main() {
ostringstream fullNameOSS; // Output string stream
ostringstream ageOSS; // Output string stream
string firstName; // First name
string lastName; // Last name
string fullName; // Full name (first and last)
string ageStr; // Age (string)
int userAge = 0; // Age
// Prompt user for input
cout << "Enter \"firstname lastname age\": " << endl;
cin >> firstName;
cin >> lastName;
cin >> userAge;
// Writes to buffer, then copies from buffer into string
fullNameOSS << lastName << ", " << firstName;
fullName = fullNameOSS.str();
// Output parsed input
cout << endl << " Full name: " << fullName << endl;
// Writes int age as chars to buffer
ageOSS << userAge;
// Appends (minor) to buffer if less than 21, then
// copies buffer into string
if (userAge < 21) {
ageOSS << " (minor)";
}
ageStr = ageOSS.str();
// Output string
cout << " Age: " << ageStr << endl;
return 0;
}
```
## Unit Testing
Testing the behavior of your functions to ensure that they are working correctly and have no aberrant behavior.
```cpp
#include <iostream>
#include <cassert>
using namespace std;
double HrMinToMin(int origHours, int origMinutes) {
int totMinutes = 0; // Resulting minutes
totMinutes = (origHours * 60) + origMinutes;
return origMinutes;
}
int main() {
cout << "Testing started" << endl;
assert(HrMinToMin(0, 0) == 0);
assert(HrMinToMin(0, 1) == 1);
assert(HrMinToMin(0, 99) == 99);
assert(HrMinToMin(1, 0) == 60);
assert(HrMinToMin(5, 0) == 300);
assert(HrMinToMin(2, 30) == 150);
// Many more test vectors would be typical...
cout << "Testing completed" << endl;
return 0;
}
```
## tools
### ctags
#### Resources
- <https://www.youtube.com/4f3AENLrdYo>
Generate tags so that you can jump to function definitions
in a file or in a group of files. tags will also find their
definitions in other files in the director(ies) it was generated in
To generate tags: `ctags -R .`
this generates a `tags` file and now in your documents you can use
the following keybindings:
`ctrl-]` jump to definition
`ctrl-o` go back to prior position
`ctrl-i` Jump forward
`:h tag-stack` for more info on tags
## Variables
Normal variables are usually camel case with first letter lower case `likeThis`
variables must have their data types declared before the name of the variable