C++ uses the following arithmetic operators:
+ | addition |
---|---|
| subtraction |
* | multiplication |
/ | division |
% | modulo |
The last one is perhaps unfamiliar. The result of x % y
("x mod y")
is the remainder that you get after dividing the integer x by the integer y.
For example, 13 % 5 is 3; 18 % 4 is 2; 21 % 7 is 0, and 4 % 6 is 4 (6 into
4 won't go, remainder 4). num = 20 % 7;
would assign the value 6
to num
.
How does the computer evaluate an expression if there is more than one operator in it? For example, given 2 + 3 * 4, does it do the addition first, thus getting 5 * 4, which comes to 20, or does it do the multiplication first, thus getting 2 + 12, which comes to 14? C++, in common with other programming languages and with mathematical convention in general, gives precedence to *, / and % over + and . This means that, in the example, it does the multiplication first and gets 14.
If the arithmetic operators are at the same level of precedence, it takes them left to right. 10 5 2 comes to 3, not 7. You can always override the order of precedence by putting brackets into the expression; (2 + 3) * 4 comes to 20, and 10 (5 2) comes to 7.
Some words of warning are needed about division.
If the operands are both of type int
, the result of a division
is also of type int
. For example, the result
of 7 / 2 is 3, not 3.5. If num
, which is an int
, had the value 7,
then num / 2
would be 3, and 18 / num
would be 2. Computers
are perfectly capable of handling floating-point numbers such as 3.5, but
the type of division carried out depends on the type of the operands.
In order to get a result of 3.5, it would be necessary for at least one
of the operands to be a floating-point number, such as 7 / 2.0
. But if
they are both of type int
, you get integer division with an integer result. I'm not going to say much about floating-point numbers in
this introduction.
A computer would get into difficulty if it tried to divide by zero. Consequently, the system makes sure that it never does. If a program tries to get the computer to divide by zero, the program is unceremoniously terminated, usually with an error message on the screen.
Write down the output of this program:
#include <iostream>
using namespace std;
int main()
{ int num = 5;
cout << num << endl;
num = num + 2; cout << num << endl;
num = num / 3 * 6; cout << num << endl;
cout << 7 + 15 % 4 << endl;
num = 24 / 3 / 4; cout << num << endl;
num = 24 / (num / 4); cout << num << endl;
}
To check your answers, click on Answers to the exercises.
I said earlier that you could use more or less any names for your variables. I now need to qualify that.
The names that the programmer invents are called identifiers. The
rules for forming identifiers are that the first character can be a letter
(upper or lower case) and subsequent characters can be letters or digits
or underscores. (Actually the first character can be an underscore but
identifiers beginning with an underscore are often used by system programs
and are best avoided.) Other characters are not allowed. C++ is
case-sensitive, so Num
, for example, is a different identifier from
num
.
The only other restriction is that you cannot use any of the language's keywords
as an identifier. You couldn't use int
as the name of a variable,
for example. There are 74 keywords but most of them are words that you
are unlikely to choose, such as reinterpret_cast
or xor_eq
.
Ones that you might accidentally hit upon are break, case, catch, class,
const, continue, delete, double, export, float, friend, long, new, return,
short, switch, this, throw, try
and union.
You should also avoid
using words which, though not technically keywords, have special significance
in the language, such as cin
, cout
and string
.
Programmers often use very short names for variables, such as i, n
or
x
for integers. There is no harm in this if the variable is used to
do an obvious job, such as counting the number of times the program goes round
a loop and its purpose is immediately clear from the context. If, however, its
function is not so obvious, it should be given a name that
gives a clue as to the role it plays in the program. If a variable is
holding the total of a series of integers and another is holding the
largest of a series of integers, for example, call them total
and max
rather than x
and y
.
The aim in programming is to write programs that are "self-documenting", meaning that a (human) reader can understand them without having to read any supplementary documentation. A good choice of identifiers helps to make a program self-documenting.
Comments provide another way to help the human reader to understand a program. Anything on a line after "//" is ignored by the compiler, so you can use this to annotate your program. You might summarise what a chunk of program is doing:
// sorts numbers into ascending order
or explain the purpose of an obscure bit:
x = x * 100 / y; // x as percent of y
Comments should be few and helpful. Do not clutter your programs with statements of the obvious such as:
num = num + 1; // add 1 to num
Judicious use of comments can add greatly to a program's readability, but they
are second best to self-documentation. Their weakness is that it is all too
easy for a programmer to modify the program but forget to make any
corresponding modification to the comments, so the comments no longer quite
go with the program. At worst, the comments can become so out-of-date as
to be positively misleading.
Say for each of the following whether it is a valid identifier in C++ and, if not, why not:
BBC, C++, y2k, Y2K, old, new, 3GL, a.out, remove,
first-choice, 2nd_choice, third_choice, constant, UNION
To check your answers, click on Answers to the exercises.
As well as variables of type int
we can have variables of type
string
. To do this we have to include another of those lines at
the start of the program whose purpose I have yet to explain:
#include <string>
We could declare a string
variable as follows:
string s;
and also initialize it if we wanted to:
string s = "Wallace";
We can change the value of a string with assignment:
s = "Feathers McGraw";
or, if we had two strings s
and t
:
s = t; // (s and t do not need to be the same length)
We can also use cin >>
to give a new value to a string:
cin >> s;
When this statement is executed, the computer will skip any leading spaces
or tabs or blank lines until it comes to a non-space character. This
will be the first character of the string s
. Then it picks up
characters and adds them to s
until it comes to a space, tab or
end-of-line, at which point it stops. So, if the input was:
Silverdale
the value in s
would be "Silverdale
" (without the leading spaces).
If the input was:
Warton Crag
the value in s
would be "Warton
", since it would stop at the space.
Another useful input function with strings is getline
, as in
getline(cin, s);
This takes the whole of the input line and puts it into s
, spaces and
tabs included. Executing this statement with the input line
Silverdale, Warton Crag
(with the line ending after "Crag")
would put the whole line into s
, including all the spaces, from
the leftmost of the leading spaces up to the "g" of "Crag".
The "+" operator has special significance with strings; it is the
concatenation operator. For example, if s
had the value
"Wallace
" and t
had the value "Grommit
", then
s = s + " and " + t;
would give s
the value "Wallace and Grommit
".
If you want to know how long a string is, you can find out with the length
function. If s
is the string, s.length()
(don't forget the
brackets) is the length. You could say, for example:
string s;
cin >> s;
int len = s.length();
And you can obtain a substring of a string with the substr
function.
For example if s
has the value "Silverdale
", then
s.substr(0,6)
will give you the first six letters, ie the string
"Silver
". The first number in brackets after the substr
says where you want the substring to begin, and the second number says how
long you want it to be. Note that the initial character of the string
is at position 0, not position 1. If you leave out the second number,
you get the rest of the string. For example, s.substr(6)
would
give you "dale
", ie the tail end of the string beginning at character 6
('d' is character 6, not 7, because the first one is character 0).
You can output substrings with cout <<
or assign them to other
strings or combine them with the "+" operator. For example:
string s = "software services";
s = s.substr(0,4) + s.substr(8,1) + s.substr(13);
cout << s << endl;
will output "soft ices".
Say what the output of the following program fragment would be:
string s = "artificial reality";
cout << s.substr(11,4) + " " + s.substr(0,3) << endl;
cout << s.substr(11).length() << endl;
To check your answers, click on Answers to the exercises.
if
statements)
To write anything more than very straightforward programs we need some way
of getting the computer to make choices.
We do this in C++ with the keyword if
.
We can write, for example,
if (num == 180)
cout << "One hundred and eighty!" << endl;
When the computer executes this, it first sees whether the variable num
currently has the value 180 or not. If it does, the computer displays
its message; if it doesn't, the computer ignores the cout
line
and goes on to the next line.
Note that the conditional expression (num == 180
) has to be
in brackets.
Note also that, to test whether num
has the value 180
or not, we have to write if (num == 180)
and not if (num = 180)
.
We have to remember to hit the "=" key twice.
This is a serious nuisance in C++, especially for beginners.
It comes about because the language uses the "=" operator for a different
purpose, namely assignment. num = 180
does not mean, " num
is
equal to 180." It means, "Give the value 180 to num
." You may feel
that it is obvious that assignment is not what is intended in
if (num = 180)
, but unfortunately the rules of the language allow
an assignment at this point, and that is
how the computer will interpret it. The line if (num = 180)
,
with one "=" sign, will actually give the value 180 to num
.
You have been warned.
The following program takes two numbers and displays a message if they happen to be the same:
#include <iostream>
using namespace std;
int main()
{ int num1, num2;
cout << "Please key in a number: ";
cin >> num1;
cout << "And another: ";
cin >> num2;
if (num1 == num2)
cout << "They are the same" << endl;
}
Conditional expressions the kind that follow an if
can be formed using the following operators:
== | is equal to |
---|---|
!= | is not equal to |
> | is greater than |
< | is less than |
>= | is greater than or equal to |
<= | is less than or equal to |
When these operators are used with integers, their meaning is obvious,
but they can also be used with strings. Here their meaning corresponds
to something like alphabetical order. For instance, if (s < t)
,
where s
and t
are strings means "If s
comes before t
in alphabetical order." So it would be true if s
had the value
"Birkbeck
" and t
had the value "College
". All the
upper-case letters come before the lower-case, so (s < t)
would
still be true if s
had the value "Zebra
" and t
had the
value "antelope
" (upper-case 'Z' comes before lower-case 'a').
But what about strings that contain non-alphabetic characters? Would s
come before t
if s
had the value "#+*
" and t
had the
value "$&!
"? To find the answer we have to consult the
ASCII table the American Standard Code for Information Interchange.
ASCII, pronounced to rhyme with "Askey",
defines a particular ordering of all the characters
on the keyboard. (There are other orderings in use, notably EBCDIC which
is used on IBM mainframe computers, but, since ASCII was adopted by PCs,
it has become the general de facto standard.) The ASCII table tells us that the
character '#' comes before the character '$', for instance.
There is a listing of the printable characters in the ASCII set at the end of this chapter. Some points worth remembering are:
s < t
would be
true or false, assuming that s
had the value on the left and t
had the value on the right:
"A" | "9" |
"Zurich" | "acapulco" |
"Abba" | "ABBA" |
"long_thing_with_a_$" | "long_thing_with_a_&" |
"King's College" | "King Kong" |
To check your answers, click on Answers to the exercises.
if .. else
)
The following program fragment tells students whether they have passed their exam:
int exammark;
cout << "Please key in your exam mark: ";
cin >> exammark;
if (exammark >= 40)
cout << "A satisfactory result" << endl;
What happens, in the case of this exam mark program, if a student's mark is
< 40? The program does nothing. This kind of if
statement is a
one-way branch. If the condition is true, we do something; if not, we do
nothing. But in this case
this seems unsatisfactory. If the exam mark is < 40, we would like
it to display "I'm afraid you have failed." We could arrange this by
including another test if (exammark < 40)
or, better, we could
do it by using the keyword else
, thus:
if (exammark >= 40)
cout << "A satisfactory result" << endl;
else cout << "I'm afraid you have failed." << endl;
The else
turns a one-way branch into a two-way branch. If the condition
is true, do this; otherwise, do that.
Write a program that takes two numbers, one representing a husband's salary and the other representing the wife's, and tells them whether or not their combined income makes them due for tax at the higher rate (exceeding £40000).
To check your answers, click on Answers to the exercises.
Let's suppose we want to extend the exam mark program so that candidates who have passed get two lines of output, thus:
if (exammark >= 40)
cout << "A satisfactory result" << endl;
cout << "You may proceed with your project." << endl;
else cout << "I'm afraid you have failed." << endl;
Unfortunately the compiler will object to this. It will say that it has
encounted an else
in an unexpected place. What is the problem?
Although the layout of this program suggests that the "satisfactory" line
and the "proceed with project" line go together, there is nothing to
indicate this to the compiler. As I pointed out earlier, the compiler
pretty much ignores the layout. So far as the compiler is concerned,
we have a one-way if
statement (the kind without an else
) which ends
at the first endl;
Then there is another cout
line (proceed with
project) which is not part of the if
statement; it's just the first
line of the rest of the program. And then, unexpectedly,
appears an else
.
We need some way of bracketing together
the "satisfactory" line and the "proceed with project" line so as to make
it clear to the compiler that both of these lines come under the if
.
This is how we do it in C++:
if (exammark >= 40)
{ cout << "A satisfactory result" << endl;
cout << "You may proceed with your project." << endl;
}
else cout << "I'm afraid you have failed." << endl;
The curly braces have the effect of grouping all the statements inside
them into a programming unit called a block. If the exam mark is
>= 40, the whole of the block is executed. If the mark is < 40, the
computer skips to the else
and executes the "I'm afraid" line.
You will find that different programmers, and different textbooks, have different ideas about the precise placement of the curly braces. Some would set out the above fragment as:
if (exammark >= 40) {
cout << "A satisfactory result" << endl;
cout << "You may proceed with your project." << endl;
}
else cout << "I'm afraid you have failed." << endl;
and there are other variations. Personally I like to see the opening and
closing curly braces lined up vertically. It helps the reader to see how
they match up.
Extend the above program fragment so that all the candidates get two lines of output, the unsuccessful ones getting "I'm afraid you have failed," and "You may re-enter next year."
To check your answers, click on Answers to the exercises.
Suppose now that we wanted to give a different message to candidates who had done exceptionally well. Our first thought might be as follows:
if (exammark >= 70)
{ cout << "An exceptional result!" << endl;
cout << "We expect a first-class project from you." << endl;
}
if (exammark >= 40)
{ cout << "A satisfactory result" << endl;
cout << "You may proceed with your project." << endl;
}
else cout << "I'm afraid you have failed." << endl;
But this would not work quite right. It's OK for candidates with marks < 70,
but candidates with marks >= 70 would get the following output:
An exceptional result
We expect a first-class project from you.
A satisfactory result
You may proceed with your project.
The problem is that if a mark is >= 70, it is also > 40. The first
condition is true, so we get the "exceptional" part, but then the second
condition is also true, so we get the "satisfactory" part. We want to
proceed to the >= 40 test only if the mark is < 70. We need another else
:
if (exammark >= 70)
{ cout << "An exceptional result!" << endl;
cout << "We expect a first-class project from you." << endl;
}
else if (exammark >= 40)
{ cout << "A satisfactory result" << endl;
cout << "You may proceed with your project." << endl;
}
else cout << "I'm afraid you have failed." << endl;
Write a program which takes two integers as input. If the first is exactly divisible by the second (such as 10 and 5 or 24 and 8, but not 10 and 3 or 24 and 7) it outputs "Yes", otherwise "No", except when the second is zero, in which case it outputs "Cannot divide by zero."
Write a program which takes an integer as its input representing the time using the 24-hour clock. 930 is 9.30 am; 2345 is 11.45 pm. Midnight is zero. The program responds with a suitable greeting for the time of day. If you want to make this a bit harder, make the program respond with a "?" if the time represented by the number is impossible, such as 2400, 5 or 1163.
To check your answers, click on Answers to the exercises.
The portion of the ASCII table dealing with printable characters is as follows. The numbers indicate the character's position in the ASCII character set; upper-case 'A', for example, is character number 65. Character number 32 is a space.
32 | 48 | 0 | 64 | @ | 80 | P | 96 | ` | 112 | p | |
33 | ! | 49 | 1 | 65 | A | 81 | Q | 97 | a | 113 | q |
34 | " | 50 | 2 | 66 | B | 82 | R | 98 | b | 114 | r |
35 | # | 51 | 3 | 67 | C | 83 | S | 99 | c | 115 | s |
36 | $ | 52 | 4 | 68 | D | 84 | T | 100 | d | 116 | t |
37 | % | 53 | 5 | 69 | E | 85 | U | 101 | e | 117 | u |
38 | & | 54 | 6 | 70 | F | 86 | V | 102 | f | 118 | v |
39 | ' | 55 | 7 | 71 | G | 87 | W | 103 | g | 119 | w |
40 | ( | 56 | 8 | 72 | H | 88 | X | 104 | h | 120 | x |
41 | ) | 57 | 9 | 73 | I | 89 | Y | 105 | i | 121 | y |
42 | * | 58 | : | 74 | J | 90 | Z | 106 | j | 122 | z |
43 | + | 59 | ; | 75 | K | 91 | [ | 107 | k | 123 | { |
44 | , | 60 | < | 76 | L | 92 | \ | 108 | l | 124 | | |
45 | - | 61 | = | 77 | M | 93 | ] | 109 | m | 125 | } |
46 | . | 62 | > | 78 | N | 94 | ^ | 110 | n | 126 | ~ |
47 | / | 63 | ? | 79 | O | 95 | _ | 111 | o |