C++ is a popular programming language that can be used to create many high level applications. It also happens to be the most popular programming language for competitive programming due to its high speed and lower memory usage. It’s an extension of the C language, with a main difference being that it supports both objects and classes while C does not.
Variables
In C++ there are different types of variables.
- int, stores integers (Up to 32 bits)
- double, stores floating point numbers with decimal places (i.e 123.123)
- char, stores single characters such as ‘a’, ‘b’ or ‘c’
- string, stores a text comprised of characters such as “hello”
- bool, stores a boolean variable with only 2 states: True or False
- long long, stores integers up to 64 bits.
To create a variable, you can declare it like so:
int myVariable = 10; (Remember that all lines of code must end with a semicolon)
string myString = “abcd”;
char myChar = ‘a’;
After declaring variables, you can also change them like so:
int myVariable = 10;
myVariable = 15;
That would change the value of myVariable to 15.
Comments
If we want to write comments in our code but not execute them, we can start them by using the // syntax. Everything after it won’t be compiled and run by the compiler. Effectively ignored.
Example:
//this is a comment
Input / Output
To output something to the console, use the cout operator followed by <<
| #include <iostream> int main() { std::cout << “Hello World!”; return 0; } |
This code would output “Hello World!”, or everything in between the “” parentheses.
If you want to print numbers, you don’t need to use the “”. For example:
| #include <iostream> int main() { std::cout << 10; return 0; } |
Will output the number 10.
You can also output variables. For example:
| #include <iostream> using namespace std; int main() { int var = 10; cout << var << endl; //will output 10 //endl means to end the current line and move on to the next line in the output return 0; } |
For inputting, use the cin keyword followed by >>. You can only read in variables:
| #include <iostream> using namespace std; int main() { int var; cin >> var; cout << var; return 0; } |
This will prompt the user to input an integer, and it will output whatever the user inputs.
Note that if the user were to input a string, the output would be undefined and random.
Operators
In C++ we can use operators to modify variables.
- + operator, adds 2 variables together.
- – operator, subtracts 2 variables
- * operator, multiplies 2 variables
- / operator, performs integer division on 2 variables (For example 5/2 = 2 in C++)
- % operator, finds the remainder after doing division between 2 variables (mod)
- ++ operator, adds 1 to a variable.
- — operator, subtracts 1 from a variable.
- >> operator, bitwise shift to the right
- << operator, bitwise shift to the left
- & operator, bitwise AND operation
- ^ operator, bitwise XOR operation
- |, bitwise OR operation.
To use operators, you can do something like this:
Note that when you use the / operator for doubles, it will perform precise division with decimal places.
int a = 10, b = 10;
int c = a+b; //so c = 10+10 = 20
int a = 10;
a++; //adds 1 to a, so now a = 11
We can also use assignment operators.
The general format is
variable [operator]= [value]
For example if I want to add 10 to a variable named var:
var += 10
Or if I wanted to XOR var by 3 I would:
var ^= 3
It’s also easy to compare variables
- == operator checks if 2 variables are equal
- != checks if 2 variables are not equal
- <= checks if one is less or equal
- >= checks if one is larger or equal
- < checks if one is strictly less
- > checks if one is strictly more
Logical operators will return either true or false.
- && operator, if 2 variables are both true then it will return true otherwise false
- || operator, if at least 1 is true then it will return true
- ! operator, returns the opposite of the variable’s value.
Math Functions
C++ also uses a variety of math functions
- min(x, y) returns the minimum of 2 variables
- max(x, y) returns the maximum
- sqrt(x) returns the sqrt
- log2(x) returns the base 2 log
- pow(x, y) returns x to the power of y
- floor(x) returns the floor of a number
- ceil(x) returns the ceiling of a number
- round(x) rounds to the nearest whole number
- log(x) returns the base 10 log.
If/Else
We already know that C++ has logical operators that return true and false. We can take advantage of this to run blocks of code depending on the result of the operators.
C++ uses the if else conditional statements:
Syntax:
if(condition is true){
//run whatever code is in here
}else{
//if condition isn’t true then run whatever is in here
}
Or you can do
if(condition){
// check condition 1, if it’s true then run code in this block
}else if(condition 2){
//if condition 1 isn’t true then check condition 2, if it’s true run this block .
}else if(condition 3){
// if 1 and 2 are not true, then try 3.
}else{
//if 1 2 and 3 are all not true, then run whatever is in here.
}
| int x = 30; int y = 30; if (x == y) { //use the == operator cout << “x is equal to y”; } |
Ternary operations:
We can also use a shorthand if else statement using a ternary operator in the following form:
Var = (condition) ? answerTrue : answerFalse
As an example instead of writing:
| int x; int y = 20; if(y > 20){ x = 10; }else x = 11; |
We can write
| x = (y > 20) ? 10 : 11; |
Loops
Loops execute a block of code inside as long as a condition is fulfilled.
While Loops:
while(condition){
//execute whatever is inside
}
This could run forever as long as the boolean condition is satisfied.
Example:
| int y = 20; while(y < 25){ cout << y << endl; y++; } |
This would output
20
21
22
23
24
For loops:
For loops have the following syntax:
for(statement 1; statement 2; statement 3){
//execute whatever is inside
}
statement 1 is executed exactly once at the beginning of the loop
statement 2 is the necessary conditional statement to keep the loop running (as long as it is satisfied the loop will continue)
statement 3 is executed once after every single iteration of the loop.
For example:
| for(int i = 0; i < 5; i++){ cout << i << endl; } |
- variable i is set to 0
- as long as i < 5 iterate
- after every iteration increment i by 1
This would output
0
1
2
3
4
| for (int i = 0; i <= 10; i += 2) { cout << i << “\n”; } |
This would output all even numbers less than or equal to 10.
You can also nest loops inside of each other:
| for(int i = 0; i < 3; i++){ for(int j = 0; j < 3; j++){ cout << i * j < ‘\n’; } } |
As you can infer, each iteration of the outer loop will have all iterations of the inner loop.
You can also use the break keyword to leave a loop immediately if you reach some condition
| for(int i = 0; i < 10; i++){ if(i == 4)break; } |
This loop would end once i == 4 since we break.
We can also use the continue keyword to move onto the next iteration of a loop
| for(int i = 0; i < 5; i++){ if(i == 3)continue; cout << i < endl; } |
Would output
0
1
2
4
Since we skip i == 3 and continue to the next iteration.
References and Pointers
A reference variable can be declared that accesses the same memory address as another variable as shown:
| int one = 10; int &two = one; |
one and two have the same memory address, so modifying two will also end up modifying one.
Pointers store the memory address of variables as its value.
| int one = 10; int *two = &one; cout << &one << endl; cout << two << endl; |
This will output the same thing since we are both accessing one’s memory address.
We can dereference (reference the actual value of the variable rather than the memory address) of pointers through the following:
| int one = 10; int *two = &one; cout << &one << endl; cout << two << endl; cout << *two << endl; |
The third output will be 10.
We can change pointers too.
| int one = 10; int *two = &one; *two = 15; cout << &one << endl; cout << two << endl; cout << *two << endl; cout << one << endl; |
We just changed the value of one AND two both to 15.
Functions
A function is a block of code that is only run when it is called.
You can pass parameters into a function.
Used to perform actions without repeating code.
| void myFunc(){ //write some code cout << “done\n”; } |
To call it simply call
| int main(){ myFunc(); return 0; } |
You can also pass parameters into the function
| void add(int x, int y){ cout << x + y << endl; } int main(){ add(3, 5); add(4, 9); return 0; } |
You can also make a function return something.
| int add(int x, int y){ return x+y; } int main(){ cout << add(3, 5) << endl; add(4, 9); return 0; } |
This code would only output 8.
You specify the return type of a function before the name (int, string, char, bool, etc).
A function can also call itself (recursion).
| void go(int x){ if(x == 0)return; cout << x << endl; go(x-1); } int main(){ go(5); return 0; } |
This would output
5
4
3
2
1
Make sure to have a termination condition or your code can call itself forever.
The C++ STL Library
Data structures are used to store and access data. C++ has a Standard Template Library which includes many useful data structures to be used.
The Library contains containers, iterators and functions.
Containers are used to store data, iterators are used to access them and functions are used to perform functions on the containers.
When using STL data structures, make sure to add
| using namespace std; |
at the top of your code or else you need to add the prefix std:: before every single declaration of a new data structure.
Vectors
A dynamic array that can automatically resize.
Declared as so:
| vector<TYPE> myVec; |
or
| std::vector<TYPE> myVec; //if you don’t use using namespace std; |
Where type is simply the data type that you want your array to store (int, double, etc).
It has many functions:
- push_back(x), add x to the end
- pop_back(), remove last element
- at(i), access an element at index i (0 based indexing)
- [i], access an element at index i
- front(), back(), access front and back elements
- insert(pos, x) insert element x at position pos
- erase(pos) erase the element at position pos
- clear() remove all elements
- size() number of elements
- resize(x) resize the array to size x
- empty() returns true if the vector has no elements
They are called like so:
vec.push_back(x)
vec.clear()
vec[i]
vec.resize(x)
…
Stacks
Last in first out container meaning that we can only access the top element.
| stack<int> myStack; |
Many operations including:
- push(x), add x to the top of the stack
- pop(), remove the top element
- top(), look at the top element
- size(), number of elements
- empty(), returns true if the stack is empty.
Notice that a stack is just a weaker version of a vector.
Queues
A first in first out container. Imagine a queue in real life, whoever comes first will be served first.
| queue<int> myQueue; |
It has functions such as:
- push(x), add element to the back
- pop(), remove the first element
- front(), back(), look at front and back elements
- size(), number of elements
- empty(), returns true if the stack is empty.
Deque
This is a double ended queue, it supports fast removals from both the front and the end as well as fast insertions at front and end.
| deque<int> myDeque; |
It has functions such as:
- push_front(x), push_back(x), add to front and back
- pop_front(x), pop_back(x), remove from front and back
- front(), back(), access first and last elements
- at(i), [i], access the ith element (0 indexed)
- clear(), clear all elements
- size(), returns the number of elements
- empty(), returns true if the deque is empty
Unordered Set
This is a container that only stores unique elements with no specific order.
| unordered_set<int> mySet; |
This data structure will not store duplicate elements, if you insert the same element twice it will only count as one insert.
- insert(x), insert an element
- erase(x), erase an element
- find(x), returns an iterator to element x or the end() iterator if no such element exists
- count(x), returns 1 if the element exists and 0 otherwise
- size(), returns the number of elements
- empty(), returns true if the set is empty
- clear(), remove all elements
- begin(), end(), iterators pointing to the front and the end()
Set
This is a container that only stores unique elements in sorted order.
| set<int> mySet; |
This data structure will not store duplicate elements, if you insert the same element twice it will only count as one insert. In addition, all elements are in sorted order.
- insert(x), insert an element
- erase(x), erase an element
- find(x), returns an iterator to element x or the end() iterator if no such element exists
- count(x), returns 1 if the element exists and 0 otherwise
- size(), returns the number of elements
- empty(), returns true if the set is empty
- clear(), remove all elements
- begin(), end(), iterators pointing to the front and the end()
- lower_bound(x), returns pointer to the first element >= x
- upper_bound(x), returns pointer to the first element > x
Map
A data structure that stores data through key-value pairs. Each key has an associated value and there are no duplicate keys.
| map<int, int> mp; mp[1] = 2; mp[2] = 3; //the key 2 has value 3 mp[2] = 4; //change the value of key 2 to 4 |
In addition, the Map data structure will maintain the keys in sorted order.
Functions include:
- [] operator, insert or access a certain key as shown above
- insert({k, x}) inserts a key k with value x
- erase(x), remove the key-value pair with key x
- find(x), finds an iterator to the key x or end() if it doesn’t exist
- count(x), checks if the key x exists
- size(), number of keys
- empty(), returns if the map is empty
- clear(), clear the map
- begin(), end() iterators
- lower_bound(x), returns iterator to the first key >= x
- upper_bound(x), returns iterator to the first key > x
Iterators
These are items that act as iterators to traverse containers.
| set<int> x; … insert some elements into x for(auto Iterator = x.begin(), Iterator != x.end(), Iterator++){ cout << *Iterator << endl; } |
Functions you can do with iterators include:
- begin(), end() traverse to beginning and end of the container
- advance(iterator, x), move the iterator forwards x times
- next(iterator), move iterator forward once
- prev(iterator), move iterator backwards once
- distance(it1, it2), distance between 2 iterators