0% found this document useful (0 votes)
29 views126 pages

Netcad Cisco C++

Uploaded by

Rasba Sibghat
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
29 views126 pages

Netcad Cisco C++

Uploaded by

Rasba Sibghat
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 126

Natural language vs programming language

We're here to show you what the C++ language is and what we can use it for. Let’s
consider for a moment what language itself is, not only the C++ language, but any
language people use. We’ll try not to use scientific sounding definitions and we’ll try to
speak informally. We can say that a language is a tool for expressing and
recording human thoughts. We really like this definition. In other words, it's a
mechanism known to us and to our partners, allowing us all to understand and to be
understood. We use language for speaking, writing, reading, listening and thinking.

At least one language accompanies us throughout our entire lives - it's our native
language (our mother tongue), which we learn almost unconsciously from the very
beginning. Many of us will learn other languages too, mostly as a result of a conscious
decision, forced by social conditions or business needs. The languages we use to
communicate with other people are called natural languages. They were created over
many centuries and still are subject to change. If we ignore languages that have been
created artificially, such as Esperanto or even Quenya (the language used by elves in
Tolkien's world), their development is almost independent of their speakers and evolves
naturally, in a way that gives us little to no control over it.

However, there are languages whose creation and development were (and often
continue to be) dictated by some specific needs, and whose development is fully subject
to control by very wide groups of people like international committees or work groups.
The shape of these languages is defined by international standards, and although they
may be understood by many people, the exchange of thoughts between human-beings
is not their priority.

Such languages are, among others, programming languages. You are probably
familiar with this concept already. A programming language is defined by a certain set
of rigid rules, much more inflexible than any natural language. For example, these rules
determine which symbols (letters, digits, punctuation marks, and so on) could be used
in the language. This part of the definition of language is called lexicon. Another set of
rules determines the appropriate ways of collating the symbols - this is the syntax of
the language. We also need to be able to recognize the meaning of every statement
expressed in the given language, and this is what we call semantics. Any program we
write must be error-free in these three ways: lexically, syntactically and
semantically, otherwise, the program won’t run, or it will produce unacceptable
results. You can be sure that you’ll encounter all of these errors, as to err is human and
it’s these fallible humans who write the computer programs.

You might be asking yourself why we need to use a programming language at all, and
that's a good question. Let’s try to answer it.

A computer, even the most technically sophisticated one, is devoid of even a trace of
intelligence. You could say that it is like a well-trained dog – it responds only to a
predetermined set of known commands. And sometimes, like a dog, it just shuts
down and refuses to do what it’s told. The recognized commands are very simple. We
can imagine that the computer responds to orders like “take that number, add to
another and save the result”.

A complete set of well-known commands is called an instruction list, sometimes


abbreviated to IL. Different types of computers may vary depending on the size of their
ILs and the instructions themselves can be entirely different in different models.

The IL is in fact an alphabet that is commonly known as machine language. This is the
simplest and the most primary language we can use to give commands to our
computer. We can say it's the computer’s mother tongue.
It is possible (and this is often done in practice) for a computer program to be coded
directly in machine language using elementary instructions (orders). This kind of
programming is tedious, time-consuming and highly susceptible to a programmer's
mistakes. During the early stages of computer technology, it was the only available
method of programming, and it very quickly revealed its serious flaws.

Programming in machine language requires full knowledge of a computer’s hardware


design and its internal structure. This also means that replacing the computer with one
that differs in design from its predecessor can make the programmer’s entire
knowledge unusable. Also, the old programs could be completely useless if the new
computer used a different IL. Thus, a program written for a specific type of computer
could be completely useless to other computers and vice versa. Secondly, programs
written in machine language are very difficult to understand for humans, including
experienced programmers. It is also the case that to develop a program in machine
language takes a lot of time and is very costly and cumbersome.

All these circumstances lead to a need for some kind of bridge between the people's
language (natural language) and computer language (machine language). That bridge is
also a language – an intermediate common language for both humans and computers
working together. Such a language is often called a high-level programming
language.

A language like this is at least somewhat similar to a natural language: it uses symbols,
words and conventions readable to humans. This language enables humans to express
complex commands for computers.

You may be asking how to persuade a computer to understand programs written in this
way. Try as you might, encouraging the computer is just not enough, but you can
translate your program into machine language. Moreover, the translation can be done
by a computer, making the whole process fast and efficient.
How great is that? You don’t need to learn a whole bunch of different machine
languages – you just need to know one high-level programming language. If there is a
translator designed for a specific computer, you can run your program without any
problems. In other words, the programs written in high-level languages can be
translated into any number of different machine languages, and thus enable them to be
used on many different computers. This is called portability.

The translation we are referring to is made by a specialized computer program called


a compiler. The process of translating from a high-level language into a machine
language is called compilation.

Now let's get back to more interesting issues related to the process of creating a new
program. We already know that the main task is to write a program in accordance with
the rules of the chosen programming language. Such a program (which in fact is just
text) is called the source code, or simply source, while the file which contains the source
is called the source file.

To write the source code, you will need a text editor that allows you to manipulate text
without any formatting information (for this reason Microsoft Word isn't a good choice -
Notepad is better). This code is placed in a file and the name of the file should imply its
content. For example, it's common for a file containing the source code in the C++
language to have its name ending with the suffix .cpp, so if you write a computer
program and decide to name it proggie, it would be a good idea to put the source code
into a file named proggie.cpp. Some platforms may prefer other suffixes like cc, cp, cxx,
c++ or even C (note that this is a capital letter). Please consult your compiler
documentation for details.

Next, your source code needs to be compiled. To do this you need to run an appropriate
compiler and instruct it where you stored the source code you want it to translate into
machine language. The compiler reads your code, makes some complex analysis, and
then determines whether or not you made any errors during the coding process. If you
have, it will tell you. This is not to make you feel bad - these analyses are very insightful
and helpful. But remember that they are made by a machine, not a human, and you
shouldn't expect too much from them. Okay, if your mistake was that you tried to add
up two numbers using # instead of + , the compiler will kindly inform you of your
mistake. However, if you typed - instead of + , the compiler can't guess that your
intention was to add two numbers, rather than to subtract them. The compiler will
not think for you. But that's okay too. If the compiler did everything, developers
wouldn't have jobs.

If the compiler doesn't find any mistakes in your source, the result will be a file
containing your program translated into machine language. That file is commonly called
an executable file. The name of the file depends on the compiler you use and the
operating system you are working with. For example, most compilers designed for
Unix/Linux system create an output file named " a.out " by default. Compilers designed
for use in MS Windows® can name the same name to this file as the source file, while
only changing the suffix from .cpp to .exe .
Of course the whole process is actually a bit more complicated. Your source code might
be huge and divided among several or even dozens of source files. It may also be that
the program was not written by you alone, but by a whole team, in which case the
division of sources into multiple files is simply a must. In this case, the compiling
process splits into two phases: a compilation of your source in order to translate it into
machine language and a joining (or gluing) of your executable code with the executable
code derived from the other developers into a single and unified product. The phase of
"gluing" the different executable codes is commonly known as linking, while the
program that conducts the process is called a linker.

What is the most common use of C++? It is the so-called object programming language,
i.e. suitable mostly for large, complex applications, especially those working in graphic
environments. Knowing the C++ language is very helpful if you want to learn C# or
Java. The conceptual apparatus used by the C++ language is common for all object
programming languages, as C++ is one of the oldest languages of that class.

Further readings
If you take the learning of the "C++" language seriously (and we expect nothing less of
you), you will certainly not end your education with this awesome course.

Among the hundreds of books written on the C++ language, there is one that we
recommend in particular. The book has been issued dozens of times all around the
world and is available in over 20 different (natural) languages. The book’s title is simply
"The C++ Programming Language". It was the first book to describe the C++
programming language, written by the language’s creator, Bjarne Stroustrup.
Stroustrup began developing C++ in 1979 and currently – not surprisingly – is
considered the most important authority in this field. You can buy the book here.

Another book worth reading is "Thinking in C++" by Bruce Eckel. This book is
available to download for free. You can find it here.

One of the recently published books that we particularly enjoy is one written by Alex
Allain, called "Jumping into C++." It’s a great book for beginners, presenting a step-by-
step guide to becoming a C++ programmer. You can order the book here.
Last but not least, for those who aim to improve their programs and learn more about
best practices in C++, there is a great book by Scott Meyers, "Effective C++." You can
order the book here.

For a more comprehensive list of good C++ books, you may wish to check this
thread at stackoverflow.com.

If you know any other good books worth recommending, please feel free to contribute
to this thread on our Facebook page.

Once you're a proficient programmer, you may want to have a source of knowledge
through which you can quickly find the answers to emerging questions, or just fill in the
gaps in your memory. Instead of a handbook, you’ll want a book that briefly describes
the language standards - everything that’s really important and nothing more. You need
what is called a report (permanently improved and updated), published by the ISO
standardization committee. You can find the most recent version of the standard
at https://isocpp.org/std.

But hey, it’s too soon for that. Look into that when you finish this course. No sooner.

Your first program


Now we’re going to show you a very simple (and, at the same time, completely useless) program
written in the C++ language. We’re going to use this example to present you some basic rules
governing the language. The program itself will be modified many times, as it becomes enriched by
various additional elements in expanding our programming knowledge. Ready? All right then, let’s
go.

First we need to define our expectations for the program. They’ll be very modest. We want a short
text to appear on the screen. Let's assume that the text will state:

It's me, your first program.

output

That’s all we want at the moment.

What further steps should our first program perform? Let's try to enumerate them here:

1. to start;
2. to write the text on the screen;
3. to stop

This type of structured and semi-formal description of each step of the program is called
an algorithm. Sources of the word algorithm can be traced back to the Arabic language and
originated in early medieval times, and for us, this represents the beginning of computer
programming.

Now it's time to see our program. It’s on the right side of the screen, in the editor.
It looks a bit mysterious, doesn't it? Let’s check out each line of the program carefully, and uncover
its meaning and purpose. The description is not particularly accurate and those of you who know a
little C++ already will probably conclude that it’s too simplistic and somewhat childish. We did this on
purpose – we’re not building Rome in a day. Not even in a week!

CODE:

#include <iostream>

using namespace std;

int main()

cout << "It's me, your first program.";

return 0;

Let's move on.

Pay attention to the character # (hash) at the beginning of the first line. It means that the content of
this line is the so-called preprocessor directive. We’re going to tell you more about the
preprocessor later, but for now we’ll only say that it’s a separate part of the compiler whose task is to
pre-read the text of the program and make some modifications in it. The prefix "pre" suggests that
these operations are performed before the full processing (compilation) takes place.

The changes the preprocessor will introduce are fully controlled by its directives. In our program,
we are dealing with the include directive. When the preprocessor meets that directive, it replaces
the directive with the content of the file whose name is listed in the directive (in our case, this is the
file named iostream ). The changes made by the preprocessor never modify the content of your
source file in any way. Any alterations are made on a volatile copy of your program that disappears
immediately after the compiler finishes its work.

So why do you need the preprocessor to include the content of a completely unknown file called
iostream? Writing a program is similar to building a construction with ready-made blocks. In our
program, we are going to use one such block and it will happen when we want to write something on
the screen. That block is called cout (you can find it inside our code), but the compiler knows
nothing about it so far. In particular, the compiler has no idea that cout is a valid name for that block
while cuot isn't. The compiler must be warned about it – it needs to be aware of the fact.

A set of preliminary information that the compiler needs is included in header files. These files
contain a collection of preliminary information about ready-made blocks which can be used by a
program to write text on the screen, or to read letters from the keyboard. So when our program is
going to write something, it will use a block called cout, which is able to do the trick (and much
more). We don't want the compiler to be surprised, so we need to warn it about that. The compiler’s
developers put a set of this anticipatory information in the iostream file. All we have to do is use the
file. This is exactly what we expect from the include directive.

But where is the iostream file located? The answer is simple, but not as clear as you might want:
that’s not our problem. The preprocessor knows where it is. Good job, preprocessor!

In the C++ language, all elements of the standard C++ infrastructure are declared inside
the namespace called std . A namespace is an abstract container or environment created to hold a
logical grouping of unique entities (blocks).

An entity defined in a namespace is associated only with that namespace. If you want to use many
of the standard C++ entities (we’re going to tell you all about them later) you must insert the using
namespace instruction at the top of each file, outside of any function.

The instruction should specify the name of the desired namespace ( std in our case). This will make
the standard facilities available throughout the program.

It's worth to add (although you're not obliged to use the knowledge just know) that you may omit
putting using namespace in your code but the cost of such omission is non-zero. Now you have to
inform the compiler where cout block come from and you must do it each time you use any of the
entities derived from the std namespace. In other words, you need to write:

std::cout

instead of:

cout

Judge for yourself if it pays off. The compiler doesn't care what you choose. Anyway, we prefer to
use using namespace as it makes code clearer and more consistent.

We’ve already said something about the blocks. Now let's go a little deeper. One of the most
common types of blocks used to build C++ programs are functions.

If you associate a function with mathematics, you’re on the right track. Imagine a function as a black
box, where you can insert something into it (though this is not always necessary) and take
something new out of it, as if from a magic hat. Things to be put into the box are called function
arguments. Things to be taken out of the box are called function results. In addition, a function
can do something else on the side.

If this sounds rather vague, don't worry, we’ll talk about functions many times and in much more
detail later.
Back to our program. The standard of the C++ language assumes that among many different blocks
that may be put into a program, one specific block must always be present, otherwise the program
won't be correct. This block is always a function with the same name: main .

Every function in C++ begins with the following set of information:

 what is the result of the function?


 what is the name of the function?
 how many arguments does the function accept and what are their names?

Take a close look at our program and try to read it properly, accepting the fact that you won’t yet fully
understand everything.

 the result of the function is an integer value (we can read it from the word int , which is
short for integer)
 the name of the function is main (we know why already)
 the function doesn't require any arguments (what we can deduce from the absence of
anything between parentheses).

This set of information is sometimes called a prototype, and it’s like a label affixed to a function
announcing how you can use that function in your program. The prototype says nothing about what
the function is intended to do. It’s written inside the function and the interior of the function is called
the function body. The function body begins with the first opening bracket { and ends with the
corresponding closing bracket } . It might sound surprising, but the function body can be empty,
which means that the function does exactly nothing.

We can even create a function that is lazy – it can be encoded like this:

void lazy() { }

The word void put in front of function's name ( main ) instructs the compiler that the function
provides no result. Indeed, laziness rarely has utilizable results so don't be surprised.

Summing up, this drone produces no result (in other words, result is void), its name is "lazy", it
doesn't take any arguments (there is nothing between parentheses) and it does absolutely nothing
(there is nothing between brackets).

By the way, the names of the functions are subject to some fairly rigid constraints. More on this later.

TIME MACHINE
It's worth to mention that previous versions of C++ preferred to use somewhat different notation to
declare the fact that a particular function (including main) doesn't accept any arguments. This is how
it looked:

int main(void) {}

Note the void put inside the parentheses. Such a convention derived from C language where the
clause () had definitely different meaning. We prefere not to stay in the past so you won't
see void in this role in our snippets.
Inside the main function body we need to write what our function (and thus the program) is supposed
to do. If we look inside, we find a reference to a block named cout .

Firstly, note the semicolon at the end of the line. Each instruction (more precisely, each statement)
in C++ must end with a semicolon – without it the program will be incorrect.

This particular statement says: instruct the entity named cout to show the following text on the
screen (as indicated by the << digraph, which specifies the direction in which the text is sent). You
might ask – how do we know that cout will do that for us? Well, we know it because it says so in the
C++ language standards.

The cout entity (in fact, it's an object, but we don't want to bring up this word too soon – more on it
later) must be fed with something that is intended to be shown on the screen. In our example, the
feed is just text (string). For simplicity, we can assume that strings in the program in C++ are always
enclosed in quotes – that way the compiler recognizes the text that is sent to the user of the
program, and the text that is intended to be compiled is translated into machine language. This
distinction is very important. Take a look:

int main();

The line above is the main function prototype (i.e. a hint saying what can we expect from a
particular function).

"int main();"

The line above is not the main function prototype, but a string that only looks like part of a source
code. The compiler is not interested in what is between the quotes, and therefore doesn’t recognize
such strings as code.

How does it work? We can picture it like this: the execution of our main function is suspended (we
can say that the main function falls asleep) and during that time cout , together with << (this kind of
symbol is named operator) prints the text on the screen. When the text is printed, the main function
wakes up and continues its activity.

The above form of source code is the most natural and perhaps the most easily read by humans, but
you’re still free to write it in a different way. For example:

cout
<<
"It's me, your first program."
;

We’re almost at the end now. There’s only one line left in our program. This is:

return 0;
This is another (beside the function invocation) statement of the C++ language. Its name is
just return and that’s what it does. Used in the function, it causes the end of function execution. If
you perform return somewhere inside a function, this function immediately interrupts its execution.

The zero after the word return is a result of your function main . It's important - this is how your
program tells the operating system the following: I did what I had to do, nothing prevented me from
doing this, and everything is okay.

If you were to write:

return 1;

this would mean that something had gone wrong, it did not allow your program to be performed
successfully and the operating system could use that information to react appropriately.

