Skip to main content

M03 - C++ Basics (Part 1)

In this module, we will cover the basics of C++ programming. We will discuss the fundamental concepts of C++, including variables, data types, operators, branching, looping, and functions.

Arithmetic Operators

C++ provides a variety of arithmetic operators that can be used to perform mathematical operations on a variety of data types (e.g., integers, floating-point numbers, etc.).

The following table summarizes the arithmetic operators available in C++:

Operator nameSyntaxFunction
Unary plus+aHas the same affect as a multiplication by 1
Unary minus-aNegates the sign
Additiona + bTakes the sum
Subtractiona - bTakes the difference of b from a
Multiplicationa * bTakes the product of a and b
Divisiona / bTakes the quotient of a divided by b
Remainder/Moduloa % bTakes the reminder from the the division of a by b
Modulo Operator

The modulo operator (%) returns the remainder of the division of the first operand by the second operand. For example, 5 % 2 returns 1 because 5 divided by 2 is 2 with a remainder of 1.

This operator is often used to determine:

  • Parity (e.g., n % 2 == 0 for even numbers, n % 2 == 1 for odd numbers)
  • Divisibility (e.g., n % 5 == 0 for numbers divisible by 5)
  • Offsets (e.g., index % size for circular buffers)
  • Digits (e.g., n * pow(10, i) % 10 for the i-th digit of n)

Relational Operators

Relational operators are binary functions that takes two operands and return a boolean value (true or false) based on the relationship between the operands. The following table summarizes the relational operators available in C++:

Operator nameSyntax
Equal toa == b
Not equal toa != b
Less thana < b
Greater thana > b
Less than or equal toa <= b
Greater than or equal toa >= b
Equality vs. Assignment

It is important to note the difference between the equality operator (==) and the assignment operator (=). The equality operator is used to compare two values, while the assignment operator is used to assign a value to a variable.

int x = 42;
int y = 42;

if (x == y) {
std::cout << "x is equal to y" << std::endl;
}

Logical Operators

Logical operators allow us to combine multiple conditions to form more complex conditions. The logical operators in C++ are:

Operator nameSyntax
Logical ANDcondition1 && condition2
Logical ORcondition1 || condition2
Logical NOT!condition
Logical NOT!condition

Concisely,

  • The logical AND operator (&&) returns true if both conditions are true.
  • The logical OR operator (||) returns true if at least one of the conditions is true.
  • The logical NOT operator (!) returns true if the condition is false, and false if the condition is true.
Short-Circuit Evaluation

C++ uses short-circuit evaluation when evaluating logical expressions. This means that the evaluation stops as soon as the result is known.

For example, in the expression condition1 && condition2, if condition1 is false, the result of the expression is false regardless of the value of condition2. Therefore, condition2 is not evaluated.

Similarly, in the expression condition1 || condition2, if condition1 is true, the result of the expression is true regardless of the value of condition2. Therefore, condition2 is not evaluated.

Chaining Relational Operators (with Logical Operators)

You can chain relational operators together to form more complex conditions. For example, you can check if a number is between two other numbers as follows:

int x = 42;

if (0 < x && x < 100) {
std::cout << "x is between 0 and 100" << std::endl;
}
Invalid Chaining

Note that you cannot chain relational operators like this:

int x = 42;
int y = 100;

if (0 < x < 100) {
std::cout << "x is between 0 and 100" << std::endl;
}

Here, the expression 0 < x < 100 is evaluated as (0 < x) < 100, which is equivalent to true < 100, which is not a valid expression in C++.

Branching

Branching is the process of taking different code paths based on conditions. In C++, branching is achieved using the if, if-else, and if-else if statements.

If Statement

The if statement is used to execute a block of code based on a condition. The syntax of the if statement is as follows:

if (condition) {
// code to be executed if the condition is true
}

The condition is evaluated, and if it is true, the code inside the block is executed. If the condition is false, the code is skipped.

For example, the following code prints "Hello, World!" if the variable x is greater than 0:

