To celebrate my 1 Million subscribers I decided to update my most popular video! This is a 1,000 page book on C++ condensed down to a 2 hour video. It was 5 hours long before editing.
For best results get the free code provided below and pause your way through the video while typing out the code.
Thank you for subscribing to my little channel! I greatly appreciate all of the wonderful people I have met on YouTube.
Get my Python Programming Bootcamp Series for $9.99 ( Expires Nov 3rd )
Like the channel? Consider becoming a Patreon and get access to exclusive videos!
GET FREE STUFF FOR SUPPORTING MY TUTORIALS
1. Get a Free Stock
2. Get 2 Free Audiobooks
Code from the Video
-------------------- main.cpp --------------------
/*
* Multi-line
* Comment
*/
// Single line comment
// Includes functions used to read and write data
#include <iostream>
// Contains functions for converting from 1 data type to
// another, random number generation, memory management,
// searching, math, sorting and other general purpose functions
#include <cstdlib>
// Allows you to use the STL string class
#include <string>
// Provides functions to find min and max values
// for data types
#include <limits>
// Will be introduced below
#include <string>
#include <vector>
#include <sstream>
#include <numeric>
#include <ctime>
#include <cmath>
#include "Shape.h"
#include "Circle.h"
// State that we can to use the standard namespace which means
// we don't have to type cout to output information, but
// can instead use cout
using namespace std;
// A global variable is declared outside of all functions
// and it can be accessed any place in your code
int imGlobal = 0;
// Use const to declare a variable constant thats value
// cannot be changed
const double PI = 3.141;
// ----- FUNCTION PROTOTYPES -----
// You define the return type and data types for functions
// using a function prototype so main knows what is to be expected
// from this function
double AddNumbers(double num1, double num2);
void AssignName();
void AssignAge(int age);
int AssignAge2(int age);
// This function receives pointers
void AssignAge3(int* pAge);
// Double values in array passed
void DoubleArray(int *arr, int size);
void ShowArea(Shape& shape);
// Execution of code starts in the main function
// argc and argv is optional data that could be passed
// to the program if it was executed in a terminal
// argc : Number of arguments passed
// argv : Array pointers to strings
int main(int argc, char** argv) {
// Outputs the string Hello World to the screen followed by a newline
// cout is your console or screen
// << : Stream insertion operator which puts the string
// into the cout stream to display it
// endl issues a newline and forces a write to the console
cout << "Hello World" << endl;
// Variable names can contain letters, numbers, underscores
// but not math operators, spaces and can't start with a number
// ---------- DATA TYPES ----------
// Data types define how much memory to set aside
// for data we want to store
// Booleans can have a value of true (1), or false (0)
bool married = true;
// Chars store 256 single characters represented by
// keys on your keyboard
char myGrade = 'A';
// There are many integer types with different min
// and max values
cout << "Min unsigned short int " <<
numeric_limits<unsigned short int>::min()
<< endl;
cout << "Max unsigned short int " <<
numeric_limits<unsigned short int>::max()
<< endl;
cout << "Min short int " <<
numeric_limits<short int>::min()
<< endl;
cout << "Max short int " <<
numeric_limits<short int>::max()
<< endl;
cout << "Min int " <<
numeric_limits<int>::min()
<< endl;
cout << "Max int " <<
numeric_limits<int>::max()
<< endl;
cout << "Min long " <<
numeric_limits<long>::min()
<< endl;
cout << "Max long " <<
numeric_limits<long>::max()
<< endl;
// Floating type numbers have decimal places
cout << "Min float " <<
numeric_limits<float>::min()
<< endl;
cout << "Max float " <<
numeric_limits<float>::max()
<< endl;
cout << "Min double " <<
numeric_limits<double>::min()
<< endl;
cout << "Max double " <<
numeric_limits<double>::max()
<< endl;
cout << "Min long double " <<
numeric_limits<long double>::min()
<< endl;
cout << "Max long double " <<
numeric_limits<long double>::max()
<< endl;
// The float is accurate to 6 digits
float f1 = 1.1111111;
float f2 = 1.1111111;
// Printf allows you to print with formatting
// Here I say I want to print 7 decimals
printf("Sum = %.7f\n", (f1 + f2));
// Doubles have 15 digits of precision
double d1 = 1.1111111111111111;
double d2 = 1.1111111111111111;
printf("Sum 2 = %.16f\n", (d1 + d2));
// You can have the compiler assign the type
auto whatAmI = true;
// Get the number of bytes assigned to a type
cout << "int Bytes : " << sizeof(int) << endl;
// More about printf()
// char, int, 5 space right justified int,
// 3 decimal float / double, string specifiers
printf("%c %d %5d %.3f %s\n", 'A', 10, 5, 3.1234, "Hi");
// Create a string
string q1 = "Enter a Number : ";
// Create strings to store values
string num1, num2;
cout << q1;
// Receive user input and store it
cin >> num1;
cout << "Enter Another Number : ";
cin >> num2;
// Convert strings into ints
int nNum1 = stoi(num1);
int nNum2 = stoi(num2);
// Math Operators
printf("%d + %d = %d\n", nNum1, nNum2, (nNum1 + nNum2));
printf("%d - %d = %d\n", nNum1, nNum2, (nNum1 - nNum2));
printf("%d * %d = %d\n", nNum1, nNum2, (nNum1 * nNum2));
printf("%d / %d = %d\n", nNum1, nNum2, (nNum1 / nNum2));
printf("%d %% %d = %d\n", nNum1, nNum2, (nNum1 % nNum2));
// ---------- CONDITIONALS ----------
// Conditional Operators : > < >= <= == !=
// Logical Operators : && || !
string sAge;
cout << "Enter your Age : ";
cin >> sAge;
int nAge = stoi(sAge);
// Used to output whether a birthday is important
if ((nAge >= 1) && (nAge <= 18)){
cout << "Important Birthday" << endl;
} else if ((nAge == 21) || (nAge == 50)){
cout << "Important Birthday" << endl;
} else if (nAge >= 65){
cout << "Important Birthday" << endl;
} else {
cout << "Not an Important Birthday" << endl;
}
// A ternary operator works like a compact if else
// statement. If the condition is true the first
// value is stored and otherwise the second
int age43 = 43;
bool canIVote = (age43 >= 18) ? true : false;
// Shows bool values as true or false
cout.setf(ios::boolalpha);
cout << "Can Derek Vote : " << canIVote << endl;
// ---------- ARRAYS ----------
// An array is a collection of data of the same type
// Declare an array of ints with the value of 1
// Once the size is defined it can't change
int arrnNums[10] = {1};
// Leave out the array length
int arrnNums2[] = {1,2,3};
// Create an array and assign some values
int arrnNums3[5] = {8, 9};
// Access array values using indexes starting with 0
cout << "1st Value : " << arrnNums3[0] << endl;
// Change a value
arrnNums3[0] = 7;
cout << "1st Value : " << arrnNums3[0] << endl;
// A multidimensional array is like a spreadsheet
// If you think of each as layers that contain columns
// 1st Number : Which layer
// 2nd Number : Which column
// 3rd Number : Which row
int arrnNums4[2][2][2] = {{{1,2}, {3,4}},
{{5,6}, {7,8}}};
cout << arrnNums4[0][1][1] << endl;
// ---------- VECTORS ----------
// Vectors are used when you don't know how big the array
// should be
vector<int> vNums(2);
// Add values
vNums[0] = 1;
vNums[1] = 2;
// Add another to the end
vNums.push_back(3);
// Get vector size
cout << "Vector Size : " << vNums.size() << endl;
// ---------- LOOPING ----------
// While loops continue to run the code in them
// as long as a condition is true
// Create the variable used in the while condition
// before the while loop
int i = 1;
while (i <= 20){
// If a value is even don't print it
if((i % 2) == 0){
i += 1;
// Continue skips the rest of the code
// and jumps back to the beginning
// of the loop
continue;
}
// Break stops execution of the loop and jumps
// to the line after the loops closing }
if(i == 15) break;
cout << i << "\n";
// Increment i so the loop eventually ends
i += 1;
}
// A stringstream object receives strings separated
// by a space and then spits them out 1 by 1
vector<string> words;
stringstream ss("Some Random Words");
string word;
// A while loop will execute as long as there are
// more words
while(getline(ss, word, ' ')){
words.push_back(word);
}
// Cycle through each index in the vector using
// a for loop
for(int i = 0; i < words.size(); ++i){
cout << words[i] << endl;
}
// An abbreviated for loop
int arr3[] = {1,2,3};
for(auto x: arr3) cout << x << endl;
// Do while loops are guaranteed to execute at
// least once
// We'll create a secret number guessing game
// We need to seed the random number generator
// time() returns the number of seconds
// since 1, 1, 1970
// Include <ctime>
srand(time(NULL));
// Generate a random number up to 10
int secretNum = rand() % 11;
int guess = 0;
do{
cout << "Guess the Number : ";
cin >> guess;
if(guess > secretNum) cout << "To Big\n";
if(guess < secretNum) cout << "To Small\n";
} while(secretNum != guess);
cout << "You guessed it" << endl;
// ---------- STRINGS ----------
// A C++ string is a series of characters that
// can be changed
string str1 = "I'm a string";
// Get the 1st character
cout << "1st : " << str1[0] << endl;
// Get the last character
cout << "Last : " << str1.back() << endl;
// Get the string length
cout << "Length : " << str1.length() << endl;
// Copy a string to another
string str2 = str1;
// Copy a string after the 1st 4 characters
string str3(str2, 4);
// Combine strings
string str4 = str1 + " and your not";
// Append to the end of a string
str4.append("!");
// Erase characters from a string from 1 index
// to another
str4.erase(12, str4.length() - 1);
cout << "New String : " << str4 << endl;
// find() returns index where pattern is found
// or npos (End of String)
if(str4.find("string") != string::npos)
cout << "String Index : " <<
str4.find("string") << endl;
// substr(x, y) returns a substring starting at
// index x with a length of y
cout << "Substring : " <<
str4.substr(6,6) << endl;
// Convert int to string
string strNum = to_string(1+2);
cout << "I'm a String : " << strNum << "\n";
// Character functions
char letterZ = 'z';
char num5 = '5';
char aSpace = ' ';
cout << "Is z a letter or number " <<
isalnum(letterZ) << endl;
cout << "Is z a letter " <<
isalpha(letterZ) << endl;
cout << "Is 3 a number " <<
isdigit(num5) << endl;
cout << "Is space a space " <<
isspace(aSpace) << endl;
// ---------- MATH FUNCTIONS ----------
// There are numerous math functions provided by
// cmath en.cppreference.com/w/cpp/numeric/math
cout << "abs(-10) = " << abs(-10) << endl;
cout << "max(5, 4) = " << max(5, 4) << endl;
cout << "min(5, 4) = " << min(5, 4) << endl;
cout << "fmax(5.3, 4.3) = " << fmax(5.3, 4.3) << endl;
cout << "fmin(5.3, 4.3) = " << fmin(5.3, 4.3) << endl;
cout << "ceil(10.45) = " << ceil(10.45) << endl;
cout << "floor(10.45) = " << floor(10.45) << endl;
cout << "round(10.45) = " << round(10.45) << endl;
cout << "pow(2,3) = " << pow(2,3) << endl;
cout << "sqrt(100) = " << sqrt(100) << endl;
cout << "cbrt(1000) = " << cbrt(1000) << endl;
// e ^ x
cout << "exp(1) = " << exp(1) << endl;
// 2 ^ x
cout << "exp2(1) = " << exp2(1) << endl;
// e * e * e ~= 20 so log(20.079) ~= 3
cout << "log(20.079) = " << log(20.079) << endl;
// 2 * 2 * 2 = 8
cout << "log2(8) = " << log2(8) << endl;
// Hypotenuse : SQRT(A^2 + B^2)
cout << "hypot(2,3) = " << hypot(2,3) << endl;
// Also sin, cos, tan, asin, acos, atan, atan2,
// sinh, cosh, tanh, asinh, acosh, atanh
// ---------- FUNCTIONS ----------
// You define function prototypes outside of main
// so main knows a functions basic settings
// Functions are also created outside of main
// and can be found after main below
// Call a function that sums values
printf("%.1f + %.1f = %.1f\n", 5.0,
4.0, AddNumbers(5, 4));
// The function AssignName below creates a
// variable called name, but variables created
// in functions are not available outside of
// that function
// Variable values changed in a function don't
// change that variables value outside of the
// function
int age2 = 43;
AssignAge(age2);
cout << "New Age : " << age2 << endl;
// You could change the value by passing it back
age2 = AssignAge2(age2);
cout << "New Age " << age2 << "\n";
// ---------- POINTERS ----------
// A Pointer stores a address in memory
// You declare a pointer to be of the same type as the data
// type to which it points
// If you are storing the address of an int then the
// pointer is an int
// When you declare a pointer give it a null value
int* pAge2 = NULL;
// The reference operator returns the address for a
// variable that can be stored in a pointer
pAge2 = &age2;
// Print the address Hexidecimal Number
cout << "Address : " << pAge2 << "\n";
// Get the value at that address with the dereference
// operator
cout << "Value at Address : " << *pAge2 << "\n";
// We can create a pointer to an array and cycle
// through the data with ++ and --
int intArray[] = {1,2,3,4};
int* pIntArray = intArray;
cout << "1st " << *pIntArray <<
" Address " << pIntArray << "\n";
pIntArray++;
cout << "2nd " << *pIntArray <<
" Address " << pIntArray << "\n";
pIntArray--;
cout << "1st " << *pIntArray <<
" Address " << pIntArray << "\n";
// You can pass a pointer to a function and then
// the function can change that variables value
// globally
age2 = 43;
// Send the address for age to the function
AssignAge3(&age2);
cout << "Pointer Age " << age2 << "\n";
// Create an array and double values
int arr[] = {1,2,3,4};
DoubleArray(arr, 4);
for(int i = 0; i < 4; ++i){
cout << "Array " << arr[i] << "\n";
}
// ---------- EXCEPTION HANDLING ----------
// Exceptions are errors that occur when things don't
// go as expected
// You try to execute code that could be troublesome
// and if an error occurs you catch it and throw
// it to another block of code for handling
double num3 = 10, num4 = 0;
try{
if(num4 == 0){
throw "Division by Zero Error";
} else {
printf("%.1f / %.1f = %.1f", num3, num4,
(num3 / num4));
}
}
catch(const char* exp){
cout << "Error : " << exp << endl;
}
// ---------- OBJECTS & CLASSES ----------
// With object oriented programming we model real
// world objects with code. Real objects have
// attributes (height, weight) and capabilities
// (run, eat)
// In object oriented programming we store
// attribute values in fields / variables and
// we simulate capabilities in methods / functions
// A class is a blueprint for modeling the above
Shape square(10, 5);
Circle circle(10);
ShowArea(square);
ShowArea(circle);
// The main function returns a 0 when it has executed
// without an error
return 0;
}
// ---------- FUNCTIONS ----------
// A function starts with the data type it will return or void
// if no value is returned
// You also list the data types for the parameters passed into
// a function and you may assign them default values
double AddNumbers(double num1 = 0, double num2 = 0){
return num1 + num2;
}
// A variable created inside a function can't be accessed
// outside of it
void AssignName(){
string name = "Derek";
}
void AssignAge(int age){
age = 24;
}
int AssignAge2(int age){
age = 24;
return age;
}
// Function that receives a pointer
void AssignAge3(int* pAge){
// Use dereference operator to change the value
// at the address
*pAge = 22;
}
// Double values in array
void DoubleArray(int *arr, int size){
for(int i = 0; i < size; ++i){
arr[i] = arr[i] * 2;
}
}
// This function receives Shapes but uses the
// correct Area() automatically
// This is an example of polymorphism
void ShowArea(Shape& shape){
cout << "Area : " << shape.Area() << "\n";
}
-------------------- Shape.h --------------------
// The header file adds declarations for your
// code file
#ifndef SHAPE_H
#define SHAPE_H
// We will model a generic Shape in this class
// Protected fields & methods can only be accessed
// in this class, or in classes that inherit from
// the Shape class
// Private is used when you want to block access
// to all code aside from code in this class
// Public is used when you want to provide access
// to anything with access to an object
class Shape{
protected:
double height;
double width;
public:
// Static variables share the same value for all
// shape objects
static int numOfShapes;
// This is the constructor and it is called
// every time a shape object is created
// You can have multiple constructors with the same
// name that differ only in the number of parameters
// they accept
// If only 1 parameter is passed will assume that
// height and width are equal
Shape(double length);
Shape(double height, double width);
Shape();
// A deconstructor is called automatically when an object
// is deleted or is no longer used
// The default is fine, but you should create custom ones
// when you must release memory, or resources
virtual ~Shape();
void SetHeight(double height);
double GetHeight();
void SetWidth(double width);
double GetWidth();
// Static methods can only access static fields
static int GetNumOfShapes();
virtual double Area();
};
#endif /* SHAPE_H */
-------------------- Shape.cpp --------------------
// Refer to the declarations in the header
#include "Shape.h"
// This file is called the implementation file
Shape::Shape(double length){
this->height = length;
this->width = length;
// Refer to class fields and methods with ::
Shape::numOfShapes++;
}
Shape::Shape(double height, double width){
this->height = height;
this->width = width;
Shape::numOfShapes++;
}
Shape::~Shape() = default;
// We can protect access to our fields using getters
// and setters. We could block certain values
// from being assigned, or we could provide
// custom output like adding inches or centimeter
// to the height, or width
// Because we create the class before naming an
// object we don't know its name. We can use this
// to refer to objects.
// The pointer operator is used to access an
// objects fields and methods
void Shape::SetHeight(double height){this->height = height;}
double Shape::GetHeight(){return height;}
void Shape::SetWidth(double width){this->width = width;}
double Shape::GetWidth(){return width;}
int Shape::GetNumOfShapes(){return numOfShapes;}
// A method marked as virtual can be used
// polymorphically.
// Polymorphism is a feature in which similar
// objects can be treated the same, but also
// utilize their differences automatically
// for any methods marked as virtual
double Shape::Area(){
return height * width;
}
int Shape::numOfShapes = 0;
/*
Because Shape has no purpose aside from grouping similar
objects it should really be an Abstract class.
class Shape{
public:
virtual double Area() = 0;
};
class Circle : public Shape{
protected:
double width;
public:
Circle(double w){
width = w;
}
// Override Area()
// You should use override to force the
// compiler to check if the base class
// virtual fucntion is the same as
// the subclass
double Area() override{
return 3.14159 * pow((width / 2), 2);
}
};
// This function receives Shapes but uses the
// correct Area() automatically
void ShowArea(Shape& shape){
cout << "Area : " << shape.Area() << endl;
}
int main()
{
Rectangle rectangle(10,5);
Circle circle(10);
ShowArea(rectangle);
ShowArea(circle);
Square square(10,10);
ShowArea(square);
return 0;
}
*
*/
-------------------- Circle.h --------------------
// Makes sure header files aren't included
// more than once
#ifndef CIRCLE_H
#define CIRCLE_H
class Circle: public Shape{
public:
Circle();
Circle(const Circle& orig);
Circle(double width);
virtual ~Circle();
double Area();
private:
};
#endif /* CIRCLE_H */
-------------------- Circle.cpp --------------------
#include "Shape.h"
#include "Circle.h"
#include <cmath>
Circle::Circle(double width): Shape(width)
{
}
Circle::~Circle() = default;
double Circle::Area(){
return 3.14159 * pow((width / 2), 2);
}
-------------------- MULTIPLE TOPICS --------------------
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <numeric>
#include <cmath>
#include <sstream>
#include <fstream> // Used for file IO
using namespace std;
// ---------- STRUCTS ----------
// Classes have default private fields and methods
// while structs have public
// Structs are used to model new data types, while
// classes model more complex real world objects
struct Shape{
// Variables are public by default
double length, width;
// Constructors are public by default
Shape(double l = 1, double w = 1){
length = l;
width = w;
}
// Structs can contain functions
double Area(){
return length * width;
}
// Structs can contain private members
private:
int id;
};
// You can inherit from a struct
struct Circle : Shape{
// Override the constructor
// You also use this with structs
Circle(double width){
this->width = width;
}
// Override Area()
double Area(){
return 3.14159 * pow((width / 2), 2);
}
};
// ---------- USED WITH LAMBDA EXPRESIONS ----------
vector<int> GenerateRandVec(int numOfNums,
int min, int max);
// ---------- OPERATOR OVERLOADING ----------
// You can define custom operators just as you define functions
// This allows you to compare, perform calculations, etc.
// with your objects in custom ways
// Create a custom Box class with overloaded operators
class Box{
public:
double length, width, breadth;
// Used to hold a string representation of a box
string boxString;
Box(){
length = 1, width = 1, breadth = 1;
}
Box(double l, double w, double b){
length = l, width = w, breadth = b;
}
// You can define customer operators just like
// you define functions
// This is a unary operator because it operates
// on 1 object
// Other Unary Operators : --, *(pointer dereference),
// -> (Member Selection), !, & (Address of), +, -
Box& operator ++ (){
length++;
width++;
breadth++;
return *this;
}
// Creates a C string representation which is a
// pointer to an array that is null terminated
operator const char*() {
// Creates a stream that can be loaded with
// characters that can then be accessed as
// a string object
ostringstream boxStream;
boxStream << "Box : " <<
length << ", " <<
width << ", " <<
breadth;
// Return a string representation of the stream
boxString = boxStream.str();
// Returns the pointer to the string array
return boxString.c_str();
}
// Binary operators operate on 2 objects
// +, -, *, /, %, ==, !=, >, <, >=, <=, &&, ||,
// !, =, +=, -=, *=, /=, ^, [], &, |
// Let's add boxes
Box operator + (const Box& box2){
Box boxSum;
boxSum.length = length + box2.length;
boxSum.width = width + box2.width;
boxSum.breadth = breadth + box2.breadth;
return boxSum;
}
// Check for box equality
bool operator == (const Box& box2){
return ((length == box2.length) &&
(width == box2.width) &&
(breadth == box2.breadth));
}
};
int main()
{
// Create a struct
Shape shape(10, 10);
// Call a Struct function
cout << "Square Area : " << shape.Area()
<< endl;
// Create a struct
Circle circle(10);
// Call a Struct function
cout << "Circle Area : " << circle.Area()
<< endl;
// You can initialize a struct or class using
// an aggregate
Shape rectangle{10,15};
cout << "Rectangle Area : " <<
rectangle.Area() << endl;
// ---------- LAMBDA EXPRESSIONS ----------
vector<int> vecVals = GenerateRandVec(10, 1, 50);
// Lambda Expressions make it easy to perform list
// operations in one line of code. You designate
// them with []
// Here we sort a vector
sort(vecVals.begin(), vecVals.end(),
[](int x, int y){ return x < y; });
for(auto val: vecVals)
cout << val << endl;
cout << endl;
// copy_if works like filter does in other languages
// Here we keep only even values in a new vector
vector<int> evenVecVals;
copy_if(vecVals.begin(), vecVals.end(),
back_inserter(evenVecVals),
[](int x){ return (x % 2) == 0; });
for(auto val: evenVecVals)
cout << val << endl;
// ----- SUM A LIST -----
int sum = 0;
// for_each cycles through all values
// [&] captures all variables used
// in the body of the lambda by reference
for_each(vecVals.begin(), vecVals.end(),
[&] (int x) {sum += x; });
cout << "SUM : " << sum << endl;
// ----- RECURSIVE LAMBDA FUNCTIONS -----
// Recursive Lambda to calculate Fibonacci Numbers
function<int(int)> Fib =
[&Fib](int n) {return n < 2 ? n : Fib(n-1) + Fib(n-2);};
// Fib(0) = 0
// Fib(1) = 1
// Fib(2) = 1
// Fib(3) = 2
// Fib(4) = 3
cout << "Fib 4 : " << Fib(4) << endl;
// ---------- OPERATOR OVERLOADING ----------
Box box(10,10,10);
// Will increment all values in the box by 1
++box;
cout << box << endl;
// Add boxes
Box box2(5,5,5);
cout << "Box1 + Box2 = " <<
box + box2 << endl;
// Check equality
cout << "Are boxes equal : " <<
(box == box2) << endl;
// ---------- FILE IO ----------
ofstream writeToFile;
ifstream readFromFile;
string txtToWrite = "";
string txtFromFile = "";
// We open the file by providing a name and then either
// ios::app : Append to the end of the file
// ios::trunc : If the exists delete content
// ios::in : Open file for reading
// ios::out : Open file for writing
// ios::ate : Open writing and move to the end of the file
writeToFile.open("test.txt", ios_base::out |
ios_base::trunc);
if(writeToFile.is_open()){
// You can write with the stream insertion operator
writeToFile << "Beginning of File\n";
// You can write data in a string
cout << "Enter data to write : ";
getline(cin, txtToWrite);
writeToFile << txtToWrite;
// Close the file
writeToFile.close();
}
// Open the file for reading
readFromFile.open("test.txt", ios_base::in);
if(readFromFile.is_open()){
// Read text from file
while(readFromFile.good()){
getline(readFromFile, txtFromFile);
// Print text from file
cout << txtFromFile << endl;
}
readFromFile.close();
}
return 0;
}
// ---------- USED WITH LAMBDA EXPRESIONS ----------
vector<int> GenerateRandVec(int numOfNums,
int min, int max){
vector<int> vecValues;
srand(time(NULL));
int i = 0, randVal = 0;
while(i < numOfNums){
randVal = min + rand() % ((max + 1) - min);
vecValues.push_back(randVal);
i++;
}
return vecValues;
}
// ---------- FUNCTIONS AS OBJECTS ----------
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <numeric>
#include <cmath>
#include <sstream>
#include <fstream> // Used for file IO
using namespace std;
// 1. Created to store as a variable and to
// pass into other functions
double MultBy2(double num){
return num * 2;
}
// 2. Functions can receive other functions
// the first double is the return type followed
// by the data types for the parameter
double DoMath(function<double(double)> func, double num){
return func(num);
}
// 3. You can store functions in a vector
double MultBy3(double num){
return num * 3;
}
int main()
{
// 1. You can store functions as variables
auto times2 = MultBy2;
cout << "5 * 2 = " <<
times2(5) << endl;
// 2. Pass a function into a function
cout << "6 * 2 = " <<
DoMath(times2, 6) << endl;
// 3. You can store functions in a vector
// Create a vector using the function parameters
// and then load the functions into the vector
vector<function<double(double)>> funcs (2);
funcs[0] = MultBy2;
funcs[1] = MultBy3;
cout << "2 * 10 = " <<
funcs[0](10) << endl;
return 0;
}
-------------------- TEMPLATES / ITERATORS --------------------
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <numeric>
#include <cmath>
#include <sstream>
#include <fstream> // Used for file IO
#include <deque>
#include <iterator>
using namespace std;
// ---------- MACROS ----------
// This is a macro constant that will replace
// PI with 3.14159 in the code before execution
#define PI 3.14159
// This is a macro function that will do the same with
// a function
#define AREA_CIRCLE(radius) (PI * (pow(radius, 2)))
// ----- TEMPLATE FUNCTIONS -----
// We use templates to create functions or classes
// that can work with many types
// Templates differ from function overloading in that
// instead of having a function that does similar
// things with different objects a template does the
// same thing with different objects
// This says this is a function template that generates
// functions that except 1 parameter
template <typename T>
void Times2(T val){
cout << val << " * 2 = " <<
val * 2 << endl;
}
// Receive multiple parameters and return a value
template <typename T>
T Add(T val, T val2){
return val + val2;
}
// Work with chars and strings
template <typename T>
T Max(T val, T val2){
return (val < val2) ? val2 : val;
}
// ----- TEMPLATE CLASSES -----
// Template classes are classes that can work with
// different data types
// You can define that you may receive parameters
// with different types, but they don't have to
// be different
template <typename T, typename U>
class Person{
public:
T height;
U weight;
static int numOfPeople;
Person(T h, U w){
height = h, weight = w;
numOfPeople++;
}
void GetData(){
cout << "Height : " <<
height <<
" and Weight : " <<
weight << endl;
}
};
// You have to initialize static class members
template<typename T, typename U> int Person<T, U>::numOfPeople;
int main()
{
cout << "Circle Area : " <<
AREA_CIRCLE(5) << endl;
// ----- TEMPLATE FUNCTIONS -----
// The template function can receive ints or floats
Times2(5);
Times2(5.3);
// Multiple parameters and returned value
cout << "5 + 4 = " <<
Add(5,4) << endl;
cout << "5.5 + 4.6 = " <<
Add(5.5,4.6) << endl;
// Get biggest value
cout << "Max 4 or 8 = " <<
Max(4, 8) << endl;
cout << "Max A or B = " <<
Max('A', 'B') << endl;
cout << "Max Dog or Cat = " <<
Max("Dog", "Cat") << endl;
// ----- END OF TEMPLATE FUNCTIONS -----
// ----- TEMPLATE CLASSES -----
// When creating the object you must define the
// data types used
Person<double, int> mikeTyson (5.83, 216);
mikeTyson.GetData();
// You access static values using the object
// and not the class
cout << "Number of people : " <<
mikeTyson.numOfPeople << endl;
// ----- END OF TEMPLATE CLASSES -----
// ----- CONTAINERS -----
// We have already seen the STL container vector
// There are many other special ways of storing data
// ----- DOUBLE ENDED QUEUE -----
// A double ended queue (Deck) is a dynamic array that can
// be expanded or contracted on both ends
deque<int> nums = {1,2,3,4};
nums.push_front(0);
nums.push_back(5);
for(int x: nums)
cout << x << endl;
// You can access index values, but they are costly
// because values aren't stored contigously, but
// instead use multiple arrays
cout << nums[0] << endl;
// ----- END DOUBLE ENDED QUEUE -----
// ----- ITERATORS -----
// Iterators are used to point at container
// memory locations
vector<int> nums2 = {1,2,3,4};
// Define an iterator as the same type
vector<int>::iterator itr;
// Refer to the vectors begin and end while
// incrementing the iterator
for(itr = nums2.begin();
itr < nums2.end();
itr++){
// Get value at the pointer
cout << *itr << endl;
}
// You can also increment a set number of spaces
// Create an iterator and point it at the beginning
// of the vector
vector<int>::iterator itr2 = nums2.begin();
// Advance 2 spaces
advance(itr2, 2);
cout << *itr2 << endl;
// Next works like advance, but it returns an
// iterator
auto itr3 = next(itr2, 1);
cout << *itr3 << endl;
// Previous moves a set number of indexes and
// returns an iterator
auto itr4 = prev(itr2, 1);
cout << *itr4 << endl;
// You can also insert at a defined index
vector<int> nums3 = {1,4,5,6};
vector<int> nums4 = {2,3};
auto itr5 = nums3.begin();
advance(itr5, 1);
copy(nums4.begin(), nums4.end(),
inserter(nums3, itr5));
for(int &i: nums3)
cout << i << endl;
return 0; }
-------------------- POINTERS / MALLOC / TEMPLATES --------------------
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <numeric>
#include <cmath>
#include <sstream>
#include <iterator>
#include <memory>
#include <stdio.h>
using namespace std;
// A Smart pointer is a class that provides the
// power of pointers, but also handles the reallocation
// of memory when it is no longer required (The pointer
// is automatically destroyed)
// typedef creates an alias for a more complex type name
typedef vector<int32_t> intVec;
int main()
{
/* MALLOC EXAMPLE
// When you define a primitive type like int or
// float you define exactly the amount of space
// to set aside
// If you need to define how much space to set aside
// you could call malloc() and tell it how much
// space to set aside and it returns the address to
// that memory address
int amtToStore;
cout << "How many numbers do you want to store : ";
cin >> amtToStore;
// Create an int pointer and set aside enough space
int * pNums;
// Cast the pointer and define how much space to set aside
pNums = (int *) malloc(amtToStore * sizeof(int));
// Check if memory was allocated
if(pNums != NULL){
int i = 0;
// Store values
while(i < amtToStore){
cout << "Enter a Number : ";
cin >> pNums[i];
i++;
}
}
cout << "You entered these numbers\n";
for(int i = 0; i < amtToStore; i++){
cout << pNums[i] << endl;
}
// Delete the pointer
delete pNums;
*/
// Smart Pointer Solution
int amtToStore;
cout << "How many numbers do you want to store : ";
cin >> amtToStore;
// This memory will be automatically reallocated
unique_ptr<int[]> pNums(new int[amtToStore]);
// unique_ptr can only have one owner
// so this throws an error
// unique_ptr<int[]> pNums2 = pNums;
// I'll cover how to do this with shared_ptr
// in a later tutorial
if(pNums != NULL){
int i = 0;
// Store values
while(i < amtToStore){
cout << "Enter a Number : ";
cin >> pNums[i];
i++;
}
}
cout << "You entered these numbers\n";
for(int i = 0; i < amtToStore; i++){
cout << pNums[i] << endl;
}
return 0;
}
// Here I demonstrate how to use templates
// polymorphically
// Base class all pizzas inherit along with MakePizza
// which will be overridden
class Pizza{
public:
virtual void MakePizza() = 0;
};
// The last templates that will be called
class NYStyleCrust {
public:
string AddIngredient() {
return "Crust so Thin You can See through it\n\n";
}
};
class DeepDishCrust {
public:
string AddIngredient() {
return "Super Awesome Chicago Deep Dish Crust\n\n";
}
};
// End of last templates called
// The middle templates called
template <typename T>
class LotsOfMeat: public T {
public:
string AddIngredient() {
return "Lots of Random Meat, " + T::AddIngredient();
}
};
template <typename T>
class Vegan: public T {
public:
string AddIngredient() {
return "Vegan Cheese, Veggies, " + T::AddIngredient();
}
};
// End of middle templates called
// We inherit from Pizza as well as the initial next template
template <typename T>
class MeatNYStyle: public T, public Pizza {
public:
void MakePizza() { cout << "Meat NY Style Pizza : " <<
T::AddIngredient(); }
};
template <typename T>
class VeganDeepDish: public T, public Pizza {
public:
void MakePizza() { cout << "Vegan Deep Dish : " <<
T::AddIngredient(); }
};
int main()
{
// unique_ptr is a smart pointer that disposes of
// a pointer when it is no longer in use
vector<unique_ptr<Pizza>> pizzaOrders;
// Generate Pizza types and place them at the end of the vector
pizzaOrders.emplace_back(new MeatNYStyle<LotsOfMeat<NYStyleCrust>>());
pizzaOrders.emplace_back(new VeganDeepDish<Vegan<DeepDishCrust>>());
// Call the pizzas and execute the directions
// for making them
for(auto &pizza: pizzaOrders){
pizza->MakePizza();
}
return 0;
}
// ---------- THREADS ----------
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <numeric>
#include <cmath>
#include <sstream>
#include <thread>
#include <chrono>
#include <ctime>
#include <mutex>
using namespace std;
int GetRandom(int max){
srand(time(NULL));
return rand() % max;
}
// ----- SIMPLE THREAD EXAMPLE -----
void ExecuteThread(int id){
// Get current time
auto nowTime = chrono::system_clock::now();
// Convert to a time we can output
time_t sleepTime =
chrono::system_clock::to_time_t(nowTime);
// Convert to current time zone
tm myLocalTime = *localtime(&sleepTime);
// Print full time information
cout << "Thread " << id <<
" Sleep Time : " <<
ctime(&sleepTime) << endl;
// Get separate pieces
cout << "Month : " <<
myLocalTime.tm_mon << endl;
cout << "Day : " <<
myLocalTime.tm_mday << endl;
cout << "Year : " <<
myLocalTime.tm_year + 1900 << endl;
cout << "Hours : " <<
myLocalTime.tm_hour << endl;
cout << "Minutes : " <<
myLocalTime.tm_min << endl;
cout << "Seconds : " <<
myLocalTime.tm_sec << "\n" << endl;
// Put the thread to sleep for up to 3 seconds
this_thread::sleep_for (chrono::seconds(GetRandom(3)));
nowTime = chrono::system_clock::now();
sleepTime =
chrono::system_clock::to_time_t(nowTime);
cout << "Thread " << id <<
" Awake Time : " <<
ctime(&sleepTime) << endl;
}
int main()
{
// Create a thread and pass a parameter
// to the function
thread th1 (ExecuteThread, 1);
// Join the thread to the main thread
// meaning main waits for this thread to
// stop executing before continuing execution
// of code in main
th1.join();
thread th2 (ExecuteThread, 2);
th2.join();
return 0;
}
// ---------- SEQUENCE CONTAINERS ----------
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <numeric>
#include <cmath>
#include <sstream>
#include <thread>
#include <ctime>
#include <deque>
#include <list>
#include<forward_list>
bool isEven(const int& val){
return (val % 2) == 0;
}
int main()
{
// Contains data stored in order
// ---------- DEQUES ----------
// A deque (Deck) is a dynamic array like vectors
// except it also allows for insertion or deletion
// from the front
deque<int> deq1;
// Add to the end and front
deq1.push_back(5);
deq1.push_front(1);
// Add values with assign
deq1.assign({11,12});
// Get the size
cout << "Size : " << deq1.size()
<< endl;
// Access by index
cout << deq1[0] << endl;
cout << deq1.at(1) << endl;
// Add at an index using an iterator
deque<int>::iterator it = deq1.begin() + 1;
deq1.insert(it, 3);
// Add multiple values
int tempArr[5] = {6,7,8,9,10};
deq1.insert(deq1.end(), tempArr, tempArr+5);
// Erase at an index
deq1.erase(deq1.end());
// Erase 1st 2 elements
deq1.erase(deq1.begin(), deq1.begin()+2);
// Pop first value
deq1.pop_front();
// Pop last
deq1.pop_back();
// Create a deque with 2 50s
deque<int> deq2(2,50);
// Swap values in deques
deq1.swap(deq2);
// Delete all values
deq1.clear();
// Cycle through the deque
for(int i : deq1)
cout << i << endl;
// ---------- END DEQUES ----------
// ---------- LIST ----------
// Lists are the most efficient at inserting,
// moving and extracting elements, but lack
// direct access to elements
// Add values
int arr[5] = {1,2,3,4,5};
list<int> list1;
list1.insert(list1.begin(), arr, arr+5);
// Adding values with assign
list1.assign({10,20,30});
// Add to end and front
list1.push_back(5);
list1.push_front(1);
// Get the size
cout << "Size : " << list1.size()
<< endl;
// Can't access index
// cout << list1[0] << endl;
// You can access the index with an iterator
list<int>::iterator it2 = list1.begin();
advance(it2, 1);
cout << "2nd Index : " <<
*it2 << endl;
// Insert at an index
it2 = list1.begin();
list1.insert(it2, 8);
// Erase at an index
list1.erase(list1.begin());
// Erase 1st 2 elements
it2 = list1.begin();
list<int>::iterator it3 = list1.begin();
advance(it3, 2);
list1.erase(it2, it3);
// Pop first value
list1.pop_front();
// Pop last
list1.pop_back();
// Create another list
int arr2[6] = {10,9,8,7,6,6};
list<int> list2;
list2.insert(list2.begin(), arr2, arr2+5);
// Sort the list
list2.sort();
// Reverse the list
list2.reverse();
// Remove duplicates
list2.unique();
// Remove a value
list2.remove(6);
// Remove if a condition is true
list2.remove_if (isEven);
// Merge lists
list1.merge(list2);
for(int i : list2)
cout << i << endl;
cout << endl;
// Cycle through the list
for(int i : list1)
cout << i << endl;
cout << endl;
// ---------- END LIST ----------
// ---------- FORWARD_LIST ----------
// A forward list is like a list, but each list
// item only has a link to the next item in the
// list and not to the item that proceeds it.
// This make them the quickest of the sequence
// containers
forward_list<int> fl1;
// Assign values
fl1.assign({1,2,3,4});
// Push and pop front
fl1.push_front(0);
fl1.pop_front();
// Get 1st
cout << "Front : " << fl1.front();
// Get iterator for 1st element
forward_list<int>::iterator it4 = fl1.begin();
// Insert after 1st element
it4 = fl1.insert_after(it4, 5);
// Delete just entered 5
it4 = fl1.erase_after(fl1.begin());
// Place in 1st position
fl1.emplace_front(6);
// Remove a value
fl1.remove(6);
// Remove if a condition is true
fl1.remove_if (isEven);
forward_list<int> fl2;
fl2.assign({9,8,7,6,6});
// Remove duplicates
fl2.unique();
// Sort
fl2.sort();
// Reverse
fl2.reverse();
// Merge lists
fl1.merge(fl2);
// Clear
fl1.clear();
for(int i : fl1)
cout << i << endl;
cout << endl;
for(int i : fl2)
cout << i << endl;
// ---------- END FORWARD_LIST ----------
return 0;
}
-------------------- MORE CONTAINERS --------------------
// ----- ASSOCIATIVE CONTAINERS -----
// Associative containers store sorted data
// which makes insertion slower, but searching
// faster
int main()
{
// ----- SET -----
// Sets store unique sorted values using a key
set<int> set1 {5,4,3,2,1,1};
cout << "Size : " << set1.size() <<
endl;
// Insert value
set1.insert(0);
// Subscript operator doesn't work
// cout << set1[0] << endl;
// Get values with an iterator
set<int>::iterator it = set1.begin();
it++;
cout << "2nd : " << *it << endl;
// Erase value
set1.erase(5);
// Erase last 2
it = set1.end();
advance(it, -2);
set1.erase(it, set1.end());
// Add multiple values
int arr[] = {6,7,8,9};
set1.insert(arr,arr+4);
// Find value, get iterator and then value
auto val = set1.find(6);
cout << "Found : " << *val << endl;
// Get iterator to value
auto eight = set1.lower_bound(8);
cout << "8 : " << *eight << endl;
// Get iterator to value after
auto nine = set1.upper_bound(8);
cout << "9 : " << *nine << endl;
// Swap values in sets
set<int> set2 {10,11};
set1.swap(set2);
// Check if empty and if not print values
if(!set1.empty()){
for(int i : set1)
cout << i << endl;
}
// ----- END OF SET -----
cout << endl;
// ----- MULTISET -----
// Stores duplicate values in sorted order
// Other than that it is the same as set
multiset<int> mset1 {1,1,2,3,4};
// Insert value
mset1.insert(4);
mset1.insert(0);
if(!mset1.empty()){
for(int i : mset1)
cout << i << endl;
}
// ----- END MULTISET -----
cout << endl;
// ----- MAP -----
// Stores using key value pairs and you
// can't have duplicate keys
map<int, string> map1;
// Insert key values
map1.insert(pair <int, string> (1, "Bart"));
map1.insert(pair <int, string> (2, "Lisa"));
map1.insert(pair <int, string> (3, "Marge"));
map1.insert(pair <int, string> (4, "Homer"));
// Find element by key
auto match = map1.find(1);
cout << match->second << endl;
// Get iterator to value
auto bart = map1.lower_bound(1);
cout << "LB : " << bart->second << endl;
// Get next iterator
auto lisa = map1.upper_bound(1);
cout << "UB : " << lisa->second << endl;
// Print elements with an iterator
map<int, string>::iterator it2;
for(it2 = map1.begin(); it2 != map1.end(); ++it2){
cout << "Key : " << it2->first << endl;
cout << "Value : " << it2->second << endl;
}
// ----- END OF MAP -----
// ----- MULTIMAP -----
// Like map except you can have duplicate keys as long
// as the values are different
multimap<int, string> mmap1;
mmap1.insert(pair <int, string> (1, "Bart"));
mmap1.insert(pair <int, string> (1, "Lisa"));
mmap1.insert(pair <int, string> (3, "Marge"));
map<int, string>::iterator it3;
for(it3 = mmap1.begin(); it3 != mmap1.end(); ++it3){
cout << "Key : " << it3->first << endl;
cout << "Value : " << it3->second << endl;
}
// ----- END OF MULTIMAP -----
// ----- CONTAINER ADAPTERS -----
// Adapt containers to provide a defined interface
// ----- STACK -----
// Provides an interface for storing elements in a LIFO
// format
stack<string> custs;
custs.push("George");
custs.push("Louise");
custs.push("Florence");
// Get number of elements
int size = custs.size();
// Check if empty
if(!custs.empty()){
for(int i = 0; i < size; i++){
// Get value with top
cout << custs.top() << endl;
// Delete last value entered
custs.pop();
}
}
// ----- END OF STACK -----
// ----- QUEUE -----
// Provides an interface for storing elements in a FIFO
// format
queue<string> cast;
cast.push("Zoidberg");
cast.push("Bender");
cast.push("Leela");
int size2 = cast.size();
if(!cast.empty()){
for(int i = 0; i < size2; i++){
// Get value with top
cout << cast.front() << endl;
// Delete last value entered
cast.pop();
}
}
// ----- END OF QUEUE -----
// ----- PRIORITY QUEUE -----
// Elements are organized with the largest first
priority_queue<int> nums;
nums.push(4);
nums.push(8);
nums.push(5);
int size3 = nums.size();
if(!nums.empty()){
for(int i = 0; i < size3; i++){
// Get value with top
cout << nums.top() << endl;
// Delete last value entered
nums.pop();
}
}
// ----- END OF PRIORITY QUEUE -----
// ----- ENUMS -----
// Custom data type that assigns names to
// constant integers so that a program is
// easier to read
// You can define the starting index, or any others
enum day{Mon=1, Tues, Wed, Thur, Fri=5};
enum day tuesday = Tues;
cout << "Tuesday is the " << tuesday <<
"nd day of the week\n";
// Cycle through days
for(int i = Mon; i <= Fri; i++)
cout << i << endl;
// ----- END OF ENUMS -----
return 0;
}
-------------------- REGULAR EXPRESSIONS --------------------
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <numeric>
#include <cmath>
#include <sstream>
#include <thread>
#include <ctime>
#include <regex>
using namespace std;
int main(int argc, char** argv) {
// The string to search
string str = "The ape was at the apex";
// We want to match for ape with or
// without a space after it
regex reg ("(ape)[^ ]?");
// Provides useful function when you
// are searching a string
smatch matches;
// If there is a match for the regex
if(regex_search(str, matches, reg) == true){
// Output the number of matches
cout << matches.size() << " Matches" << endl;
// Cycle through the matches
while(regex_search(str, matches, reg)){
// Get the match
cout << matches.str(1) << endl;
// Get the index
cout << "At Index " << matches.position(1) << endl;
// Eliminate the previous match and create
// a new string to search
str = matches.suffix().str();
}
}
return 0;
}