4.4. Programming in C++#

4.4.1. Understanding Basic Operators#

4.4.1.1. Mathematical Operators:#

We have already used some mathematical operators in the previous sections like +, -, *, /, =. Among these operators, we should examine / further, since the usage of this operator with different data types may lead to some trouble. Let’s observe this trouble first:

Write a very simple program that divides 2 by 4 and writes the results to console. If you want to assign the result of division to a variable, be sure that the type of this variable is double. When you run this program, you will see “0” as result in the console.

The reason is the following: While you are coding, as you write “2” or “4”, the compiler stores it temporally as integers. The division of two integers returns an integer, so fractional part of the result is disregarded. Even assigning the result to a double variable does not solve this problem, since the calculation is done before assigning the value to the variable. To avoid this kind of problems, you should use these numbers as “2.0” or “4.0”. By this way, the numbers are stored in double type and division operation can be handled correctly. Now, you can modify your program to see the correct result.

You should also be very careful about the precedence of the operators. Just like in a mathematical notation, * and / have higher precedence than + and -. You can use parentheses, ( … ), to give higher precedence to a part of the mathematical operation. That is, if you write a+b/c, then the program will do the division operation first and addition operation second, where (a+b)/c first adds a and b and divides the result by c. A table that shows precedence levels of operators is given in the Section on Operator precedence. However, you can always safely use parentheses if you don’t want to memorize this table.

There are also very commonly used operators that make life easier like ++, --. They are used along with a variable as [Variable]++ or [Variable]--. They add one to or subtract one from a variable. To see their effect, run the following code piece.

int a=5; 
a++;

int b=5; 
b--;

std::cout << "The value of a is " << a << ", and the value of b is" << b << std::endl;

Exercise 4.4

The command [Variable]++ is in the postfix notation. There is a similar prefix notation ++[Variable] for incrementing as well as the -- variant for decrementing. Write a simple code that displays the difference between them.

Another mathematical operator is %. This operator is used as

result = [Variable1] % [Variable2]

and it gives the remainder of the division [Variable1]/[Variable2].

Exercise 4.5

Write a simple code that takes two numbers as input, calculates the remainder of the division operation “number1/number2” and prints the remainder to the console.

4.4.1.2. Comparison operators#

Comparison operators in C++ are given in Table 4.3. These operators return true or false (0 or 1 if you assign the value to an integer) depending on the result of the comparison.

Table 4.3 Comparison Operators#

Operator

Name

Syntax

Output

==

equal to

a == b

Returns true if a is equal to b

and false otherwise.

!=

not equal to

a != b

Returns true if as is not equal

to b and false otherwise.

>

greater than

a > b

Returns true if a is greater

than b and false otherwise.

<

less than

a < b

Returns true if a is less

than b and false otherwise.

>=

greater than or equal to

a >= b

Returns true if a is greater than

or equal to b and false otherwise.

<=

less than or equal to

a <= b

Returns true if a is less than

or equal to b and false otherwise.

Exercise 4.6

Write a simple program that takes two numbers as input and compares them. If the first number is greater than the second one then the program should write 1 to the console and 0 otherwise.

Be careful when comparing floating point numbers!

Integer type numbers are always exact. Comparing two different calculations of the same integer type number always works. However, due to the way floating point types (float and double type variables) are stored, two different calculations that lead to the theoretical same number may not be precisely equal.

Be cautious of this when comparing floating point types, for instance by comparing to a range of values such as in the code below. See the section on Logical Operators for an explanation about the ‘and’ operator &&.

double a, b, c, expected; 
double epsilon; 
a = 4.0; 
b = 2.0; 
c = a/b;
expected = 2.0; 
epsilon = 0.0001; 
bool correct = c < expected + epsilon && c > expected - epsilon;

4.4.1.3. Logical Operators#

The logical operators can be seen in Table 4.4. These operators are for comparing logical values (true and false or 0 and 1). They are used with control structures very frequently as you will see in the section on Control Structures.