int x = 5;

if (x > 0) {
cout << "Hello, World!" << endl;
}

Here, the condition x > 0 is true since x is 5. Therefore, the code inside the block is executed, and "Hello, World!" is printed to the console.

If-Else Statement

The if-else statement is used to execute a block of code based on a condition. The syntax of the if-else statement is as follows:

if (condition) {
// code to be executed if the condition is true
} else {
// code to be executed if the condition is false
}

The condition is evaluated, and if it is true, the code inside the first block is executed. If the condition is false, the code inside the second block is executed.

For example, the following code checks if the balance is sufficient to make a purchase:

int balance = 100;
int price = 150;

if (balance >= price) {
cout << "Purchase can be made" << endl;
} else {
cout << "Insufficient funds" << endl;
}

Here, the condition balance >= price is false since the balance is 100 and the price is 150. Therefore, the code inside the else block is executed, and "Insufficient funds" is printed to the console. Had the balance been greater than or equal to the price, say 200, there would be sufficient funds to make the purchase and "Purchase can be made" would be printed.

If-Else If Statement

The if-else if statement is used to execute a block of code based on multiple conditions. The syntax of the if-else if statement is as follows:

if (condition1) {
// code to be executed if condition1 is true
} else if (condition2) {
// code to be executed if condition2 is true
} else {
// code to be executed if all conditions are false
}

The condition1 is evaluated first. If it is true, the code inside the first block is executed. If condition1 is false, condition2 is evaluated. If condition2 is true, the code inside the second block is executed. If all conditions are false, the code inside the else block is executed.'

For example, the following code checks the grade based on the score:

int score = 85;

if (score >= 90) {
cout << "A" << endl;
} else if (score >= 80) {
cout << "B" << endl; // Only this block is executed
} else if (score >= 70) {
cout << "C" << endl;
} else if (score >= 60) {
cout << "D" << endl;
} else {
cout << "F" << endl;
}

Notice that we can have multiple else if blocks to check multiple conditions. Also take note that that the else if blocks are evaluated in order. Once a condition is true, the corresponding block is executed, and the rest of the blocks are skipped.

Looping

Loops are used to execute a block of code repeatedly. C++ provides several types of loops, including the while loop and the for loop.

While-Loop

The while loop is used to execute a block of code repeatedly as long as a condition is true. The syntax of the while loop is as follows:

while (condition) {
// code to be executed
}

The condition is evaluated before each iteration. If the condition is true, the code inside the loop is executed. The loop continues until the condition is false.

For example, the following code prints the numbers from 0 to 4:

int i = 0;
while (i < 5) {
cout << i << endl;
i++;
}

Here, i is initialized to 0, and the loop continues as long as i is less than 5. After each iteration, i is incremented by 1. When i reaches 5, the loop stops since the condition i < 5 is false.

For-Loop

The for loop is used to iterate over a range of values. The for loop has three parts: the initialization, the condition, and the statement (usually called the increment).

The syntax of the for loop is as follows:

for (initialization; condition; increment) {
// code to be executed
}

The initialization is executed once at the beginning of the loop. The condition is evaluated before each iteration. If the condition is true, the code inside the loop is executed, and the increment is executed. The loop continues until the condition is false.

For example, the following code prints the numbers from 0 to 4:

for (int i = 0; i < 5; i++) {
cout << i << endl;
}

Here, i is initialized to 0, and the loop continues as long as i is less than 5. After each iteration, i is incremented by 1. When i reaches 5, the loop stops.

Scope of the Loop Variable

The variable initialized in the for loop is accessible only within the loop. For example, the following code will produce an error:

for (int i = 0; i < 5; i++) {
cout << i << endl;
}

cout << i << endl; // Error: i is not defined
Infinite Loops

Loops can run indefinitely if the condition is always true. For example, the following code creates an infinite loop:

for (int i = 0; i < 5; i--) {
cout << i << endl;
}

