0% found this document useful (0 votes)
8 views87 pages

CPP 2

Uploaded by

riveagerald90
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
0% found this document useful (0 votes)
8 views87 pages

CPP 2

Uploaded by

riveagerald90
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 87

Programming in C++

Programming in C++
Tony Wong (microtony)
2021-02-20
Programming in C++

Why C++?
● C++ shares similar syntax with many other programming languages
○ Java, Javascript, C#, Objective C, PHP etc..

● Centered around important CS concepts


○ Data types, Control structures, Object-oriented programming

● Wide range of applications and can be run in different environments


○ Servers, operating systems, games, embedded systems, etc
○ C++ standard provides a portable interface. Programs can be compiled into executable
for different systems.
Programming in C++

Why C++ for competitive programming?


● C++ programs runs the fastest
○ In many contests, problems are not guaranteed to be solvable by all languages.
IOI: “The ISC and ITC do not want to put a guaranteed percentage on points that could be gained
by a second class language, or have different time limits based on language.”
Code Jam: “... it is not guaranteed that any problem can be solved in any language; … Just as in
everyday software engineering, part of the contest is using the right tool for each job!”

● C++ STL comes with useful algorithms and data structures


○ Sorting, binary search, stack, heap, BST, etc...

● C++ programs are easy to debug def has_odd(l):


○ Compilation step can help uncover bugs flag = False
This Python program
for elm in l:
if elm % 2 == 1: would not even cause
flga = True runtime error
return flag
Programming in C++

Today I am going to teach you how to write C++ programs.


Programming in C++

Survey
How well do you know C++?
● I don’t know C++ at all
● I know about the basics and can write simple problems
● I know a lot about the language features, enough for
me to solve OI problems.
● I am an expert in C++. I have knowledge beyond those
needed in OI.
Programming in C++

Today I am going to teach you how to write C++ programs.


Programming in C++

Today I am going to teach you how to write C++ programs.


Programming in C++

Therefore, we will focus on making the


best use of new C++ features.
Unless otherwise stated, we are using C++17 here.

To learn more about data types and C++ language,


you may refer to the 2019 slides.
Introduction to C++ Data Processing
Programming in C++

Basic program structure

#include <iostream> Include library headers


using namespace std;
int main() { <iostream> provides input
cout << "Hello, World!" << endl; and output functionality
return 0; (cout and endl in this
} example)

#include <iostream>
Programming in C++

Basic program structure

#include <bits/stdc++.h> When using GCC C++ compiler,


using namespace std;
<bits/stdc++.h> provides
int main() {
cout << "Hello, World!" << endl; most functions needed for
return 0; competitive programming
}
● Shorter header
● Avoid compilation errors
caused by missing header,
especially in contests with
no feedback

<bits/stdc++.h>
Programming in C++

Basic program structure

#include <bits/stdc++.h>
using namespace std; This line is to “move” everything in
int main() {
the std namespace into the our
cout << "Hello, World!" << endl;
return 0; program.
} Pro:
● No need to type std:: prefix
Con:
● Program may not be forward
compatible
namespace
Programming in C++

Basic program structure

#include <bits/stdc++.h>
Example without
int main() {
using namespace std;
std::cout << "Hello, World!" <<
std::endl;
return 0;
}
Programming in C++

Basic program structure

#include <bits/stdc++.h>
using std::cout; Bring in specific symbols.
using std::endl;
int main() { This won’t have the forward
cout << "Hello, World!" << endl; compatibility issue.
return 0;
}

using declaration
Programming in C++

Forward compatibility issue

#include <bits/stdc++.h> What does the program output


using namespace std;
// Move first character to the end.
when compiled in C++03?
string move(string s) { g++ -std=c++03 program.cpp -o program
return s.substr(1) + s[0];
}
int main() {
cout << move("abcdef") << endl; What does the program output
return 0; when compiled in C++11?
}
g++ -std=c++11 program.cpp -o program

substr
Programming in C++

Basic program structure

#include <bits/stdc++.h>
using namespace std;
int main() { This is the main program.
cout << "Hello, World!" << endl;
return 0;
} Note that the return type is int.

Main function
Programming in C++

Basic program structure

#include <bits/stdc++.h> A return code of 0 indicates that


using namespace std; the program ended successfully.
int main() { Other numbers can be used to
cout << "Hello, World!" << endl;
indicate that there is some warning
return 0;
} / error.
You can use && in the console
to chain commands. In this
example, program B runs only if
(windows) a.exe && b.exe program A returns 0.
(linux) ./a && ./b return 0; is optional

Main function
Programming in C++

Basic program structure

#include <bits/stdc++.h>
using namespace std;
int main() {
cout << "Hello, World!" << endl; Send “Hello, World!” and
return 0; line break to the output stream.
}

endl also flushes the stream.


