Revise your C++🚀
Tags: cpp, beginners, programming, tutorial
Published: 2021-05-02 11:11:59

Hello fellow coders, my name is Hritik Agarwal. I am an undergraduate student in IIT (ISM) Dhanbad, India.

C++ is a very popular language bringing imperative, object-oriented & generic programming features. Along with that due to its speed and libraries such as algorithms and STL, it has become a preferred language in competitive programming. 

Here, I want to present to you, a sort of cheat sheet to quickly revise C++ concepts. 

*Note: I have not explained each code, they are simple enough to understand. But please feel free to comment any queries and suggestions.*

So, let's begin.🚀

{% details Primitive Data Types, Literals & Storage Classes %}
 
```cpp
// Primitive Data Types

char a;    // character variable
int b;     // integer variable
float c;   // decimal variable
double d;  // decimal variable 
bool e;    // boolean variable
wchar_t f; // wide characters 

// These can be further modified using modifiers like - 

unsigned int a; 
unsigned short int b;
long long int c;
long double; 

// Integer Literals
0x12 // 0x → used for hexadecimal values
06   // 0 → used for octal values
23u  // u → used for unsigned values
12ll // ll → used for long long values

// Floating Point Literals
12e5   // 12 x 10^5
-5e-10 // -5 x 10^(-10) 

// Character Literals
\\ // \ character
\' // ' character
\? // ? character
\n // newline characters
\t // tab 

// Storage Class
// They define the scope and lifetime of the variables 
// and/or functions within a c++ program.

auto       
// The auto keyword specifies that the type of the variable that is being declared will be automatically deducted from its initializer.

register   
// To be used when the variable has to be stored in the register instead of RAM 

static     
// It allows a variable to maintain its value during function calls 
// when it is used inside a class, all the objects share the same variable

extern     
// used to declare a global variable or function in another file

mutable    
// allows a member of an object to override the const member function.
```
{% enddetails %} 
{% details Operators, Loops & Decision Making %}
```cpp
// Operators 

Arithmetic    → + - / * % ++ --
Relational    → == <= >= != < >
Logical       → && || !
Bitwise       → & | ^ ~ << >>
Assignment    → = += -= *= /= %= <<= >>= &= ^= |=
Miscellaneous → sizeof, ternary, comma, dot, arrow, cast, address(&), pointer(*)

// Loops & Decision Making

Type of loops   → while, do..while, for, nested for
Loop controls   → break, continue, goto
Decision making → if, if..else, switch, nested if, nested switch conditional 
```
{% enddetails %}
{% details Functions %}
```cpp
// Functions Definition

return_type function_name( parameters list ) {
	function_body
}

// Call by value

void fun(int x){ x += 10; }
int main(){ int x = 5; fun(x); cout<<x; }
output: 5

// Call by pointer

void fun(int *x){*x = 10;}
int main(){ int x = 5; fun(&x); cout<<x; }
output: 10

// Call by reference
void fun(int &x){ x = 10; }
int main(){ int x = 5; fun(x); cout<<x; }
output: 10

// Return by value

int fun(int x){ x = 10; return x; }
int main(){ int x = fun(5); cout<<x; }
output: 10

// Return by reference

int arr[5] = {1,2,3,4,5};
int& fun(int i){ return arr[i]; }
int main(){ fun(0) = 3; cout<<arr[0]<<" "; }
OUTPUT: 3

// Return by pointer

int arr[5] = {1,2,3,4,5};
int* fun(int i){ return &arr[i]; }
int main(){ *fun(0) =3; cout<<arr[0]<<" ";}
OUTPUT: 3
```
{% enddetails %}
{% details Working with files %}
```cpp
// For file operation we need a library called fstream. 
It defines 3 new classes:-
ofstream → used to create files & write to them
ifstream → used to read from files
fstream → can be used to do functionalities of both ofstream and ifstream.

// Example code on doing CRUD operation on a file say "record.txt"

#include<iostream>
#include<fstream>            // required to do file operations
#include<string>

using namespace std;

int main(){
   
   // Writing to a file
   ofstream outfile;            // Object instaniation of ofstream class
   outfile.open("record.txt");  // Associating the file "file.txt" with outfile object

   // Say we have these information( may be inputted from the user)
   string name = "Hritik Agarwal", college = "IIT (ISM), Dhanbad"; 
  
   // Similar to use of cout, we use the object outfile to write to the file
   outfile << name <<endl;
   outfile << school <<endl;
   outfile.close();    // It is good practice to close the object when it's no longer needed
   
   // Reading from the file
   ifstream infile;          // Object instaniation of ifstream 
   infile.open("file.txt");  // Associating the file "file.txt" with infile object

   string rname, rcollege;
   // Similar to use of cin, we use infile object to read from file
   getline(infile, rname); 
   getline(infile, rcollege);
   infile.close();

   // Updating an information
   string newName = "Preet Yadav";
   
   // We can also do directly without using open method
   ifstream infile("record.txt"); 
   ofstream outfile("temp.txt");   // Creating a temp file
   
   string data;
   while(getline(infile, data)){
     if(data == "Hritik Agarwal") outfile << newName << endl;
     else outfile << data << endl;
   }

   infile.close():
   outfile.close();

   remove("record.txt");
   rename("temp.txt", "record.txt");

   // Deleting a piece of information from a file
   // Similar to updating but when we find the information like
   // the name in update case we don't write anything in the file

   return 0;
}

// Different modes in which files can be opened 
ios::in → read mode
ios::out → write mode
ios::app → append mode
ios::trunc → if the file already exists, its content will be truncated before opening
ios::ate → open file for output & move read/write control to the end of file 

// Example :- To open file in append mode 
fstream  afile;
afile.open("file.txt", ios::app );

// File position pointers
Both istream and ostream provide member functions for repositioning the file-position pointer.
These member functions are seekg ("seek get") for istream and seekp ("seek put") for ostream.

fileObject.seekg( n );            // position to the nth byte of fileObject (assumes ios::beg)
fileObject.seekg( n, ios::cur );  // position n bytes forward in fileObject
fileObject.seekg( n, ios::end );  // position n bytes back from end of fileObject
fileObject.seekg( 0, ios::end );  // position at end of fileObject
``` 
{% enddetails %}
{% details Dynamic Memory Allocation %}
```cpp
// Memory in your C++ program is divided into two parts  
The stack -> All variables declared inside the function will take up memory from the stack.
The heap -> This is unused memory of the program and can be used to allocate the memory dynamically when the program runs. 

// Dynamic Memory Allocation for double, 1d array, 2d array & an array of objects

double* pvalue  = NULL;       // Pointer initialized with null
pvalue  = new double;         // Request memory for the variable
delete pvalue;                // free up the memory

char* pvalue  = NULL;         // Pointer initialized with null
pvalue  = new char[20];       // Request memory for the variable
delete [] pvalue;             // Delete array pointed to by pvalue

double** pvalue  = NULL;      // Pointer initialized with null 
pvalue  = new double [3][4];  // Allocate memory for a 3x4 array
delete [] pvalue;             // Delete array pointed to by pvalue

Box* myBoxArray = new Box[4]; // Allocate memory for array of four Box objects
delete [] myBoxArray;         // Delete array
```
{% enddetails %}
{% details Namespaces%}
```cpp
// Namespaces
Suppose we are writing a function called xyz() and there is another library available which is also having the same function xyz().  Now the compiler has no way of knowing which version of xyz() function is being referred to within the code.
A namespace is designed to overcome this difficulty and is used as additional information to differentiate similar functions, classes, variables, etc. with the same name available in different libraries. 

// Example 
#include <iostream>
using namespace std;

namespace first_space {
   void func() {cout << "Inside first_space" << endl;}
}
namespace second_space {
   void func() {cout << "Inside second_space" << endl;}
}

int main () {
   first_space::func();    
   second_space::func(); 
   return 0;
}

OUTPUT:
Inside first_space
Inside second_space


// The using directive
This directive tells the compiler that the subsequent code is making use of names in the specified namespace.
In the above code, we have used "using namespace std;"  
It means we don't have to use std::cout & directly use cout. 
```
{% enddetails %}
{% details Templates %}
```cpp
// Function Template 

#include <iostream>
#include <string>

using namespace std;

template <typename T> 
inline T const& Max (T const& a, T const& b) { 
   return a < b ? b:a; 
}

int main () {
   int i = 39, j = 20;
   double f1 = 13.5, f2 = 20.7; 
   string s1 = "Hello", s2 = "World"; 

   cout << "Max(i, j): " << Max(i, j) << endl;    
   cout << "Max(f1, f2): " << Max(f1, f2) << endl;    
   cout << "Max(s1, s2): " << Max(s1, s2) << endl; 

   return 0;
}

OUTPUT:
Max(i, j): 39
Max(f1, f2): 20.7
Max(s1, s2): World

// Class Template

#include <iostream>
using namespace std;

template <class T> 
class Arithmetic{
    private:
        T a,b;
    public:
        Arithmetic (T a, T b);
        T add();
        T sub();
};

template <class T>
Arithmetic<T> :: Arithmetic(T a, T b){ 
  this->a = a; 
  this->b = b; 
}

template <class T>
T Arithmetic<T> :: add(){
    T c;
    c = a + b;
    return c;
}

template <class T>
T Arithmetic<T> :: sub(){
    T c;
    c = a - b;
    return c;
}

int main()
{
    Arithmetic<int> ar1(10, 5);
    cout<<ar1.add()<<endl;
    cout<<ar1.sub()<<endl;
    
    Arithmetic<float> ar2(10.56, 5.25);
    cout<<ar2.add()<<endl;
    cout<<ar2.sub()<<endl;

    return 0;
}

OUTPUT:
15
5
15.81
5.31
```
{% enddetails %}
{% details Preprocessors %}
```cpp
// Other than #include preprocessor which we use to import header files.
// We also have

// #define 
#include <iostream>
using namespace std;

#define PASSWORD 12345
#define MIN(a,b) (((a)<(b)) ? a : b)

int main () {
   cout << "My Password is: " << PASSWORD << endl; 
   int i=100, j=30;
   cout <<"The minimum is " << MIN(i, j) << endl;
   return 0;
}

OUTPUT:
My Password is: 12345
The minimum is 30

// Conditional Compilation
#include <iostream>
using namespace std;

#define TRUSTY
#define PASSWORD 12345

int main () {

#ifdef TRUSTY
   cout << "My Password is: " << PASSWORD << endl; 
#endif

   cout << "You are not trustworthy. You can't have my password." << endl;

   return 0;
}

OUTPUT:
My Password is: 12345

// # operator
#include <iostream>
using namespace std;

#define debug(x) cout<<#x<<": "<<x<<endl;

int main () {
   int var = 10;
   debug(var);
   return 0;
}

OUTPUT:
var: 10
```
{% enddetails %}
{% details STL %}
```cpp
#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <stack>
#include <queue>
#include <iomanip>

using namespace std;

int main() {
  
  vector<int> vt;                // dynamic array
  deque<int> dq;                 // double ended queue i.e. push & pop at both sides
  list<int> li;                  // linked list
  
  set<int> st;                   // Repetition of elements -> Not allowwed, Storing Order -> Defalut : Non-Decreasing
  multiset<int> mst;             // Repetition of elements -> Allowwed, Storing Order -> Defalut : Non-Decreasing
  map<int,bool> mp;              // Repetition of elements -> Not allowed, Storing Order -> Defalut : Non-Decreasing
  multimap<int,bool> mmp;        // Repetition of elements -> Allowwed, Storing Order -> Defalut : Non-Decreasing
  unordered_map<int,bool> ump;   // Repetition of elements -> Not allowwed, Storing Order -> No sorted sequence

  stack<int> stk;                // stack, push at top & pop at top
  queue<int> q;                  // queue, push at back & pop at front
  priority_queue<int> pq;        // Defalut : Max Heap, to create Min Heap -> priority_queue<int, vector<int>, greater<int>> pq

  int arr[] = {-1, 12, 34, 12, 0, -34, 18, 0, 33, 44};

  for(auto num : arr){
    vt.push_back(num);
    dq.push_front(num);
    li.push_back(num);

    st.insert(num); mst.insert(num);
    mp[num] = ump[num] = true; mmp.insert({num, true});

    stk.push(num);
    q.push(num);
    pq.push(num);
  }

  // Some Iterators
  vt.begin();  // iterator to 1st element
  vt.end();    // iterator to one position ahead of last element
  vt.rbegin(); // iterator to 1st element from last
  vt.rend();   // iterator to one position before of first element

  // Iterating over container
  cout<<setw(20)<<"Array: "; for(auto num : arr) cout<<num<<" "; cout<<endl;
  cout<<setw(20)<<"Vector: "; for(auto it=vt.begin(); it!=vt.end(); it++) cout<<*(it)<<" "; cout<<endl; // iterating over container using iterator
  cout<<setw(20)<<"Deque: "; for(auto num : dq) cout<<num<<" "; cout<<endl;
  cout<<setw(20)<<"List: "; for(auto num : li) cout<<num<<" "; cout<<endl;
  cout<<setw(20)<<"Set: "; for(auto num : st) cout<<num<<" "; cout<<endl; // Another way to iterate over a container
  cout<<setw(20)<<"Multiset: "; for(auto num : mst) cout<<num<<" "; cout<<endl;
  cout<<setw(20)<<"Map: "; for(auto p : mp) cout<<"{"<<p.first<<" "<<p.second<<"} "; cout<<endl;
  cout<<setw(20)<<"Multimap: "; for(auto p : mmp) cout<<"{"<<p.first<<" "<<p.second<<"} "; cout<<endl;
  cout<<setw(20)<<"Unordered Map: "; for(auto p : ump) cout<<"{"<<p.first<<" "<<p.second<<"} "; cout<<endl;
  cout<<setw(20)<<"Stack: "; while(!stk.empty()){cout<<stk.top()<<" "; stk.pop();}  cout<<endl;
  cout<<setw(20)<<"Queue: "; while(!q.empty()){cout<<q.front()<<" "; q.pop();}  cout<<endl;
  cout<<setw(20)<<"Priority Queue: "; while(!pq.empty()){cout<<pq.top()<<" "; pq.pop();}

}

OUTPUT:
             Array: -1 12 34 12 0 -34 18 0 33 44 
            Vector: -1 12 34 12 0 -34 18 0 33 44
             Deque: 44 33 0 18 -34 0 12 34 12 -1 
              List: -1 12 34 12 0 -34 18 0 33 44
               Set: -34 -1 0 12 18 33 34 44
          Multiset: -34 -1 0 0 12 12 18 33 34 44
               Map: {-34 1} {-1 1} {0 1} {12 1} {18 1} {33 1} {34 1} {44 1} 
          Multimap: {-34 1} {-1 1} {0 1} {0 1} {12 1} {12 1} {18 1} {33 1} {34 1} {44 1}
     Unordered Map: {18 1} {-34 1} {-1 1} {44 1} {33 1} {0 1} {12 1} {34 1} 
             Stack: 44 33 0 18 -34 0 12 34 12 -1
             Queue: -1 12 34 12 0 -34 18 0 33 44
    Priority Queue: 44 34 33 18 12 12 0 0 -1 -34
```
{% enddetails %}
{% details Miscellaneous %}
```cpp
// Setting Decimal Precision 
#include <iostream>
#include <iomanip>

using namespace std;

int main () {
   double f =3.14159;
   cout<<setprecision(3)<<f<<"\n";
   cout<<fixed<<setprecision(9)<<f<<"\n";
   return 0;
}

OUTPUT:
3.14
3.141590000

// Formatting the output
#include<iostream>
#include<iomanip>
using namespace std;

int main () {
  cout<<setw(7)<<"Number"<<setw(10)<<"Square"<<endl;
  for(int i=1;i<=5;i++) cout<<setw(7)<<i<<setw(10)<<i*i<<endl;
}

OUTPUT:
 Number    Square
      1         1
      2         4
      3         9
      4        16
      5        25

// Getting system current data & time 
#include<iostream>
#include<ctime>
using namespace std;

int main () {

  // system time
  time_t now = time(0);    // current date/time based on current system
  string dt = ctime(&now); // convert now to string form

  cout<<"The local date and time is: "<<dt;

  // print various components of tm structure
  tm *ltm = localtime(&now);.
  cout<<"Year:"<<1900+ltm->tm_year<<endl;
  cout<<"Month: "<<1+ltm->tm_mon<<endl;
  cout<<"Day: "<<ltm->tm_mday<<endl;
  cout<<"Week Day: "<<ltm->tm_wday<<endl;
  cout<<"Time: "<<ltm->tm_hour<<":"<<ltm->tm_min<<":"<<ltm->tm_sec<<endl;

}

OUTPUT:
The local date and time is: Thu Apr 29 23:36:16 2021
Year:2021
Month: 4
Day: 29
Week Day: 4
Time: 23:36:16

// Generate random numbers 
#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int main() {
  // seeding srand() with the current time
  // allow us to get different random numbers in different execution of program
  srand((unsigned) time(0));

  // Let say we want to generate random number in the range [a,b]
  int num, a=100, b=1000;
  for (int i = 0; i < 5; i++) cout << (rand() % (b-a)) + a << endl;
}

OUTPUT:
962
256
435
479
355
```
{% enddetails %}

Thank You for checking out this cheat sheet.
If you liked it, then a ❤ would be appreciated. 

Any queries, suggestions & offtopic talks are welcomed.😎