Maria Deslis

github.com/eternalearth888
mdeslis@gmail.com

General Structure
					
/* Header comment 
* Program name, author, purpose 
*/
//preprocessing directives

#include < iostream >
using namespace std;

//header file for functions prototypes go here

int main() { 
// what your program does 
cout << "Hello World!" << endl;
// exiting the program
return 0; 
}	
			
Variable Declarations
					
int puppies;
double seconds = 23.6;
// const means that this cannot be altered
const char YES = 'y'; 
bool aceTest = true;

int cats, dogs; // multiple declaration
cats = dogs = 20; // multiple assignment
			
Expressions
Have a pragmatic understanding of operator precedence. When in doubt or to express clarity, use parenthesis.
					
int maleDogs = 3;
int femaleDogs = 2;
int puppies;

puppies = maleDogs * femaleDogs;
puppies++; // one more puppy
puppies += 5; // five more puppies
puppies *= 5; // five times as many puppies!

int example = maleDogs / femaleDogs; // why does this yield 1?
example = 0 % maleDogs; // 0 % anything is always 0

int x = 5;
int y = 2;

// first evaluate the expression, 
// then increment the x
y = 2 + x++; 
//VERSUS
// first increment the x,
// then evaluate the expression
y = ++x + 2; 
			
Operations with Mixed Types
An int operator int yields an int. A double operator double yields a double.
Operations with mixed types will yield a value whose type is of the "greater precision," so to speak. A double operator int yields a double.
Flow control: if, else if, else
					
char answer;
cout << "Do you like cookies? (enter Y or N)\n";
cin >> answer;
if (answer == 'Y') {
    cout << "No way! I love cookies too!\n";
} else if (answer == 'N') {
    cout << "Hm, maybe I can offer you some green beans.\n";
} else {
    cout << "I'm confused. Guess I'll go eat a cookie.\n"
}
			
Remember, flow control constructs can be nested. Keep it tidy.

char likesCookies;
char likesArtichokes;
cout << "Do you like cookies? (enter Y or N)\n";
cin >> likesCookies;
if (likesCookies == 'Y') {
    cout << "Ok, but do you like artichokes? (Y or N)\n";
    cin >> likesArtichokes;
    if (likesArtichokes == 'Y') {
        cout << "Artichokes, nice!\n";
    } else {
        cout << "Geez, no artichokes?\n";
    } 
} else if (answer == 'N') {
    cout << "Hm, maybe I can offer you some green beans.\n";
} else {
    cout << "I'm confused. Guess I'll go eat a cookie.\n"
}
				
Flow control: while
Remember, a while loop assumes some initial state of the world before it begins, checks the terminating condition, and usually includes something to change the condition within the loop.
					
int countdown = 10;
while ( countdown > 0 ) {
    cout << countdown << endl;
    countdown--;
}
			
Flow control: for
A for loop has the same three main loop components (initialization, condition, modifier) as a while loop but in a more concise syntax.

for ( initialization; condition; modifier ) {
   //do something
}
Here's the above while loop rewritten as a for loop.
					
int countdown = 10;
for ( int countdown = 10; countdown > 0; countdown-- ) {
    cout << countdown << endl;
}
			
Defining Functions
Functions are always defined according to the following pattern.

returnType functionName(parameterList) {
    // function drama
    // properly indented, of course
    // proper return value based on returnType
}
Every function has a return type, name and parameter list. However, parameter lists can be empty if the function accepts no arguments. If the function does not return a value to its caller, then the return type should be void.
More importantly, you need to be able to write a function given a particular definition. Here is one example: "Write a function called dance that accepts one int parameter called howLong, one string parameter called move and returns a boolean value."

bool dance(int howLong, string move) {
    // function drama properly indented, of course
    if (move != "" || move != "null") {
    	return true;	
	}
    // returns some boolean value
    return false;
}
			
Arrays
The general pattern for array declaration is like this:

dataType arrayName[size];
					
int ages[10]; // declares an array of ten integers
char letters[5]; // declares an array of ten characters
int scores[2] = {10, 20}; // declares and initializes values
int ratings[5] = {0}; // initializes all array values to 0

