In Python when we want to increase a value by 1 we do one of the following:
value = value + 1
value += 1
In C++ both of the above also work, but there is a shorter way
using the increment operator ++
:
value++; // +1
Now you know why the language after C is called C++ 😁
C++ also has a decrement operator --
that
subracts one from the value in the variable.
The increment and decrement unary operators can come before or after the variable name. The only difference between the two operators is how the expression is evaluated:
int num = 1;
printf("num++ is: %d", num++); // print value of num *before* the +1
printf("++num is: %d", ++num); // print value of num *after* the +1
The following Python and C++ functions are equivalent
def sum_digits(n):
"""Return the sum of the digits of positive integer n.
>>> sum_digits(6)
6
>>> sum_digits(2021)
5
"""
if n < 10:
return n
else:
all_but_last = n // 10
last = n % 10
return sum_digits(all_but_last) + last
/**
* Return the sum of the digits of positive integer n.
* Ex: sum_digits(6) == 6
* Ex: sum_digits(2021) == 5
*/
int sum_digits(int n) {
if (n < 10) {
return n;
}
else {
int all_but_last = n / 10;
int last = n % 10;
return sum_digits(all_but_last) + last;
}
}
Note that in C++ the parentheses ( )
are
required around the if
expression.
Note that in C++ you use braces { }
instead of the
colon :
for statements after the if
and
else
.
The following Python and C++ functions are equivalent
if temperature < 0:
clothing = "snowsuit"
elif temperature < 32:
clothing = "jacket"
else:
clothing = "shirt"
std::string clothing;
if (temperature < 0) {
clothing = "snowsuit";
}
else if (temperature < 32) {
clothing = "jacket";
}
else {
clothing = "shirt";
}
Note that in C++ there is no elif
, just nested
if/else
blocks.
Note that in C++ we need to declare the
string
variable before using it in the
if/else
blocks.
def fact(n):
""" Compute the factorial !n recursively.
>>> fact(2)
2
>>> fact(3)
6
>>> fact(6)
720
"""
if n <= 0:
raise ValueError("Sorry, 'n' must be positive.")
def inner_fact(n):
return inner_fact(n-1) * n if n > 0 else 1
return inner_fact(n)
int inner_fact(int n) {
if (n > 0) {
return inner_fact(n-1) * n;
} else {
return 1;
}
}
int fact(int n) {
if (n <= 0) {
throw std::invalid_argument("Sorry, 'n' must be positive.");
}
return inner_fact(n);
}
Note that the C++ function inner_fact
is callable by
any function.
You need to have #include <stdexcept>
at the
top of your file to use std::invalid_argument
.
⚠️ WARNING ⚠️ Order matters in C++, so
inner_fact
must be defined before
fact
, otherwise the code will not compile.<
C++11 (published in 2011) added support for lambda functions 😍, but it is verbose 😒
#include <functional> // need for `std::function`
int fact(int n) {
if (n <= 0) {
throw std::invalid_argument("Sorry, 'n' must be positive.");
}
// declare the types and name for the lambda function
std::function<int(int)> inner_fact = [&inner_fact](int n) -> int
{
if (n > 0) {
return inner_fact(n-1) * n;
} else {
return 1;
}
}; // need a semicolon at the end of the lambda
return inner_fact(n);
}
The [&inner_fact]
part of the lambda is required for
recursion.
std::function<int(int)>
says that the function
returns an int
and has one parameter which is type
int
.
Here is the EBNF for simple lambda functions:
"[]" "(" [TYPE identifier ["," TYPE identifier]*] ")" [ "->" TYPE] "{" statements "}"
auto sum = [] (int first, int second) -> int
{
return first + second;
};
printf("13 + 14 = %d", sum(13, 14));
Note that instead of using std::function
you can use
the auto
keyword in C++14.
The return type, which is after the ->
, is optional
if C++ can determine the type. This lambda function will work in
place of the one above because both parameters are
int
:
[] (int first, int second) // no `-> int` needed; can be inferred
{
return first + second;
};
while
statements in C++ are very similar to Python:
def fact(n):
total = 1
k = 1
while k <= n:
total *= k
k += 1
return total
int fact(int n) {
int total = 1;
int k = 1;
while (k <= n) {
total *= k;
k += 1;
}
return total;
}
The braces after the while statement aren't required if we only want one statement executed. The braces allow us to execute multiple statements and are considered best practice even for single statement bodies.
for
statements in C++ are not very similar to
Python:
def sum_up_to(n):
"""Returns the sum of positive
numbers from 1 up to N (inclusive).
>>> sum_up_to(5)
15
"""
sum = 0
for i in range(0, n+1):
sum += i
return sum
int sum_up_to(int n) {
int sum = 0;
for (int i = 0; i < n + 1; i++) {
sum += i;
}
return sum;
}
Note the C++ for
statement has three parts:
for (initialization; condition; iteration) { ... }
Syntax Part | When Executed | Description |
---|---|---|
initialization |
Once on entry into for loop. Next thing executed
is the condition.
|
Usually used to define the variable used as the counter
(common practice is to call it i ).
|
condition |
Before execution of all statements in the
for loop. Next thing executed is the
first statement inside the for loop
body.
|
Compare the loop counter to some bound. Similar to the
condition of a while loop.
|
iteration (a.k.a. update) |
After the last statement inside the for loop
body. Next thing executed is the condition.
|
Usually used to increment or decrement the loop counter. Can
modify loop counter in any way, e.g. i += 2 skips
every other value of i .
|
for
statements are often used with arrays.
#include <cstdio>
const int MAX_SIZE = 50;
void zeroize(int array[MAX_SIZE]) {
for (int i = 0; i < MAX_SIZE; i++) {
array[i] = 0;
}
}
int main() {
int values[MAX_SIZE];
zeroize(values);
printf("Last should be zero, is: %d\n", values[MAX_SIZE-1]); // will be 0
return 0;
}
Note that the size of the array is a global constant used by the
function zeroize
. If we want the function to work for
any size array we would write it as:
void zeroize(int array[], int size) { ... }
The Standary Library vector
class is similar to a
Python list
. You must have
#include <vector>
at the top of your file to use
vectors.
It is common to use vectors over arrays, since vectors can grow dynamically and they keep track of their size.
tas = ["Haylee", "Easton", "Dallin", "Savannah"]
std::vector<std::string> tas{"Haylee", "Easton", "Dallin", "Savannah"};
⚠️ WARNING ⚠️ A vector
object can only store elements
of a single, specified type unlike Python lists.
Here are some common methods provided by the
vector
class:
Method | Parameter(s) | Description |
---|---|---|
at | int — index | Accesses the specified element with bounds checking |
push_back | Value with same type as elements | Add new value to the end of vector |
pop_back | (none) | Remove the last element (not returned) |
clear | (none) | Clears the contents |
empty | (none) |
Returns true if empty,
false otherwise
|
size | (none) | Returns an unsigned integer type with number of elements |
Has front
and back
like
string
and many more. See
C++ Reference.
Both strings and vectors have two methods for accessing individual characters or elements.
The first way is to use brackets [ ]
, same as Python
strings and lists:
std::vector<std::string> tas{"Haylee", "Easton", "Dallin", "Savannah"};
printf("%c", tas[0][2]); // prints 'y'
The second way is to the method .at()
:
std::vector<std::string> tas{"Haylee", "Easton", "Dallin", "Savannah"};
printf("%c", tas.at(2).at(0)); // prints 'D'
The method .at()
performs bounds checking 👀
which means it will throw an exception if the index is out of
range (too big) for the size of the string or vector. This
provides protection against malicious buffer overflow attacks 💣.
Using [ ]
is faster, but unsafe.
There are two different ways to print output.
We've already seen printf
which is similar to format
strings in Python, but printf
doesn't play well with
the C++ string
class.
The C++ iostream
library does work well with C++
strings.
#include <iostream>
int main() {
std::string name = "Brett";
printf("%s\n", name); // prints garabage chars like �HDQ�
printf("%s\n", name.c_str()); // prints "Brett" from C-style string
std::cout << name << std::endl; // prints "Brett"
return 0;
}
cout
stands for console or
character output.
endl
stands for end line.
The for each statement is used with vectors and other collections that are iterable.
Python for each loop
for <value> in <sequence>:
<statement>
<statement>
C++ for each loop
for (<TYPE> <value> : <sequence>) {
<statement>
<statement>
}
std::vector<std::string> tas{"Haylee", "Easton", "Dallin", "Savannah"};
for (std::string ta : tas) {
std::cout << "Thank you, " << ta << "!" << std::endl;
}
C++ often has multiple syntax options for the same thing because of the decision to be backward compatible with C code (C++ has everything in C and then more).
Create a C++ program equivalent to the following Python program:
def sum_digits(n):
digit_sum = 0
while n > 0:
last = n % 10
n = n // 10
digit_sum += last
return digit_sum
def sum_digits(n):
digit_sum = 0
while n > 0:
last = n % 10
n = n // 10
digit_sum += last
return digit_sum
int sum_digits(int n) {
int digit_sum = 0;
while (n > 0) {
int last = n % 10;
int n = n / 10;
digit_sum += last;
}
return digit_sum;
}
Create a C++ program equivalent to the following Python program:
def exp_fast(b, n):
if n == 0:
return 1
elif n % 2 == 0:
return square(exp_fast(b, n // 2))
else:
return b * exp_fast(b, n-1)
square = lambda x: x * x
auto square = [] (auto x) { return x * x; };
int exp_fast(int b, int n) {
if (n == 0) {
return 1;
}
else if (n % 2 == 0) {
return square(exp_fast(b, n / 2));
}
else {
return b * exp_fast(b, n-1);
}
}
⚠️ WARNING ⚠️ Order matters in C++, so square
must be
defined before exp_fast
, otherwise the code
will not compile.