C Essentials Mod 2 Notes
C Essentials Mod 2 Notes
Now it's time to talk about another type, which is designed to represent and to
store numbers that (as a mathematician would say) have a non-empty decimal
fraction.
In other words, they’re the numbers that have (or may have) a fractional part
after the decimal point, and although such a definition is very poor, it’s certainly
good enough for our purposes. Whenever we use a term like “two and a half” or
“zero point four”, we think of numbers which a computer considers floating
numbers.
If you want to use a value of just “two and a half”, you should write it as shown in
the picture. Note once again – there is a point between “2” and “5” - not a
comma.
As you can probably imagine, the value of “zero point four” could be written in “C”
as:
0.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 as shown on
the right.
For example: the value of 4.0 could be written as 4. without changing its type or
value.
4.0
For you, they might be exactly the same, but the “C” compiler sees these two
numbers in a completely different way:
We can say that the point makes a double. Don't forget that.
When you want to use any numbers that are very large or very small, you can use scientific
notation. Take, for example, the speed of light, expressed in meters per second. Written
directly it would look like this:
300000000
To avoid tediously writing so many zeros, physics textbooks use an abbreviated form, which
you have probably already seen:
3 • 10^8
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:
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 × 10-34
If you would like to use it in a program, you would write it this way:
6.62607E-34
Knowing that we can declare two floating-point variables, we're going to declare one
named PI (we can't name it Π because – as you already know – the “C” language does not
allow variable names written with Greek letters) and the other one named Field . We don't
need a high degree of precision for our calculations (and we want to save memory), so we're
going to use the float data type:
As you can see, from the syntax's point of view, the difference in declaring integer and float
variables is quite small.
int i;
float x;
i = 10 / 4;
x = 10.0 / 4.0;
This difference is very significant in terms of semantics, which is shown by the example on
the right. With a little anticipation, we can say that the symbol (more precisely –
the operator) which performs the mathematical division is a single character / (slash). Take
a look at this code.
You might find it a little surprising, however, that the value placed in the variable i is 2 (yes,
just 2!), while the variable x is equal to 2.5. Look at this example carefully, because it
illustrates a very important difference between these two data types.
What happens when we’re forced to convert integer values into float values or vice versa?
The transformation from type int into float is always possible and feasible, but in some
cases can cause a loss of accuracy. Consider the example below:
int i;
float f;
i = 100;
f = i;
After the second assignment, 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.
As you’ve probably guessed, these substitutions result in a loss of accuracy – the value of
the variable i will be 100. Twenty-five hundredths has no meaning in the int world. There’s
another aspect of the operation: converting a float into an int is not always feasible. 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 int values, you’re only able to use the
numbers from the range of -2147483648..2147483647.
int i;
float f;
f = 100.25;
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
may be completely random.
This is what we call an implementation dependent issue. It's the second (and uglier) face
of software portability.
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
may be completely random.
This is what we call an implementation dependent issue. It's the second (and uglier) face
of software portability.
int i;
float f;
f = 1E10;
i = f;
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Check the program in the editor. Find all possible compilation errors and logic errors. Fix
them.
Your version of the program must print the same result as the expected output. Before you
use the compiler, try to find the errors only by manual code analysis.
Expected output
The value of seven is: 7.000000
#include <stdio.h>
int main()
return 0;
}
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Check the program in the editor. Find all possible compilation errors and logic errors. Fix
them.
Your version of the program must print the same result as the expected output. Once you
have fixed the errors, remove all the unnecessary characters from the code. Check which
characters may be left without triggering an error.
Before you use the compiler, try to find the errors only by manual code analysis.
Expected output
The value of nine is: 9.000000
#include <stdio.h>
int main()
return 0;
}
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Check the program in the editor. Find all possible compilation errors and logic errors. Fix
them.
Your version of the program must print the same result as the expected output. Before you
use the compiler, try to find the errors only by manual code analysis. Later, you can use the
constant value of Pi.
Expected output
The value of half is: 0.500000
int main()
return 0;
}
Operators
An operator is a symbol of the programming
language which is able to operate on the values.
For example, one assignment operator is
the = sign. You already know that it can assign
values to variables.
Multiplication
An asterisk ( * ) is a multiplication operator. If you take a look at the code, 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,j,k;
float x,y,z;
i = 10;
j = 12;
k = i * j;
x = 1.25;
y = 0.5;
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. Consider the snippet of the program: of course, k will be set
to 2 , z to 0.5 .
int i,j,k;
float x,y,z;
i = 10; j = 5;
k = i / j;
x = 1.0; y = 2.0;
z = x / y;
Division by zero
As you’ve probably guessed, division by zero is strictly forbidden, but the penalty for
violating this rule will come to you at different moments. If you dare to write something like
that, a judgment will be issued by the compiler – you may get a compilation error and you
won't be able to run your program.
float x;
x = 1.0 / 0.0;
In the following example, the compiler won't tell you anything, but when you try to execute
the code it may terminate abnormally and produce unreliable results. You’ll be informed
of this sad fact by a relevant message and then nothing else will happen.
float x,y;
x = 0.0;
y = 1.0 / x;
Addition
The addition operator is the + (plus) sign, which is one that we already know from
mathematics. Again, take a look at the snippet of the program – of course, k becomes 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;
Substraction
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.
As usual, let's get ourselves acquainted with a code snippet – you can probably 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.
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.
int i,j;
i = -100;
j = -i;
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,j;
i = 100;
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 (or modulus as it is often called) is quite a peculiar operator,
because it has no equivalent among traditional arithmetic operators. Its graphical
representation in the “C” language is the following character: % (percent), which may look a
bit confusing. It’s a binary operator and both arguments cannot be floats (don't forget this!).
i = 13;
j = 5;
k = i % j;
You cannot compute the remainder with the right argument equal to zero. We hope you
can guess why.
Priorities
So far, we’ve treated each operator as if it has no connection with the others. Obviously,
such an ideal and simple situation is a rarity in real programming. Also, we very often find
more than one operator in one expression, and then our presumption is no longer so
obvious. Consider the following expression.
2 + 3 * 5
If your memory hasn't failed you, you should know from school that
multiplication precedes addition. You surely remember that you should multiply 3 by 5 and,
keeping 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 a larger (higher) priority perform their operations before the operators with a
lower priority. So, if we know that * has a higher priority than + , the computation of the
final result is pretty obvious.
Bindings
The binding of the operator determines the order of the 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 the expression
shown here 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
You’re probably snorting at this point and saying that all children know perfectly well that
addition is commutative and the order in which the additions are performed has no
meaning. Yes, you're right, but not quite.
Additions performed by computers are not always commutative. Really. We’ll show you this
phenomenon later. Be patient.
List of priorities
Since you're new to “C” language operators, it’s not a good idea to show you the complete
list of the operators' priorities right now. Instead, we’ll show you a truncated version and
expand it consistently as we introduce new operators. The table now looks as follows:
+, - unary
*, /, %
+, - binary
Note: we list the operators in order from the highest to the lowest priority.
We want to check if you’ve understood the concept of binding successfully. 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:
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,j,k,l;
i = 100;
j = 25;
k = 13;
l = (5 * ((j % k) + i) / (2 * k)) / 2;
There are some operators in the “C” language which you won’t find in the mathematics
textbooks. Some of them are frequently used when you want to increment a variable by
one. We often do this when something is counted (e.g. sheep). Let's consider the following
snippet:
int SheepCounter;
SheepCounter = 0;
Every time a sheep runs through our thoughts we want the variable to be incremented, like
this:
SheepCounter = SheepCounter + 1;
Similar operations appear very frequently in typical programs so the creators of the “C “
language introduced a set of special operators for them. One is the ++ (plus plus) operator.
You can achieve the same effect in a shorter way:
SheepCounter++;
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:
++SheepCounter;
--DaysUntilHoliday;
Operation:
++Variable
--Variable
Effect:
Increment/decrement the variable by one 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 one.
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.
int i,j;
i=1;
j=i++;
First, the variable i is set to 1 . In the second statement, we’ll see the following steps:
i=1;
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.
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.
Shortcut operators
It's time for the next set of assignment operators that make a developer's life easier. Those
described earlier deal with addition and subtraction of one. Very often we need something
other than addition or subtraction, or we want to use a value other than one. Consider the
expression below:
i = i * 2;
i *= 2;
SheepCounter += 10;
variable op = expression;
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Check the program in the editor. Find all possible compilation errors and logic errors. Fix
them, but do not change any numeric values.
Your version of the program must print the same result as the expected output. Before you
use the compiler, try to find the errors only by manual code analysis.
Expected output
The value of half is: 0.500000
#include <stdio.h>
int main()
return 0;
}
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Check the program in the editor. Find all possible compilation errors and logic errors. Fix
them, but do not change any numeric values.
Your version of the program must print the same result as the expected output. Before you
use the compiler, try to find the errors only by manual code analysis.
Expected output
The value of four is: 4
#include <stdio.h>
int main()
int fourValue = 2 2 1;
int fiveValue = 2 - 3;
return 0;
}
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Check the program in the editor. Find all possible compilation errors and logic errors. Fix
them, but do not change any numeric values.
Your version of the program must print the same result as the expected output. Before you
use the compiler, try to find the errors only by manual code analysis.
Expected output
The value of ten is: 10.000000
#include <stdio.h>
int main()
float tenValue = 2 3 4;
return 0;
}
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Check the program in the editor. Find all possible compilation errors and logic errors. Fix
them, but do not change any numeric values.
Your version of the program must print the same result as the expected output. Before you
use the compiler, try to find the errors only by manual code analysis.
Expected output
The value of ten is: 10
#include <stdio.h>
int main()
return 0;
}
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Check the program in the editor. Find all possible compilation errors and logic errors. Fix
them, but do not change any numeric values.
Your version of the program must print the same result as the expected output. Before you
use the compiler, try to find the errors only by manual code analysis.
Expected output
The value of eight is: 8
#include <stdio.h>
int main()
int xValue = 4 * 6 % 5;
return 0;
}
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
• Using operators,
• Building simple expressions,
• Translating verbal description into programming language
Scenario
Take a look at the code we've provided in the editor: it assigns two integer values, manipulates them
and finally outputs the result and bigresult variables.
int result;
Test your code using the data we've
provided. int bigResult;
decrement result by 1
*/
return 0;
}
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Check the program in the editor. Find all possible compilation errors and logic errors. Fix
them, but do not change any numeric values.
However, you may use parentheses (you can add or remove them). Your version of the
program must print the same result as the expected output. Before you use your the, try to
find the errors only by manual code analysis.
Expected output
the result is: 28
#include <stdio.h>
int main()
int xValue = 5;
int yValue = 9;
return 0;
}
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Check the program in the editor. Find all possible compilation errors and logic errors. Fix
them, but do not change any numeric values.
However, you can use parentheses (you can add or remove them). Your version of the
program must print the same result as the expected output. Before you use the compiler,
try to find the errors only by manual code analysis.
int xValue = 3;
int yValue = 2;
return 0;
}
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Check the program in the editor. Find all possible compilation errors and logic errors. Fix
them, but do not change any numeric values.
However, you can use parentheses (you can add or remove them). Your version of the
program must print the same result as the expected output. Before you use the compiler,
try to find the errors only by manual code analysis.
int xValue = 5;
int yValue = 3;
return 0;
}
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Complete the program in the editor. Compute the accrued amount of money with a starting
value of 100 and an annual interest rate of 1.5%. Compute and print the results for the first
three years.
Your version of the program must print the same result as the expected output for each
year. Compute each annual value on the basis of the previous year's value.
float firstYearValue;
float secondYearValue;
float thirdYearValue;
/* Your code */
return 0;
}
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
• Using operators,
• Using shortcut and pre/post increment/decrement operators,
• Building simple expressions,
• Translating verbal description into programming language
Scenario
Take a look at the code we've provided in the editor: it assigns two integer values,
manipulates them and finally outputs the result and bigresult variables.
The problem is that the manipulations have been described using natural language, so the
code is completely useless now.
We want you to act as an intelligent compiler and to translate the formula into real "C" code
notation. It's the same code as the one we've provided in one of the previous labs, but this
time, try to use pre/post and short-cut operators - they fit perfectly into some of the steps.
Expected output
result: 38
int main(void)
int xValue=5;
int yValue=9;
int result;
int bigResult;
/*
increment xValue by 3
decrement result by 1
*/
return 0;
}
The char type
So far, we’ve treated the “C” language (and the computer itself) as a tool for performing
calculations on numbers. This is consistent with the common belief that a computer is just a
smarter calculator. But you know this isn’t true, as a 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 these strings during the first lesson when we used the puts function to write
some text on the computer screen.
Now, however, we we’re going to ignore strings consisting of multiple characters and focus
our attention on single characters. The problem with processing strings, though, will come
back to haunt us when we start working on arrays, because in the “C” language all strings
are treated as arrays.
To store and manipulate characters, the “C” language provides a special type of data. This
type is called a char, which is an abbreviation of the word character.
char Character;
Looks familiar, doesn't it? Now let's say a few words 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) 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.
Character Dec Hex Character Dec Hex Character Dec Hex Character D
(NUL) 0 0 (space) 32 20 @ 64 40 ` 96
(SOH) 1 1 ! 33 21 A 65 41 a 97
(STX) 2 2 " 34 22 B 66 42 b 98
(ETX) 3 3 # 35 23 C 67 43 c 99
(EOT) 4 4 ($) 36 24 D 68 44 d 10
(ENQ) 5 5 % 37 25 E 69 45 e 10
(ACK) 6 6 & 38 26 F 70 46 f 10
(BEL) 7 7 ' 39 27 G 71 47 g 10
(BS) 8 8 ( 40 28 H 72 48 h 10
(HT) 9 9 ) 41 29 I 73 49 i 10
(LF) 10 0A * 42 2A J 74 4A j 10
(VT) 11 0B + 43 2B K 75 4B k 10
(FF) 12 0C , 44 2C L 76 4C l 10
(CR) 13 0D - 45 2D M 77 4D m 10
(SO) 14 0E . 46 2E N 78 4E n 11
(SI) 15 0F / 47 2F O 79 4F o 11
(DLE) 16 10 0 48 30 P 80 50 p 11
(DC1) 17 11 1 49 31 Q 81 51 q 11
(DC2) 18 12 2 50 32 R 82 52 r 11
(DC3) 19 13 3 51 33 S 83 53 s 11
(DC4) 20 14 4 52 34 T 84 54 t 11
(NAK) 21 15 5 53 35 U 85 55 u 11
(SYN) 22 16 6 54 36 V 86 56 v 11
(ETB) 23 17 7 55 37 W 87 57 w 11
(CAN) 24 18 8 56 38 X 88 58 x 12
(EM) 25 19 9 57 39 Y 89 59 y 12
(SUB) 26 1A : 58 3A Z 90 5A z 12
(ESC) 27 1B ; 59 3B [ 91 5B { 12
(FS) 28 1C < 60 3C \ 92 5C | 12
(GS) 29 1D = 61 3D ] 93 5D } 12
(RS) 30 1E > 62 3E ^ 94 5E ~ 12
(US) 31 1F ? 63 3F _ 95 5F 12
We do this as follows:
Character = 'A';
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?
Firstly, because it’s illegible. Without knowing ASCII code, it’s 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 uses this devious way to save the number of sheep that have already been
counted.
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) 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:
Character = '?';
the compiler running on that computer would notice the question mark and use the appropriate
EBCDIC code for that character.
Character = 63;
you wouldn’t give the compiler a chance to guess what your intention was. We can assure you (even
without having the EBCDIC code table at hand), that 63 certainly does not represent the question
mark in the EBCDIC code.
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.
Character literals
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 which also extends to other characters, not only to
apostrophes. Let's start with an apostrophe anyway. The correct format looks as follows:
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
'\''
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';
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 Char;
Char = 'A';
Char += 32;
This sequence of subsequent addition and subtraction will bring the Char value to its original value
( A ). You should be able to explain why, right?
Now look at the assignments below. They're all correct. Try to interpret their meanings – this should
be a good exercise for you:
Check
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Check the program in the editor. Find all possible compilation errors and logic errors. Fix them, but
do not change any character values.
Your version of the program must print the same result as the expected output. Before you use the
compiler, try to find the errors only by manual code analysis.
Expected output
Diff beetween 'c' and 'a' is : 2
#include <stdio.h>
int main()
printf("Diff beetween '%c' and '%c' is : %d\n", 'c', 'a', 'c', 'a');
printf("Diff beetween '%c' and '%c' is : %d\n", 'a', 'c', 'a' 'c');
return 0;
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
• Character types and values
• Fixing errors in a program
• Printing on screen
Scenario
Check the program below. Find all possible compilation errors and logic errors. Fix them,
but you may not change any character values. You may change variable names. Your
version of the program must print the same result as the expected output. Before you use
your compiler, try to find the errors only by manual code analysis.
Expected output
Upper case letters beetween (and with) 'Z' and 'A' is : 26
#include <stdio.h>
int main()
printf("Upper case letters beetween (and with) '%c' and '%c' is : %d\n",
printf("Lower case letters beetween (and with) '%c' and '%c' is : %d\n",
return 0;
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Write a small program which prints the differences between all ten digit characters (from '1'
to '0') and zero ('0'). Print each one on a separate line. Your program must print the same
result as the expected output.
Expected output
'1' - '0' is: 1
#include <stdio.h>
'2' - '0' is: 2
}
'9' - '0' is: 9
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?
x == y
Now let’s ask a few more questions. Try to guess the answers.
Exercise: Is x equal to y ?
Question: 2 == 2
This question is simple. Of course 2 is equal to 2. The computer will answer true .
Question: 1 == 2
Question: i == 0
Note that we can’t know the answer if we don’t know what value is currently stored in the
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 runtime.
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:
BlackSheepCounter == 2 * WhiteSheepCounter
Due to the low priority of the == operator, this question shall be treated as equivalent to this one:
BlackSheepCounter == (2 * WhiteSheepCounter)
DaysUntilTheEndOfTheWorld != 0
The answer true gives us the chance to go to the theater or to visit our friends.
If we want to find out whether or not we have to wear a warm hat, we ask the following question:
If the answer is true because Value1 is greater than or equal to Value2 , the computer will
assign 1 to Answer ( 1 is arguably different from zero). If Value1 is less than Value2 , the
variable Answer will be assigned 0 .
+, - unary
*, /, %
+, - binary
< , <= , > , >=
== , !=
= , += , -= , *= , /= , %=
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;
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).
• 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.
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 GoForAWalk() and HaveLunch() we can write the following snippet:
if(TheWeatherIsGood) GoForAWalk();
HaveLunch();
As we already know, our friend the developer falls asleep when he counts 120 sheep. His sleep is
implemented as a special function named SleepAndDream() . This function does not require any
parameters.
We can read it as: “if SheepCounter 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.
FeedTheSheepdogs();
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 using the K & R style. The letters K and R are the initials of the
creators of the “C” language, Mr. Kernighan and Mr. Ritchie. They presented this style in their classic
book and we will follow it.
The same snippet, written in accordance with the K & R style, will look as follows:
MakeABed();
TakeAShower();
SleepAndDream();
FeedTheSheepdogs();
Note that a conditionally executed block is indented – it improves the readability of the program
and manifests its conditional nature.
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.
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Check the program in the editor. Find all possible compilation errors and logic errors. Fix
them and try to find proper conditions for all of the three statements.
Your version of the program must print the same result as the expected output. Before you
use the compiler, try to find the errors only by manual code analysis.
Expected output
First condition is true
int main()
int a = 10;
if (a 9)
if (a 9)
if (a, 9 + 1)
return 0;
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Write a small program which prints the absolute value of a given number if the number is
less than zero. Next it should print the value of the given number on a separate line.
Your program must print the same result as the expected output. Test it for several other
cases (positive numbers, other negative numbers, etc.)
Expected output
The absolute value of -3 is 3
The value of n is -3
#include <stdio.h>
int main(void)
int n = -3;
/* your code */
return 0;
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Write a program that prints the name of a given day of the week. Your program must print
the same result as the expected output.
Test it for all days of the week (for now, test it only for valid values).
Expected output
The day of the week is: Monday
#include <stdio.h>
int main(void)
int dayOfWeek = 1;
/* your code */
return 0;
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.
You've already learned about one function which serves to output data – but can you remember its
name? Yes, it’s the puts function, and we used it in the very first program we wrote in the “C”
language. The puts function's capabilities aren't really all that stunning – it can write a string on a
computer screen and nothing else. You mustn’t use it if you want to print an integer value or a single
character.
Why? Because of impairment of the puts function. Its argument can only be a string (more
precisely – data of type char * ; but don't be confused by this; we’re going to tell you more about it
soon). No other parameters will be accepted, so the compiler will be unrelenting and it will not
compile such a program.
Output
To accomplish these, and even more complex, tasks, there’s a very powerful function in the “C”
language named printf (print formatted). This function can easily output several values of
different types and mix them with the text. We can’t show you all of its capabilities now because,
firstly, there are many, and secondly, we still lack some theoretical foundations to understand many
of them.
The printf function has several unique features: it doesn’t specify how many arguments must be
provided; the only requirement is that there must be at least one argument; additionally, only the
first argument has a strict type (it must be a string); all subsequent arguments may be of any type. It
isn’t sorcery. The “C” language enables us to write these functions ourselves.
The first, mandatory, argument is called the format. It’s a recipe or a specification according to
which the printf function will proceed with its subsequent arguments.
printf reads the instruction carefully and learns from it which data is to be printed and how it
should be presented to the user. Let's look at it in a few applications. The first is simple – we
tell printf to print some text. We do it like this:
See, now the printf function is invoked with two arguments. The first is the format. The second is a
variable of type int . Take a look at the format – there’s a suspicious character there: % . What is this
mysterious percent intended for?
If there’s a percent symbol inside the format, the printf considers it a hint on how to
proceed with the arguments following the format. The first hint refers to the first argument after the
format, the second to the second, etc. (but there are some exceptions to this simple rule).
The % joined together with some other character(s) is sometimes called a specifier. In the example
here below the format contains one specifier: %d :
The letter d indicates that the corresponding argument should be treated as a value of type int and
sent to the screen as a number.
Let’s have a look at an abbreviated list of specifiers now. The complete list is much more exhaustive,
while the general form of the specifier is far more complex and gives more opportunities to deal with
the look and shape of the data presented.
• %d (as in decimal) specifies that the corresponding argument is a value of type int and
should be presented as a fixed-point decimal number; its synonym is a %i specifier (as
in integer).
• %x (as in hexadecimal) specifies that the corresponding argument is a value of type int and
should be presented as a fixed-point hexadecimal number.
• %o (as in octal) specifies that the corresponding argument is a value of type int and should
be presented as a fixed-point octal number.
• %f (as in float) specifies that the corresponding argument is a value of type float and
should be presented as a single-precision floating-point number.
• %lf specifies that the corresponding argument is a value of type double and should be
presented as a double-precision floating-point number.
Note: Do you remember the difference between a float and a double ? You probably remember
that the main difference is precision: a double is double the size of a float (the size of float is 4
bytes, while the size of double is 8 bytes), which means double has higher precision than float ,
but it also takes up more memory and is slower.
You may ask how to display the percent sign itself if this character is treated as the start of a
specifier. The answer is perhaps not all that obvious: in this case, you need to write two percent
signs side by side (but only one will be displayed). We can also consider it to be a specifier, so let's
add it to our list:
• analyses the format and when it doesn’t encounter any specifiers, puts the
string The year is on the screen;
• at this point, printf encounters a specifier and learns from it that there’s
an int which should be displayed as a decimal number; it retrieves the first
argument after the format (the variable VarInt ) and the screen shows the
number 2012 ;
• printf resumes from reviewing the format and displays the string The radius is
denoted as ;
• next, another specifier is met; this time
one which demands the program to #include <stdio.h>
display the value of type char as a single
character; the character is taken from
the second argument after the format int main(void) {
( VarChar ) and the character r is
displayed; int VarInt;
• printf resumes from reviewing the char VarChar;
format and displays the string while PI
is equal to ; float VarFloat;
• the next (and last) specifier requires it
to display a float value, which is taken
from the third argument after the format VarInt = 2012;
( VarFloat ).
VarChar = 'r';
The year is 2012. The radius is printf("The year is %d. The radius is denoted as %c
denoted as r while PI is equal to while PI is equal to %f",
3.141500
VarInt, VarChar, VarFloat);
return 0;
}
Note that the format contains almost exclusively specifiers – three of them to be exact. This
means that you have to deliver three arguments for the format.
In our example in the editor, this is done by repeating the same variable name three times –
it’s correct in every respect.
Executing this program will output the same variable (or more precisely, its value: 31 ) three
times – once as a decimal number, once as a hexadecimal number and once as an octal
number.
31 1f 37
#include <stdio.h>
int main(void) {
int i;
i = 31;
return 0;
• Mistake #1: there are more format specifiers than arguments, e.g.:
printf("%d %d %d", i, j);
There are three specifiers but only two arguments – the last specifier is missing its argument. If
your compiler is clever enough, it’ll pay attention to this (most modern compilers do). However, if
your compiler is rather clumsy, you won’t get a warning and when you start the program the value
printed for the orphaned specifier will be completely random.
• Mistake #2: there are fewer format specifiers than arguments, e.g.:
printf("%d", i, j);
If the compiler doesn't warn you, the compilation will finish with no obstacles and nothing bad will
happen during the execution. The argument for the missing specifier will simply not be displayed.
• Mistake #3: the type announced by the specifier is different from the type of the
corresponding argument.
int i;
i = 100;
printf("%f", i);
The specifier requires a float but you’ve provided a variable of type int . If the compiler doesn’t
notice, the value that will be printed on the screen at run time will really surprise you. It’ll have little
to do with the actual value of the variable i , which is associated with a different representation of
the int and float data in the computer memory.
• Mistake # 4: a slightly less dramatic example, you demand an int but you provided
a char .
char c;
c = '?';
printf("%d", c);
Nothing bad will happen. Why? Not long ago, we said that the data of type char is treated as integer
data. If you deliver the character value to the printf function, but request a decimal to be shown,
the printf will output the ASCII code of that character which was used as the corresponding
argument.
One issue still needs some additional explanation. The string sent to the screen by
the printf function will appear character by character and if you don't request it explicitly it
will fill the entire line from the left to right margin of the screen (or the window).
will produce a continuous line (maybe spanned over more than one row) filled with text:
We’ll show you a solution – try to explain the way in which it works.
Input
Of course, as equally important as data output is data input. Actually, it’s difficult to imagine any
complex program that does not require any data from the user, although you could do in this
carefree way:
• 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 is not a particularly convenient solution. It’s far better to get information from the user, transfer
it to the program, and then use it for calculations. How can the “C” language program get any data
from a human and store it in variables? As in most cases, if you need to perform some complex
operations, you should begin a search for the function that performs this task, and only if such a
function doesn’t exist should you write it on your own.
In this case however, we’re lucky – the function used for data input already exists and is easily
available.
The function is named scanf (scan formatted) and is a close relative of the printf function. Where
did this relationship come from? You'll see soon.
Imagine that we want to ask the user about the maximum number of sheep that we want to count
before the developer falls asleep. The user enters the value from the keyboard and the program
stores it in a specified variable ( MaxSheep ). An appropriate scanf invocation looks as follows:
scanf("%d", &MaxSheep);
Perhaps you see the similarity to the printf . The first parameter is also a format that tells the
function which data will be given to the program, and in which form. As before, we give arguments
for the format in the amount equal to the number of the given specifiers. At this point, the
similarities end and the differences begin. First, the argument for the print may not be a variable. It
may be an expression as well. Take a look:
printf("%d", 2 * i);
Here we’d like to print the doubled value of i – this is feasible. Using the scanf specifier, we
must explicitly specify the variable that is able to store the data entered by the user. This,
however, is not the end of the differences.
Look at the scanf function invocation once again:
scanf("%d", &MaxSheep);
Do you see the odd & sign in front of the variable MaxSheep ? It’s not a coincidence. Forgive us, but
at this stage of your education, our explanations of this phenomenon will be rather simplistic.
Actually, this is part of a more general and rather complex issue that we want to discuss later.
For now, we’ll tell you that whenever we use the variable name in the program (e.g. MaxSheep ) we
mean the value that this variable is currently storing.
However, the interests of the scanf function are different – it isn’t at all interested in the variable's
value, because it will soon be replaced by the one the user enters.
scanf needs something completely different: precisely where is the variable placed in the
memory? The mysterious & is a unary operator which gives the information about its argument's
location. The scanf 's format provides information about the type of the data while the & , along
with the variable name, says where it has to be placed. Leaving out the & doesn’t cause any
problems during compilation, so therefore you have to remember that scanf essentially needs
it and cannot operate without the & .
Furthermore, the scanf format uses the same specifiers as printf . This should bring to you a sigh
of relief.
Now we’ll show you a simple yet complete program that does the following:
We assure you that analyzing this program shouldn’t be any problem for you.
#include <stdio.h>
int main(void)
scanf("%d", &value);
return 0;
Do you prefer square roots to squares? No problem, but we need to remember two things:
first, there’s no such thing as the square root operator; second, square roots of negative
numbers do not exist.
We can resolve the former issue by finding a function that knows how to compute the root.
This function exists and takes an argument of type float . The result is also
a float (obviously, 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 sqrt (square root float) and requires just one
argument. Oh, one more thing – to use this function, you must include a header file
named math.h .
We need to deal with negative numbers as well. If you’re so reckless as to provide a negative
number, the program will just ignore you and your input completely. It may not be polite,
but at least we won’t be trying to bend the rules of mathematics. Whether we see the result
or not will be decided by the conditional statement.
Now direct your attention to the use of floating point data and the sqrt function.
#include <stdio.h>
#include <math.h>
int main(void) {
scanf("%f", &value);
squareroot = sqrt(value);
return 0;
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Your task is to print values in four different formats. Check the program in the editor.
Find all possible compilation errors and logic errors. Fix them, but do not change any
character values. Your version of the program must print the same result as the expected
output.
Before you use the compiler, try to find the errors only by manual code analysis.
Expected output
2016-02-20 - YYYY-MM-DD format - ISO 8601
#include <stdio.h>
int main()
int month = 2;
printf("%04d-%02d-%02d - YYYY-MM-DD format - ISO 8601\n", year month day year month day);
return 0;
}
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
You have the data (included in code) of three students' grades
( StudentA , StudentB , StudentC ). Write a program to print this data in rows - the first row
is a header in the format:
The next three rows contain: student name ( StudentA , StudentB , StudentC is enough),
grade ( 1stYGrade 2ndYGrade 3rdYGrade ), and the average of these three grades ( Avg ).
Your version of the program must print the same result as the expected output.
To print only two digits of a floating-point number, use the "%.2f" format specifier, and to
fill it with spaces you can use the "%9.2f" format specifier where 9 is the length of the
number and spaces.
Expected output
int main()
/* your code */
return 0;
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Write a small program which prints a figure like the one in the Expected Output section
below.
Your version of the program must print the same result as the expected output. Remember,
if you want to print the \ character, then you have to escape it, like this: \\ .
Expected output
^
/ \
/ \
< >
\ /
\ /
#include <stdio.h>
int main()
/* your code */
return 0;
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Your version of the program must print the same result as the expected output.
Sample Input
7
3.14
Sample Output
How many days in the week: 7
Pi value is 3.140000.
#include <stdio.h>
int main()
/* your code */
return 0;
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Write a program which records two float values. Next, print the sum, the difference and the
result of the multiplication of these two values.
Your version of the program must print the same result as the expected output.
Sample Input
5.5
5.6
Sample output
Value A: 5.5
Value B: 5.6
Sample Input
9.13
4.18
Sample output
Value A: 9.13
Value B: 4.18
#include <stdio.h>
int main()
/* your code */
return 0;
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Write a program that asks the user for a day and month (separate integer values for both).
Next, it should print the day number of the year for the given day and month.
Assume that the year is a leap year (February has 29 days). Your program must print the
same result as the expected output.
Test the program for days of different months. Assume that the user input is valid.
Sample Input
1
1
Sample output
The day of the year: 1
Sample Input
31
Sample output
The day of the year: 31
Sample Input
29
Sample output
The day of the year: 60
Sample Input
31
12
Sample output
The day of the year: 366
#include <stdio.h>
int main()
return 0;
}
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
Scenario
Write a program that prints the name of a given day of the week. Your program must print
the same result as the expected output. This task is similar to the previous lab, but this time
you have to get the day of the week from the user and validate the input.
Test the program for all the days of the week (add code to print a message to the user when
he/she enters an invalid day of the week).
Sample Input
Enter the day of the week (1-7): 1
Sample output
The day of week is: Monday
Sample Input
Enter the day of the week (1-7): 2
Sample output
The day of week is: Tuesday
Sample Input
Enter the day of the week (1-7): 9
Sample output
Invalid input. Please enter a number between 1 and 7.
Sample Input
Enter the day of the week (1-7): -1
Sample output
Invalid input. Please enter a number between 1 and 7.
#include <stdio.h>
int main()
/* your code */
return 0;
LAB
Level of difficulty
Easy
Objectives
Familiarize the student with:
• Getting data from the user
• Validating the input
• Processing the data
• Printing data in different formats
• Fixing errors in a program
Scenario
Write a program that asks the user for a day, month and year (as separate integer values).
Next, it should print the day number of the year for the given day, month and year.
This task is similar to one of the previous labs, but this time you have to get the year from
the user and check if that year is a leap year. You must use this information (whether this is
a leap year or not) for computation. Your program must print the same result as the
expected output. Test it for several days of different years (check some of them on paper).
Assume that the user input is valid.
Sample Input
Enter day:
Enter month:
Enter year:
2016
Sample output
Day of the year: 1
Sample Input
Enter day:
31
Enter month:
Enter year:
2015
Sample output
Day of the year: 31
Sample Input
Enter day:
Enter month:
Enter year:
2016
Sample output
Day of the year: 61
Sample Input
Enter day:
31
Enter month:
12
Enter year:
2015
Sample output
Day of the year: 365
int main()
/* your code */
if (year % 400 == 0)
puts("Leap");
puts("Not leap");
else if (year % 4 == 0)
puts("Leap");
/* your code */
return 0;
Well done! You've reached the end of Module 2 and completed a major milestone in your
programming education and learning the fundamentals of C. Here's a short summary of the
objectives you've covered and got familiar with in Module 2:
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.