letters[0] = 'q'; // stores the value 'q' in the 0th position
int x = scores[1]; // assign the value in the 1th position to x
			
Arrays + Operational Offset
The general formula for finding an array element in memory is like this:

elementAddress = baseAddress + (dataTypeSize * offset)
Example:

Given:
int myArray[2] = {4,7,8};
Find:
cout << myArray[2] << endl;

/*
Base Address is 4235
DataType size for ints is 4
NumColsPerRow is 4
Offset is 2

elementAddress = 4235 + (4*2) 
			   = 4235 + 8
			   = 4243
*/
The general formula for finding an element in a 2D array in memory is like this:

elementAddress = baseAddress
                 + (dataTypeSize * numColsPerRow * rowOffset)
                 + dataTypeSize * colOffset
             
Example:

Given:
int myArray[2][4] = { {4,7,3,2}, {8,1,9,0} };
Find:
cout << myArray[1][2] << endl;

/*
Base Address is 6789
DataType size for ints is 4
NumColsPerRow is 4
Row Offset is 1
Col Offset is 2

elementAddress = 6789 + (4*4*1) + (4*2)
			   = 6789 + 16 + 8
			   = 6789 + 24
			   = 6813
*/
 			
Arrays & Loops
Remember, for loops naturally complement arrays, and the for loop's counter variable is often used inside the loop to access the array.
					
const int NUMBER_OF_AGES = 10;
int ages[NUMBER_OF_AGES];
for (int i = 0; i < NUMBER_OF_AGES; ++i) {
    ages[i] = 21;
}
// ages now contains ten 21's. Have a root beer.
			
2D Arrays & Loops
The general pattern for a 2D array declaration is like this:

dataType arrayName[rows][columns];
The key idea here is that the outer loop determines "which row" while the inner loop determines "which column."
					
const int DAYS_IN_WEEK = 7;
const int WEEKS = 2;
int temperatures[WEEKS][DAYS_IN_WEEK];
for (int i = 0; i < WEEKS; ++i) {
    for (int j = 0; j < DAYS_IN_WEEK; ++j) {
        temperatures[i][j] = 0; // cold
    }
}
// temperatures now contains two rows of seven values (all 0). Have a kombucha.
			
Vectors
Remember, a vector is like an array but without the extra baggage.
					
#include < vector >

vector< int > numbers; // a vector called numbers that holds ints
vector< Bunny > rabbits; // a vector called rabbits that holds cute Bunny objects
			
Structs
The general pattern for a Struct is like this:

struct structName {
	// other variables 
	// that build our struct
};
					
#include < iostream >
#include < cstring >

using namespace std;


// declare before person so that it exists already for Person - derp!
struct ImperialHeight {
    int feet; 
    int inches;
};


struct Person {
    ImperialHeight height;
    string name;
    string secretIdentity;
    char gender;
    int age;
    char hairColor;
    bool rightHandDominant;
    bool rightEyeDominant;
};

int main() {
    Person peterParker;
    peterParker.name = "Peter Parker";
    peterParker.hairColor = 'b';
    peterParker.secretIdentity = "SpiderMan";
    peterParker.height.feet = 5;
    peterParker.height.inches = 10;
    peterParker.age = 15;
    peterParker.gender = 'm';
    peterParker.rightHandDominant = true;
    peterParker.rightEyeDominant = true;
    
    cout << "Hi! I'm " << peterParker.name << "! But my friends know me as "
            << peterParker.secretIdentity << "!" << endl;
    cout << "I am " << peterParker.height.feet << "\"" << 

    peterParker.height.inches << "\'"<< endl;
    
    return 0;
    
}
			
Pass By Refernce (Overall Concept)
The key reason that happens is because when we use the &, it is passing the memory address so that both variables share the same memory address. So when x changes and goes away, the value change sticks to a and that's why it doesn't reset to the old value :)
I am using method 2 for functions, where prototypes exist above main and the function definition exist below main. I want you to copy paste this code, and run it, and then read the comments so you can see everything that is happening.
					
#include< iostream >

using namespace std;

// notice how we have to include the & symbol even in our prototype for
 it to work
int addition(int &x, int y); //NOTE THE SEMICOLON!