(Useful for interactive tasks).

cout endl
Programming in C++

Arrays
We can use a character array to store strings.

#include <bits/stdc++.h> Input Output


using namespace std;
4 7 11
int a[10];
HKOI
const char s[] = "HKOI";
int main() {
cin >> a[0] >> a[1];
cout << a[0] + a[1] << endl;
cout << s << endl;
return 0;
}
Programming in C++

C++ array
With the exception of const arrays, (e.g. const char s[])
modern C++ discourages the use of raw arrays.
The type and size of an array is fixed once declared.

#include <bits/stdc++.h> Input Output


using namespace std;
4 7 11
array<int, 10> a;
HKOI
const char s[] = "HKOI";
int main() {
cin >> a[0] >> a[1];
cout << a[0] + a[1] << endl;
cout << s << endl;
return 0;
}

array
Programming in C++

C++ array
Arrays can also be declared with initialization.
The size and type will be automatically determined.
Here, the type of a is array<int, 3>.
#include <bits/stdc++.h> Input Output
using namespace std;
15
array a{4, 8, 3};
int main() {
cout << a[0] + a[1] + a[2] << endl;
return 0;
}
Programming in C++

Benefits of C++ array


For C array, the identifier degenerates into a pointer when passed into
functions.
Provides index checking via .at(index), which makes debugging easier.

#include <bits/stdc++.h> #include <bits/stdc++.h>


using namespace std; using namespace std;
int a[] = {4, 8, 3}; array a{4, 8, 3};
int main() { int main() {
cout << a[0] + a[3] << endl; cout << a.at(0) + a.at(3) << endl;
return 0; return 0;
} }
Likely Output: 4 Runtime error

terminate called after throwing an instance of 'std::out_of_range'


what(): array::at: __n (which is 3) >= _Nm (which is 3)

at
Programming in C++

Dynamic size array: vector


Very often the task requires us to read N integers.
We can use vector, which is a dynamic size array to store the data.
#include <bits/stdc++.h>
using namespace std;
int main() {
int n; Input Output
cin >> n;
vector<int> a(n); Initial size 6 27
for (int i = 0; i < n; ++i) { 1 4 2 8 5 7
cin >> a[i];
}
int sum = 0;
for (int i = 0; i < n; ++i) {
sum += a[i];
}
cout << sum << endl;
return 0;
}

vector
Programming in C++

Dynamic size array: vector


Alternatively, we can start with an empty vector and use push_back(x) to
add items to the vector while reading.

int main() {
int n;
cin >> n;
vector<int> a; Input Output
Empty vector
for (int i = 0; i < n; ++i) {
int x; 6 27
cin >> x; 1 4 2 8 5 7
a.push_back(x);
}
int sum = 0;
for (int i = 0; i < n; ++i) {
sum += a[i];
}
cout << sum << endl;
return 0;
}

push_back
Programming in C++

vector assignment
We can replace the entire vector by assigning another vector to it.

#include <bits/stdc++.h> Output


using namespace std; 10
int main() { 2
vector<int> a(4, 10);
cout << a[0] << endl;
a = vector<int>{1, 2, 3};
cout << a[1] << endl;
return 0;
}

operator=
Programming in C++

Iterate over vector - int i


#include <bits/stdc++.h> Output
using namespace std;
vector<int> a{1, 4, 2, 8, 5, 7}; 1
int main() { 4
for (int i = 0; i < a.size(); ++i) { 2
cout << a[i] << endl;
} 8
return 0; 5
} Current size 7

#include <bits/stdc++.h> Output


using namespace std;
vector<int> a{1, 4, 2, 8, 5, 7}; -3
int main() { 2
for (int i = 0; i + 1 < a.size(); ++i) {
cout << a[i] - a[i + 1] << endl;
-6
} 3
return 0; -2
}

Is it ok to write i < a.size() - 1?


size
Programming in C++

Iterate over vector - range-based loop


#include <bits/stdc++.h> Output
using namespace std;
vector<int> a{1, 4, 2, 8, 5, 7}; 1
int main() { 4
for (int x : a) { 2
cout << x << endl;
} 8
return 0; 5
} 7

#include <bits/stdc++.h> Output


using namespace std;
vector<int> a{1, 4, 2, 8, 5, 7}; 1
int main() { 4
for (auto x : a) {
cout << x << endl;
2
} 8
return 0; 5
} 7

You can use auto when type can be automatically determined.


Range-based loop
Programming in C++

Modifying values in range-based loop


#include <bits/stdc++.h> Output
using namespace std;
vector<int> a{1, 4, 2, 8, 5, 7}; 1
int main() {
for (int x : a) {
x = 3;
} Value of v[0], v[1], ... is copied to x
cout << a[0] << endl;
return 0;
}

#include <bits/stdc++.h> Output