Usually, if a function declares itself as a integer value provider (like our main function) it's obliged to
contain the return statement while the return statement is obliged to return an integer value.
Expect compilation error if you don't see to it. It seems to be clear, doesn't it? It's not fair to promise
a value and to break faith (it's not just about functions).

However, the main function is exceptional. It must be declared as int but doesn't have to return it.
Sounds weird? Absolutely! Moreover, if there is no return statement inside the main function,
compiler assumes that return 0 has been implicitly used. Sounds weirder? Not at all - thanks to
that you don't have to make additional efforts if you're going to point that execution of your code
terminated successfully.

Of course, it's a matter of taste in a measure. We definitely prefer to use return in main . Your
preferences may be different.

So is that all? Yes, that’s it! Let's look again at our program and see what’s happening step by step:

 we introduced the function named main into our program - it will be executed when you start
the program;
 we made use of an entity named cout inside the main function - it will print the text on the
screen;
 the program finishes immediately after printing, indicating that everything you expected to
achieve has been achieved.

So hopefully it wasn’t as difficult as it seemed at first glance. Now let’s try to persuade the computer
to compute something for us – after all, that’s what they’re for.

In the C++ language it isn’t necessary to write just one statement per line. You can place two (or
more) statements on the same line, or split one statement into several lines, but bear in mind
that readability (for humans) is a very important factor. However, compilers, unlike humans, will
never complain about your style.

Numbers and how computers see them


Do you know how computers perform calculations on numbers? Maybe you've heard of
the binary system and know that it’s the system computers use for storing numbers
and that they can perform any operation upon them. We’re not going to go the
intricacies of positional numeral systems here, but we will say that the numbers handled
by modern computers are of two types:

 integers, that is, those which are devoid of the fractional part;
 floating-point numbers (or simply floats), that contain (or are able to contain)
the fractional part.

This definition is quite simplistic, but good enough for our purposes. This distinction is
very important and the boundary between these two types of numbers is very strict.
Both of these kinds of numbers significantly differ in how they are stored in a computer
memory and in the range of acceptable values. Additionally, the characteristic of a
number which determines its kind, range and application is called type.

So now we know two types of the C++ language – an integer type (known as int ) and a
floating point type (known as float ).

For now, let's leave the floating-point numbers aside (that’s right: more on them later)
and let’s consider a question that’s maybe a bit banal at first glance: how does the C++
language recognize the integers?

Well, it’s almost the same as when you write them on a piece of paper – they’re simply
a string of digits that make up a number. But there’s a catch – you can’t include any
characters that are not digits inside the number. There is only one exception to the rule:
if you think that the number contains so many digits that it becomes ambiguous, you
can insert as many single quotes (apostrophes) inside the number. These quotes don't
change the number's value and compiler ignores them completely.

TIME MACHINE
Using single quotes as separators enhancing integer numbers readability have been
introduced in C++17 - don't be surprised if an older compiler rejects such a notation

Take for example the number eleven million one hundred and eleven thousand one
hundred and eleven. If you took a pencil in your hand right now, you would probably
write the number like this:

11,111,111

or (if you are a Pole or a German) like this:

11.111.111

or even like this:

11 111 111

For sure, this makes it easier to read if the number consists of many digits. However,
C++doesn’t like this at all. You have to write this number as follows:
11111111

or - if you want your number to be extremely legible - you can write it down as:

11'111'11

If you don’t, the compiler will shout at you. And how do you code negative numbers in
C++? As usual, by adding a minus. You can write:

-11111111

Positive numbers don’t need to be preceded by the plus sign, but you can do it if you
want. The following lines describe the same number:

+123

123

For now we’ll deal only with integers – we’ll introduce floating-point numbers very soon.

There are three additional conventions, unknown to the world of mathematics. The first
of them allows us to use the numbers in an octal representation. If an integer number
is preceded by the 0 digit, it will be treated as an octal value. This means that the
number must contain digits taken from the 0 to 7 range only.

0123

is an octal number with a (decimal) value equal to 83.

The second allows us to use hexadecimal numbers. Such number should be preceded
by the prefix written as 0x or 0X .

0x123

is a hexadecimal number with the (decimal) value equal to 291 .

The third allows us to introduce binary numbers which are preceded by the prefix
written as 0b or 0B .

0B1111

is a binary number equal to decimal value 15 .


A variable is variable
So the C++ language allows us to write numbers. It probably won't surprise you that we
can do some arithmetic operations with these numbers too: add, subtract, multiply and
divide. Contain your excitement – we’ll be doing that soon enough. But it’s quite normal
to ask how to store the results of such operations in order to use them in other
operations. There are special "containers" for that purpose and these containers are
called variables. As the name variables suggests, the content of a container can be
varied in (almost) any way.

What does every variable have?

 a name;
 a type;
 a value;

Let's start with the issues connected with a variable’s name. Variables don’t magically
appear in our program. We (as developers) decide how many, and which variables, we
want to have in our program. We also give them their names, almost becoming their
godparents. If you want to give a name to the variable, you have to follow some strict
rules:

 the name of the variable must be composed of upper-case or lower-case


Latin letters, digits and the character _ (underscore);
 the name of the variable must begin with a letter;
 the underline character is a letter (strange but true);
 upper- and lower-case letters are treated as different (a little differently than in
the real world – Alice and ALICE are the same given names but they are two
different variable names, consequently, two different variables);

These same restrictions apply to all entity names used in C++

The standard of the C++ language does not impose restrictions on the length of
variable names, but a specific compiler may have a different opinion on this matter.
Don't worry; usually the limitation is so high that it’s unlikely you would actually want to
use such long variable names (or functions).
Here are some correct, but not always convenient variable names:

 variable
 i
 t10
 Exchange_Rate
 counter
 DaysToTheEndOfTheWorld
 TheNameOfAVariableWhichIsSoLongThatYouWillNotBeAbleToWriteItWithoutMista
kes
 _

The last name may be ridiculous from your perspective, but your compiler thinks it’s
just great.

And now some incorrect names:

 10t (does not begin with a letter)


 Adiós_Señora (contains illegal characters)
 Exchange Rate (contains a space)

You can find more information about C++ naming style and conventions in the C++
Core Guidelines.

The type is an attribute that uniquely defines which values can be stored inside the
variable. We’ve already encountered the integer ( int ) and floating point ( float ) types.
The value of a variable is what we have put into it. Of course, you can only enter a value
that is compatible with the variable’s type. Only an integer value can be assigned to an
integer variable (or in other words, to a variable of type int ). The compiler will not allow
us to enter a floating-point number here.

Let's talk now about two important things – how the variables are created and how to
enter a value inside them (or rather – how to give them a value).

The variable exists as a result of a declaration. A declaration is a syntactic structure


that binds a name provided by the programmer with a specific type offered by the C++
language. The construction of such a declaration (or the declaration syntax) is simple:
just use the name of the desired type, then the variable name (or variable names
separated by commas if there are more than one). The whole statement ends with a
semicolon.

Let's try to declare a variable of type int named counter. The relevant portion of the program looks
like this:

int counter;

What is declared by the following fragment of a program?

int variable_1, account_balance, invoices;

It declares three variables of type int named


(respectively) variable_1 , account_balance and invoices .

Remember that you are allowed to use as many variable declarations as you need to achieve
your goal.

And how do we give a value to the newly declared variable? You need to use the so-
called assignment operator. Although this sounds rather mysterious, the operator has a simple
syntax and unambiguous interpretation. The assignment operator looks very familiar – here it is:

Let's look at some examples:

counter = 1;

The above statement says: assign a value of 1 to a variable named counter or a bit shorter assign 1
to counter.

Some programmers use a different convention and read such a statement as: counter becomes 1.

It's worth to mention now that you're are allowed and even encouraged to place the variable
declaration and its first assignment in the same place. Look: a piece of code like this:

int variable;
variable = 1;

can be compacted into the following form:

int variable = 1;

Such a solution shows some important advantages. The most valuable is that declaring variable with
immediate assigning it with its initial value is less error-prone than performing these two activities in
two different places. The code is more legible, programmer's intentions are better recognizable and if
you're used to declare and initialize variable in one step you minimize the risk of use an uninitialized
variable. This is why we prefer such declarations in our code.

As usual on such occasions, a new word arrives into our vocabulary: the part of the declaration
placed on the right side of the = sign is called an initiator.

The initiator you saw before was a simple value, but you can also use more complex expressions,
like the one below.

int twosquared = 2 * 2;

We’ll be using initiators often. They’re extremely convenient, quite useful and can be applied to
virtually all C++ data types.

Another assiagnment example:

result = 100 + 200;

In this case, the new value of the variable result will be the result of adding 100 to 200, but you
probably already guessed that, right?

And now a slightly more difficult example:

x = x + 1;

Seeing that, a mathematician would probably protest – no value may be equal to itself plus one. This
is a contradiction.
But in the "C" language the sign "=" does not mean is equal to, but assign a value.

So how do we read such a record in the program?

Take the current value of the variable x, add 1 to it and store the result in the variable x

In effect, the value of variable x was incremented by one, which has nothing to do with comparing
the variable to any value.

Keywords – why they are the keys?


Take a look at the right side of the screen – you’ll see a list of words that play a very special role in
every C++ language program. They are called keywords or (more precisely) reserved keywords.
They are reserved because you can’t use them as names: neither for your variables, nor for your
functions or any other named entities you want to create. The meaning of the reserved word is
predefined and can’t be changed in any way.

TIME MACHINE
Don't be surprised by the fact that each C++ version uses different set of keywords. As you probably
suspects, the list grows with each new C++ standard. The list you see comes from C++17 and some
of the keywords aren't present in earlier releases.

Fortunately, because the C++ compiler is case-sensitive, you can modify any of these words by
changing the case of any letter, thus creating a new word, which is not reserved any more.

For example - you can't do this:

int int;

You can’t have a variable named int - it’s prohibited. But you can do this instead:

int Int;

The compiler will be happy, very happy although it's worth to emphasize that using names similar to
keywords may leads to troublesome misunderstandings. Moreover, names starting with capital
letters may have very specific meanings and in general, are not recommended for naming creations
as simple as int variables. Think twice and judge for yourself whether such a name won't look better:

int int_value;
omments on the comments
Now we’re going to make some comments. We don't mean comments on either your
achievements or our achievements, although we’re sure you have many achievements
to be proud of. We’re referring to other comments, namely comments on the program
and inside the program at the same time.

The developer may want to add a few words addressed not to the compiler but to
humans, usually to explain to other readers of the code how the tricks used in the code
work, or the means of variables and functions, and possibly, to store information on who
the author is and when the program was written.

Good and responsible developers describe each newly created important entity; in
particular, explaining the role of the parameters and the values modified or returned as
results, as well as explaining what the code actually does.

How do we leave something like this in the source code? We have to do it in a way that
won't force the compiler to interpret it as part of the code. The remark inserted into the
program, which is omitted at the time of compiling, is called a comment.

If we want to be precise, we should say that each comment is lexically equivalent


to one space. Whenever the compiler encounters a comment in your program, the
comment is completely transparent to it - from its point of view this is only one space
(regardless of how long the real comment is).

The C++ language supports two ways of inserting comments:

// comment - single-line comments

and

/* comment */ - block comments (also knows as C-style comments due to fact that
they are in use since the very beginning of the C programming language, the C++
progenitor).

A single-line comment discards everything from where the pair of slash signs ( // ) is
found up to the end of that same line.

In the C++ language a block comment is a text that begins with a pair of the following
characters:

/*

and ends with a pair of the following characters:

*/

The comment can span several lines or can occupy only one line or part of a line.

Here you can see an example in which everything from the pair of slash signs on is
ignored by the compiler. The single-line comment can start anywhere on the line. This
could be a blank line too, with no content at all.

int counter; // counts the number of sheep in the meadow

Look at the snippet below. Here you can see an example of a similar comment, but
introduced into the code using the second method.

Any new developer reading the program will be aware of the true meaning of the
variable. The developer will read the code faster and it’ll take less time to understand it.

/* the counter variable counts the number of sheep in the meadow */


int counter;

Developers often place a note at the beginning of the source informing when they write
the program stating who amended it and why. The note may appear like this:

/* ************************************************************
Counting sheep version 1.0
Author: Ronald Sleepyhead, 2012
email: [email protected]
Changes:
2012-09-13: Ginny Drowsy: counting black sheep improved
************************************************************ */

Note that, despite the complicated structure and the multitude of stars, the condition
stating how the comment should be started and finished is fully met.

Comments may be useful in another respect - you can use them to mark a piece of
code that you currently don’t need for whatever reason. We often do this during the
testing of the program in order to isolate the place where an error could be hidden.

We’ve just got one more thing to say about comments. Compilers differ in assessing
whether another comment may be placed within a single comment. Consider the
following program:

/* int i; /* int j; */ int k; */

The question is: are you allowed to nest one block comment (like /* int j; */ ) inside
another block comment?

The answer is no. Such a notation may not be accepted by a particular compiler and in
effect makes our code prone to compiler's whims - we don't want to rely on uncertain
assumptions.

We strongly discourage you from use such a construction in your code even if your
compiler seems to be indifferent to it.

Floating-point numbers
A word (or 2.0 words) about floating-point numbers in real life and in the C++ language.

Previously, we became acquainted with the concept of data type, and learned that one
of the basic types known in the C++ language is the integer type named int. Now it's
the time to talk about another type, designed to represent and store the numbers that
(as a mathematician would say) have a non-empty decimal fraction.

These are the numbers that have (or may have) a fractional part after the decimal
point, and although this is a very simplistic definition, it is sufficient for our purposes.
Whenever we use a term like "two and a half" or "zero point four" we think of numbers
which the computer considers to be floating numbers.
Let's go back to the values we quoted a moment ago. "Two and a half" looks normal
when you write it in a program, although if your native language uses a comma instead
of a point in the number, you should make sure that your number contains points
and not commas. The compiler will either not accept it or (in very rare circumstances)
will misunderstand your intentions, as the comma itself has its own reserved meaning in
the C++ language.

If you want to use a value of just "two and a half", you should write it as shown here:

2.5

Note once again – there is a point between "2" and "5" - not a comma.

As you can probably imagine, you can write the value of "zero point four" in C++ as:

.4

Don’t forget this simple rule – you can omit zero when it’s the only digit in front of or
after the decimal point. In essence you can write the value 0.4 like on the right.

For example: the value of 4.0 could be written as 4. without changing its type or value.

Note: the decimal point is essential to recognize floating-point numbers in C++. Look at
these two numbers:

4
4.0

You might think that they’re exactly the same, but the C++ compiler sees them
completely differently:

4 is an int.
4.0 is a float.

We can say that the point makes a float. Don't forget that.

When you want to use any numbers that are very large or very small, you can use so-
called scientific notation. Take, for example, the speed of light expressed in meters
per second. Written directly it would look like:

300000000.

As you probably suspect, you're also allowed to write the value in a more legible form:
300'000'000.

as the single quotes can be used inside floats either.

To avoid the tedious job of writing of so many zeros, physics textbooks use an
abbreviated form, which you’ve probably seen already:

3 • 108

It reads: "three times ten to the power of eight"

In the C++ language, the same effect is achieved in a slightly different form – take a
look:

3E8

The letter E (you can also use the lower case letter e – it comes from the word
exponent) is a concise version of the phrase "times ten to the power of".

Note:

 the exponent (the value after the "E") has to be an integer.


 the base (the value in front of the "E") may or may not be an integer; in other
words, not only dot makes float - E (even alone) can do it too.
 Let's see how we use this convention to record numbers that are very small (in
the sense of their absolute value, which is close to zero). A physical constant
called Planck's constant (and denoted as h) has, according to the textbooks, the
value of:
 6.62607 x 10-34
 If you would like to use it in a program, you would write it this way:
 6.62607E-34
 And that’s it. Not so hard, right?


 Let's go back to the floating-point values. We already know what a variable is,
and we also know how to declare an integer variable, so now it’s time to declare
variables of a floating-point type.
 We do this using the keyword float . Knowing that we can declare two floating-
point variables, named PI (we can't name it Π because - as you already know -
the C++ language freaks out when variable names are written with Greek
letters) and Field :
 float PI, Field;
 As you can see, the difference in declaring the integer and float variables is quite
small from the syntax's point of view.

 This difference in terms of semantics is significant, as you can see in the example
below. With a little thought, we can figure out that the symbol (more precisely -
the operator) that performs the mathematical division is a single
character / (slash). Take a look at the code:
 int i = 10 / 4;
 float x = 10.0 / 4.0;
 It might be a bit surprising for you to know that the value that will be entered in
the variable i is 2 (yes - just 2 !) while the variable x will be equal to 2.5 . Look at
the example carefully, because it illustrates a very important difference between
these two data types.
 What happens when we have to convert integer values into float values or vice
versa? We can always transform from int into float , but it can lead to a loss of
accuracy. Consider the example below:
 int i = 100;
 float f = i;
 After changing from int to float , the value of the variable f is 100.0 , because
the value of type int ( 100 ) is automatically converted into a float ( 100.0 ).
 The transformation affects the internal (machine) representation of those values
as computers use different methods for storing floats and ints in their
memory.

 Let's consider the opposite situation now.


 As you’ve probably guessed, these substitutions will result in a loss of accuracy -
the value of the variable i will be 100 . Twenty-five hundredths has no meaning
in the ints world. Furthermore, converting a float into an int is not always
feasible.
 float f = 100.25;
 int i = f;
 Integer variables (like floats) have a limited capacity. They cannot contain
arbitrarily large (or arbitrarily small) numbers.
 For example, if a certain type of computer uses four bytes (i.e. 32 bits) to store
integer values, you can only use the numbers from the range of -
2147483648 to 2147483647.
 Let's consider the following snippet:
 float f = 1E10;
 int i = f;
 The i variable is unable to store such a large value, but it isn’t clear what will
happen during the assignment. Certainly a loss of accuracy will occur, but the
value assigned to the variable i is not known in advance.
 In some systems it may be the maximum permissible int value, while in others
an error occurs, and in others still the value assigned can be completely random.
 This is what we call an implementation dependent issue. It's the second (and
uglier) face of software portability.

Operators
An operator is a symbol of the programming language, which is able to operate on the
values. For example, an assignment operator is the = sign. We already know that it
can assign values to variables.

Now let’s look at some other operators available in the C++ language and find out
which rules govern their use and how to interpret the operations they perform. Let’s
begin with the operators associated with widely recognizable arithmetic operations. The
order of their appearance is not accidental. We’ll talk more about this afterward.
Multiplication
An asterisk * is a multiplication operator. If you take a look at the code here, you’ll
see that the variable k will be set to the value of 120 , while the z variable will be set
to 0.625 .

int i = 10, j = 12;

float x = 1.25, y = 0.5;

int k = i * j;

float z = x * y;

Division
A slash (" / ") is a divisional operator. The value in front of the slash is a dividend, the
value behind the slash, a divisor. Look at the snippet of the program below: of
course, k will be set to 2 , z to 0.5 .

int i = 10, j = 5;

float x = 1.0, y = 2.0;

int k = i / j;

float z = x / y;

Division by zero
As you’ve probably guessed, dividing by zero is strictly forbidden, but the penalty for
violating that rule will come to you at different times.

float x = 1.0 / 0.0;

If you dare to write something like that, the compiler will go nuts – you’ll get a
compilation error, runtime error or some message at runtime, possibly also a few choice
words about your programming capabilities. OK, the last one was a joke. Still, in some
cases you won't be able to run your program. As a general rule, you shouldn't divide by
zero.