Table 4.4 Logical operators#

Operator

Name

Syntax

Output

!

logical negation

!a

Returns true if a is false and

false otherwise.

&&

logical AND

a && b

Returns true if both a and b

are true and false for all other cases.

||

logical OR

a || b

Returns false if both a and b are false

and true for all other cases.

4.4.1.4. Other Operators#

Operators can also be library dependent. For example, one of the commands that you use, the cout command of iostream library, has the operator << to take inputs. The header files of the libraries present available operators of the library together with their functionality. Also, reading the manual of a library (if there is one) helps a lot.

4.4.1.5. Operator precedence#

If you have a statement that has more than one operator, you should be very careful of the precedence levels of the operators (as mentioned in Section on Mathematical Operators). Table 4.5 presents a list of precedence that involves mathematical, comparison and logical operators. Lower numbers represent a higher precedence or priority. As you can see from this list, parenthesis ( ) operator has the highest precedence, so by using them, you can arrange the precedence as you want.

Table 4.5 Precedence of mathematical operators#

Precedence

Operators

1

++, --, ( ), [ ]

2

!, * (dereference), & (address of), (see Section 4.7 for the last two)

3

*, /, %

4

+, -,

5

>, <, >=, <=

6

==, !=

7

&&

8

||

4.4.2. Control Structures#

Control structures make up the main structure of the code along with the iterative statements. In this section, we will talk about the control structures if, else if, else and switch.

4.4.2.1. The if (...) control statement#

The control structure if is made up of two parts: condition which is written in parenthesis ( ... ), and a code piece inside { ... }. If the condition of if is true or any value other than 0, then the code piece is executed. If the condition of if is false or 0, then code piece is skipped. It is used in the following form:

if ([CONDITIONS]) 
{
    [CODE LINES]
}    

Let’s examine the program below:

#include <iostream>
int main() {
    double number1;
    double number2;

    std::cout << "Please enter two numbers:" << std::endl;
    std::cin >> number1 >> number2;

    if (number1 < number2)
    {
        std::cout << "Second number is bigger than the first number." << std::endl;
    }
    if (number1 > number2)
    {
        std::cout << "First number is bigger than the second number." << std::endl;
    }
    if (number1 == number2)
    {
        std::cout << "The numbers are the same." << std::endl;
    }

    return 0;
}

This program takes two numbers as input from the console. In the first if statement, the program checks if number1 is less than number2. If that is true, then the program executes the cout line. If not, it skips the code inside that if and executes further.

4.4.2.2. else if (...) and else:#

There are other supporting elements that can be used in combination with if: else if and else. These commands can be used as:

if([CONDITIONS 1])
{
    [CODE PIECE 1]
}
else if([CONDITIONS 2])
{
    [CODE PIECE 2]
}
.
.
.
else if([CONDITIONS N])
{
    [CODE PIECE N]
}
else
{
    [CODE PIECE N+1]
}

If you use else if, you add a hierarchy to if commands. If [CONDITION 1] is true, then [CODE PIECE 1] will be executed, and all other else if commands are skipped. If [CONDITION 1] is false, than [CONDITION 2] will be checked. If it is true, [CODE PIECE 2] will be executed and all remaining else if commands are skipped and so on. Finally if the conditions of all else if commands are false, then the code piece inside else is executed.

Using else if doesn’t only provide easier code management, but also makes your code faster since unnecessary conditional checks are avoided. Actually our first if program could be written as below:

#include <iostream>
int main() {
    double number1;
    double number2;

    std::cout << "Please enter two numbers:" << std::endl;
    std::cin >> number1 >> number2;

    if (number1 < number2)
    {
        std::cout << "Second number is bigger than the first number." << std::endl;
    }
    else if (number1 > number2)
    {
        std::cout << "First number is bigger than the second number." << std::endl;
    }
    else if (number1 == number2)
    {
        std::cout << "The numbers are the same." << std::endl;
    }

    return 0;
}

