Exceptions:
Exceptions Basics
Standard Exceptions
Custom Exceptions
Exception Catching Order
Files:
Writing Text Files
Reading Text Files
Parsing Text Files
Structs and Padding
Reading and Writing Binary Files
The Standard Template Library:
Vectors
Vectors and Memory
Two-Dimensional Vectors
Lists
Maps
Custom Objects as Map Values
Custom Objects as Map Keys
Multimaps
Sets
Stacks and Queues
Sorting Vectors, Deque and Friend
STL Complex Data Types
Operator Overloading:
Overloading the Assignment Operator
Printing - Overloading the Left Bit Shift
A Complex Number Class
Complex.cpp
Complex.h
Overloading Plus
Complex.cpp
Complex.h
Overloading the Comparison Operator
Complex.cpp
Complex.h
Overloading the Dereference Operator
Complex.cpp
Complex.h
Output:
string error message: Something else went wrong.
Still running
Exception Basics:
#include <iostream>
#include <string>
using namespace std;
void mightGoWrong()
{
bool error1 = false;
bool error2 = true;
if (error1)
throw “Something went wrong.”;
if (error2)
throw string(“Something else went wrong.”);
}
void usesMightGoWrong()
{
mightGoWrong();
}
int main()
{
try
{
usesMightGoWrong();
}
catch(int e)
{
cout << “Error code: ” << e << endl;
}
catch(char const* e)
{
cout << “Error message: ” << e << endl;
}
catch(string& e)
{
cout << “string error message: ” << e << endl;
}
cout << “Still running” << endl;
return 0;
}
Output:
Caught exception: vector<T> too long
Still running
Standard Exceptions:
Output:
Something bad happened!
Custom Exceptions:
#include <iostream>
#include <exception>
using namespace std;
class MyException : public exception
{
public:
virtual const char* what() const throw()
{
return “Something bad happened!”;
}
};
class Test
{
public:
void goesWrong()
{
throw MyException();
}
};
int main()
{
Test test;
try
{
test.goesWrong();
}
catch(MyException& e)
{
cout << e.what() << endl;
}
return 0;
}
Output:
Catching bad_alloc: bad allocation
Exception Catching Order:
#include <iostream>
#include <exception>
using namespace std;
void goesWrong()
{
bool error1Detected = true;
bool error2Detected = false;
if (error1Detected)
throw bad_alloc();
if (error2Detected)
throw exception();
}
int main()
{
try
{
goesWrong();
}
catch (bad_alloc& e)
{
cout << “Catching bad_alloc: ” << e.what() << endl;
}
catch (exception& e)
{
cout << “Catching exception: ” << e.what() << endl;
}
return 0;
}
Output:
Hello there
123
Writing Text Files:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
// ofstream outFile;
fstream outFile;
string outputFileName = “text.txt”;
// outFile.open(outputFileName);
outFile.open(outputFileName, ios::out);
if (outFile.is_open())
{
outFile << “Hello there” << endl;
outFile << 123 << endl;
outFile.close();
}
else
cout << “Could not create file: ” << outputFileName << endl;
return 0;
}
Output:
This is a line.
This is another line.
This is a third line.
Reading Text Files:
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main()
{
string inFileName = “test.txt”;
ifstream inFile;
inFile.open(inFileName);
if (inFile.is_open())
{
string line;
while(inFile)
{
getline(inFile, line);
cout << line << endl;
}
inFile.close();
}
else
cout << “Cannot open file: ” << inFileName << endl;
return 0;
}
Output:
‘Population UK’ — ‘64000000’
‘Population France’ — ‘66400000’
Parsing Text Files:
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main()
{
string filename = “stats.txt”;
ifstream input;
input.open(filename);
if (!input.is_open())
return 1;
while(input)
{
string line;
getline(input, line, ‘:’);
int population;
input >> population;
// input.get();
input >> ws;
if (!input)
break;
cout << “‘” << line << “‘” << ” — ‘” << population << “‘” << endl;
}
input.close();
return 0;
}
Output:
size of struct Person1: 64
size of struct Person2: 62
Structs and Padding:
Output:
Frodo, 220, 0.8
Reading and Writing Binary Files:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
#pragma pack(push, 1)
struct Person
{
char name[50];
int age;
double height;
};
#pragma pack(pop)
int main()
{
Person someone = {“Frodo”, 220, 0.8};
string fileName = “test.bin”;
//// Write binary file ////////////////
ofstream outputFile;
outputFile.open(fileName, ios::binary);
if (outputFile.is_open())
{
outputFile.write(reinterpret_cast<char*>(&someone), sizeof(Person));
outputFile.close();
}
else
cout << “Could not create file ” + fileName;
//// Read binary file ////////////////
Person someoneElse = {};
ifstream inputFile;
inputFile.open(fileName, ios::binary);
if (inputFile.is_open())
{
inputFile.read(reinterpret_cast<char*>(&someoneElse), sizeof(Person));
inputFile.close();
}
else
cout << “Could not read file ” + fileName;
cout << someoneElse.name << “, ” << someoneElse.age << “, ” << someoneElse.height << endl;
return 0;
}
Output:
For loop:
onr
two
three
Iterator Loop:
one
two
three
Single item.
three
Vectors:
Output:
Size: 0
Capacity: 0
Capacity: 1
Capacity: 2
Capacity: 3
Capacity: 4
Capacity: 6
Capacity: 9
Capacity: 13
Capacity: 19
Capacity: 28
Capacity: 42
Capacity: 63
Capacity: 94
Capacity: 141
Capacity: 211
Capacity: 316
Capacity: 474
Capacity: 711
Capacity: 1066
Capacity: 1599
Capacity: 2398
Capacity: 3597
Capacity: 5395
Capacity: 8092
Capacity: 12138
2
Size: 10000
Capacity: 100000
Vectors and Memory:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<double> numbers(0);
cout << “Size: ” << numbers.size() << endl;
int capacity = numbers.capacity();
cout << “Capacity: ” << capacity << endl;
for (int i = 0; i < 10000; i++)
{
if (numbers.capacity() != capacity)
{
capacity = numbers.capacity();
cout << “Capacity: ” << capacity << endl;
}
numbers.push_back(i);
}
numbers.reserve(100000);
cout << numbers[2] << endl;
cout << “Size: ” << numbers.size() << endl;
cout << “Capacity: ” << numbers.capacity() << endl;
return 0;
}
Output:
7777
77778
7777
Two-Dimensional Vectors:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<vector<int>> grid(3, vector<int>(4, 7));
grid[1].push_back(8);
for (int row=0; row < grid.size(); row++)
{
for (int col=0; col < grid[row].size(); col++)
cout << grid[row][col] << flush;
cout << endl;
}
return 0;
}
Output:
Element: 1
Element: 1
0
1
2
3
Lists:
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> numbers;
numbers.push_back(1);
numbers.push_back(2);
numbers.push_back(3);
numbers.push_front(0);
list<int>::iterator it = numbers.begin();
it++;
numbers.insert(it, 100);
cout << “Element: ” << *it << endl;
list<int>::iterator eraseIt = numbers.begin();
eraseIt++;
eraseIt = numbers.erase(eraseIt);
cout << “Element: ” << *eraseIt << endl;
for (list<int>::iterator it = numbers.begin(); it != numbers.end(); it++)
cout << *it << endl;
return 0;
}
Output:
Found Vicky
Mike: 70
Peter: 100
Raj: 20
Vicky: 30
Mike: 70
Peter: 100
Raj: 20
Vicky: 30
Maps:
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
map<string, int> ages;
ages[“Mike”] = 40;
ages[“Raj”] = 20;
ages[“Vicky”] = 30;
ages[“Mike”] = 70;
ages.insert(make_pair(“Peter”, 100));
cout << ages[“Raj”] << endl;
if (ages.find(“Vicky”) != ages.end())
cout << “Found Vicky” << endl;
else
cout << “Key not found.” << endl;
for (map<string, int>::iterator it = ages.begin(); it != ages.end(); it++)
{
pair<string, int> age = *it;
cout << age.first << “: ” << age.second << endl;
}
for (map<string, int>::iterator it = ages.begin(); it != ages.end(); it++)
cout << it->first << “: ” << it->second << endl;
return 0;
}
Output:
Copy constructor running!
Copy constructor running!
Copy constructor running!
Copy constructor running!
1: Raj: 20
32: Vicky: 30
50: Mike: 40
55: Bob: 45
Custom Objects as Map Values:
#include <iostream>
#include <map>
#include <string>
using namespace std;
class Person
{
private:
string name;
int age;
public:
Person() : name(“”), age(0)
{
}
Person(string name, int age) : name(name), age(age)
{
}
Person(const Person& other)
{
cout << “Copy constructor running!” << endl;
name = other.name;
age = other.age;
}
void print()
{
cout << name << “: ” << age << endl;
}
};
int main()
{
map<int, Person> people;
people[50] = Person(“Mike”, 40);
people[32] = Person(“Vicky”, 30);
people[1] = Person(“Raj”, 20);
people.insert(make_pair(55, Person(“Bob”, 45 )));
people.insert(make_pair(55, Person(“Sue”, 24 )));
for (map<int, Person>::iterator it = people.begin(); it != people.end(); it++)
{
cout << it->first << “: ” << flush;
it->second.print();
}
return 0;
}
Output:
40: Mike: 40
123: Mike: 444
20: Raj: 40
30: Sue: 30
Custom Objects as Map Keys:
using namespace std;
class Person
{
private:
string name;
int age;
public:
Person() : name(“”), age(0)
{
}
Person(string name, int age) : name(name), age(age)
{
}
Person(const Person& other)
{
name = other.name;
age = other.age;
}
void print() const
{
cout << name << “: ” << age << flush;
}
bool operator<(const Person& other) const
{
if (name == other.name)
return age < other.age;
else
return name < other.name;
}
};
int main()
{
map<Person, int> people;
people[Person(“Mike”, 40)] = 40;
people[Person(“Mike”, 444)] = 123;
people[Person(“Sue”, 30)] = 30;
people[Person(“Raj”, 40)] = 20;
for (map<Person, int>::iterator it = people.begin(); it != people.end(); it++)
{
cout << it->second << “: ” << flush;
it->first.print();
cout << endl;
}
return 0;
}
Output:
10: Vicky
20: Bob
30: Mike
30: Raj
Multimaps:
Output:
10
20
30
Number found.
10:
20:
30:
333:
Sets:
Output:
Sue
John
Sue
Mike
John
Sue
Stacks and Queues:
Output:
5: Mike
7: Raj
10: Sue
3: Vicky
Soting Vectors, Deque and Friend:
Output:
Mike: 10 20
Vicky: 15
STL Complex Data Types:
Output:
Print test1: 10: Mike
Assignment running
Print test2: 10: Mike
Assignment running
Print test3: 10: Mike
Copy constructor running
10: Mike
Overloading the Assignment Operator:
Output:
(2,3): (2,3)
Printing – Overloading the Left Bit Shift:
Output:
(2,3): (2,3)
A Complex Number Class:
#include <iostream>
#include “Complex.h”
using namespace std;
using namespace complex;
int main()
{
Complex c1(2, 3);
Complex c2(c1);
Complex c3;
c3 = c2;
cout << c2 << “: ” << c3 << endl;
return 0;
}
Output:
Complex.cpp:
#include “Complex.h”
namespace complex
{
ostream& operator<<(ostream& out, const Complex& c)
{
out << “(” << c.getReal() << “,” << c.getImaginary() << “)”;
return out;
}
Complex::Complex() : real(0), imaginary(0)
{
// Nothing to do here
}
Complex::Complex(double real, double imaginary) : real(real), imaginary(imaginary)
{
}
Complex::Complex(const Complex& other)
{
real = other.real;
imaginary = other.imaginary;
}
const Complex& Complex::operator=(const Complex& other)
{
real = other.real;
imaginary = other.imaginary;
return *this;
}
} /* namespace complex */
Output:
Complex.h:
#ifndef COMPLEX_H_
#define COMPLEX_H_
#include <iostream>
using namespace std;
namespace complex
{
class Complex
{
private:
double real;
double imaginary;
public:
Complex();
Complex(double real, double imaginary);
Complex(const Complex& other);
const Complex &operator=(const Complex& other);
double getReal() const
{
return real;
}
double getImaginary() const
{
return imaginary;
}
};
ostream &operator<<(ostream& out, const Complex& c);
} /* namespace complex */
#endif /* COMPLEX_H_ */
Output:
(3,4)
(10,14)
(11,2)
(4.2,7)
(30,14)
Overloading Plus:
#include <iostream>
#include “Complex.h”
using namespace std;
using namespace complex;
int main()
{
Complex c1(3, 4);
Complex c2(2, 3);
Complex c3 = c1 + c2;
cout << c1 << endl;
cout << c1 + c2 + c3 << endl;
Complex c4(4, 2);
Complex c5 = c4 + 7;
cout << c5 << endl;
Complex c6(1, 7);
cout << 3.2 + c6 << endl;
cout << 7 + c1 + c2 + 8 + 9 + c6 << endl;
return 0;
}
Output:
Complex.cpp:
#include “Complex.h”
namespace complex
{
ostream& operator<<(ostream& out, const Complex& c)
{
out << “(” << c.getReal() << “,” << c.getImaginary() << “)”;
return out;
}
Complex operator+(const Complex& c1, const Complex& c2)
{
return Complex(c1.getReal() + c2.getReal(), c1.getImaginary() + c2.getImaginary());
}
Complex operator+(const Complex& c1, double d)
{
return Complex(c1.getReal() + d, c1.getImaginary());
}
Complex operator+(double d, const Complex& c1)
{
return Complex(c1.getReal() + d, c1.getImaginary());
}
Complex::Complex() : real(0), imaginary(0)
{
// TODO Auto-generated constructor stub
}
Complex::Complex(double real, double imaginary) : real(real), imaginary(imaginary)
{
}
Complex::Complex(const Complex& other)
{
real = other.real;
imaginary = other.imaginary;
}
const Complex& Complex::operator=(const Complex& other)
{
real = other.real;
imaginary = other.imaginary;
return *this;
}
} /* namespace complex */
Output:
Complex.h:
#ifndef COMPLEX_H_
#define COMPLEX_H_
#include <iostream>
using namespace std;
namespace complex
{
class Complex
{
private:
double real;
double imaginary;
public:
Complex();
Complex(double real, double imaginary);
Complex(const Complex& other);
const Complex& operator=(const Complex& other);
double getReal() const
{
return real;
}
double getImaginary() const
{
return imaginary;
}
};
ostream& operator<<(ostream& out, const Complex& c);
Complex operator+(const Complex& c1, const Complex& c2);
Complex operator+(const Complex& c1, double d);
Complex operator+(double d, const Complex& c1);
} /* namespace complex */
#endif /* COMPLEX_H_ */
Output:
Not equal
Not equal
Overloading the Comparison Operator:
#include <iostream>
#include “Complex.h”
using namespace std;
using namespace complex;
int main()
{
Complex c1(3, 2);
Complex c2(3, 3);
if (c1 == c2)
{
cout << “Equal” << endl;
}
else
{
cout << “Not equal” << endl;
}
if (c1 != c2)
{
cout << “Not equal” << endl;
}
else
{
cout << “Equal” << endl;
}
return 0;
}
Output:
Complex.cpp:
#include “Complex.h”
namespace complex
{
ostream& operator<<(ostream& out, const Complex& c)
{
out << “(” << c.getReal() << “,” << c.getImaginary() << “)”;
return out;
}
Complex operator+(const Complex& c1, const Complex& c2)
{
return Complex(c1.getReal() + c2.getReal(), c1.getImaginary() + c2.getImaginary());
}
Complex operator+(const Complex& c1, double d)
{
return Complex(c1.getReal() + d, c1.getImaginary());
}
Complex operator+(double d, const Complex& c1)
{
return Complex(c1.getReal() + d, c1.getImaginary());
}
Complex::Complex() : real(0), imaginary(0)
{
// TODO Auto-generated constructor stub
}
Complex::Complex(double real, double imaginary) : real(real), imaginary(imaginary)
{
}
Complex::Complex(const Complex& other)
{
real = other.real;
imaginary = other.imaginary;
}
const Complex& Complex::operator=(const Complex& other)
{
real = other.real;
imaginary = other.imaginary;
return *this;
}
bool Complex::operator==(const Complex& other) const
{
return (real == other.real) && (imaginary == other.imaginary);
}
bool Complex::operator!=(const Complex& other) const
{
return !(*this==other);
}
} /* namespace complex */
Output:
Complex.h:
#ifndef COMPLEX_H_
#define COMPLEX_H_
#include <iostream>
using namespace std;
namespace complex
{
class Complex
{
private:
double real;
double imaginary;
public:
Complex();
Complex(double real, double imaginary);
Complex(const Complex& other);
const Complex &operator=(const Complex& other);
double getReal() const
{
return real;
}
double getImaginary() const
{
return imaginary;
}
bool operator==(const Complex& other) const;
bool operator!=(const Complex& other) const;
};
ostream &operator<<(ostream& out, const Complex& c);
Complex operator+(const Complex& c1, const Complex& c2);
Complex operator+(const Complex& c1, double d);
Complex operator+(double d, const Complex& c1);
} /* namespace complex */
#endif /* COMPLEX_H_ */
Output:
(6,-7)
Overloading the Dereference Operator:
#include <iostream>
#include “Complex.h”
using namespace std;
using namespace complex;
int main()
{
Complex c1(2, 4);
cout << *c1 + *Complex(4, 3) << endl;
return 0;
}
Output:
Complex.cpp:
#include “Complex.h”
namespace complex
{
ostream& operator<<(ostream& out, const Complex& c)
{
out << “(” << c.getReal() << “,” << c.getImaginary() << “)”;
return out;
}
Complex operator+(const Complex& c1, const Complex& c2)
{
return Complex(c1.getReal() + c2.getReal(), c1.getImaginary() + c2.getImaginary());
}
Complex operator+(const Complex& c1, double d)
{
return Complex(c1.getReal() + d, c1.getImaginary());
}
Complex operator+(double d, const Complex& c1)
{
return Complex(c1.getReal() + d, c1.getImaginary());
}
Complex Complex::operator*() const
{
return Complex(real, -imaginary);
}
Complex::Complex() : real(0), imaginary(0)
{
}
Complex::Complex(double real, double imaginary) : real(real), imaginary(imaginary)
{
}
Complex::Complex(const Complex& other)
{
real = other.real;
imaginary = other.imaginary;
}
const Complex& Complex::operator=(const Complex& other)
{
real = other.real;
imaginary = other.imaginary;
return *this;
}
bool Complex::operator==(const Complex& other) const
{
return (real == other.real) && (imaginary == other.imaginary);
}
bool Complex::operator!=(const Complex& other) const
{
return !(*this==other);
}
} /* namespace complex */
Output:
Complex.h:
#ifndef COMPLEX_H_
#define COMPLEX_H_
#include <iostream>
using namespace std;
namespace complex
{
class Complex
{
private:
double real;
double imaginary;
public:
Complex();
Complex(double real, double imaginary);
Complex(const Complex &other);
const Complex &operator=(const Complex &other);
double getReal() const
{
return real;
}
double getImaginary() const
{
return imaginary;
}
bool operator==(const Complex &other) const;
bool operator!=(const Complex &other) const;
Complex operator*() const;
};
ostream& operator<<(ostream& out, const Complex& c);
Complex operator+(const Complex& c1, const Complex& c2);
Complex operator+(const Complex& c1, double d);
Complex operator+(double d, const Complex& c1);
} /* namespace complex */
#endif /* COMPLEX_H_ */