In the following example the compiler won't tell you a thing, but when you try to
execute that code, the result of the operation may be surprising. It’s not a number. It’s
a special featured value named inf (as in infinitive). Generally, this kind of illegal
operation is a so-called exception.

float x = 0.0;

float y = 1.0 / x;

When you find exceptions in your program, you should react accordingly. We’ll discuss
this later.

Addition
The addition operator is the " + " (plus) sign, which most of us already know from maths
class. Again, take a look at the snippet of the program – as you can surmise, k is equal
to 102 and z to 1.02 .

int i, j, k;

float x, y, z;

i = 100; j = 2;

k = i + j;

x = 1.0; y = 0.02;

z = x + y;

Subtraction
The subtraction operator is obviously the " - " (minus) sign, although you should note
that this operator also has another meaning – it can change the sign of a number. This
is a good time to show you a very important distinction
between unary and binary operators (in the C++ language there is also a ternary
operator – more on that a bit later).

As usual, let’s get acquainted with a snippet of the program – you can guess that k will
be equal to -100 , while z will be equal to 0.0 .

int i, j, k;

float x, y, z;

i = 100; j = 200;
k = i - j;

x = 1.0; y = 1.0;

z = x - y;

Unary minus
In "subtracting" applications, the minus operator expects two arguments: the left
(a minuend in arithmetic terms) and the right (a subtrahend). For this reason, the
subtraction operator is considered one of the binary operators, just like the addition,
multiplication and division operators. But the minus operator may be used in a different
way – take a look at the snippet.

int i = -100;

int j = -i;

As you’ve probably guessed, the variable j will be assigned the value of 100 . We used
the minus operator as a unary operator, as it expects only one argument – the right
one.

Unary plus
The same dual nature is expressed by the " + " operator, which can be also used as a
unary operator – its role is to preserve the sign. Take a look at the snippet.

int i = 100;

int j = +i;

Although such a construction is syntactically correct, using it doesn’t make much


sense and it would be hard to find a good rationale for doing so.

Remainder
The remainder operator is quite peculiar, because it has no equivalent among traditional arithmetic
operators.

Its graphical representation in the C++ language is the % (percent) character, which may look a bit
confusing, although you have to admit that its appearance resembles the / operator which is
responsible for the division while finding the remainder forces the computer to perform a division.

% a binary operator (it performs the modulo operation) and both arguments cannot be floats (don't
forget that!). Look at the example:
int i = 13;

int j = 5;

int k = i % j;

The k variable is set to the value of 3 (because 2 * 5 + 3 = 13).

Oh, and one more thing you need to remember: you cannot compute the remainder with the
right argument equal to zero. Can you guess why? Click Check below to see if you were right:

Check

You probably remember what we said earlier about dividing by zero. And because
division by 0 invokes undefined behaviour, the modulo operation, which relies on
division, is undefined, too.
Well, that’s what the C++ Standard says. We have to accept that.

Priorities
So far, we’ve treated each operator as if it had no connection with the others. Of course,
in real programming, nothing is ever as simple as that. Also, we very often find more
than one operator in an expression and then things can get complicated very quickly.
Consider the following expression:

2 + 3 * 5

If your memory hasn't failed you, you should remember from school that multiplications
precede additions. You probably remember that you have to multiply 3 by 5 , keep
the 15 in your memory, add it to 2 , thus getting the result of 17 .

The phenomenon that causes some operators to act before others is known as
the hierarchy of priorities. The C++ language precisely defines the priorities of all
operators and assumes that operators of larger (higher) priority perform their
operations before the operators with lower priority.

So if we know that * has a higher priority than + , we can figure out how the final result
will be computed.

Bindings
The binding of the operator determines the order of computations performed by some
operators with equal priority, put side by side in one expression. Most operators in the
C++ language have the left-sided binding, which means that the calculation of this
sample expression is conducted from left to right, i.e. 3 will be added to 2 , and 5 will be
added to the result.
2 + 3 + 5

Now at this point you might be snorting and saying that all children know perfectly well
that addition is commutative and it doesn’t matter in which order the additions are
performed. And yes, you're right, but not quite. Additions performed by the computer
are not always commutative. Really. We’ll show you this in more detail later. But for
now, be patient and trust us.

Priorities
Since you're new to C++ language operators, presenting a complete list of operators'
priorities may not be a good idea. Instead, we’ll show you its truncated form, and we’ll
expand on it consistently during the introduction of new operators.

This table now looks as follows:

+- unary

*/%

+- binary

Note: we’ve gone through the operators in order from the highest to the lowest
priority.

We want to check if you understand the concept of binding. Try to work through the
following expression:

2 * 3 % 5

Both operators ( * and % ) have the same priority, so the result could be guessed only
when you know the binding direction.

Do you know the result? Click Check below to see if you were right:

Check
1

Yes, the result is 1. Congratulations!

Parentheses
Of course, we’re always allowed to use parentheses, which can change the natural
order of calculation. Just like with arithmetic rules, subexpressions in parentheses
are always calculated first. You can use as many parentheses as you need and we
often use them to improve the readability of an expression, even if they don't change
the order of operations.

An example expression involving multiple parentheses is given below. Try to compute


the value given to the l variable.

int i = 100;

int j = 25;

int k = 13;

int l = (5 * ((j % k) + i) / (2 * k)) / 2;

Click Check below to see if you were right:

Check
10

Yes, it's 10.

Operators continued
Here are some operators in the C++ language which you won’t find in maths textbooks.
Some of them are frequently used to increment a variable by one. This is often done
when we’re counting something (e.g. sheep). Let's consider the following snippet:

int sheep_counter = 0;

Every time a sheep runs through our thoughts we want the variable to be incremented,
like this:

sheep_counter = sheep_counter + 1;

Similar operations appear very frequently in typical programs, so the creators of the C+
+ language introduced a set of special operators for these actions. One of them is the +
+ (plus plus) operator. You can achieve the same effect in a shorter way:

sheep_counter++;

It looks much more elegant now, doesn't it?

Similarly, you can also decrease the value of a chosen variable. For example, if we can
hardly wait for our holiday, our mind does the following operation every morning:
days_until_holiday = days_until_holiday - 1;

We can write it in a more compact way:

days_until_holiday--;

Sorry, but now we have to introduce a few new words.

The " ++ " is called the increment operator.

The " -- " is called the decrement operator.

We’ve shown you the ++ and -- operators after a variable (a specialist in the syntax of
programming languages would say that they’re used as postfix operators). However,
both operators can be placed in front of a variable as well (as prefix operators), like this:

++sheep_counter;

--days_until_holiday;

The effect will be exactly the same: sheep_counter will be increased by


1, days_until_holiday decremented by 1. There’s a fairly significant difference,
however, which is described by the precise names of these operators.

Here they are.


That may seem a little weird to you, but it’ll only take a short time to understand. Let's
discuss the effects of these operators.

Operation:

++variable

--variable

Effect:

Increment/decrement the variable by 1 and return its value already increased/reduced.

Operation:

variable++

variable--

Effect:

Return the original (unchanged) variable's value and then increment/decrement the
variable by 1.

This behavior justifies the presence of the prefix pre- (before) and post- (after) in the
operators’ names: pre- because the variable is modified first and then its value
is used; post- because the variable's value is used and then modified.

Pre-and post-operators and their priorities


Take a look at two simple examples.

int i = 1;
int j = i++;

First, the variable i is set to 1 . In the second statement, we’ll see the following steps:

 the value of i will be taken (as we use the post-incrementation);


 the variable i will be increased by 1 .

In effect, j will receive the value of 1 and i the value of 2 .


Things go a bit differently here.

int i = 1;
int j = ++i;

The variable i is assigned with the value of 1 ; next, the i variable is incremented and is
equal to 2 ; next, the increased value is assigned to the j variable.

In effect, both i and j will be equal to 2 .

Look carefully at this program. Let’s trace its execution step by step.

int i = 4;
int j = 2 * i++;
i = 2 * --j;
1. The i variable is assigned the value of 4 ;
2. We take the original value of i ( 4 ), multiply it by 2 , assign the result ( 8 ) to j and
eventually (post-)increment the i variable (it equals 5 now);
3. We (pre-)decrement the value of j (it equals 7 now); this reduced value is taken
and multiplied by 2 and the result ( 14 ) is assigned to the variable i .

What else do you need to know about the new operators? Firstly, their priority is quite
high – higher than the * , / and % operators. Secondly, their binding depends on
whether you use the prefix or postfix version. The prefix version operators have a right-
to-left binding, while the postfix operators bind from left to right.

Our priority table now reads as follows:

++ -- + - unary
*/%
+- binary
=

Shortcut operators
Now it's time for the next set of operators, ones that make a developer's life easier. The
one’s we’ve already described deal with addition and subtraction of one.

i = i * 2;
However, we often need something other than addition or subtraction, or we want to
use a different value; we can use this operator when we want to calculate a series of
successive values of powers of 2.

Here’s another example. We use this expression when our herd is extremely numerous:

sheep_counter = sheep_counter + 10;

In the C++ language there is a short way to write these operations. You can write them
as follows:

i *= 2;

sheep_counter += 10;

Let's try to present a general description for such operations. If op is a two-argument


operator (this is a very important condition!) and the operator is used in the following
context:

variable = variable op expression;

then this expression can be simplified as follows:

variable op= expression;

Take a look at the examples here:


Make sure you understand them all. And relax, because we still have a lot of work
ahead.

Character type
So far we have treated the C++ language (and the computer itself) as a tool for
performing calculations on numbers. This is consistent with a common belief that a
computer is just a calculator, albeit a very smart one. You know it’s not true, as the
computer can be easily used for word processing, too.

We can define a word as a string of characters (letters, numbers, punctuation marks,


etc.). We dealt with such strings in the first lesson when we used cout to write some
text on the computer screen.

Now, however, we’ll ignore the string consisting of multiple characters and we’ll focus
our attention on single characters. We’ll come back to the problem of processing strings
when we start working on arrays, because in the C++ language strings behave in a very
similar way.
To store and manipulate characters, the C++ language provides a special type of data.
This type is called char , which is an abbreviation of the word character and according
to Bjarne Stroustrup's hint should be pronounced as "tchar", not "kar".

Let's try to declare a variable for storing a single character.

char character;

Looks familiar, doesn't it? Now let's talk a bit about how computers store characters.

ASCII code

Computers store characters as numbers. Every character used by a computer


corresponds to a unique number, and vice versa. This system of assignments includes
more characters than you would probably expect. Many of them are invisible to humans
but essential for computers. Some of these characters are called white spaces, while
others are named control characters, because their purpose is to control the
input/output devices. An example of a white space that is completely invisible to the
naked eye is a special code, or a pair of codes (different operating systems may treat
this issue differently), which are used to mark the ends of lines inside text files. People
don’t see this sign (or these signs), but they can see their effect where the lines are
broken.

We can create virtually any number of assignments, but a world in which each computer
type uses different character encoding would be extremely inconvenient. This has
created a need to introduce a universal and widely accepted standard implemented by
(almost) all computers and operating systems all over the world. ASCII (which is a short
for American Standard Code for Information Interchange and is usually probounced
as "ASS-kee") is the most widely used system in the world, and it’s safe to assume that
nearly all modern devices (like computers, printers, mobile phones, tablets, etc.) use
this code. The code provides space for 256 different characters, but we’re only
interested in the first 128. If you want to see how the code is constructed, go to the
table on the right.

Look at it carefully – there are some interesting facts about it that you might notice.
We'll show you one. Do you see what the code of the most common character is – the
space? Yes – it’s 32. Now look at what the code of the lower-case letter “a” is. It’s 97,
right? And now let's find the upper-case “A”. Its code is 65. What’s the difference
between the code of “a” and “A”? It’s 32. Yes, that's the code of a space. We’ll use that
interesting feature of the ASCII code soon.

Also, note that the letters are arranged in the same order as in the Latin alphabet.

By the way, ASCII code is being superseded (or rather extended) by a new international
standard named UNICODE.

Fortunately, the ASCII set is a UNICODE subset. UNICODE is able to represent virtually
all characters used throughout the world. We’ll spend a little more time on this later.

Character Dec Hex Character Dec Hex Character Dec Hex Character Dec Hex