Alternatively we can use else, since if a is not greater than b and b is not greater than a, only option left is a=b.

#include <iostream>
int main() {
    double number1;
    double number2;

    std::cout << "Please enter two numbers:" << std::endl;
    std::cin >> number1 >> number2;

    if (number1 < number2)
    {
        std::cout << "Second number is bigger than the first number." << std::endl;
    }
    else if (number1 > number2)
    {
        std::cout << "First number is bigger than the second number." << std::endl;
    }
    else
    {
        std::cout << "The numbers are the same." << std::endl;
    }

    return 0;
}

Exercise 4.7

Write a code that takes two numbers as input and checks if the first one is divisible with the second one without any remainder.

Two or more conditions can be combined by using logical operators. For example, if you want to check whether a number is between 0 and 10, then you should write if (number>0 && number<10). If you want to check if a number is less than -10 or bigger than 10, then you can write the condition as if (number<-10 || number>10).

4.4.2.3. The switch statement#

Actually, using switch statement is similar to using a couple of if, else if and else statements. However, in some cases using switch might be more comfortable for the programmer. The way of using switch is as below:

switch([EXPRESSION])
{
    case [CHOICE 1]:
        [CODE PIECE 1]
    case [CHOICE 2]:
        [CODE PIECE 2]
    case [CHOICE 3]:
        [CODE PIECE 3]
    .
    .
    .
    case [CHOICE N]:
        [CODE PIECE N]
    default:
        [CODE PIECE N+1]
}

So let’s say you want to write a simple calculator program:

#include <iostream>
int main() {
    double number1, number2;
    int input;

    std::cout << "Please enter two numbers" << std::endl;
    std::cin >> number1 >> number2;
    std::cout << "If you want to add these numbers, enter 1" << std::endl;
    std::cout << "If you want to subtract these numbers, enter 2" << std::endl;
    std::cout << "If you want to multiply these numbers, enter 3" << std::endl;
    std::cout << "If you want to divide these numbers, enter 4" << std::endl;
    std::cin >> input;

    switch (input) {
        case 1:
            std::cout << "Result is " << number1+number2 << std::endl;
            break;
        case 2:
            std::cout << "Result is " << number1-number2 << std::endl;
            break;
        case 3: // multiple values can share same statements
            std::cout << "Result is " << number1*number2 << std::endl;
            break;
        case 4:
            std::cout << "Result is " << number1/number2 << std::endl;
            break;
        default:
            std::cout << "invalid input" << std::endl;
    }

    return 0;
}

In this program switch statement compares the value of the variable input to the special cases 1, 2, 3 and 4. With break command, if one of the cases is true, other cases are skipped. In other words, using break equals to using if, else if combination, where not using break equals to using only if statements.

The default case is very similar to the usage of else. That is, the code under default is executed if all the cases fail.

4.4.3. Iterative Statements:#

Iterative statements make it possible to build up “loops”. Loops are used for executing a code piece repeatedly. These statements are while, for, and do while.

4.4.3.1. while statement:#

The code inside the while loop is executed if the condition is true, and it is repeated until the condition becomes false.
The way to use while is as below:

while([CONDITION])
{
    [CODE PIECE]
}

Let’s say you want to print numbers between 0 and 100. You don’t have to enter these values manually; just use while as below:

#include <iostream>

int main()
{
    int a = 0;

    while (a<101) 
    {
        std::cout << a << std::endl; 
        a++; 
    }
    return 0;
}

Here, the code piece inside while is executed, until a is 101. With a++;, a is incremented by 1 in each iteration, and when it reaches 101, the program exits from while statement. Another example can be the following:

bool good_input = false; 
double input;

std::cout << "Please enter a number between 0 and 10" << std::endl;
std::cin >> input;

while (!good_input)
{
    if(input<0 || input>10)
        {
            std::cout << "The number you entered is out of bounds." << std::endl;
            std::cout << "Please enter a number between 0 and 10" << std::endl;
            std::cin >> input;
        }
    else
        {
            good_input = true;
        }
}