using namespace std;
vector<int> a{1, 4, 2, 8, 5, 7}; 3
int main() {
for (int& x : a) {
x = 3;
} Reference: x is same as a[0], a[1]...
cout << a[0] << endl;
return 0;
}

Reference declaration
Programming in C++

Iterate over vector - iterator


#include <bits/stdc++.h> Output
using namespace std; Advance the iterator
1 Type: vector<int>::iterator
vector<int> a{1, 4, 2, 8, 5, 7};
int main() { 4
for (auto it = a.begin(); it != a.end(); ++it) { 2 .begin() .end()
cout << *it << endl;
} 8
return 0; De-reference (get data being 5
}
pointed at) 7
1 4 2 8 5 7
7
#include <bits/stdc++.h> Output
using namespace std;
vector<int> a{1, 4, 2, 8, 5, 7}; 7
int main() { 5 .rend() .rbegin()
for (auto it = a.rbegin(); it != a.rend(); ++it) {
cout << *it << endl;
8
} 2 Type: vector<int>::reverse_iterator
return 0; 4
} 1

begin end rbegin rend


RandomAccessIterator
Programming in C++

Modifying values using iterator


#include <bits/stdc++.h> Output
using namespace std;
vector<int> a{1, 4, 2, 8, 5, 7}; 3
int main() {
auto it = a.begin(); .begin() .end()
*it = 3;
cout << a[0] << endl;
return 0;
}
1 4 2 8 5 7
#include <bits/stdc++.h> Output
using namespace std;
vector<int> a{1, 4, 2, 8, 5, 7}; 1
int main() {
auto it = a.end();
*it = 3;
cout << a[0] << endl;
return 0; Possibly
} runtime error
Programming in C++

Find element in vector


find(first, last, value) searches for value between [first, last)
and returns an iterator to the first matching value.
It returns last if value is not found.
Use distance to get the index.
#include <bits/stdc++.h> Input Output
using namespace std;
vector<int> a{1, 4, 2, 8, 5, 7}; 3
int main() { 1
auto it1 = find(a.begin(), a.end(), 8);
cout << distance(a.begin(), it1) << endl;
auto it2 = find(a.begin(), a.end(), 3);
cout << (it2 == a.end()) << endl;
return 0;
}

find distance
Programming in C++

Sort a vector
Use sort(first, last) to sort a vector in ascending order.
Use reverse(first, last) to reverse a vector.

vector<int> a{1, 4, 2, 8, 5, 7}; Input Output


sort(a.begin(), a.end());
for (int x : a) { 1 2 4 5 7 8
cout << x << " "; 8 7 5 4 2 1
}
cout << endl;
reverse(a.begin(), a.end());
for (int x : a) {
cout << x << " ";
}
cout << endl;

sort reverse
Programming in C++

Removing duplicates from a vector


Use unique(first, last) to move the first element in each identical group to
the front, keeping their relative order. The returned iterator points to the position
after the last remaining element.
Use erase(first, last) to remove elements from a vector.
vector<int> a{4, 4, 1, 1, 1, 4, 6, 6}; Input Output
auto it = unique(a.begin(), a.end()); .begin() .end()
for (int x : a) { 4 1 4 6 1 4 6 6
cout << x << " "; 4 1 4 6
}
cout << endl; 4 1 4 6 ? ? ? ?
a.erase(it, a.end());
for (int x : a) {
cout << x << " ";
} returned iterator
cout << endl;

unique erase
Programming in C++

Comparing vectors
You can use equality operator == != to check if the vectors has the same length
and the same contents in the same order.
Comparison operators < <= >= > compare 2 vectors in lexicographical order.

vector<int> a{3, 4, 5}; Input Output


vector<int> b{3, 4};
0
vector<int> c{3, 4, 6};
1
vector<int> d{3, 4, 5};
0
cout << (a == b) << endl;
1
cout << (a > b) << endl;
cout << (a > c) << endl;
cout << (a == d) << endl;

vector comparison
Programming in C++

Internal storage
Vector always store the data in contiguous segment of memory.
When it is already full and you try to push one more element, it finds a larger
piece of memory elsewhere and move all the data there.
1
vector<int> a; Input Output
cout << a.capacity() << " ";
0 0
cout << a.data() << endl;
1 0x192400
for (int i = 1; i <= 6; ++i) { 1 2
2 0x196230
a.push_back(i);
1 2 3 4 0x192400
cout << a.capacity() << " ";
4 0x192400
cout << a.data() << endl;
8 0x196230
}
1 2 3 4 8 0x196230

capacity data
1 2 3 4 5
Programming in C++

Time complexity for push_back


Assume that you call push_back(x) N times.
The total cost comprises of:
● Cost of adding an element
○ 1 operation per push_back
○ Total N operations for N push_back
● Cost of moving elements when vector is full
○ 1, 2, 4, 8, …, 2^k (where 2^k < N)
○ The sum of above = 2^(k+1) - 1 < 2N