int main() {
int a = 10;
int b = 5;
cout << "BEFORE PASSING BY REFERENCE: " << endl;
cout << "a = " << a << " , b = " << b << endl;

// \n is just a fast way to start a new line, this is called an escape 
// character
cout << "\nCALLING THE FUNCTION AND PRINTING THE RESULT OF ADDITION(a,b): " <<
endl;
cout << "A = 10, then it gets passed into addition, where X does X+5" << endl;
cout << "X becomes 15, and because it is being added to Y which has the value
of B = 5,\n we get a result of:" << endl;
cout << "return x+y --> return 15+5 -- > result is 20" << endl;
cout << "ADDITION(10,5) = " << addition(a,b) << endl;
cout << "\nAFTER PASSING BY REFERENCE: " << endl;
cout << "Since we passed A in by reference to X in addition, the change in\n
value to X changes the value of A permanenetly for the code\n So now A = 15 
too" << endl;
cout << "a = " << a << " , b = " << b << endl;
// what happens to a if i call addition again?
addition(a,b);
cout << "\nAFTER PASSING BY REFERENCE SECOND TIME: " << endl;
cout << "If we call addition again, even if we don't print the new result, the
permanent change to A and X\n still occurs anyway and we add another 5 to 
it." << endl;
cout << "a = " << a << " , b = " << b << endl;
return 0;
}

// notice how I have the & symbol next to x, this means that x is being passed
// by reference
// passing by reference means that instead of the value  from a variable that
// x is given in main, 
// instead x in our function gets the value that is the memory address of the
// variable that x was given in main
int addition(int &x, int y) {
// for concept purposes I am doing this on purpose to show what will happen
// later
// because x is being passed by reference, any changes in the value of x will 
// happen to same thing in 
// the variable we gave it, in this case the a variable from main.
// BREAKDOWN: if x changes from 5 to 10, then a is also now 10
x = x + 5; 
return x + y;
}
			
Passing Arguments by Reference
Remember, the "rule of thumb" is to (almost always) pass objects [structs, arrays (sometimes), vectors (sometimes), strings] by reference.
In order to tell the machine that a function should receive its argument by reference, you simply prepend a & before the parameter name.
					
void changeRed(Square &sq) {
    sq.red = 255;
}

Square s;
changeRed(s);
// s.red is now 255
			
Functions in Files
A function is basically a subprogram in your code that acts on the data related to that code and can return a value.

Every C++ program already has at least one function --> main().
When your program starts, main() is called automatically. Inside of main(), one can call other functions to do the extra work in main. And it's totally possible to have functions call other functions within them (We will see this in A4)

There are 3 possible ways to setup a function so that we can call it in main to do the work for us.
1. Is to create our function above main.

#include < iostream >
using namespace std;

int subtraction(int x, int y) {
	return x - y;
}

int main() {
int a = 10;
int b = 5;
  
//There are two ways we can call this function and get the value it 
// calculateswithout passing by reference (we can talk about that later)
// The first way is to store it in another variable
int result = subtraction(a,b);
// result will store the vale the subtraction function returns once the program 
//hits this line and calls the function subtraction


// The second way is to output it using cout
cout << "The difference is " << subtraction(a,b) << "." << endl;

return 0;
}
2. Split that function up into two parts! Prototype and definition!
What I personally like to do is make all my functions like we have above with just declaring and defining my functions above main.
Once I have what I want working and everything is running smoothly. I now feel confident enough to split that function into two parts:
  • i. Prototypes stay above main, so that the computer/ program know that this function exists
  • ii. Definition goes under main once your prototype is done

So what I do in this case is :
  • a. Copy the function you have above main entirely and put it under main, boom you now have your function definition!
  • b. Copy only the "header" part of the function for your prototype. This includes the datatype, function name, and parameters

This is what it should look like once that happens:

#include < iostream >
using namespace std;

int subtraction(int x, int y) ; // FUNCTION PROTOTYPE

int main() {
int a = 10;
int b = 5;
  
//There are two ways we can call this function and 
// get the value it calculates without passing by reference 
// (we can talk about that later)
// The first way is to store it in another variable
int result = subtraction(a,b);
// result will store the vale the subtraction 
//function returns once the program hits this line 
// and calls the function subtraction

// The second way is to output it using cout
cout << "The difference is " << subtraction(a,b) << "." << endl;

return 0;
}