In this case, i is initialized to 0, and the loop continues as long as i is less than 5. However, i is decremented by 1 after each iteration. Since i will never be less than 5, the loop will run indefinitely.

Be careful when writing loops to ensure that the condition will eventually evaluate to false.

Early Exit & Continuation

The break and continue statements are used to alter the flow of a loop. Specifically, break is used to exit the loop early, while continue is used to continue immediately with the next iteration of the loop.

Break

The break statement is used to exit the loop immediately. When the break statement is encountered, the loop is terminated, and the program continues with the next statement after the loop.

For example, the following loops both print the numbers from 0 to 2:

// Using a for-loop
for (int i = 0; i < 5; i++) {
if (i == 3) {
break;
}
cout << i << endl;
}

// Using a while-loop
int i = 0;
while (i < 5) {
if (i == 3) {
break;
}
cout << i << endl;
i++;
}

Continue

The continue statement is used to end the current iteration of the loop and continue with the next iteration. When the continue statement is encountered, the loop skips the rest of the code in the current iteration and continues with the next iteration starting from the loop condition.

For example, the following loops both print the numbers from 0 to 4, skipping the number 3:

// Using a for-loop
for (int i = 0; i < 5; i++) {
if (i == 3) {
continue;
}
cout << i << endl;
}

// Using a while-loop
int i = 0;
while (i < 5) {
if (i == 3) {
i++;
continue;
}
cout << i << endl;
i++;
}

Functions

Functions are blocks of code that perform a specific task. Functions allow us to break down a program into smaller, more manageable pieces. Functions can be called multiple times from different parts of the program, making the code more modular and easier to maintain.

Functions take parameters as input, perform some computation, and return a value. Functions can also be defined to perform a task without returning a value (i.e., a void function).

Calling Functions

To call a function, you need to provide the function's name and any required parameters. For example, the following code calls a function named add with two parameters 3 and 4:

int sum = add(3, 4); // Call the add function with the parameters 3 and 4

Here, add is the function name, and 3 and 4 are the parameters passed to the function. The result of the function call is stored in the variable sum.

greet(); // Call the greet function

Here, greet is the function name, and no parameters are passed to the function.

Function Declarations

A function declaration tells the compiler about a function's name, return type, and parameters. A function definition provides the actual body of the function (see below).

For instance, the following code declares a function named add that takes two parameters of type int and returns an int:

void greet();

int add(int x, int y);

Notice that function declarations end with a semicolon. This is because declarations are statements and all statements in C++ end with a semicolon. Also notice that function declarations do not include the function's body.

Why do we need function declarations?

Function declarations allow us to indicate to the compiler that a function exists and will be defined later in the program. This is useful when a function is defined after it is called in the program.

// Function declaration
int add(int x, int y);

int main() {
int sum = add(3, 4);
return 0;
}

// Function definition (see below for info)
int add(int x, int y) {
return x + y;
}

Header files contain function declarations for functions defined in the corresponding source files. This allows us to include the header file in multiple source files and call the functions defined in the source file.

We will discuss header files and their use in the compilation process later.

Function Definitions

A function definition provides the actual body of the function. The function definition includes the function's return type, name, parameters, and body.

For instance, the following code defines a function named add that takes two parameters of type int and returns an int:

int add(int x, int y) {
return x + y;
}

Notice that the function definition includes the function's body, which is enclosed in curly braces {}. The function's body contains the statements that are executed when the function is called.

Return Statement

The return statement is used to return back to the caller of the function. The return statement can also be used to return a value from the function.

For example, the following function add returns the sum of two integers x and y:

int add(int x, int y) {
return x + y;
std::cout << "This line is never executed" << std::endl;
}

Here, the return x + y; statement returns the sum of x and y back to the caller of the function.

Void Functions

Functions that do not return a value are declared with a return type of void. For example, the following function greet does not return a value:

void greet() {
std::cout << "Hello, World!" << std::endl;
}

Here, the function greet prints "Hello, World!" to the console but does not return a value.