Total cost for N push_back = N + (<2N) < 3N, and therefore is O(N)
We can say that push_back is amortized O(1)
push_back
Programming in C++

Be careful about iterators


Some manipulation operations, especially when they affect the internal
storage, invalidate iterators. Read the docs for details.
If unsure, always get fresh iterators.

vector<int> a{1, 2, 3}; Input Output


auto it = a.begin();
3 1
cout << a.capacity() << " " << *it << endl;
6 7890304
a.push_back(4); // it is invalidated.
cout << a.capacity() << " " << *it << endl;

push_back
Programming in C++

2D vector
vector<vector<int>> a{{1, 2, 3}, {4}, {5, 6}}; Output
cout << a[0].size() << endl; 3
cout << a[1].size() << endl; 1
cout << a[2].size() << endl; 2
cout << a[2][0] << endl; 5

int n = 4; int n = 4;
int m = 5; int m = 5;
vector<vector<int>> a(n, vector<int>(m)); vector<vector<int>> a;
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) { vector<int> b;
cin >> a[i][j]; for (int j = 0; j < m; ++j) {
} int x;
} cin >> x;
b.push_back(x);
}
a.push_back(b);
}
Programming in C++

Remember move()?
vector<vector<int>> a; Output
vector<int> b{1, 2, 3}; 0x22400
cout << b.data() << endl; 0x26580
a.push_back(b); 3
cout << a[0].data() << endl;
cout << b.size() << endl;
Data is copied

vector<vector<int>> a; Output
vector<int> b{1, 2, 3}; 0xf82400
cout << b.data() << endl; 0xf82400
a.push_back(move(b)); 0
cout << a[0].data() << endl;
Not guaranteed
cout << b.size() << endl;
to be 0

std::move() is complicated.
No need to care about it in competitive programming.
data move
Programming in C++

Difference between array and vector


Using 2D array and 2D vector as an example
● All data in a 2D array are contiguous in memory
● Each row of data in a 2D vector can stored separately

array<array<int, 4>, 4> a; Output Same address


vector<vector<int>> b(4, vector<int>(4)); 0x61fd90 16 bytes
cout << a.data() << endl; 0x61fd90 0x61fda0 0x61fdb0 0x61fdc0
cout << a[0].data() << " " << a[1].data() << " "; 0xe26580
cout << a[2].data() << " " << a[3].data() << endl; 0xe26230 0xe265f0 0xe26610 0xe26630
cout << b.data() << endl;
cout << b[0].data() << " " << b[1].data() << " ";
cout << b[2].data() << " " << b[3].data() << endl;
Programming in C++

vector<bool>
vector<bool> is a very special kind of vector.
Its implementation allows efficient storage of bools, 1 bit (vs 1 byte) for each bool.
Some vector functions cannot be used.

vector<bool> a{true, false, true}; Output


cout << a[0] << a[1] << a[2] << endl; 101
cout << a.capacity() << endl; 32
a.flip(); 010
cout << a[0] << a[1] << a[2] << endl;

vector<bool>
Programming in C++

string
C++ strings are very easy to use.
You can concatenate strings together using the + operator.

string s = "ab"; Output


string t = "d"; 3
s += 'c'; // append a character abcdef
t += "ef"; // append a string
cout << s.length() << endl;
cout << s + t << endl;

length operator+ operator+=


Programming in C++

Iterate over string


You can also use ranged-based loop to iterate over a string.

string s = "abcdef"; Output


for (int i = 0; i < s.length(); ++i) { a
cout << s[i] << endl; b
} c
for (char& c : s) { d
c -= 32; e
} f
cout << s << endl; ABCDEF
Programming in C++

Using string::iterator
You can get iterators from string to perform operations similar to vector.

string s = "abcdef"; Output


for (auto it = s.begin(); it != s.end(); ++it) { a
cout << *it << endl; b
} c
reverse(s.begin(), s.end()); d
cout << s << endl; e
f
fedcba
Programming in C++

Using string::iterator
You can get iterators from string to perform operations similar to vector.

string s = "abcdef"; Output


for (auto it = s.begin(); it != s.end(); ++it) { a
cout << *it << endl; b
} c
reverse(s.begin(), s.end()); d
cout << s << endl; e
f
fedcba
Programming in C++

string comparison
You can compare strings directly using comparison operators.
You can also use .compare(), which returns 0 when the strings are equal,
negative number when the left string is smaller, and positive otherwise.

cout << (string{"abc"} == string{"abc"}) << endl; Output