// FUNCTION DEFINITION
int subtraction(int x, int y) { 
return x - y;
}

3. Last but not least, splitting the function into multiple files
In my opinion, this part is easiest if you already have your function prototypes and definitions split up like we did just now. But the reason we can/are able to do multiple files is because well - imagine video game code for example. Having all of their functions and their main in one file means they will end up with a CRAZY long file and it will slow down the program a bit as it tries to find all the functions in the same file. It's not so much a "YOU MUST DO IT THIS WAY!" as it is just a convenient way to clean and organize your code for the long term

Note:
i. Header files are the .h files. They will/should only hold onto your function prototypes
ii. Implementation files are .cpp files, this is where all your function definitions go and where all the work will be done. In this case, your implementation file name MUST have the same name as your header file name. So if you make a cat.h, you need to make a cat.cpp.



So let's take the example we have been working with and try to split it up into files. To make a header file from here, I want you to right click on your Project Folder and click "Create New Header File" and you can call it something like calculator.h. Then right click your Project folder again and click "Create New Source File" and you can call it calculator.cpp.

We have now made our header ad implementation files.

But WAIT! There's more!

From here, we will cut and paste the prototype in main and put in in the header file in between the #if and #endif thing that the file came with.

Once that is done, go back to main.cpp and where our prototypes were, we are now gonna have a new line of code there that says #include "calculator.h"

This his how the program will know to look for that file and those function prototypes for main.

Then, we want to copy paste the same preprocessing directives plus our new #include "calculator.h" and put that in calculator.cpp

After that, cut paste your function definitions after the preprocessing directives in calculator.cpp

So visually you will have three files that look something like this:

-------------------main.cpp------------------------
#include < iostream >
using namespace std;

#include "calculator.h" // <---this is now symbolic,
// this tells the computer that all the function prototypes are in this file
// it MUST come after all the libraries/preprocessing 
// directives so it can use them for their prototypes

int main() {
int a = 10;
int b = 5;
  
//There are two ways we can call this function and get the value it calculates 
//without passing by reference (we can talk about that later)
// The first way is to store it in another variable
int result = subtraction(a,b);
// result will store the vale the subtraction function returns once the 
//program hits this line and calls the function subtraction

// The second way is to output it using cout
cout << "The difference is " << subtraction(a,b) << "." << endl;

return 0;
}
-----------------------------------------------------

-------------------calculator.h----------------------
// PROJECTNAME_HEADERFILENAME_H will be automatically generated 
// for you when you create your header file in CLION
#ifndef PROJECTNAME_HEADERFILENAME_H 
#define  PROJECTNAME_HEADERFILENAME_H

int subtraction(int x, int y) ; // FUNCTION PROTOTYPE

#endif // PROJECTNAME_HEADERFILENAME_H
-----------------------------------------------------

---------------------calculator.cpp------------------
#include < iostream >
// we need to add the same libraries we have in our
//  main.cpp so we can keep our calculations going
using namespace std; 

// we need to include the header file so it 
// knows where it's prototypes are
#include "calculator.h" 

// FUNCTION DEFINITION
int subtraction(int x, int y) { 
	return x - y;
}
----------------------------------------------------
Now when you run this code, it should work as if the entire time all you had was this:

#include< iostream >
using namespace std;

int main() {
	int a = 10;
	int b = 5;

	cout << "The difference between a and b is " << a-b << endl;

	return 0;
}
Algorithms - Min/Max
This finds the Min/Max value in an array, but does not sort them
Pseudocode
  • Store the first value of the array as our current min/max
  • For every element in the array
  • Min – if an element is smaller than our current min, then that element is our new min
  • Max - If an element is larger than our current max, then that element is our new max
					
#include < iostream >
using namespace std;

const int SIZE = 10;