This code piece requests an input from the user between 0 and 10. The boolean variable good_input is initialized as false. Thus !good_input is true, and the program enters the while loop. If input is less than 0 or greater than 10, then the program requests an input again. If input is inside the bounds, then the variable good_input is changed to true, which makes the condition of while false, and this terminates the loop.

4.4.3.2. for statement:#

for statement is very similar to while. However, with for you can change values of variables while imposing the loop condition.

for([EXECUTION_BEFORE_STARTING];[ENDING_CONDITION];[INCREMENT])
{
    [CODE PIECE]
}    

It is better to explain it with an example. Let’s print numbers between 0 and 100, but this time by using for instead of while.

#include <iostream>

int main() 
{
    for(int a = 0; a < 101; a++)
    {
        std::cout << a << std::endl;
    }
    return 0;
}

At the beginning of the for statement, the variable a is declared and set to 0. The execution ends when a is NOT less than 101, and at each loop cycle, a is incremented by 1.

for statement is very useful for nested loops (loops in loops). Let’s say you want to check all the members of a matrix. Then, you can use two loops one nested inside the other as follows:

for(int i = 0; i < 10; i++)
{
    for(int j = 0; j < 10; j++)
    {
        if (mymatrix[i][j] > 0)
        {
            std::cout << mymatrix[i][j] << std::endl;
        }
    }
}

This program checks all the members of the matrix mymatrix and prints out the numbers that are positive.

Exercise 4.8

Take 5 numbers as input from the user, arrange the numbers in ascending order and print them to the console. Hint: Record these numbers into an array. Then, you can write two for loops like above to compare the numbers inside the array.

Exercise 4.9

Write all prime numbers to the console between 0 and 1000.

4.4.3.3. do …while statements#

while statement can be used together with do. This time, the code piece assigned to these statements is executed once before checking the condition of while. The following executions are done depending on the condition of while.

do
{
    printf_s("\n%d",i++);
} while (i < 3);

4.4.4. I/O Operations#

Now, it is time to learn how to give an input to a program other than using the console. One way of doing this is to read from a file using file streams. You can think of file streams as a data line connected to a file (say a .txt file) to read and write information. C++ has a standard library for that use: fstream. In this library there is ifstream object (input file stream) to read from a file, and ofstream object (output file stream) to write to a file. To use these streams, you should first include the standard header file fstream.h and then define these objects as follows:

ifstream myInputStream;
ofstream myOutputStream;

Then, you should open these streams by giving the file name:

myInputStream.open("myfile.txt");
myOutputStream.open("myfile.txt");

Reading and writing through these file streams are done using >> and << operators respectively. After reading from / writing to a file, the stream should be closed as follows

myInputStream.close();
myOutputStream.close();

If you do not close your file stream, it will be closed by the end of the program. However, you can not open another file stream to the same file, so it is always safe to close the stream. The program below writes a string to a file.

#include <iostream>
#include <fstream>
#include <string>

int main()
{
    // file object
    std::ofstream myOutputStream;

    // open file
    myOutputStream.open("myfile.txt");

    // write to file
    std::string mystring = "text text text";
    myOutputStream << mystring;

    // close file
    myOutputStream.close();

    return 0;
}

The following program is an example of reading from a file.

#include <iostream>
#include <fstream>
#include <string>

int main()
{
    std::string mystring;
    std::ifstream myInputStream;

    myInputStream.open("myfile.txt");

    myInputStream >> mystring;
    std::cout << mystring << std::endl;

    myInputStream.close();
}

However, you may notice that, with >> operator, only one word is read from a file.

Exercise 4.10

Write a program (using iterative statements) that reads all the words from a file and prints them.

Hint: [INPUT_STREAM_NAME].eof() function returns true if ‘End Of File’ is reached, and returns false otherwise.

There are other useful functions of fstream library. You can check internet, or header file of the library for more information.