cout << (string{"abc"} < string{"def"}) << endl; 1
cout << (string{"abcd"} > string{"abc"}) << endl; 1
cout << string{"abc"}.compare("abx") << endl; 1 It can be any negative integer
cout << string{"xyz"}.compare("xyz") << endl; -1
cout << string{"def"}.compare("a") << endl; 0
1
It can be any positive integer

compare
Programming in C++

Break
Please read M2102 problem statement
Programming in C++

Functions
Functions with return type should have a return statement.
Void functions can omit the return statement.

int Square(int x) { Output


return x * x;
}
25
void PrintMax(int a, int b, int c) { 9
cout << max(a, max(b, c)) << endl;
}
int main() {
cout << Square(5) << endl;
PrintMax(4, 9, 1);
return 0;
}

Function declaration
Programming in C++

Early Return
If you have a return statement at the end of a if block, no need to add else.

void PrintMax(int a, int b, int c) { Output


if (a > b && a > c) {
cout << a << endl;
9
return;
}
cout << (b > c ? b : c) << endl;
}
int main() {
PrintMax(4, 9, 1);
return 0;
}
Programming in C++

Pass by reference
Pass by reference makes the identifier refer to the same variable specified in
the argument. Therefore, the value can be changed inside the function.
void PassByValue(int a) { Output
a = 5; Value 1
}
1 5
void PassByReference(int& a) {
a = 5;
}
int main() { Refers to y
int x = 1;
int y = 2;
PassByValue(x);
PassByReference(y);
cout << x << " " << y << endl;
return 0;
}

Reference declaration
Programming in C++

Pass by reference: vector


All types are passed by value. (unlike Java / Javascript)

void PassByValue(vector<int> a) { Output


a[0] = 5; Value {1}
}
1 5
void PassByReference(vector<int>& a) {
a[0] = 5;
}
int main() { Refers to y
vector<int> x{1};
vector<int> y{2};
PassByValue(x);
PassByReference(y);
cout << x[0] << " " << y[0] << endl;
return 0;
}
Programming in C++

Pass by value is slow


int PassByValue(string s) { Output
return s.length();
} 260000000
int PassByReference(string& s) {
return s.length();
2.6825
} 260000000
int main() { 0.0452582
auto start_time = chrono::steady_clock::now();
string s = "abcdefghijklmnopqrstuvwxyz";
int total = 0;
for (int i = 0; i < 10000000; ++i) {
total += PassByValue(s);
}
cout << total << endl;
auto end_time = chrono::steady_clock::now();
cout << chrono::duration<double>(end_time - start_time).count() << endl;
start_time = end_time;
total = 0; PassByValue:
for (int i = 0; i < 10000000; ++i) {
total += PassByReference(s); A new string a is created
}
cout << total << endl; and the content is
end_time = chrono::steady_clock::now();
cout << chrono::duration<double>(end_time - start_time).count() << endl; copied from s
return 0;
} now duration
Programming in C++

Cannot pass something other than variable by reference


int PassByReference(string& s) { Output
return s.length();
} 260000000
int main() { 0.050572
auto start_time = chrono::steady_clock::now();
string s = "abcdefghijklmnopqrstuvwxyz";
int total = 0;
for (int i = 0; i < 10000000; ++i) { Compilation
total += PassByReference(s); Error
// total += PassByReference("123");
}
cout << total << endl;
auto end_time = chrono::steady_clock::now();
cout << chrono::duration<double>(end_time - start_time).count() << endl;
return 0;
}
Technical term:
To pass by reference,
the argument must be
an lvalue.
Programming in C++

Pass by Const Reference


int PassByConstReference(const string& s) { Output
return s.length();
} 290000000
int main() { 1.36043
auto start_time = chrono::steady_clock::now();
string s = "abcdefghijklmnopqrstuvwxyz";
int total = 0;
for (int i = 0; i < 10000000; ++i) {
total += PassByConstReference(s);
total += PassByConstReference("abc");
}
cout << total << endl;
auto end_time = chrono::steady_clock::now();
cout << chrono::duration<double>(end_time - start_time).count() << endl;
return 0;
}
Don’t do this for
primitives such as
int, double, bool
Programming in C++

struct
Use struct to declare data structures that can hold multiple data.

struct Point { Output


double x, y; 3.6 4.2
};
int main() { Braces initializer list
Point p;
p.x = 1.0; Follows the order of member
p.y = 2.5; variable declaration
Point q{3.6, 4.2}; struct is a class with all
cout << q.x << " " << q.y << endl;
return 0; members declared public
}
Don’t forget the semi-colon ;

class
Programming in C++

Constructor
If you declare your own constructor, default constructor will not be
implicitly declared and defined.
struct Point { Output
double x, y; 1.73205 1
Point(double d, double r) {
x = d * cos(r);
y = d * sin(r);
}
};
int main() {
Point p(2, 0.5235988);
cout << p.x << " " << p.y << endl;
// Point q;
return 0; Compilation Error
}