// Not passing the array by reference cause we
// are returning a found value
// and not altering the array
int findMin(int arr[], int arraySize) {
    // grab the first value by default to have
    // something to compare against
    int currentMinimum = arr[0];
    for (int i = 0; i < arraySize; i++) {
        // compare that value to every value
        // in the array
        if (arr[i] < currentMinimum) {
            // grab the new smallest value
            currentMinimum = arr[i];
        }
    }
    // return the smallest value
    return currentMinimum;
}

int findMax(int arr[], int arraySize) {
    // grab the first value by default to have
    // something to compare against
    int currentMaximum = arr[0];
    for (int i = 0; i < arraySize; i++) {
        // compare that value to every value
        // in the array
        if (arr[i] > currentMaximum) {
            // grab the new largest value
            currentMaximum = arr[i];
        }
    }
    // return the largest value
    return currentMaximum;
}


int main() {
                    //index  :  0 1 2 3 4 5 6 7 8 9 
int unsortedArray[SIZE] = {7,7,4,3,5,2,1,3,4,9};

cout << "The minimum value is : " << findMin(unsortedArray,SIZE) << endl;
cout << "The maximum value is : " << findMax(unsortedArray,SIZE) << endl;


return 0;
}
			
Algorithms - Sorted Array
Sorting them means you will be able to search faster!
Pseudocode
  • Find the minimum value, swap with the 1st position
  • Find the next minimum value, swap in the 2nd position
  • Continue until you have found the second to largest value and swapped in the second to last position
					
#include < iostream >
using namespace std;

const int SIZE = 10;

void selectionSort(int arr[], int arraySize) {
    int temp;
    // After we find the smallest element and 
    // put it in the first position
    // 1 element is sorted
    // N-1 elements are unsorted
    for (int i = 0; i < arraySize-1; i++) {
		for (int j = i+1; j < arraySize; j++) {
		    // find min value, swap with 1st position
		    // find next min value, swap wth 2nd position
			if (arr[i] > arr[j]) {
				temp = arr[i];
				arr[i] = arr[j];
				arr[j] = temp;
			}
		}
    }
}

void printArray(const int arr[], int arraySize) {
    cout << " { ";
    for (int i = 0; i < arraySize; i++ ) {
        cout << arr[i];
        if (i < arraySize - 1) {
            cout <<", ";
        }
    }
    cout << " }" << endl;
}

int main() {
	               //index  :  0 1 2 3 4 5 6 7 8 9 
	int unsortedArray[SIZE] = {7,7,4,3,5,2,1,3,4,9};

	//NOW SORT THE ARRAY
	selectionSort(unsortedArray,SIZE);
	cout << "The sorted array is : ";
	printArray(unsortedArray,SIZE);

	return 0;
}
			
Algorithms - Binary Search
Binary Searches must use arrays/vectors that are already sorted from min value to max value
					
#include< iostream >

using namespace std;

const int N = 5;
/* Function to print an array */
void printArray(const int arr[], int n)
{
    for (int i=0; i < n; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
}

// A recursive binary search function. It returns 
// location of x in given array arr[l..r] is present, 
// otherwise -1
int binarySearch(int arr[], int l, int r, int x)
{
   // if ending element is greater or equal to starting
   if (r >= l)
   {
       // grab the mid point between starting and ending
       // l = 0, r = 4 
       // 0 + (4 - 0) /2
       // 0 + 4/2 --> 0 + 2
       // mid = 2
        int mid = l + (r - l)/2;
 
        // If the element is present at the middle 
        // itself
        if (arr[mid] == x)  
            return mid;
 
        // If element is smaller than mid, then 
        // it can only be present in left subarray
        if (arr[mid] > x) 
            return binarySearch(arr, l, mid-1, x);
 
        // Else the element can only be present
        // in right subarray
        return binarySearch(arr, mid+1, r, x);
   }
 
   // We reach here when element is not 
   // present in array
   return -1;
}  
 

int main() {
    // already sorted array
    int searchMe[N] = {2, 3, 4, 10, 40};
    // value we are looking for
    int x = 10;
    
    printArray(searchMe, N);
    
    // pass array, starting index, 
    //ending index, and value we are looking for
    int result = binarySearch(searchMe, 0, N-1, x);
    
    cout << "The value is in index: " << result << endl;
    
    return 0;
}
			
Do Not Let What You Cannot Do Interfere With What You Can Do
s