(NUL) 0 0 (space) 32 20 @ 64 40 ` 96 60

(SOH) 1 1 ! 33 21 A 65 41 a 97 61

(STX) 2 2 " 34 22 B 66 42 b 98 62

(ETX) 3 3 # 35 23 C 67 43 c 99 63

(EOT) 4 4 ($) 36 24 D 68 44 d 100 64

(ENQ) 5 5 % 37 25 E 69 45 e 101 65

(ACK) 6 6 & 38 26 F 70 46 f 102 66

(BEL) 7 7 ' 39 27 G 71 47 g 103 67

(BS) 8 8 ( 40 28 H 72 48 h 104 68

(HT) 9 9 ) 41 29 I 73 49 i 105 69

(LF) 10 0A * 42 2A J 74 4A j 106 6A

(VT) 11 0B + 43 2B K 75 4B k 107 6B

(FF) 12 0C , 44 2C L 76 4C l 108 6C

(CR) 13 0D - 45 2D M 77 4D m 109 6D
(SO) 14 0E . 46 2E N 78 4E n 110 6E

(SI) 15 0F / 47 2F O 79 4F o 111 6F

(DLE) 16 10 0 48 30 P 80 50 p 112 70

(DC1) 17 11 1 49 31 Q 81 51 q 113 71

(DC2) 18 12 2 50 32 R 82 52 r 114 72

(DC3) 19 13 3 51 33 S 83 53 s 115 73

(DC4) 20 14 4 52 34 T 84 54 t 116 74

(NAK) 21 15 5 53 35 U 85 55 u 117 75

(SYN) 22 16 6 54 36 V 86 56 v 118 76

(ETB) 23 17 7 55 37 W 87 57 w 119 77

(CAN) 24 18 8 56 38 X 88 58 x 120 78

(EM) 25 19 9 57 39 Y 89 59 y 121 79

(SUB) 26 1A : 58 3A Z 90 5A z 122 7A

(ESC) 27 1B ; 59 3B [ 91 5B { 123 7B

(FS) 28 1C < 60 3C \ 92 5C | 124 7C

(GS) 29 1D = 61 3D ] 93 5D } 125 7D

(RS) 30 1E > 62 3E ^ 94 5E ~ 126 7E

(US) 31 1F ? 63 3F _ 95 5F 127 7F

Character type values


How do we use the values of the char type in the C++ language? We can do it in two
ways, which are not entirely equivalent.

The first way allows us to specify the character itself, but enclosed in single
quotes (apostrophes). Let’s assume that we want the variable we declared a few slides
earlier to be assigned the value of the upper-case letter A .

We do this as follows:

character = 'A';
You’re not allowed to omit apostrophes under any circumstances.

Now let’s assign an asterisk to our variable. We do this as follows:

character = '*';

The second method consists of assigning a non-negative integer value that is the
code of the desired character. This means that the assignment below will put an “ A ”
into the character variable.

character = 65;

The second solution, however, is less recommended and if you can avoid it, you should.
Why?

First, because it is illegible. Without knowing the ASCII code, it is impossible to guess
what that “65” really means. Perhaps this is the code for a character, but it can also
happen that a sociopathic programmer used this devious way to save the number of
already counted sheep.

The second reason is more exotic, but still true. There’s a significant number of
computers in the world which use codes other than ASCII. For example, many of the
IBM mainframes use a code commonly called EBCDIC (Extended Binary Coded Decimal
Interchange Code - we won't dare to instruct you how to pronounce this abbreviation,
sorry) which is very different from ASCII and is based on radically different concepts.
ASCII vs EBCDIC
Now imagine that you’ve written a wonderful program and decided to compile and run it
on a computer utilizing the EBCDIC code. If you wrote something like this, the compiler
running on that computer would notice the question mark and use the appropriate
EBCDIC code for that character.

character = '?';

But if you wrote it like this:

character = 63;

Literal
Now’s probably a good time to bring a new term into the mix: a literal. The literal is a
symbol which uniquely identifies its value. Some prefer to use a different definition:
the literal means itself. Choose the definition that you consider to be clearer and look
at the following simple examples:

 character : this is not a literal; it’s probably a variable name; when you look at it,
you cannot guess what value is currently assigned to that variable;
 'A' : this is a literal; when you look at it you can immediately guess its value; you
even know that it’s a literal of the char type;
 100 : this is a literal, too (of the int type);
 100.0 : this is another literal, this time of a floating point type;
 i + 100 : this is a combination of a variable and a literal joined together with
the + operator; this structure is called an expression.

 If you’re an inquisitive person, you probably want to ask a question: if a literal of


type char is given as the character enclosed in apostrophes, how do we code the
apostrophe itself?

 The C++ language uses a special convention that also extends to other
characters, not only to apostrophes. Let's start with an apostrophe anyway. An
apostrophe looks like this:

 character = '\'';

 The \ character (called backslash) acts as an escape character, because by


using the \ we can escape from the normal meaning of the character that follows
the slash. In this example, we escape from the usual role of the apostrophe (i.e.
delimiting the literals of type char ).

 You can also use the escape character to escape from the escape character.
Yes, it does sound weird, but the example below should make it clear. This is how
we put a backslash into a variable of type char .
 character = '\\';

 Escape characters
 The C++ language allows us to escape in other circumstances too. Let's start
with those that denote literals representing white spaces.

 \n – denotes a transition to a new line and is sometimes called an LF (Line


Feed), as printers react to this character by pulling out the paper by one line of
text.

 \r – denotes the return to the beginning of the line and is sometimes called
a CR (Carriage Return – “carriage” was the synonym of a “print head” in the
typewriter era); printers respond to this character as if they are told to re-start
printing from the left margin of the already printed line.

 \a – (as in alarm) - is a relic of the past when teletypes were often used to
communicate with computers (do you know what a teletype is, are you old
enough to remember them?); sending this character to a teletype turns on its
ringer; hence, the character is officially called BEL (as in bell); interestingly, if
you try to send the character to the screen, you’ll hear a sound – it won't be a
real ringing but rather a short beep. The power of tradition works even in the IT
world.

 \0 (note: the character after the backslash is a zero, not the letter O):
called nul (from the Latin word nullus – none) is a character that does not
represent any character; despite first impressions, it could be very useful, as
we’ll show you in the lessons to come.

 Now we’ll try to escape in a slightly different direction. The first example explains
the variant when a backslash is followed by two or three octal digits (the digits
from the range of 0 to 7). A number coded in this manner will be treated as
an ASCII value. It may look like this:
 character = '\47';
 047 octal is 39 decimal. Look at the ASCII code table and you'll find that this is
the ASCII code of an apostrophe, so this is equivalent to the notation
 '\''
 (but only for computers implementing the ASCII code).
 The second escape refers to the situation when a \ is followed by the
letter X (lower case or upper case – it doesn't matter). In this case there must be
either one or two hexadecimal digits, which will be treated as ASCII code.
Here's an example:
 character = '\x27';
 As you’ve probably guessed, 27 hexadecimal is 39 decimal.

char values are int values


There’s an assumption in the C++ language that may seem surprising at first glance:
the char type is treated as a special kind of int type. This means that:

 You can always assign a char value to an int variable;


 You can always assign an int value to a char variable, but if the value exceeds
255 (the top-most character code in ASCII), you must expect a loss of value;
 The value of the char type can be subject to the same operators as the data of
type int .

We can check this using a simple example. We said earlier that in ASCII, the "distance"
between upper and lower case letters is 32, and that 32 is the code of the space
character. Look at this snippet:

char character = 'A';

character += 32;

character -= ' ';

This sequence of subsequent addition and subtraction will bring the character value to
its original value (" A "). You should be able to explain why, right?

All of these assignments are correct. Try to interpret their meanings – this should be a
good exercise for you.

char character = 'A' + 32;

character = 'A' + ' ' ;

character = 65 + ' ';

character = 97 - ' ';

character = 'a' - 32;


character = 'a' - ' ';
Check the answer
97, 97, 97, 65, 65, 65

Well done! Here are the answers: 97, 97, 97, 65, 65, 65.

One who asks does not err


A programmer writes a program and the program asks questions. A computer executes the
program and provides the answers. The program must be able to react according to the answers it
receives. Fortunately, computers know only two kinds of answer: yes, this is true or no, this is
false. You will never get a response like “I don’t know” or “Probably yes, but I don’t know for sure”.

To ask questions, the C++ language uses a set of very special operators. Let’s go through them one
by one, illustrating their effects using some simple examples.

Question: is x equal to y?
Question: are two values equal?

To ask this question you use the == (equal equal) operator.

Don't forget this important distinction:

 = is an assignment operator
 == is the question “are these values equal?”

It’s a binary operator with a left-side binding. It needs two arguments and checks
if they’re equal. Now let’s ask a few questions. Try to guess the answers.

Is x equal to y?
1. 2 == 2

Check

This question is simple. Of course 2 is equal to 2 . The computer will answer true .

2. 1 == 2

Check

This one’s simple, too. The answer will be false .

3. i == 0
Check

Here we’re not able to find the answer if we do not know what value is currently stored
in variable i . If the variable has been changed many times during the execution
of your program, the answer to this question can be given only by the
computer and only at run time.

Question: is x equal to y?
There’s another developer who counts white and black sheep separately and falls
asleep only when there are exactly twice as many black sheep as white ones. The
question will be as follows:

black_sheep_counter == 2 * white_sheep_counter

Due to the low priority of the == operator, this question shall be treated as equivalent to
this one:

black_sheep_counter == (2 * white_sheep_counter)

Question: is x not equal to y?


To ask this question, we use the != (exclamation equal). It’s a very close relative of
the == operator. It’s also a binary operator and has the same low priority. Imagine that
we want to ask whether the number of days left to the end of the world is currently not
equal to zero:

days_until_the_end_of_the_world != 0

The answer true gives us the chance to go to the theater or to visit our friends.

Question: is x greater than y?


You can ask this question by using the > (greater than) operator. If you want to know
if there are more black sheep than white ones, you can write it as follows. The
answer true confirms the statement; the answer false denies it.

black_sheep > white_sheep

Question: is x greater than or equal y?


The “greater than” operator has another special, non-strict variant, but it’s denoted
differently in classical arithmetic notation: >= (greater than or equal). There are two
subsequent signs, not one. Both of these operators (strict and non-strict), as well as the
other two that we discuss in the next section, are binary operators with left-side
binding, and their priority is greater than the ones indicated by == and != .

If we want to find out whether or not we have to wear a warm hat, we ask the following
question:

centigrade_outside >= 0.0

Question: is x less than (or equal to) y?


As you’ve probably already guessed, the operators we use in this case are: the < (less
than) operator and its non-strict sibling <= (less than or equal). Look at this simple
example: we’re going to check if there’s a risk that we’ll be fined by the highway police
(the first question is strict, the second isn't).

current_velocity < 110

current_velocity <= 110

How to use the answer we got?


The C++ language defines a very special data type designed to store values resulting
from any of the previously presented comparisons. The type is called:

bool

It's name come from the famous English mathematician, George Bool (1815 –1864), the
creator of Boolean algebra, a branch of mathematics devoted to operations on truth
values

The type itself shows many similarities to the previously presented char type. Here are
some of them:

 it's actually an integer type using the minimal storage offered by a computer (it's
one byte usually, just like in the char type);
 it can be assigned with integer values;
 it can participate in any integer evaluations and used in this way behaves like an
ordinary int ;

Along with the bool type there are two literals representing two
possible boolean values - these are:
 false (a boolean equivalent of integer 0 );
 true (a boolean equivalent of integer 1 although is should be mentioned here
that any non-zero integer value is interpreted as true by the C++ language).

Note that all the three presented words are keywords - don't forget about that and
don't blame the compiler when it refuses a declaration of a variable named e.g. true .

How can we use the newly met type? The most obvious answers says that it's an ideal
tool to memorize (store it in a variable) results of comparisons and make use of them
later. How do we do that? Well, we would use an arbitrary variable of type bool , like
this:

int value1 = 0, value2 = 0;

bool answer = value1 >= value2;

If the answer is true because value1 is greater than or equal to value2 , the computer
will assign true to answer (although if you take a look inside the variable, you'll find an
integer 1 ). If value1 is less than value2 , the variable answer will be assigned
with false (actually 0 ).

If you are unsatisfied with information about the logic of computers, we want to
reassure you. We're going to discuss the issue soon. Stay tuned.

TIME MACHINE
The bool type and its two literals are relatively new C++'s components. It's a common
thing to find a code which uses an ordinary integers to achieve the same effects.
Anyway, we prefer to uses bool out of respects for Mr. Bool's achievements and to
increase readability of your code. Follow us, please!

The priority table – an update.


The second possibility is more convenient and far more common: we can use the
answer to make a decision about the future of our program. We use a special instruction
for this purpose and we’ll tell you what that is very soon.

Now we need to update our priority table. It now looks as follows:

+- unary

*/%

+- binary

< <= > >=

== !=
= += -= *= /= %=

Conditions and conditional executions


You already know how to ask, but you still don’t know how to make reasonable use of
the answers. We must have a mechanism which allows us to do something if a condition
is met (it evaluates to true) and not to do it if it isn’t (when its result is false. It's just
like in life: we do certain things or we don’t when a specific condition is met or not, e.g.
we go for a walk if the weather is good, or stay home if it’s wet and cold.

To make these decisions, the C++ language has a special instruction. Due to its nature
and its application, it’s called a conditional instruction (or conditional statement).

There are several variants of the conditional instruction. We’ll start with the simplest,
and slowly move on to the more difficult ones. The first form of a conditional statement,
which you can see below, is written very informally but figuratively:

if(true_or_not) do_this_if_true;

This conditional statement consists of the following, strictly necessary, elements in this
and this order only:

 if keyword;
 left (opening) parenthesis;
 an expression (a question or an answer) whose value will be interpreted
solely in terms of true (when its value is non-zero) and false (when it is equal to
zero);
 right (closing) parenthesis;
 an instruction (only one, but we’ll learn how to deal with that limitation).

How does this statement work?

 if the true_or_not expression enclosed inside the parentheses represents the


truth (i.e. its value is not equal to zero), the statement behind this condition
( do_this_if_true ) will be executed;
 if the true_or_not expression represents a falsehood (its value is equal to
zero), the statement behind this condition is omitted and the next executed
instruction will be the one that lies after the conditional statement.

Note: the true_or_not expression is not required to be necessarily of type int or any
of integer type's derivates. It may be of type float too and the general rule of
the if statement's execution remains in force

In real life we often express a will:

if the weather is good we will go for a walk next, we will have lunch
As you can see, having lunch is not a conditional activity and doesn’t depend on the
weather (what luck). Knowing what conditions influence our behavior and assuming that
we have the parameterless functions go_for_a_walk() and have_lunch() we can write
the following snippet:

if(the_weather_is_good) go_for_a_walk();
have_lunch();

As we already know, our friend the developer falls asleep when he counts 120 sheep.
His sleep is implemented as a special function named sleep_and_dream() . This function
does not require any arguments.

We can read it as: “if sheep_counter is greater than or equal to 120, then fall asleep
and dream!”

We’ve said that there may be only one statement after the if statement. When we
have to conditionally execute more than one instruction, we need to use
braces { and } which create a structure known as a compound statement or (much
simpler) a block. The block is treated as a single instruction by the compiler.

This is how we can circumvent the if statement limitation.

Let’s treat our programmer a little nicer:

if(sheep_counter >= 120){make_a_bed(); take_a_shower();


sleep_and_dream(); }

feed_the_sheepdogs();
Now it’s time for some stylistic remarks. Writing blocks one after the other is, of course,
syntactically correct, but very inelegant. It may cause the text of our program to run
outside the right margin of the editor. There are a few styles of coding the blocks. We
won't try to argue that some of them are better than others, but we will be follow the
style being used by Bjarne Stroustrup in his book "A Tour of C++". It's likely that you
may encounter code written according to different guidelines (as there are quite few of
them in use worldwide) and it's also likely that after some time you'll elaborate your
own coding style. Anyway, we prefer to follow in the footsteps of C++ creator.

The same snippet, written in accordance with the Bjarne's style, will look as follows:

if (sheep_counter >= 120) {

make_a_bed();

take_a_shower();

sleep_and_dream();

feed_the_sheepdogs();

Note:

 a conditionally executed block is indented – it improves the readability of the


program and manifests its conditional nature;
 the opening brace is located in the same line as if ;
 the closing brace occupies separate line.

In the next section, we’re going to discuss another variant of the conditional statement,
which also allows you to perform an action only when the condition is not met.

Now feed your sheep dogs, please. They’ve been waiting ages for your attention.

Input and output


Now we’re going to set aside conditional statements for a while and spend some time
on two important and extremely useful features we use to provide connectivity between
the computer and the outside world.

Sending data in the direction from human (user) to the computer program is
called input. The stream of data transferred in the opposite direction, i.e. from the
computer to the human, is called output.

We've already learned about one useful entity that serves to output data – can you
remember its name? Yup, it’s the cout stream, and we used it along with
the << operator in the very first program we wrote in the C++ language, right at the
beginning of this course.
The << operator itself is sometimes referred to as an insertion operator as it inserts a
string of characters into the character device (e.g. a console).

The actual cout capabilities are much more impressive: it’s capable of writing the data
of virtually any type on a computer screen.

So what do we do if we want to output the value of type int or float , or char , not only
a simple string?

Output
To do this and other more complex tasks, we need to use any of the output streams
associated with the screen (more formally: with the console) and send a value of a
variable there.

cout is one of these streams and is ready to work without any special preparations – it
only needs the header file name.

If you want to print the value of an integer variable to the screen, the only thing you
have to do is send it to the cout stream through the << operator, which indicates the
desired direction of data transfer.

Both the << operator and the cout stream are responsible for two important actions:

 converting the internal (machine) representation of the integer value into a


form acceptable for humans
 transferring the converted form to the output device e.g. console

Streams are very powerful and convenient tools for both input and output. They can
easily output several values of different types and mix them with the text. They can also
easily input many values at once.

Let's look at streams in a few applications. The first one is trivial - we use cout to print a
value of an int variable. We do it like this:

int herd_size = 110;

cout << herd_size;

We can expect that a string consisting of characters 1 , 1 and 0 will appear on the
screen immediately.

You can also connect more than one << operator in one cout statement and each of the
printed elements may be of a different type and a different nature.

Take a look at the example on the right. We’re using a string literal (as the former
element) and an integer variable (as the latter element) in one cout operation.
In this example:

int herd_size = 123;


cout << "Sheep counted so far: " << herd_size;

This snippet of code results in the string Sheep counted so far: 123 printed on the
screen.

An expression is a legal cout element too. The example below demonstrates one such
case:

int square_side = 12;


cout << "The square perimeter is: " << 4 * square_side;

If you want a value of type int to be presented as a fixed-point hexadecimal number,


you need to use the so-called manipulator. A manipulator is a special kind of entity
that tells the stream that the data form has to be changed immediately. All elements
outputted after the manipulator activation will be presented in the desired form.

A manipulator that is designed to switch the stream into a hexadecimal mode is called
a hex . The snippet on the right will output a string consisting of characters 'F' and 'F'.

Technically, a manipulator is a function that changes one of the output stream’s


properties, called basefield . The property is used to determine what number should be
used as a base (as an mathematician would say: a radix) during the conversion of
any int value into human readable text.

int byte = 255;


cout << "Byte in hex: " << hex << byte;

There are two important facts you need to understand here:

1. any manipulator starts its work from the point it was placed at and continues its
work even after the end of the cout statement; it finishes working only when
another manipulator cancels its action;
2. the name of the manipulator may be in conflict with any other name declared by
the programmer; e.g. you can have your own variable named hex which could
hide the manipulator’s name; such conflicts are resolved by a specialized
mechanism called namespace; more on this later.

The example below demonstrates how manipulators begin and finish their work:

int byte = 255;


cout << hex << byte;
cout << byte << dec << byte;

Note: the dec manipulator switches the stream into a decimal form. We don’t have it
explicitly in most cases, since the decimal is the default working mode for output
streams.
The snippet will output the three specimens of the same value:

1. FF as a hexadecimal representation of 255 (as an effect of the hex manipulator)


2. FF again (the previous hex activation is still working here)
3. 255 (as a result of the dec manipulator activation)

The oct manipulator switches the stream into the octal mode.

The snippet below will output 377 to the screen. Can you guess why?

int byte = 255;


cout << oct << byte;

Yes, 255 in decimal is 377 in octal. Well done.

Note: unfortunately, there is no predefined bin manipulator so consequently there is no


simple way to output binary image of an integer value although there are no obstacles
to do the same thing in a different, user-defined way. However, we must admit it needs
some more knowledge than you have in the moment.

The three manipulators we showed you previously are only one of the methods (probably the
simplest one) of accessing the basefield property. You can achieve the same effect by using
the setbase manipulator, which directly instructs the stream on what base value it should use
during conversion.

The only acceptable values for the setbase parameter are 8, 10 and 16 (note: 2 is not in this set
so you still are not able to output integer values in the binary form). As you probably suspect, there is
direct connection between these values and the previously discussed manipulators:

 10 → dec
 16 → hex
 8 → oct

The program in the editor demonstrates the usage of the setbase manipulator.

Note: it requires a header file called iomanip (the three previous manipulators don’t).

#include <iostream>

#include <iomanip>

using namespace std;

int main()

{
int byte = 255;

cout << setbase(16) << byte;

Output: ff

In general, output streams (including cout ) are able to recognize the type of the printed
value and act accordingly i.e. they’ll use a proper form of data presentation for char and float values.

The snippet in the editor will cause the stream to print the following text on the screen:

X-2.5

output

Note: there is one exception that should mentioned here - although cout stream is smart enough to
recognize values of different types, it takes booleans as ordinary integers. In effect, the following
snippet outputs 1 , not true (as you may expect):

#include <iostream>

using namespace std;

int main()
{
bool verdict = 1 > 0;
cout << verdict;
}
#include <iostream>

using namespace std;

int main()

char character = 'X', minus = '-';

float floating = 2.5;

cout << character << minus << floating;


}
Output: X-2.5
cout is able to recognize the actual type of its element even when it is an effect of
a conversion (an phenomenon which occurs when data is subject to type change).

We’ll discuss the conversions later, but for now we only want to mention that a phrase written as:

static_cast<newtype>(expr)

changes the type of the expr expression into the newtype type.

What it means is that we can see the ASCII code of any character stored within a char variable and
vice versa, or see a character whose ASCII code is placed inside an int variable.

The snippet in the editor outputs the following text to the screen:

X 88 88 X
#include <iostream>

using namespace std;

int main()

char character = 'X';

int integer = character;

cout << character << " " << static_cast<int>(character);

cout << " " << integer << " " << static_cast<char>(integer);

}
Output: X 88 88 X

Sometimes we may want to (and sometimes we may have to) break the line being
sent to the screen.

When we present many different results one by one in the same line of text, it doesn’t
look nice and you won’t want to look at it. One line is okay, but a thousand lines written
like that will make you go blind.

We can break the line in two ways. First, we can use one of the control characters called
“newline” and coded as \n (note: we use two characters to write it down but the
compiler sees it as one character - don’t let it fool you).

We can achieve exactly the same effect by using a manipulator called endl (as “end
line”).
The snippet below:

cout << "1\n2" << endl << "3\n";

illustrates both methods and causes the console to display the following three lines of
text:

1
2
3

Input
Of course, equally important as data output is data input. Actually, it’s difficult to
imagine any non-trivial program that doesn’t require any data from the user, although
you can do the following:

 encode all the data needed inside the source code (which is sometimes
called hard coding)
 when you need to repeat the execution of the program with other data, you just
modify the program, compile it and run it again.

This isn’t a particularly convenient solution. It’s far better to get the information
from the user, transfer it to the program, and then use it for calculations. So how does a
C++ language program get data from a human and store it in variables?

The simplest way is to mentally reverse the direction of the transfer and to
acknowledge that for the data input:

 we use cin stream instead of cout


 we use >> operator instead of << .

By the way, the >> operator is often referred to as an extraction operator.

The cin stream, along with the extraction operator, is responsible for:

 transferring the human-readable form of the data from the input device e.g. a
console;
 converting the data into the internal (machine) representation of the value being
input.
 Imagine that we need to ask the user about the maximum number of sheep we
want to count before the programmer falls asleep.
 The user enters the value from the keyboard and the program stores it in a
specified variable ( max_sheep ). That statement looks like this:
 cin >> max_sheep;
 You probably see the similarity to emitting data using cout : we have a stream,
we have an operator and we have a variable.
 At this point the similarities end and the differences begin. First, the argument
for cout may not be a variable. It can also be an expression.
 Take a look:
 cout << 2 * i;
 Here we want the doubled value of i to be printed – and that’s feasible. Using an
input stream, we need to explicitly specify the variable that can store the
data entered by the user.

Now we’ll show you a simple but complete program that does the following:

 prompts the user to enter a single integer value,


 squares it,
 prints the result with an appropriate comment.

Analysing this program shouldn’t be a problem for you, should it?

#include <iostream>

using namespace std;

int main()
{
int value;

cout << "Give me a number and I will square it!\n";


cin >> value;

int square = value * value;


cout << "You've given " << value << endl;
cout << "The squared value is " << square << endl;
}

Output: Give me a number and I will square it!


6
You've given 6
The squared value is 36

So you prefer square roots to squares? No problem, but we need to remember two things: first,
there’s no such thing as a square root operator; and second, that square roots of negative
numbers do not exist.

We can solve the first issue by finding a function that knows how to compute the root. This type of
function does exist and takes the argument of the float type.

The result is also a float (of course - the square of an integer is still an integer, but the root of any
number is not always an integer, like the square root of 2).

The function we’re going to use is called sqrtf (square root float) and needs exactly one argument.
Oh, one more thing - to use this function you need to include a header file named cmath .

We need to deal with negative numbers as well. If you’re careless and enter a negative number, the
program will just ignore you and your input completely. It may not be polite, but at least it won’t
attempt to bend the rules of mathematics. Whether we see the result or not will be decided by the
conditional statement.

Now it’s time to focus on the use of floating point data and the sqrtf function.

Complete program is in the editor.

#include <iostream>

#include <cmath>

using namespace std;

int main()

float value;

cout << "Give me a number and I will find its square root:" << endl;

cin >> value;

if(value >= 0.0) {

float squareroot = sqrtf(value);

cout << "You have given: " << value << endl;

cout << "The square root is: " << squareroot << endl;

}
}

Output: Give me a number and I will find its square root:


8
You have given: 8
The square root is: 2.82843

Congratulations! You have completed Module 1.


Well done! You've reached the end of Module 1 and completed a major milestone in your C++
programming education. Here's a short summary of the objectives you've covered and got familiar
with in Module 1:

 the difference between machine and high-level languages;


 the machine code and compilation;
 variables, integers, floats, booleans, characters;
 comments;
 the basics of flow control;
 dealing with streams and basic I/O operations;
 writing simple programs.

You are now ready to take the module quiz and attempt the final challenge: Module 1 Test, which
will help you gauge what you've learned so far.

C++ Essentials: Module 2

In this module, you will learn about:

 how to control the flow of the program;


 more data types;
 conditional instructions: if, else, switch;
 loops and controlling the loop execution;
 logic, bitwise and arithmetic operators;
 vectors, multidimensional arrays;
 declaring and initializing structures.

The conditional statement – more conditional than before


We concluded our last discussion on conditional statements with a promise that we
would introduce a more complex and flexible form soon. We started our tale with a
simple phrase which read: If the weather is good, we will go for a walk.

Note – there is not a word about what will happen if it rains cats and dogs. We only
know that we certainly won’t go outdoors, but what we would do instead isn’t
mentioned. We may want to plan something in case of bad weather, too.

We can say, for example: If the weather is good we will go for a walk, otherwise we will
go to a theater. This sentence makes our plans more resistant to the whims of fate – we
know what we’ll do if the conditions are met and we know what we we’ll do if not
everything goes our way. In other words, we have a plan “B”.
Luckily, the C++ language allows us to express alternative plans. We do this with a
second, slightly more complex form of the conditional statement – here it is:

if(true_or_false_condition)

perform_if_condition_true;

else

perform_if_condition_false;

Thus, we have a new word: else – this is a keyword (reserved word). A statement which
begins with else tells us what to do if the condition specified for the if is not met.

So the if-else execution goes as follows:

 if the condition is true (its value is not equal to zero)


the perform_if_condition_true is executed and the conditional statement
comes to an end;
 if the condition is false (its value is equal to zero)
the perform_if_condition_false is executed and the conditional statement
comes to an end;

if(the_weather_is_good)

go_for_a_walk();
else
go_to_the_theater();
have_lunch();

By using this form of the conditional statement we can describe our plans as follows:
As well as in other simplified forms of this instruction, like the ones we’ve already
encountered, both if and else may contain only one statement.

If you’re going to write more than one instruction, you have to use a block, as in the
example below:

if(the_weather_is_good){
go_for_a_walk();
have_fun();
}
else {
go_to_the_theater();
enjoy_the_movie();
}
have_lunch();

Now it’s time to discuss two special cases of the conditional statement. First, think
about when the instruction placed after if is another if .
Listen to what we have planned for this Sunday: If the weather is fine, we’ll go for a
walk. If we find a nice restaurant, we’ll have lunch there. Otherwise, we’ll eat a
sandwich. If the weather is poor, we'll go to the theater. If there are no tickets, we’ll go
shopping in the nearest mall.

Complicated, right? Let’s write the same thing in C++ language. Consider the code
below carefully:

if(the_weather_is_good)
if (nice_restaurant_is_found)
have_lunch();
else
eat_a_sandwich();
else
if(tickets_are_available)
go_to_the_theater();
else
go_shopping();

Let’s examine two important points:

 such a use of the if statement is known as nesting; remember that


every else refers to the closest former if which did not match any
other else ; we need to know this to determine how the if s and else s pair up;
 consider how the indentation improves readability and emphasizes the nesting
of inner conditional statements; the depth of the indentation is in fact a matter of
style but we prefer to use 4 spaces for each indentation level.

This second special case is somewhat similar to nesting, but with an important
difference. Again, we’re going to change our plans and express them as follows: “If the
weather is fine, we'll go for walk, otherwise if we get tickets, we’ll go to the theatre,
otherwise if there are free tables at the restaurant, we’ll go for lunch. If everything fails,
we’ll return home and play chess”.

Can you see how many alternatives we’ve listed here? Let’s write the same scenario in
C++ language:

if(the_weather_is_good)
go_for_a_walk();
else if(tickets_are_available)
go_to_the_theater();
else if(table_is_available)
go_for_lunch();
else
play_chess_at_home();

This way of assembling subsequent if statements is called a cascade. Notice how


the indentation improves the readability of the code.
Now, let our minds work out all that we’ve told them about conditional statements,
while we pay attention to our old friends: types int , char and float . We’re going to
meet their siblings.

Not only the int is an int


It would seem that the developer’s life would be organized well enough if they had
type int to operate with integers, type char to manipulate characters and
type float for floating-point calculations.

However, this practice has shown that such a narrow repertoire of types may raise
some problems.

Most of the computers currently in use store int s using 32 bits (4 bytes); this means
that we can operate the int s within the range of [-2147483648 .. 2147483647]. It may
happen that:

 we don’t need such big values; if we count sheep, it’s unlikely that we’ll need to
count two billion of them, so why waste the majority of these 32 bits if we don’t
need them;
 we need much larger values; for example, we intend to calculate the exact
number of humans living on Earth; in this case we need more than 32 bits to
represent that number;
 this brings us to another observation – after all, the number of inhabitants on
Earth will never be a negative number; it seems like a real waste that up to half
of the permissible range will never be used.

For these reasons, the C++ language provides some methods for defining precisely how
we intend to store large/small numbers. This allows the compiler to allocate memory,
either smaller than usual (e.g. 16 bits instead of 32) or larger than usual (e.g. 64 bits
instead of 32). We can also declare that we guarantee that the value stored in the
variable will be non-negative.

In this case the width of the variable’s range does not change, but is shifted toward
the positive numbers. This means that instead of the range of [-2,147,483,648 ..
2,147,483,647] we get the range of [0 .. 4294967295].
To specify our memory requirements, we can use some additional keywords
called modifiers:

 long – is used to declare that we need a wider range of int s than the standard
one;
 short – is used to determine that we need a narrower range of int s than the
standard one;
 unsigned – used to declare that a variable will be used only for non-negative
numbers; this might surprise you, but we can use this modifier together with the
type char ; we’ll explain it soon.

Let’s look at some examples.

The counter variable will use fewer bits than the standard int (e.g., it could be 16 bits
long – in this case, the range of the variable will be suppressed to the range of [-32768
to 32767]):

short int counter;

The word int may be omitted and the meaning of the declaration remains the same,
like this:
short counter;

The ants variable will occupy more bits than the standard int (e.g. 64 bits, so it can be
used to store numbers from the range of [-9223372036854775808 ..
9223372036854775807] – can you read such huge numbers?

long int ants;

Note – we can again omit the word int :

long ants;

If we come to the conclusion that a variable will never be a negative value, we can
use the unsigned modifier:

unsigned int positive;

Of course, we can omit the int as usual:

unsigned positive;

We can also mix some of the modifiers together – take a look:

unsigned long int big_number;

We can remove the word int and the declaration will preserve its meaning:

unsigned long big_number;

A more modest example is here:

unsigned short int lambs;

Its equivalent form is:

unsigned short lambs;

The long and short modifiers must not be used in conjunction with the
type char (which length is always the mininal possible) and (for obvious reasons) must
not be used simultaneously in a single declaration.
You may ask (and it would be very reasonable question) whether char type is
defaultly signed (like other integers) or unsigned (in contrast to other integers)?

The answer my surprise you: char is neither signed nor unsigned. We are serious. As its
primary purpose is storing characters, not numbers, so we don't need to take care of
the sign.

Anyway, if you really want to use an eight bit integer variable (that may be enough to
store a small value such as the number of month or even the day of the month) and
want it to behave as a signed/unsigned integer, you can express your need explicitly
using either signed or unsigned modifier.

If we treat the char variable as a signed integer number, its range would be [-128 ..
127]. If we take it as a signed value, its range shifts to [0 .. 255]. This may be sufficient
for many applications and may also result in significant savings in memory usage. The
examples below presents both possible cases:

unsigned char little_counter = 0;

signed char satisfaction_level = -1;

Note:

 you’re not allowed to omit the word char ;


 you can use the signed modifier in conjunction with int , long and short but it
will change nothing in the variables' life (nothing unusual);
 don't try to put signed and unsigned side by side in the same declaration as the
variable will suffer from split personality (it's a joke, of course - as compilers
show no sense of humor at all, we have to make up this lack).

We need to add an important remark. So far we’ve used integer literals, assuming that
all of them are of type int . This is generally the case, but there are some cases when
the compiler recognizes literals of type long . This will happen if:

 a literal value goes beyond the acceptable range of type int ;


 letter L or l is appended to the literal, such as 0L or 1981l – both of these
literals are of type long .

Another float types


The short and long modifiers cannot be used alongside the float but it doesn't mean
that the float type has no floating point siblings. In fact, there are at least two of
them: double and long double . The variables of types double and long double may
differ from the variables of type float , not only in range, but also in accuracy.

What does this mean? The data stored in a floating-point variable has finite
precision – in other words, only a certain number of digits are precisely stored in the
variable.
For example, we expect that the value:

1111111111111111111.111111111111111111111

will be stored by a specific type of computer as:

1111111131851653120.000000

We say that the variable saves (only) 8 precise digits. This is within the expected
accuracy of 32-bit long (4 bytes) float s. Using a double (which is usually 64 bits/8 bytes
long) guarantees that the variable will save a more significant number of digits –
about 15-17. This is where the name double comes from – its accuracy
is doubled compared to float . In turn, the long double variable occupy 128 bit (16
bytes) bit and is able to store 33-36 significant digits. This is why this type is
sometimes called quadruple.

It's worth to mention that some hardware platforms my offer even longer floating point
types like 256 bit long octuple - if a specific compiler is able to operate with data of this
kind, it will accept long long double as a corresponding type specifier.

Now, when you're initiated to the details of floating point data life, it's time to tell you
an important secret regarding literals. It may sound shocking - we are aware of it - an
ordinary floating point literal like 3.1415 is recognized by a compiler as double and as a
consequence occupies 64 bits of computer storage.

If you're determined to convince the compiler that any of your literals is actually an
ordinary float , you should append suffix "f" or "F" to it. It means
that 3.1515f and 6.626E-34f are of type float .

Floats and their traits


We told you some time ago that computer addition is not always commutative. Do
you know why? Imagine that you have to add a large number of floating-point values –
some of them are very large, some very small (close to zero). If a very small float value
is added to another that’s very large, the result can be quite surprising.

Take a look at the picture – we’ll assume that our computer only saves 8 precise digits
of any float . If we add these two floats, we’ll probably get:

11111110656.000000

as the result. The lower value simply vanished without a trace.

We can’t avoid these effects when we add/subtract the numbers of type float (and of
its cousins as well, because they’re also affected by this issue). The phenomenon
described here is what we call a numerical anomaly.
Doubles and their traits
Don't think that lenghtening the floating points data is a cure for numeric anomalies. It may mask
some of them but creates new in the same time. One of the most famous innacuracies the doubles
are burdened with is shown in the editor.

The code seems to be trivial. It's obvious that 0.1 added to 0.2 is equal to 0.3, isn't it?

Of course, it is. But not always. Run the code, please!

And what did you see?

Yes, your eyes don't deceive you. This is an effect of the fact that numbers stored as floating point
data can be different from their real (precise) values. If you want to trace that phenomenon deeper,
try to change type from double to float and check the result.

#include <iostream>

using namespace std;

int main()

double a = 0.1;

double b = 0.2;

double c = 0.3;

if(a + b != c)

cout << "Your computer is out of order";


}
Output: Your computer is out of order

Two simple programs


Now we’re going to show you some simple but complete programs. We won’t explain them in detail,
because we think the comments inside the code are sufficient guides.

All these programs solve the same problem – they find the largest of several numbers and print it
out.
Let’s start with the simplest case – how to identify the larger of two numbers.

/* finding the larger of two numbers */

#include <iostream>

using namespace std;

int main()

/* the two numbers */

int number1, number2;

/* read two numbers */

cin >> number1;

cin >> number2;

/* we will save the larger number here */

/* we temporarily assume that the former number is the larger one */

/* we will check it soon */

int max = number1;

/* we check if the assumption was false */

if (number2 > max)

max = number2;

/* we print the result */

cout << "The larger number is " << max << endl;

}
Output: 1
2
The larger number is 2

Now let's try to find the largest of three numbers. We find the larger of the first two and compare it
with the third one. Here we go.
/* finding the largest of three numbers */

#include <iostream>

using namespace std;

int main()

/* the three numbers */

int number1, number2, number3;

/* read three numbers */

cin >> number1;

cin >> number2;

cin >> number3;

/* we will save the larger number here */

/* we temporarily assume that the former number is the larger one */

/* we will check it soon */

int max = number1;

/* we check if the second value is the largest */

if (number2 > max)

max = number2;

/* we check if the third value is the largest */


if (number3 > max)

max = number3;

/* we print the result */

cout << "The largest number is " << max << endl;
}

Output: 4
7
8
The largest number is 8

Some simple programs


By this point, you should be able to write a program that finds the largest of four, five, six or even ten
numbers. You already know the scheme, so the extension of the program doesn’t need to be
particularly complex.

But what happens if we ask you to write a program that finds the largest of a hundred of numbers?
Can you imagine the code?

 You’d need hundreds of declarations of type int variables. If you think you can cope with
that, then try to imagine searching for the greatest of a million numbers;
 Imagine the code that contains 99 conditional statements and a hundred cin statements.
 Some simple programs
 Let’s ignore the C++ language for the moment and try to analyze the problem
while not thinking about the programming. In other words, let’s try to write
the algorithm, and when we’re happy with it, we'll try to implement it.
 We’re going to use a kind of notation that is not a programming language at all
(it could be neither compiled nor executed), but is formalized, concise and
readable. We call this pseudo-code.
 There is an example of pseudo-code below. Take a look at it. What’s going on?
 1. max = -999999999;
 2. read number
 3. if(number == -1) print max next stop;
 4. if(number > max) max = number
 5. go to step 2

 First, we can simplify our program if, at the very beginning of the code, we assign
the variable max with a value which will be smaller than any of the numbers
entered. We’ll use -999999999 for this purpose.
 Second, we assume that our algorithm doesn’t know in advance how many
numbers will be delivered to the program. We expect that the user will enter as
many numbers as she/he wants – the algorithm will work equally well with one
hundred or one thousand numbers. How do we do that? Well, we make a deal
with the user: when the value -1 is entered, it will be a sign that there is no more
data and the program should end its work. Otherwise, if the entered value is not
equal to - 1, the program will read another number and so on.
 The trick is based on the assumption that any part of the code can be
performed more than once – in fact, as many times as you need.
 Performing a certain part of the code more than once is called a loop. You
probably already know what a loop is. See, steps 2 through 5 make a loop. Can
we use a similar structure in the program written in the C++ language? Yes, we
can. And we’re going to tell all you about it soon.

The “while” loop


 We want to ask you a strange question: how long do you usually take to wash
your hands? Don’t think about it, just answer. Well, when your hands are very
dirty, you wash them for a very long time. Otherwise it takes less time. Do you
agree with this statement:
 while my hands are dirty
 I am washing my hands;
 Note that this also implies that if our hands are clean, we won’t wash them at all.
 So now you've learnt one of the loops available in the C++ language. In general,
the loop manifests itself as follows:
 while(conditional_expression)
 statement;
 If you think it looks similar to the if instruction, you’re quite right. Indeed,
there’s only one syntactic difference: we replaced the word if with the
word while .
 The semantic difference is more important: when the condition is met, if
performs its statements only once; while repeats the execution as long as the
condition evaluates to true .

Let’s make a few observations:

 if you want while to execute more than one statement, you must (like with
the if statement) use a block – take a look at the code in the editor;
 an instruction or instructions executed inside the loop are called the loop's body;
 if the condition is false (equal to zero) as early as when it’s tested for the first time,
the body is not executed even once (note the analogy of not having to wash your hands if
they’re not dirty);
 the body should be able to change the condition value, because if the condition is true at the
beginning, the body might run continuously to infinity (notice that washing changes the
state of impurity).
while(conditional_expression) {

statement_1;

statement_2;

statement_n;
}

Here is an example of a loop that is not able to finish its execution. This loop will infinitely print I am
stuck inside a loop on the screen.

while(true) {

cout << "I am stuck inside a loop" << endl;

Analyze this program carefully. Locate the loop’s body and find out how the body is exited.

See how the above code implements the algorithm we made earlier.

#include <iostream>

using namespace std;

int main()

/* temporary storage for the incoming numbers */

int number;

/* get the first value */

cin >> number;

/* we will store the currently greatest number here */


int max = number;

/* if the number is not equal to -1 we will continue */

while (number != -1) {

/* is the number greater than max? */

if (number > max)

/* yes – update max */

max = number;

/* get next number */

cin >> number;

/* print the largest number */

cout << "The largest number is " << max << endl;

This program counts odd and even numbers coming from the keyboard. Have a look at it.

Certain snippets can be simplified without changing the program’s behavior. Take a look at the next
slide.

#include <iostream>

using namespace std;

int main()

/* we will count the numbers here */

int evens = 0, odds = 0;

/* we will store the incoming numbers here */

int number;
/* read first number */

cin >> number;

/* 0 terminates execution */

while (number != 0) {

/* check if the number is odd */

if (number % 2 == 1)

/* increase „odd” counter */

odds++;

else

/* increase „even” counter */

evens++;

/* read next number */

cin >> number;

/* print results */

cout << "Even numbers: " << evens << endl;

cout << "Odd numbers: " << odds << endl;

Try to recall how the C++ language interprets the truth of a condition and note that
these two forms are equivalent.

while(number != 0) {...}
while(number) {...}

The condition that checks if a number is odd can be coded in like this:

if(number % 2 == 1)...
if(number % 2)...

We guess that nothing surprises you, right? But there are two things that we can write
more compactly. First, the condition of the while loop.

int main()
{
int counter = 5;

while(counter != 0) {
cout << "I am an awesome program" << endl;
counter--;
}
}

Another change requires us to have some knowledge of how the post-decrement works.
We’ll use it to compact our program once again.

int main()
{
int counter = 5;

while(counter) {
cout << "I am an awesome program" << endl;
counter--;
}
}

We’re convinced that this is the simplest form of this program, but you can challenge us
if you dare.

int main()
{
int counter = 5;

while(counter--)
cout << "I am an awesome program" << endl;
}

The “do” loop or do it at least once


We already know that the while loop has two important features:

 it checks the condition before entering the body,


 the body will not be entered if the condition is false.

These two properties can often cause unnecessary complications. For this reason, there’s another
loop in the C++ language which acts like a mirror image of the while loop.

We say this because in that loop:

 the condition is checked at the end of the body execution,


 the loop's body is executed at least once, even if the condition is not met.

This loop is called the do loop. Its simplified syntax is listed in the editor.
If you want to execute a body containing more than one statement, you need to use a block.

do

statement;

while(condition);

do {

statement_1;

statement_2;

statement_n;

} while(condition);

Let’s return to the program that searches for the largest number. Firstly, we will use the “ do ” loop
instead of “ while ” for teaching purposes. Secondly, we remove the vulnerability involved in the
excessive trust in the user’s good will. Our new program won’t be misled by entering the value of -
1 as the first number. Look at the editor. Here's our code.

Take a look. We used the counter variable to count the numbers entered so we can instruct the
user that we cannot search for the greatest number if no number is given.

As we have to read at least one number, it makes sense to use the do loop. We use this approach
in the program.

#include <iostream>

using namespace std;

int main()

int number;

int max = -100000;

int counter = 0;
do {

cin >> number;

if (number != -1)

counter++;

if (number > max)

max = number;

} while (number != -1);

if (counter)

cout << "The largest number is " << max << endl;

else

cout << "Are you kidding? You haven't entered any number!" << endl;

“for” - the last loop


The last available kind of loop in C++ language comes from the fact that sometimes it’s
more important to count the “turns” of the loop than to check the conditions.

Imagine that a loop's body needs to be executed exactly one hundred times. If you want
to use the while loop for that purpose, it may look something like this:

int i = 0;

while(i < 100) {

/* the body goes here */

i++;

We can distinguish three independent elements there:

 the initialization of the counter


 the checking of the condition
 the modification of the counter

It’s possible to create something like a generalized scheme for these kinds of loops,
here it is:
initialization;

while(checking) {

/* the body goes here */

modifying;

This way of coding the loop is very common, so there’s a special, brief way of writing it
in the C++ language.

Below we’ve gathered all three decisive parts together. The loop is clear and easy to
understand. Its name is for .

for(initialization; checking; modifying) {

/* the body goes here */

The for loop can take the form shown in the editor.

The variable used for counting the loop's turns is often called a control variable.

Notice, that if a control variable is declared within the initialization clause (like in the example) the
variable is available only inside the loop's body.

If it's not desirable and you want to use the same variable somewhere outside the loop's body you
need to declare it outside the loop, like this:

int i;

/*
some code
*/

for(i = 0; i < 100; i++) {


// the body goes here
}

The for loop has an interesting singularity. If we omit any of its three components, it is presumed
that there is a 1 there instead.
One of the consequences of this is that a loop written in this way is an infinite loop (do you know
why?).

Check

Well, the conditional expression is not there, so it is automatically assumed to be true.


And because the condition never becomes false, the loop becomes infinite.

for(int i = 0; i < 100; i++) {

/* the body goes here */

Let’s look at a short program whose task is to write some of the first powers of 2.

The exp variable is used as a control variable for the loop and indicates the current value of the
exponent. The exponentiation itself is replaced by multiplying by 2. Since 2 0 is equal to 1, then 2 ∙ 1
is equal to 21, 2 ∙ 21 is equal to 22 and so on.

Answer this question: what is the greatest exponent for which our program still prints the result?

#include <iostream>

using namespace std;

int main()

int pow = 1;

for(int exp = 0; exp < 16; exp++) {

cout << "2 to the power of " << exp << " is " << pow << endl;

pow *= 2;

break and continue – the loop's spices


So far, we’ve treated the body of the loop as an indivisible and inseparable sequence of
instructions that are performed completely at every turn of the loop. However, as a developer, you
could be faced with the following choices:

 it appears that it is unnecessary to continue the loop as a whole; we should stop executing
the loop's body and go further;
 it appears that we need to start the condition testing without completing the execution of the
current turn.

The C++ language provides us with two special instructions to implement both these tasks. Let's say
for the sake of accuracy that their existence in the language is not necessary - an experienced
programmer can code any algorithm without these instructions.

The famous Dutch computer scientist Edsger Dijkstra proved it in 1965. These additions, which don't
improve the language's expressive power but only simplify the developer's work, are sometimes
called syntactic sugar.

These two instructions are:

 break - exits the loop immediately and unconditionally ends the loop’s operation; the
program begins to execute the nearest instruction after the loop's body;
 continue – behaves as the program suddenly reached the end of the body; the end of the
loop's body is reached and the condition expression is tested immediately.

Both these words are keywords.

Now let’s look at two simple examples. We’ll return to our program that recognizes the largest of the
numbers entered. We’ll convert it twice, using both instructions. Analyze the code and judge whether
and how you would use any of them.

You can see the break variant in the editor.

Note that the only way to exit the body is to perform the break, as the loop itself is infinite ( for
(;;) ).

#include <iostream>

using namespace std;

int main()

int number;

int max = -100000;

int counter = 0;
for (;;) {

cin >> number;

if (number == -1)

break;

counter++;

if (number > max)

max = number;

if (counter)

cout << "The largest number is " << max << endl;

else

cout << "Are you kidding? You haven't entered any number!" << endl;

break and continue – the loop's spices


And now the continue variant.

#include <iostream>

using namespace std;

int main()

int number;

int max = -100000;

int counter = 0;

do {

cin >> number;


if(number == -1)

continue;

counter++;

if(number > max)

max = number;

} while (number != -1);

if(counter)

cout << "The largest number is " << max << endl;

else

cout << "Are you kidding? You haven't entered any number!" << endl;

Computers and their logic


Have you noticed that the conditions we’ve used so far are very simple, quite primitive,
in fact? The conditions we use in real life are much more complex. Let's look at this
following sentence:

If we have some free time, and the weather is good, we will go for a walk.

We have used the conjunction “and”, which means that going for a walk depends on
the simultaneous fulfillment of the two conditions.

In the language of logic, connecting conditions like this is called a conjunction. And now
another example:

If you are in the mall or I am in the mall, one of us will buy a gift for Mom.

The appearance of the word “or” means that the purchase depends on at least one of
these conditions. In logic terms, this is called a disjunction.

So clearly, the C++ language needs to have operators to build conjunctions and
disjunctions. Without them, the expressive power of the language would be
substantially weakened. They are called logical operators.
Pride && Prejudice
The logical conjunction operator in the C++ language is a digraph && (ampersand
ampersand).

This is a binary operator with a priority lower than the comparison operators. It allows
us to code complex conditions without the use of parentheses like this one:

counter > 0 && value == 100

The result provided by the && operator can be determined on the basis of the truth
table. If we consider the conjunction of:

left && right

the set of possible values of arguments and corresponding values of the conjunction
looks as follows:

left right left && right

false false false

false true false

true false false

true true true


TIME MACHINE
The && operator derives directly from C++'s ancestor, the C language and in the
opinion of many using it may be error prone for at least two reasons:

 it's very (too) similar to the & operator performing completely different operation;
 it's counter-intuitive.

Due to this reasons C++ introduced a more verbose and unequivocal synonym for the
conjunction: it's a keyword and . Feel free to use one of them in your code - they work
exactly the same.

To be || not to be
The disjunction operator is the digraph || (bar bar). It’s a binary operator with a lower
priority than && (just like “ + ” compared to “ * ”). Its truth table looks as follows:

left right left | | right

false false false

false true true

true false true

true true true

TIME MACHINE
The || has its synonym too - it's a keyword or .

In addition, there’s another operator that can be used to construct conditions. It’s a
unary operator performing a logical negation. Its operation is simple: it turns true into
false and false into true. This operator is written as a single character ! (exclamation
mark) and its priority is very high: the same as the increment and decrement operators.

Its truth table is truly simple:

arg !arg

false true

true false

TIME MACHINE
Can you guess how to write ! 's keyworded synonym? Yes, it's a keyword not . Note that
the exclamation mark can be really dangerous - it can be confused with the digit 1 or
even overlooked (it's tiny so you can miss it when the logical expression is long and
complicated). not is definitely more eye-catching.
Some logical expressions
Note that the following conditions are equivalent, respectively:

variable > 0 !(variable <= 0)

variable != 0 !(variable == 0)

You may remember De Morgan's laws from school. They say that:

The negation of a conjunction is the disjunction of the negations. The negation of a


disjunction is the conjunction of the negations.

Let's try to write the same thing using the “C” language:

!(p && q) == !p || !q

!(p || q) == !p && !q

Note how the parentheses have been used to code the expressions.

We should add that none of the previous two-argument operators can be used in the
abbreviated form known as op= . This exception is worth remembering.

How to deal with single bits


Logical operators take their arguments as a whole, regardless of how many bits
they contain. The operators are aware only of the value: 0 (when all the bits are reset)
means “ false ”; not 0 (when at least one bit is set) means “ true ”. The result of their
operations is one of the values: 0 or 1 . This means that the following snippet:

bool i = false;
bool j = !!i;

will assign a value of 1 to the j variable if i is not zero; otherwise, it will be 0 (why?).

However, there are four operators that allow you to manipulate single bits of data. We
call them bitwise operators. They cover all the operations we mentioned before in the
logical context and one additional operator. This is the xor (exclusive or) and is denoted
as ^ (caret). Here are all of them:

& (ampersand) bitwise conjunction


| (bar) bitwise disjunction
~ (tilde) bitwise negation
^ (caret) bitwise exclusive or

TIME MACHINE
All these single-character operators have they modern verbose synonyms - here they
are:.

& bitand
| bitor
~ compl (as in compliment)
^ xor

Let's make it easier:

 & requires exactly two “1s” to provide “1” as the result


 | requires at least one “1” to provide “1” as the result
 ^ requires only one “1” to provide “1” as the result
 ~ (is one argument and) requires “0” to provide “1” as the result

But take note: arguments of these operators must be integers (int as well
as long , short or char ); we must not use any of floats here.

The difference in the operation of the logical and bit operators is important: the logical
operators do not penetrate into the bit level of its argument. They’re only interested in
the final boolean value.

Bitwise operators are stricter: they deal with every bit separately. If we assume
that the int variable occupies 32 bits, you can imagine the bitwise operation as a 32-
fold evaluation of the logical operator for each pair of bits of the arguments. Obviously,
this analogy is somewhat imperfect, as in the real world all these 32 operations are
performed at the same time.

left right left&right left|right left^right


0 0 0 0 0
0 1 0 1 1
1 0 0 1 1
1 1 1 1 0

arg ~arg
0 1
1 0
Let’s have a look at an example of the difference in operation between logical and bit
operations. Let’s assume that the following declaration has been performed:

int i = 15, j = 22;

If we assume that the int s are stored with 32 bits, the bitwise image of the two
variables will be as follows:

i: 00000000000000000000000000001111

j: 00000000000000000000000000010110

The declaration is given:

int log = i && j;

We’re dealing with a logical conjunction. Let’s trace the course of the calculations. Both
variables i and j are not zeros so will be deemed to represent “ true ”.

If we look at the truth table for the && operator, we can see that the result will be “true”
and that it’s an integer equal to 1. This means that the bitwise image of the log variable
is as follows:

log:00000000000000000000000000000001

Now the bitwise operation – here it is:

int bit = i & j;

The & operator will operate with each pair of corresponding bits separately, producing
the values of the relevant bits of the result. Therefore the result is this:

bit:00000000000000000000000000000110

These bits correspond to the integer value of 6.

Let's try the negation operators now. First the logical one:

int i = 15; logneg = !i;

The logneg variable will be set to 0 , so its image will consist of zeros only.

The result:
logneg:00000000000000000000000000000000

The bitwise negation goes here:

int i = 15, bitneg = ~i;

The result:

bitneg:11111111111111111111111111110000

It may surprise you to learn that the bitneg variable value is -16. Strange? No, not at
all!

If it surprises you, try to spend some time looking into the secrets of the binary numeral
system and the rules governing so-called two's complement numbers. It makes for
good bedtime reading.

We can use each of the previous two-argument operators in their abbreviated forms.
These are the examples of equivalent notations:

x = x & y; x &= y;

x = x | y; x |= y;

x = x ˜ y; x ˜= y;

Note: keyworded bitwise operators cannot be used in shortcut forms. You may find it
inconsistent (so do we).

We'll now show what you can use bitwise operators for.

Imagine that you have to write an important piece of an operating system. You’ve been
told that you’re to use a variable declared in the following way:

int flag_register;

The variable stores the information about various aspects of system operation. Each bit
of the variable stores one yes/no value.

You’ve also been told that only one of these bits is yours – bit number three (remember
that bits are numbered from 0 and bit number 0 is the lowest one, while the highest is
number 31).

The remaining bits are not allowed to change because they’re intended to store other
data.
Here's your bit marked with the letter “x”:

0000000000000000000000000000x000

You may face the following tasks:

#1:

Check the state of your bit – you want to find out the value of your bit; comparing the
whole variable to zero will not do anything, because the remaining bits can have
completely unpredictable values, but we can use the following conjunction property:

x & 1 = x

x & 0 = 0

If we apply the & operation to the flag_register variable along with the following bit
image:

00000000000000000000000000001000

(note the "1" at your bit's position) we obtain one of the following bit strings as a result

00000000000000000000000000001000

if your bit was set to “1”

00000000000000000000000000000000

if your bit was reset to “0”.

A sequence of zeros and ones whose task is to grab the value or to change the selected
bits is called a bitmask. Let’s try to build a bitmask to detect the state of your bit. It
should point to the third bit. That bit has the weight of 23 = 8. A suitable mask could be
created by the following declaration:

int the_mask = 8;

or (in the more detailed way):

int the_mask = 0b1000;

We can also make a sequence of instructions depending on the state of your bit – here it
is:

if(flag_register & the_mask) {


/* my bit is set */
} else {
/* my bit is reset */
}

#2:

Reset your bit – you assign a zero to the bit while all other bits remain unchanged;
we’ll use the same property of the conjunction as before, but we’ll use a slightly
different mask – just like this:

1111111111111111111111111111110111

Note that the mask was created as a result of the negation of all bits
of the_mask variable.

Resetting the bit is simple and looks like these (choose the one you like most):

flag_register = flag_register & ~the_mask;

flag_register &= ~the_mask;

#3:

Set your bit – you assign a “one” to your bit while all the remaining bits must remain
unchanged; we’ll use the following disjunction's property:

x | 1 = 1

x | 0 = x

We’re ready to set your bit with one of the following instructions:

flag_register = flag_register | the_mask;

flag_register |= the_mask;

#4:
Negate your bit – you replace a “one” with a “zero” and a “zero” with a “one”. We’ll
use an interesting property of the xor operator:

x ^ 1 = !x

x ^ 0 = x

Now let's negate your bit with one of the instructions:

flag_register = flag_register ^ the_mask;

flag_register ^= the_mask;

The C++ language offers us yet another operation relating to single bits: shifting. It applies only to
integer values and you can’t use it with floats as arguments. You use this operation unconsciously all
the time. How do you multiply any number by 10? Take a look:

12345 ∙ 10 = 123450

As you can see, multiplying by ten is in fact a shift of all the digits to the left and filling the resulting
gap with a “0”. Division by 10? Let's look:

12340 ÷ 10 = 1234

Dividing by 10 is nothing more than shifting the digits to the right.

The same kind of operation is performed by the computer, but with one difference: as 2 is the base
for binary numbers (not 10), shifting a value one bit to the left corresponds to multiplying it by 2;
respectively, shifting one bit to the right is like dividing by 2 (notice that the right-most bit is lost).

Bit shifting can be:

 logical, if all the bits of the variable are shifted; shifting takes place when you apply it to the
unsigned integers;
 arithmetic, if the shift omits the sign bit – in two's complement notation, the role of the sign
bit is played by the highest bit of a variable; if it’s equal to "1", the value is treated as a
negative; this means than the arithmetic shift cannot change the sign of the shifted value.

The shift operators in the C++ language are a pair of digraphs, << and >> , clearly suggesting in
which direction the shift will act. The left argument of these operators is the integer value whose bits
are shifted. The right argument determines the size of the shift. This shows that this operation is
certainly not commutative.

The priority of these operators is very high. You'll see them in the updated table of priorities which
we’ll show you at the end of this section.
value << bits

value >> bits

Let’s assume the following declarations exist:

int w_sign = -8;


unsigned wo_sign = 4;

Take a look at the shifts in the editor. Run the code and make sure that you can explain each of the
results.

Note: both operators can be used in the shortcut form as below:

signed >>= 1; /* division by 2 */


unsigned <<= 1; /* multiplication by 2 */

#include <iostream>

using namespace std;

int main()

int w_sign = -8;

unsigned wo_sign = 4;

int var_s;

unsigned var_u;

/* equivalent to division by 2 –> var_s == -4 */

var_s = w_sign >> 1;

cout << var_s << endl;

/* equivalent to multiplication by 4 –> var_s == -32 */


var_s = w_sign << 2;

cout << var_s << endl;

/* equivalent to division by 4 –> var_u == 1 */

var_u = wo_sign >> 2;

cout << var_u << endl;

/* equivalent to multiplication by 2 –> var_u == 2 */

var_u = wo_sign << 1;

cout << var_u << endl;

And here’s the updated priority table, containing all the operators introduced in this
section.

! ~ (type) ++ -- + - unary
*/%
+- binary
<< >>
< <= > >=
== !=
&
|
&&
||
= += -= *= /= %= &= ^= | >>= <<=

Case and switch vs. if


As we already know, an if-cascade is a name for a construction of code where many if instructions
are placed consecutively one after another, as in the example in the editor.

Of course, there are no obstacles to using and maintaining a code like this, but there are a few
disadvantages that may be discouraging. The longer the cascade, the harder it is to read and
understand what it’s indented for.

Amending the cascade is also hard: it's hard to add a new branch into it and it's hard to remove any
previously created branch.
The C++ language offers us a way to make these selections easier. By the way, this is only more
syntax candy. You can manage without it, but don't hesitate to use it when your if s start growing
extensively.

if(i == 1)

cout << "Only one?" << endl;

else if(i == 2)

cout << "I want more" << endl;

else if(i == 3)

cout << "Not bad" << endl;

else

cout << "OK" << endl;

Let's take a look at the snippet in the editor. It's an example of how to replace an if cascade with a
specialized instruction. Note that the words switch and case are keywords.

The new instruction is called switch and it is, in fact, a switch. So how does it work?

First, the value of the expression enclosed inside the parenthesis after the switch keyword
is evaluated (this is sometimes called a switching expression).

Then the block is searched in order to find a literal preceded by the case keyword which is equal to
the value of the expression. The pair consisting of the case keyword and the correspoding constant
is sometimes calles case label.

When this case is found, the instructions behind the colon are executed. If there’s a break among
them, the execution of the switch statement is terminated, otherwise, all instructions are executed
until the end of the block is reached or another break is met.

What happens if the switching expression has a value that does not occur in any of the cases? The
answer is simple: nothing will happen – none of the branches of the switch statement are
executed.

Note the way we used to layout we used to encode the switch . Such a format increases legibility of
the code and makes it elegant - do you agree?

switch(i) {

case 1:

cout << "Only one?" << endl;

break;
case 2:

cout << "I want more" << endl;

break;

case 3:

cout << "Not bad" << endl;

break;

case 4:

cout << "OK"<< endl;

Let's modify the requirements. We’ll assume now that our program is satisfied (it says “OK”) if
the i variable is equal to 4 or to 3 . Does this mean that we have to create two branches for both
possibilities?

Fortunately not. We’re allowed to place more than one case in front of any branch, like the one in
the editor.

switch(i) {

case 1:

cout << "Only one?" << endl;

break;

case 2:

cout << "I want more" << endl;

break;

case 3:

case 4:

cout << "OK" << endl;

We can also assume that our program does not have an opinion when i values are
different from the ones specified so far and we want the program to express it in a clear
form. Have we made a million new cases covering the entire int type's range?

No. We can use a generalized case that covers all these events which haven’t been
enumerated in the previous cases. Take a look at the code in the editor.
Note that default is a keyword too.

Don't forget to use the break. Leaving out this keyword is one of the most common
mistakes developers make (not only at the beginning of their careers).

Simple, right? And how elegant.

But now a few more important remarks to note:

 the value after the case must not be an expression containing variables or
any other entities whose values aren't known at compilation time;
 the default can be located anywhere (even as the first switch's label) although
putting it at the last position makes the code easier to analyze;
 all labels must be unique;
 default cannot be used more than once.

Now we say goodbye to our switch statement; it's time to take up an important
challenge – we’re going to discuss arrays.

switch(i) {

case 1:

cout << "Only one?" << endl;

break;

case 2:

cout << "I want more" << endl;

break;

case 3:

case 4:

cout << "OK" << endl;

break;

default:

cout << "Don't care" << endl;

Vectors – why?
There may come a time when we have to read, store, process, and finally, print dozens, maybe
hundreds, perhaps even thousands of numbers. What then? Must we declare a separate variable for
each value? Will we have to spend long hours writing statements like the one in the editor.

If you think this is a simple task, then we suggest that you take a piece of paper and write a program
that reads five numbers of type int and prints them in order from the smallest to the largest (NB this
is called sorting). We don’t think your piece of paper will be big enough for the task.

So far, we’ve declared variables that can store exactly one given value at a time. These variables
are called scalars, analogous to mathematical terms. All variables we’ve used so far have actually
been scalars.

Think of how convenient it would be if we could declare a variable that can store more than one
value. For example, 100 or 1000 or even 10,000 variables. It would still be one and the same
variable, but very wide and extensive. Does that sound appealing? Perhaps, but how would it handle
all these different values? How would it choose just the one we need?

Should we just number them? And we'll say: give me the value number 2; assign the value number
15; increment the value number 10000.

Maybe... what do you think?

We'll show you how to declare these multi-value variables. We’ll do this with the example that we
suggested before. We’ll try to write a program that sorts a sequence of integers, but we won't be
particularly ambitious right now – we’ll assume that there will be 5 numbers.

int var1, var2, var3, var4, var5;

We read this record as follows:

 as we're going to declare a vector we need to include a header file named vector (no
suprise)
 as we prefer not to write std:: in front of each vector declaration we instruct the compiler
to use std namespace as the default one;
 we create a variable of type vector ;
 the vector is intended to store int values (note: you specify the vector element's type
putting its name between < and > );
 the newly declared variable is called numbers ;
 it’s intended to store five values (note the number enclosed inside parentheses).

Let’s say the same thing using the appropriate terminology: numbers is a vector consisting of 5
values of type int .

All the elements of a vector have the same type. There are no exceptions to this rule. There are
other programming languages which allow the use of vectors with elements of various types, but C+
+ is not one of them. It’s not, as you might think, a troublesome limitation and it can be effectively
avoided, if necessary. However, this is a very complex subject and you have to wait some time for
the solution to this puzzle.
It’s time for a bit of intrigue. The C++ language has a convention which says that the elements in a
vector are numbered starting from 0. This means that the item stored at the beginning of the vector
will have the number 0. Since there are 5 elements in our vector the last one will have the number
4. Don't forget this. However, you’ll soon get used to it and it’ll become second nature.

Before we go any further, we have to note the following: our vector is a collection of elements, but
each element is a scalar.

TIME MACHINE
The presented way of declaring vectors is the recommended and timely solution for creating new
code but it doesn't meant that there are not other ways of achieving (nearly) the same effect. Don't
be surprised seeing the following line in someone else's code:

int numbers[5];

The above declaration doesn't need any additional header file to be included (what seems attractive)
but the functionality offered by such a vector is significantly smaller. This is why we prefer the
modern way although we reserve the right to use the older form as well.

#include <vector>

using namespace std;

vector<int> numbers(5);

How do we assign a value to the chosen element of the vector?

Let's assign the value of 111 to the first element of the vector. We do it this way:

numbers[0] = 111;

We need a value stored in the third element of the vector and we want to assign it to
the integer variable i . This is how we can do it:

int i = numbers[2];

And now we want the value of the fifth element to be copied to the second element –
can you guess how to do it? int numbers[5];

for(int i = 0; i < 5; i++)

numbers[i] = 2012;
numbers[1] = numbers[4];

The value inside the brackets, which selects one element of the vector, is called
an index, while the operation of selecting an element from the vector is known
as indexing.

Note: all the indices we’ve used so far are literals. Their values are fixed at run time,
but any expression could be the index too. This opens up lots of opportunities.

We want to calculate the sum of all values stored in the numbers vector. We declare a variable
where the sum will be stored and initially assign a value of 0 to it – its name is sum.

Then we add to it all the elements of the vector using the for loop, which is a great tool for
processing vectors. Take a look at the snippet in the editor.

Let’s talk about this example for a moment. The i variable will take the values 0 , 1 , 2 , 3 ,
and 4 subsequently and will index the numbers vector by selecting subsequent elements: the first,
second, third, fourth and fifth. Each of these elements will be added by the += operator to
the sum variable, giving the final result at the end of the loop.

#include <vector>

using namespace std;

vector<int> numbers(5);

int sum = 0;

for(int i = 0; i < 5; i++)

sum += numbers[i];
The next task is to assign the same value (e.g. 2020) to all the elements of the array.

Now let‘s try to rearrange the elements of the vector i.e. reverse the order of the elements: the first
and the fifth as well as the second and fourth elements will be swapped. The third one will remain
untouched.

Question: how can we swap the values of two variables? Let's look at the snippet in the editor - if
we do something like this, we would lose the value we stored previously in variable2 .

Changing the order of the assignments won‘t help us either. Unfortunately, we need a third variable
that serves as an auxiliary storage.

int variable1 = 1, variable2 = 2;


variable2 = variable1;

variable1 = variable2;
Look at the editor - this is how we do it.

int variable1 = 1, variable2 = 2, auxiliary;

auxiliary = variable1;

variable1 = variable2;

variable2 = auxiliary;
This is how we can utilize the presented receipt to reverse the whole 5 element vector. It works for
sure, but we definitely do not like this (do you?). It’s acceptable with a vector of 5 elements, but try to
image similar code operating on 99 elements - you wouldn't want to write it.

/* swap elements #1 and #5 */

auxiliary = numbers[0];

numbers[0] = numbers[4];

numbers[4] = auxiliary;

/* swap elements #2 and #4 */

auxiliary = numbers[1];

numbers[1] = numbers[3];

numbers[3] = auxiliary;

Let’s use the services of a for loop. Look carefully at how we manipulate the indices values.

During the first turn of the loop, the i variable will be equal to 0, so the instructions in the body will
actually perform the following operations:

auxiliary = numbers[0];

numbers[0] = numbers[4];

numbers[4] = auxiliary;

At the second turn, i will be equal to 1 , so:

auxiliary = numbers[1];
numbers[1] = numbers[3];

numbers[3] = auxiliary;

As you can see, the loop does the same job by shortening the source code and making it more
readable.

for(int i = 0; i < 2; i++) {

auxiliary = numbers[i];

numbers[i] = numbers[4 – i];

numbers[4 – i] = auxiliary;

} Vector initialization
Defaultly, a newly created vector is filled with zeros. It's a good starting point for many of applications
but sometimes you may want the vector to begin its life with a different set of values. Fortunately,
you can initiate vectors, i.e. assign initial values to them at the time of declaration. We do this slightly
differently than the initiation of scalars because we need to specify more than one value.

The syntax of a vector initiator is clear and legible. Imagine that we want to create an array where
the value of any element is equal to its index. A suitable initiator would look like this:

vector<int> int_vector = {0,1,2,3,4};

As you can see, the vector initiator is simply a list of values enclosed inside curly brackets.

Note: using an initializer precludes the possibility of specifying the size of the vector as the compiler
deduces vector's size from the initiator's length.

The equal sign ( = ) can be omitted so the following line is still valid and causes the same effect:

vector<int> int_vector {0,1,2,3,4};

If you provide neither the vector's size nor the initiator, the created vector will be of size 0 . Such a
vector seems to be completely useless but it's only a guise - the vectors are able to change their size
dynamically so there is no obstacle to make the vector more capacious in the future. This is how
such a zero-length can be created:

vector<int> int_vector;

TIME MACHINE do końca!


The old style vector declaration can use initiator too but its syntax is a bit different - look:

int int_vector[5] = {0, 1, 2, 3, 4};


If you provide fewer values than the size of a vector, like this, nothing bad will happen. The compiler
determines that those elements you didn‘t specify any value to should be set to 0.

int int_vector[5] = {0,1,2};

Not only ints


So far, we’ve discussed vectors whose elements are of type int only. Don't worry. You
can also use vectors of any other type.

Let's assume that we've already included the <vectors> header file and the using
namespace directive has been successfully issued. Having these two things done we can
present you some examples.

This is an array in which you can store ten floating-point values.

vector<float> float_vec(10);

And you can store twenty characters here:

vector<char> surname(20);

...as well as the logical (Boolean) values:

vector<bool> votes(100);

Virtually every piece of data can be aggregated into a vector. Even a vector. We‘ll show
you that soon.

TIME MACHINE
The above declarations expressed in the older form would look like:

float float_vec[10];
char surname[20];
bool votes[100];

We're sure that you're able to successfully switch between both forms of vector's
declaration.

Not only vectors


We’ve assumed thus far that vectors consist of scalars, but in fact, vectors can
contain elements of a much more complex structure. Let’s consider the case
when an vector's elements are just vectors. Such a construct isn't a vector any
more - as it has more than one dimension (as vectors do) it becomes an array.
Surprising? Not at all! We often find arrays like this in our lives. Probably the best
example of this is simply a chessboard.

What we’re going to say now will probably outrage experienced chess players, so we
apologize in advance for all our simplifications and inaccuracies. If you’re a chess
master... it’s nothing personal.

A chessboard is composed of rows and columns. There are 8 rows and 8 columns.
Each column is marked with the letters A through H. Each row is marked with a number
from 1 to 8. The location of each square is identified by letter-digit pairs. Thus, we know
that the bottom right corner of the board (the one with the white rook) is A1, while the
opposite corner is H8

Let’s assume that we can use the selected integer values to represent any chess piece.
We can also assume that every row on the chessboard is a... vector!

Let's try to declare it – here it is (assuming that we've already done what it takes):

vector<int> row(8);

Unfortunately, we have 8 of these rows. Does this mean that we have to declare 8
arrays like this?

vector<int> row1(8), row2(8), row3(8), row4(8), row5(8), row6(8),


row7(8), row8(8);

Do you feel some sort of déjà vu? We’ve already gone through a similar dilemma, when
we were trying to figure out the reason for using vectors.

A chessboard is in fact an 8-element array of elements as single rows. Let's summarize


our observations:

 elements of rows are fields, 8 of them per row;


 elements of the chessboard are rows, 8 of them per chessboard.

We’re now ready to create an array for the chessboard – here’s the declaration:

vector<vector<int>> chessboard(8, vector<int>(8));

The chessboard variable is a two dimensional array. It’s also called, by analogy to
algebraic terms, a matrix.

Let's analyze the declaration step-by-step:

 the declared variable is a vector;


 each of the vector's elements is another vector containing integer values;
 the declared variable's name is chessboard ;
 the number 8 says that there is space for 8 vectors (but till now we know nothing
about their sizes!);
 the inner declaration vector<int>(8) says that each of the inner vectors
contains space for 8 integers.

Note: the matrix is initially filled with zeros (i.e. each of the 64 fields is set to zero
during matrix creation).

To make the story more generic let us present the following case:

 we are going to declare a matrix consisting of ROWS rows;


 each of the rows contains COLS elementes of type TYPE.

The relevant declaration looks as follows:

vector<vector<TYPE>> matrix(ROWS, vector<TYPE>(COLS));

TIME MACHINE
Similar old-style declaration for the chessboard would look as follows:

int chessboard[8][8];

Yes, it looks much, much simpler but the price we pay for the simplicity isn't worth the
profits we can get from newer mechanisms.

A vector is one-dimensional structure so if you need to access any of its elements,


you're obliged do provide exactly one index. A matrix (just like a chessboard) is a two-
dimensional creation thus one index is not enough - you must use two indices to identify
any of the elements:

 the first index selects the row;


 the second one selects the field number inside the row, which is de
facto a column number.

Look at our chessboard. Every field contains a pair of indices which should be given in
order to access the field's content.

Glancing at the figure here → we can set some chess pieces on our board. First, let's put
all the rooks on the board:

chessboard[0][0] = ROOK;
chessboard[0][7] = ROOK;
chessboard[7][0] = ROOK;
chessboard[7][7] = ROOK;

If we wanted to place a knight on C4, we would do this as follows:


chessboard[3][2] = KNIGHT;

And now a pawn to E5:

chessboard[4][4] = PAWN;

As clear as check mate, right?


Now let's go deeper into the multi-dimensional nature of matrices. To find any element of a two-
dimensional array, we have to use two “coordinates”: a vertical (row number) one and
a horizontal (column number) one. Imagine that we develop a piece of software for an automatic
weather station. The device records the air temperature on an hourly basis and does it throughout
the month. This gives us a total of 24 * 31 = 744 values. Let's try to design an array capable of
storing all these results.

First, we have to decide which data type would be adequate for this application. We think that
a float would be the best, since our thermometer can measure the temperature with an accuracy
of 0.1 degree Centigrade. Then we decide that the rows will record the readings every hour on the
hour (so the row will have 24 elements) and each of the rows will be assigned to one day of the
month (so we need 31 rows). Here’s the appropriate declaration:

vector<vector<float>> temp(31, vector<float>(24));

Now we’ll try to determine the monthly average noon temperature. We’ll add all 31 readings
recorded at noon and divide the sum by 31. We assume that the midnight temperature is stored first.
In the editor you can find the relevant code along with the necessary declarations.

TIME MACHINE
An old-style declaration causing the same effect looks as follows:

float temp[31][24];

vector<vector<float>> temp(31, vector<float>(24));

float sum = 0.0;

for (int day = 0; day < 31; day++)

sum += temp[day][11];

float average = sum / 31;

cout << "Average temperature at noon: " << average << endl;
Now let's find the highest temperature for the whole month – see the code in the editor.

vector<vector<float>> temp(31, vector<float>(24));

float max = -100.0;

for (int day = 0; day < 31; day++)

for (int hour = 0; hour < 24; hour++)

if (temp[day][hour] > max)

max = temp[day][hour];
cout << "The highest temperature was " << max << endl;

We want to count the days when the temperature at noon was at least 20 oC.

vector<vector<float>> temp(31, vector<float>(24));

int hotdays = 0;

for (int day = 0; day < 31; day++)

if (temp[day][11] >= 20.0)

hotdays++;

cout << hotdays << " days were hot.";


We’re going to fill the entire array with zeros in order to prepare it for use in the coming month.

vector<vector<float>> temp(31, vector<float>(24));

for (int d = 0; d < 31; d++)

for (int h = 0; h < 24; h++)

temp[d][h] = 0.0;

The C++ language doesn’t limit the size of the array's dimensions. Here we show
an example of a 3-dimensional array (i.e. a vector of vectors of vectors).

Now imagine a hotel. It's a huge hotel consisting of three buildings, 15 floors each.
There are 20 rooms on each floor. We need an array that can collect and process
information on the number of guests registered in each room.

Step one – the type of the array's element. We think an unsigned would fit as there’s no
such thing as a negative number of guests.

Step two – calm analysis of the situation. Summarize the available information: 3
towers, 15 floors, 20 rooms.

Now we can write the declaration (look at the editor).

We agree that declarations like this need a lot of cold blood both to write and read
(we're sure that the most cold blooded of the readers is the compiler). Don't panic, keep
calm and let us to guide you through the dark sides of 3-dimensional declarations:
 let's start from the type: as it's a "vector of vectors of vectors" the corresponding
part of the code seems to be obvious: it's vector<vector<vector<int>>> ; (note
how the nested parts of the clause reflects our verbally expressed idea);
 the right side of the declaration is a harder nut to crack but we aren't going to be
intimidated (after all, we are no less smart than the compiler); let's start from the
fact that the most nested element is a vector of 20 rooms - we marked in red;
can you see it?

vector<vector<vector<int>>> guests(3,
vector<vector<int>>(15, vector<int>(20)));

 each of 20 room vectors is immersed inside a 15 floor tower - we marked the


tower's part in blue:

vector<vector<vector<int>>>
guests(3, vector<vector<int>>(15, vector<int>(20)));

 as there are 3 towers the most outer part of the guests description looks like the
fragment showed in green:

vector<vector<vector<int>>> guests(3, vector<vector<int>>(15, vector


<int>(20)));

The first index (0 through 2) selects one of the buildings; the second (0 through 14)
selects the floor, the third (0 through 19) selects the room number.

Now we can book a room for two newlyweds: in the second building, on the tenth floor,
room fourteen:

guests[1][9][13] = 2;

and release the second room on the fifth floor located in the first building:

guests[0][4][1] = 0;

Before we say goodbye and finish this part of our course, let's check if there are any
vacancies on the fifteenth floor of the third building:

int room;
int vacancy = 0;
for (room = 0; room < 20; room++)
if (guests[2][14][room] == 0)
vacancy++;
The vacancy variable contains 0 if all the rooms are occupied; otherwise it displays the
number of available rooms.

TIME MACHINE
An equivalent old-style declaration would say:

int guests[3][15][20];

vector<vector<vector<int>>> guests(3, vector<vector<int>>(15, vector<int>(20)));

We have a feeling that you may want to ask us about a delicate issue: why we want you
to use these complicated and winding vector declarations when the old-style vectors
look so simple and tempting? How would you benefit from not to write something as
simple as:

int vect[10];

but write that a bit mysterious phrase instead:

vector<int> vect(10);

which must be also accomplished with additional #include <vector> and using
namespace std; ? What's going on here? Where is the advantage of the new over the
old?

The old-style vectors, matrices and arrays are stiff as a rock. Created once, they exist
unchanged until the end of their existence. You can neither expand them to
accommodate more data then you initially expected nor shrink them to release
unneeded and wasted memory. If you're going to implement a vector with a variable
content you have to do everything yourself: create a counter storing the actual number
of elements (which has to be less than vector's size at every moment of the program
execution), move some elements to the right when a new element is inserted into the
vector and move them to the left when an existing element is removed from the vector
(yes, we assume that vector's elements are deployed from left to right hence the
direction of our moves).

Modern vector can do all these things for us themselves. Really.

But before we tell you about all these magical amenities, we have to introduce you to
the new world - world of methods. Not so far from here you will start your journey
through the object oriented programming when you create your own classes equipped
with properties and methods so we don't want to burden you with unnecessary
(currently) details - there will be time for them soon. For now, we'll tell you that
a method is a close relative of function but the way in which the method is invoked
looks a bit different. Let's assume that there is a variable of type float and we want to
find square root of the variable. This is how we do it:

float value = 144;


float root = sqrt(value); // 12.
Each vector has a method named size which provides you with current size of the
subject vector. To obtain this information you need to invoke the method in the
following way:

vector<int> vect(10);
int current_size = vect.size(); // 10

Note: the method is invoked from within the vector! The vector (whose size is being
determined by the invocation) is not an argument but a place where the method lives
thus you have to invoke it in this distinctive way.

The power of the modern vectors (compared to old-style solutions) lies in the fact that
they are equipped with a numerous methods what makes them elastic and flexible.

Let's take a look at some of these conveniences, but before we want you to analyze and
run the code inside the editor. Thank you.

#include <iostream>

#include <vector>

using namespace std;

int main()

int elements = 10;

vector<int> vect(elements);

int current_size = vect.size();

cout << current_size << endl;

When a vector is brought to life using the old-fashioned declaration (like the one presented in the
code window) there is no simple way to determine number of vector's elements -
the size() method does not exist and cannot be invoked (try do it yourself!). One of possible tricks
that can be used instead is to determine whole vector's size and to divide it by single element's size -
this is how we do it!
Let's dive into more advanced modern vector's skills.

#include <iostream>

using namespace std;

int main()

int elements = 10;

int vect[elements];

int current_size = sizeof(vect) / sizeof(vect[0]);

cout << current_size << endl;

Modern vectors can be freely expanded - the old ones can't. A method
named push_back(value) is able to extend vector's size by one and to put a new value at vector's
end. To make the sample more spectacular we set vector's initial size to zero and pushed back three
values changing vector's size to 3.

Note: don't forget that the type of value being pushed back should be compatible with vector's
elements type!

There are much more facilities that new style vectors provide and old one doesn't. We're not going to
tell about them now as we prefer to do it later along with more advanced topics. The more important
factor is to convince you that modern vectors are worth using - their potential cannot be overrated.

#include <iostream>

#include <vector>

using namespace std;

int main()

vector<int> vect(0);

vect.push_back(1);
vect.push_back(-1);

vect.push_back(0);

cout << vect.size() << endl;

for(int i = 0; i < vect.size(); i++)

cout << vect[i] << " ";

cout << endl;

Structures – why do we need them?


Before we start going on about structures, we need to tell you about a completely new
type, named string. For now, we’re not going to tell you any more than what we use it
for and how we operate on variables of this type. We promise we’ll give you more
details in a separate section devoted exclusively to strings, and we’ll show you how to
manipulate them and how to enjoy using them.

To be honest, a string is little more than a type, and all we want to tell you at this point
is that variables of type string are able to store strings of characters, like surnames,
family names, street names and all other names you can think of, including R2D2.

Note: if you want to utilize the string type in your code you've to ensure that:

 the string header file has been included i.e. your source file should contains
directive: #include <string>
 the using namespace std; statement has been placed at the top of your code
unless you agree to use prefix std:: every time you make use of string .

Variables of type string may be assigned with the same operators as any other
variable we’ve previously encountered. For example, if we want to store the name of
our favourite dish in a string variable, we do it in the following way:

string dish_to_order = "pizza";

Imagine that we, the developers, have the following job to do: we’re obliged to design a
data-base that can store information about students attending our course. It needs to
store the name of each student, the time spent on studying the chapters and the
number of the last completed chapter. We know that the total number of all students
will not exceed 100,000. This leads us to write the following declaration:

vector<string> student_name(100000);

The array allows us to store up to 100,000 names.


Let's try to manipulate that array. For example, suppose that the first registered student
was Mr. Bond (James Bond). Let’s store the information in our array:

student_name[0] = "Bond";

The time spent on the site will be stored as a float. This is not particularly convenient,
but we can certainly handle it. The number of hours will be represented as a decimal
fraction. This leads us directly to the following statement.

vector<float> student_time_spent(100000);

We know that Mr. Bond spent three hours and thirty minutes studying our course. We’ll
denote it in the following way:

student_time_spent[0] = 3.5;

Note: 3h30m = three and a half hours, thus 3.5.

The recent chapter number is obviously an int . This is the declaration we need:

vector<int> student_recent_chapter(100000);

Using some advances spying techniques we noticed that James finished his study at
chapter number 7 (we don't write it as 007 as it would be an octal number what may
introduce unnecessary confusion - sorry!). We record this fact using the following
assignment:

student_recent_chapter[0] = 7;

The main issue here is that the data concerning the same object (a student) is dispersed between
three variables, although it should logically exist as a consolidated unit. Handling multiple arrays is
cumbersome and error-prone, and when life forces us to collect additional student's information (e.g.
e-mail address) we’re going to need to declare another array and make a lot of other changes
throughout the program. We don’t like it, and you can be sure you won't like it either.

We already know what a vector is. The vector is an aggregate of elements. The elements are
numbered and are of the same type. Can we use an aggregate whose elements could be of
different types? Could they be identified by names, not by numbers? And is it a good idea?

Yes, it's a great idea! This magical aggregate is called a structure.

A structure contains any number of elements of any type. Each of these elements is called a field.
Each field is identified by its name, not by its number. Obviously, the field names must
be unique and cannot be doubled within a single structure. We’ll show you how to declare a
structure suitable for our needs and we’ll explain its meaning.

You can see the declaration of the structure in the editor.

 the declaration of the structure always starts with the keyword struct ;
 there is a so-called struct tag after the keyword ( Student in this case); it's the name of the
structure itself; there is a widely accepted custom of composing structure tags starting with
capital letter simply to distinguish them from ordinary variables;
 here comes the opening curly bracket – a sign that the field declaration begins at this point;
 our structure has three fields: the first is a string and is called name ; the second is
a float and is called time_spent ; the third is an int and it’s called recent_chapter
 the declaration ends with the closing curly bracket followed by a semicolon.
struct Student {

string name;

float time_spent;

int recent_chapter;

};

We want to emphasize that the previous declaration doesn't create a variable, but only
describes the structure we’re going to use in our program. If we want to declare a
variable as a structure, we can do it in one of two possible ways:

Student stdnt;
Student stdnt2;

This declaration sets up two variables (structured variables)


named stdnt and stdnt2 respectively. The variables are of type struct STUDENT or
just STUDENT (notice, that the structure declaration creates a new type name). We know
that this variable consists of three named fields, but we don’t yet know how to access
them.

As the C++ language offers a specialized indexing operator [] for arrays, it also gives
us a so-called selection operator designed for structures and is denoted as a single
character . (dot).

The priority of the selection operator is very high, equal to the priority of
the [] operator.

This is a binary operator. Its left argument must identify the structure while the right
argument must be the name of the field known in this structure.

The result of this operator is the selected field of structure, and therefore the expression
containing this operator is sometimes called a selector.

This means that the selector here:

stdnt.time_spent

results in the selection of a field named time_spent . The type of this expression is the
type of the selected field and this expression is an l-value (i.e. a value that can be put
at the left side of a assignment operator = .
Consequently, you can use both of these selectors:

stdnt.time_spent = 1.5;

and

float t = stdnt.time_spent;

TIME MACHINE
Modern C++ treats structure's names in the same way as other types names (like
the Student in our example) but there's also possibility (derived from C where it was
the only method to name structured types) to use phrase struct Student as type's
name. In effect, the following declaration is correct either, but - you will admit it, won't
you? - definitely looks uglier:

struct Student stdnt;

Virtually any data could be used as a structure's field: scalars, vectors and other arrays
and also almost all of the structures. We say “almost” because a structure cannot be
a field of itself.

Structures can be aggregated inside a vector, so if we want to declare a vector


consisting of Student structures, we do it in this way:

vector<Student> stdnt(100000);

Access to the selected fields requires two subsequent operations:

 in the first step, the [] operator indexes the vector in order to access the
structure we need;
 in the second step, the selection operator selects the desired field.

This means that if we want to select the time_spent field of the fourth stdnts ' element,
we'll write it like this:

stdnts[3].time_spent

We’ve collected all these assignments which have been performed for the three
separate arrays. Analyze them carefully:

stndts[0].name = "Bond";
stndts[0].time_spent = 3.5;
stdnts[0].recent_chapter = 7;

Declaring the structures


For the purposes of further considerations we’ll use a simple structure designed to store the date. It’s
equipped with three fields, each of type int , named year , month and day , which clearly denote
their role and purpose.

The first possible way of declaring the structure is in the editor.

Of course, we can write this declaration much more compactly:

struct Date {
int year, month, day;
};

Both variants are equivalent.

That declaration doesn't create any new variables, but only announces to the compiler our
intention to use this structure tag to declare new variables. The new variable would be declared, for
example, in this way:

Date DateOfBirth;

We can use it to store Harry Potter's date of birth:

DateOfBirth.year = 1980;
DateOfBirth.month = 7;
DateOfBirth.day = 31;

We can also use the structure tag to declare an array of structures:

vector<Date> visits(100);

Accessing a single structure stored in the array is easy. If we want to modify the data of the first visit,
we do this:

Visits[0].year = 2020;
Visits[0].month = 1;
Visits[0].day = 1;

It’s also possible to kill two birds with one stone by defining the structure tag and declaring any
number of variables simultaneously in the same statement, like this:

struct Date {
int year, month, day;
} DateOfBirth, ExpirationDate, ETA;

Date current_date;

We can also omit the tag and declare the variables only:

struct {
int year, month, day;
}
the_date_of_the_end_of_the_world;

In this case, however, determining the type of the


variable the_date_of_the_end_of_the_world becomes troublesome. To show you how it may
reflect programmer's life let's take into consideration a very useful and meritorious operator
named sizeof() (don't be misled - despite its appearance it's an operator, not a function!) which
returns a number of bytes occupied by a variable or a type. E.g. the following line:

cout << sizeof(char) << endl;

will always print 1 - it's one fundamental axioms of both C and C++. If you want to get to know how
many bytes you must to spend to store one date's data, you can obtain this information from the
following expression:

sizeof(Date)

Without a struct you won't have such a possibility although you can
use the_date_of_the_end_of_the_world; instead.

struct Date {

int year;

int month;

int day;

};

Structures – how do we use them?


A structure could be a field inside another structure. Imagine that we have to extend
our Student structure and add a field to save the date when a particular student last accessed the
course. We can do it the way shown in the editor.

It means that we’ll have to use two subsequent selection operations to go deeper into the structure
i.e. first we select a structure within the structure and then we select the desired field of the inner
structure.

This is how it works:

HarryPotter.last_visit.year = 2020;
HarryPotter.last_visit.month = 12;
HarryPotter.last_visit.day = 21;

So now you should be able to answer the following question: when did Harry visit us recently?
struct Student {

string name;

float time_spent;

int recent_chapter;

Date last_visit;

};

Student HarryPotter;

Structures – a few important rules


A structure's field names may overlap with the tag names, and this is generally not considered a
problem, although it may cause some difficulty in reading and understanding the program.

The snippet shown in the editor is completely correct.

struct Struct {

int Struct;

} Structure;

Structure.Struct = 0; // Struct is a field name here

It may be the case that the particular compiler you’re working with doesn't like it when a structure’s
tag name overlaps with the variable's name (you know how those compilers are); – therefore, it's
better to avoid tricks like the ones shown in the editor.

Alternatively, get yourself a new compiler – one that doesn’t complain so much. OK, just kidding.

struct Str {

int field;

} Structure;

int Str;
Structure.field = 0;

Str = 1; // works for us


Two structures can contain fields with the same names – the snippet in the editor is correct.

struct S1 {

int f1;

};

struct S2 {

char f1;

};

S1 str1;

S2 str2;

str1.f1 = 32;

str2.f1 = str1.f1;

Structures can be initialized as early as at the time of declaration. The structure's


initiator is enclosed in curly brackets and contains a list of values assigned to the
subsequent fields, starting from the first.

The values listed in the initiator must conform to the types of the fields. If the
initiator contains fewer elements than the number of the structure's fields, it’s
presumed that the list is automatically extended with zeros. This also means that an
empty structure initializer {} will zero all structure's fields. Keep in mind that zeroing
may cause completely different effects depending on field's type - integers and floats
will be actually zeroed while string fields will be assigned with an empty string
(definitely not with a string "0" ).

If the particular field is an array or a structure, it should have its own initiator, which is
also subject to the rule of zero extension. If an “internal” initiator is complete, we can
omit the surrounding curly parentheses.

Take a look at the example:

struct Date moon_landing = { 1969, 7, 20 };

This initiator is equivalent to the following sequence of assignments:


date.year = 1969;
date.month = 7;
date.day = 20;

And this is a sample initiator for the Student structure:

Student he = { "Bond", 3.5, 4, {2020, 12, 21} };

The initiator of this form is functionally equivalent to the following assignments:

he.name = "Bond";
he.time_spent = 3.5;
he.recent_chapter = 4;
he.last_visit.year = 2012;
he.last_visit.month = 12;
he.last_visit.day = 21;

Due to the completeness of the inner initializer, we can write the following, simplified
form:

Student he = { "Bond", 3.5, 4, 2012, 12, 21};

This simplification (omitting the internal curly brackets) cannot be applied in the
following case (although we must admin that such a way is not recommended and some
compilers may emit a warning message here):

Student she = { "Mata Hari", 12., 12, { 2012 } };

The internal initiator, referring to the last_visit field , doesn't cover all the fields.
This means that it’ll be equivalent to the following sequence of assignments:

she.name= "Mata Hari";


she.time_spent = 12.;
she.recent_chapter = 12;
she.last_visit.year = 2012;
she.last_visit.month = 0;
she.last_visit.day = 0;

Let's see what happens when we apply an “empty” initializer:

Student nobody = {};

Here's the answer:

nobody.name = "";
nobody.time = 0.0;
nobody.recent_chapter = 0;
nobody.last_visit.year = 0
nobody.last_visit.month = 0;
nobody.last_visit.day = 0;

Congratulations! You have completed Module 2.

Well done! You've reached the end of Module 2 and completed a major milestone in your C++
programming education. Here's a short summary of the objectives you've covered and got familiar
with in Module 2:

 how to control the flow of the program;


 more data types;
 conditional instructions: if, else, switch;
 loops and controlling the loop execution;
 logic, bitwise and arithmetic operators;
 vectors, multidimensional arrays;
 declaring and initializing structures.

You are now ready to take the module quiz and attempt the final challenge: Module 2 Test, which
will help you gauge what you've learned so far.

You might also like