Constructors
Default constructor
Programming in C++

Constructor
We can also use initializer list.

struct Point { Output


double x, y; 1.73205 1
Point(double d, double r)
: x(d * cos(r)), y(d * sin(r)) {}
};
int main() {
Point p(2, 0.5235988);
cout << p.x << " " << p.y << endl;
return 0;
}
Programming in C++

Member functions
struct Point { Output
double x, y;
Point(double d, double r) 1.73205 1
: x(d * cos(r)), y(d * sin(r)) {} 2
double DistanceToOrigin() { -1 1.73205
return sqrt(x * x + y * y);
}
void Rotate() {
swap(x, y);
x = -x;
}
};
int main() {
Point p(2, 0.5235988);
cout << p.x << " " << p.y << endl;
cout << p.DistanceToOrigin() << endl;
p.Rotate();
cout << p.x << " " << p.y << endl;
return 0;
} swap
Programming in C++

Overloading
struct Point { Output
double x, y;
Point Dot(double scalar) {
8.8 13.6
return {scalar * x, scalar * y}; 11.8
}
double Dot(const Point& p) {
return x * p.x + y * p.y;
}
};
int main() {
Point p{2.2, 3.4};
Point q = p.Dot(4.0);
cout << q.x << " " << q.y << endl;
Point r{1.5, 2.5};
double s = p.Dot(r);
cout << s << endl;
return 0;
}
Overload resolution
Programming in C++

Operator overloading
struct Point { Output
double x, y; 5.5 8.5
Point& operator*=(double scale) {
x *= scale;
y *= scale;
return *this;
}
};
int main() {
Point p{2.2, 3.4};
p *= 2.5;
cout << p.x << " " << p.y << endl;
return 0;
}

Operator overloading
Programming in C++

Operator overloading
struct Point { Output
double x, y;
Point& operator*=(double scale) {
5.5 8.5
x *= scale;
y *= scale;
return *this;
}
};
ostream& operator<<(ostream& os, const Point& p) {
os << p.x << " " << p.y;
return os;
}
int main() {
Point p{2.2, 3.4};
p *= 2.5; cout is a ostream
cout << p << endl;
return 0;
}
operator<<
See section Stream extraction and insertion
Programming in C++

Output a vector
ostream& operator<<(ostream& os, Output
const vector<int>& c) { 1 2 3 4 5
for (auto&& x : c) { 10 11 12
cout << x << " ";
}
cout << endl;
return os;
}
int main() {
vector<int> a{1, 2, 3, 4, 5};
vector<int> b{10, 11, 12};
cout << a << b;
return 0;
}
Programming in C++

Template
template<class T> Output
ostream& operator<<(ostream& os, 1 2 3 4 5
const vector<T>& c) { 1.2 3.4 5.6
for (auto&& x : c) {
cout << x << " ";
}
cout << endl;
return os;
}
int main() {
vector<int> a{1, 2, 3, 4, 5};
cout << a;
vector<double> b{1.2, 3.4, 5.6};
cout << b;
return 0;
}

Templates
Programming in C++

Output a 2D vector
template<class T> Output
ostream& operator<<(ostream& os, 11 12 13
const vector<T>& c) { 21 22
for (auto&& x : c) { 31 32 33
cout << x << " ";
}
cout << endl;
return os;
}
int main() {
vector<vector<int>> a{{11, 12, 13},
{21, 22},
{31, 32, 33}};
cout << a;
return 0;
}
Programming in C++

Pair
Pair can hold two values (first, second) of possibly different types.
Pairs can be compared. The first value will be compared first. If they are equal,
the second value will be compared.

int n; Input Output


cin >> n;
vector<pair<int, string>> students(n); 4 1 Tony
for (int i = 0; i < n; ++i) { 3 Percy 2 Ian
cin >> students[i].first >> students[i].second; 2 Ian 3 Jeremy
} 3 Jeremy 3 Percy
sort(students.begin(), students.end()); 1 Tony
for (auto& student : students) {
cout << student.first << " ";
cout << student.second << endl;
}

pair
Programming in C++

Pair
Pair can be useful to return multiple values.

pair<int, int> CountLetters(const string& s) {


int upper = 0, lower = 0;
for (char c : s) {
upper += isupper(c) > 0; Input Output
lower += islower(c) > 0;
} 2 8
return {upper, lower};
}
int main() {
auto p = CountLetters("Hello, World!");
cout << p.first << " " << p.second << endl;
return 0;
}

isupper islower
Programming in C++

Tuple
What about more values?

tuple<int, int, int> CountLetters(const string& s) {


int upper = 0, lower = 0, spaces = 0;
for (char c : s) {
upper += isupper(c) > 0;
lower += islower(c) > 0; Input Output
spaces += c == ' ';
} 2 8 1
return {upper, lower, spaces};
}
int main() {
auto p = CountLetters("Hello, World!");
cout << get<0>(p) << " " << get<1>(p) << " ";
cout << get<2>(p) << endl;
return 0;
}

get(tuple)
Programming in C++

J021 Date sorting


Given N dates, sort the dates in chronological order.

Input Output
3 4, July 1981
4, July 1981 22, December 1981
18, October 1982 18, October 1982
22, December 1981
Programming in C++

Reading the input


Let’s read one line of input.
cin.get() reads the next character, which is comma here.

int day, year; Input Output


string month_string;
20, February 2021 20
cin >> day;
February
cin.get();
2021
cin >> month_string >> year;
cout << day << endl;
cout << month_string << endl;
cout << year << endl;

get
Programming in C++

Converting the month into an integer


const vector<string> kMonths = Input
{"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"};
20, February 2021
int main() {
int day, month, year;
string month_string;
cin >> day;
cin.get();
cin >> month_string >> year;
auto it = find(kMonths.begin(), kMonths.end(), month_string); Output
month = distance(kMonths.begin(), it);
cout << day << endl; 20
cout << month << endl; 1
cout << year << endl; 2021
return 0;
}

find distance
Programming in C++

Storing the dates in a vector<tuple<int, int, int>>


const vector<string> kMonths = Input
{"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"}; 3
int main() { 4, July 1981
int n; 18, October 1982
cin >> n;
22, December 1981
vector<tuple<int, int, int>> dates;
for (int i = 0; i < n; ++i) {
int day, month, year;
string month_string;
cin >> day; Output
cin.get();
cin >> month_string >> year; 11
auto it = find(kMonths.begin(), kMonths.end(), month_string);
month = distance(kMonths.begin(), it);
dates.push_back({year, month, day}); The most significant
// dates.emplace_back(year, month, day); component should go first
}
cout << get<1>(dates[2]) << endl; You can also use emplace_back
return 0;
}

emplace_back
Programming in C++

Alternative way
const vector<string> kMonths = Input
{"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"};
3
int main() { 4, July 1981
int n; 18, October 1982
cin >> n; 22, December 1981
vector<tuple<int, int, int>> dates(n);
for (auto& date : dates) {
cin >> get<2>(date);
cin.get(); Output
string month_string;
cin >> month_string >> get<0>(date); 11
auto it = find(kMonths.begin(), kMonths.end(), month_string);
get<1>(date) = distance(kMonths.begin(), it);
}
cout << get<1>(dates[2]) << endl;
return 0;
}
Programming in C++

Even fancier
const vector<string> kMonths = Input
{"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"};
3
int main() { 4, July 1981
int n; 18, October 1982
cin >> n; 22, December 1981
vector<tuple<int, int, int>> dates(n);
for (auto& [year, month, day] : dates) {
cin >> day;
Structured binding declaration
cin.get(); Output
Must be auto
string month_string;
cin >> month_string >> year; 11
auto it = find(kMonths.begin(), kMonths.end(), month_string);
month = distance(kMonths.begin(), it);
}
cout << get<1>(dates[2]) << endl;
return 0;
}
Programming in C++

Output the sorted dates


vector<tuple<int, int, int>> dates(n); Input
... input ... 3
sort(dates.begin(), dates.end()); 4, July 1981
for (auto& date : dates) { 18, October 1982
cout << get<2>(date) << ", "; 22, December 1981
cout << kMonths[get<1>(date)] << " ";
cout << get<0>(date) << endl;
}
return 0; Output
}
4, July 1981
22, December 1981
18, October 1982
Solved with only 25 lines!
Programming in C++

M2102 Social Distancing and miamia


Input Output

4 9.200000
&1.2
(120)
{4}
1,,2,,3,,4,,8,,7,,6,,5,,

5 4.625000
&1
(16
0){8}1,2,3,4,5,6,7,8,1,8,2,7
,{4}[1,8],[2,7],[3,6],(240)[4,5
],
Programming in C++

M2102 Social Distancing and miamia


Programming in C++

Reading the start time


int main() { Input
int n; 4
cin >> n; &1.2
char c; (120)
cin >> c; {4}
double current_time; 1,,2,,3,,4,,8,,7,,6,,5,,
cin >> current_time;
cout << current_time<< endl;
return 0; Output
}
1.2
Programming in C++

Reading the rest of the data - Method 1


... Input
string s; 4
for (int i = 1; i < n; ++i) { &1.2
string t; (120)
cin >> t; {4}
s += t; 1,,2,,3,,4,,8,,7,,6,,5,,
}
cout << s << endl;
Output

(120){4}1,,2,,3,,4,,8,,7,,6,,5,,
Programming in C++

Reading the rest of the data - Method 2


int main() { Input
int n;
cin >> n;
4
char c; &1.2
cin >> c; (120)
double current_time; {4}
cin >> current_time; 1,,2,,3,,4,,8,,7,,6,,5,,
string s = accumulate(istream_iterator<string>(cin),
istream_iterator<string>(), string());
cout << s << endl; Output
return 0;
}
End of stream Empty string (120){4}1,,2,,3,,4,,8,,7,,6,,5,,

Uses operator + to concatenate strings.


Note: press CTRL+Z (windows) / CTRL+D (linux)
for end-of-file
accumulate
istream_iterator
Programming in C++

Tokenize the input


Break down the string into space separated tokens.

(120){4}1,,2,,3,,4,,8,,7,,6,,5,,

bpm 120 notevalue 4 1,,2,,3,,4,,8,,7,,6,,5

(160){8}1,2,3,4,5,6,7,8,1,8,2,7,{4}[1,8],[2,7],[3,6],(240)[4,5],

bpm 160 notevalue 8 1,2,3,4,5,6,7,8,1,8,2,7, notevalue 4 [1,8] ,


[2,7] , [3,6] , bpm 240 [4,5] ,
Programming in C++

Tokenize the input


stringstream ss; Input
for (char c : s) {
if (c == '(') { 5
ss << " bpm "; &1
} else if (c == '{') { (16
ss << " note_value "; 0){8}1,2,3,4,5,6,7,8,1,8,2,7
} else if (c == '[') { ,{4}[1,8],[2,7],[3,6],(240)[4,5
ss << " ["; ],
} else if (c == ')' || c == '}' || c == ']') {
ss << " ";
} else {
Output
ss << c;
} bpm 160 notevalue 8
}
1,2,3,4,5,6,7,8,1,8,2,7,
cout << ss.str() << endl;
notevalue 4 [1,8 , [2,7 , [3,6 ,
bpm 240 [4,5 ,
Change closing brackets to whitespace
stringstream
Programming in C++

Process BPM and note value


double bpm = 0, note_value = 0; Input
while (!ss.eof()) { 5
string token; &1
ss >> token; (16
if (token == "bpm") { 0){8}1,2,3,4,5,6,7,8,1,8,2,7
ss >> bpm; ,{4}[1,8],[2,7],[3,6],(240)[4,5
cout << bpm << endl; ],
} else if (token == "note_value") {
ss >> note_value; ss
cout << note_value << endl;
bpm 160 notevalue 8
}
1,2,3,4,5,6,7,8,1,8,2,7,
}
notevalue 4 [1,8 , [2,7 , [3,6 ,
bpm 240 [4,5 ,

stringstream is useful for type conversions Output

160
8
4
240
Programming in C++

Process beats and ignore brackets


double bpm = 0, note_value = 0; Input
while (!ss.eof()) {
string token;
5
ss >> token; &1
if (token == "bpm") { (16
ss >> bpm; 0){8}1,2,3,4,5,6,7,8,1,8,2,7
} else if (token == "note_value") { ,{4}[1,8],[2,7],[3,6],(240)[4,5
ss >> note_value; ],
} else if (token[0] != '[') {
int commas = count(token.begin(), token.end(), ','); ss
current_time += commas * 240.0 / bpm / note_value;
} bpm 160 notevalue 8
} 1,2,3,4,5,6,7,8,1,8,2,7,
cout << fixed << setprecision(9) << current_time << endl; notevalue 4 [1,8 , [2,7 , [3,6 ,
bpm 240 [4,5 ,
Set to fixed point format (default = scientific notation) Output

Precision = 9 d.p. is sufficient. 4.625000000

count fixed setprecision


Programming in C++

Solved?
C++17 C++20
Sadly, the 40 line program fails
to solve the task :(
because operator+ creates a
new string every time.
This will be “fixed” in C++20
where the intermediate value
will be moved using std::move.

accumulate
Programming in C++

Closing
Use a lot of library functions != Good programs
Programming in C++

C++ style guide


Google C++ style guide
Indentation: 2 spaces
1 space around binary operators
1 space before and after parenthesis ()
etc.
Programming in C++

Macros #define
#define
x first
y second dxxxxxe
#define pii pair<int,int>
#define ll long long
Some competitive #define
#define
pll pair<ll,ll>
pbb pair<bool,bool>
programmers use #define
#define
mp make_pair
pb push_back
#define pf push_front
macros to shorten #define popb pop_back
#define popf pop_front
their code. #define xmod (ll)(1e9+7) mxxxxxg
#define hmod 1286031825167LL

This is discouraged for several reasons:


● It makes code hard to read for others
● It makes the code longer (harder to find main)
● It is easy to introduce subtle bugs
● It makes debugging harder
Programming in C++

Exercises
01007 Packet Re-assembly
01009 Words
M1902 Zero and Scheduling Problem
M2001 Corona and WFH

You might also like