Documente Academic
Documente Profesional
Documente Cultură
EDITURA
CONSPRESS
2013
CONSPRESS
B-dul Lacul Tei nr 124, sector 2
cod 020396, Bucureti
Tel: (021) 242 2719 / 300; Fax: (021) 242 0781
To my Grandparents
Contents
Introduction .......................................................................................................... 9
Chapter 1 Programming basics .......................................................................... 11
Chapter 2 Logical diagrams ............................................................................... 15
2.1 The elements of a logical diagram ........................................................... 15
2.2 Solved problems....................................................................................... 20
2.3 Questions and exercises ........................................................................... 24
Chapter 3 Data and data types ........................................................................... 30
3.1 General concepts ...................................................................................... 30
3.1.1 Data types.......................................................................................... 31
3.1.2 Variables ........................................................................................... 34
3.1.3 Constants ........................................................................................... 34
3.1.4 Operators ........................................................................................... 35
3.1.5 Expressions ....................................................................................... 38
3.2 Data types description .............................................................................. 41
3.2.1 The integer type ................................................................................ 41
3.2.2 The real type ..................................................................................... 43
3.2.3 The char type..................................................................................... 43
3.2.4 The logical type................................................................................. 44
3.2.5 The void type .................................................................................... 45
3.2.6 Type casting ...................................................................................... 45
3.3 Questions and exercises ........................................................................... 46
Chapter 4 A first C program .............................................................................. 50
4.1 Stages of a C program implementation .................................................... 50
4.2 The structure of a C program ................................................................... 51
4.3 Possible errors .......................................................................................... 55
Contents
7.1.6 A complete example ....................................................................... 116
7.2 Two-dimensional arrays......................................................................... 117
7.2.1 Declaring a two-dimensional array ................................................. 117
7.2.2 Accessing elements ......................................................................... 118
7.2.3 Initialization of elements................................................................. 118
7.2.4 Reading the elements values from the keyboard ........................... 119
7.2.5 Printing a matrix ............................................................................. 119
7.2.6 Traversing a matrix ......................................................................... 120
7.2.7 Particular ways of traversing a square matrix ................................. 121
7.2.8 A complete example ....................................................................... 124
7.3 Solved problems..................................................................................... 125
7.4 Questions and exercises ......................................................................... 131
Chapter 8 Strings.............................................................................................. 135
8.1 Characters .............................................................................................. 135
8.2 Strings .................................................................................................... 137
8.3 Questions and exercises ......................................................................... 145
Chapter 9 Pointers ............................................................................................ 149
9.1 Pointer variables..................................................................................... 149
9.2 Operations with pointers ........................................................................ 151
9.3 Pointers and other elements ................................................................... 153
9.4 Questions and exercises ......................................................................... 156
Chapter 10 User-defined functions .................................................................. 158
10.1 User-defined functions ......................................................................... 159
10.1.1 The prototype of a function........................................................... 159
10.1.2 The description of a function ........................................................ 160
10.1.3 The call of a function .................................................................... 163
10.1.4 The scope of variables .................................................................. 169
7
Introduction
Communication has become a widely used concept over the last decades, playing an important role in all activities. People communicate using words or
signs when they want to do something together, when they need to interact or
to transmit information, feelings and so on. Such a way of communication is
also required between humans and computers. A programming language is used
in order to transmit to a computer how to perform a special task. Similar to the
languages used in human communication, a programming language consists of
words, sentences and well defined syntactical rules. In a programming language, the sentences are combined so that the program is able to provide the
communication between human and computer. Without programs, a computer
is nothing. On the other hand, a person that is able to write such programs has a
lot of advantages over those who know only to use computers and their applications.
This handbook is easy to read, fast and efficient, being useful to the students
who try to become familiar with programming issues. Those who will use this
book in their training process as software developers (including the design, not
only the implementation) will have the opportunity to become competent in the
programming domain, because the offered items lead to acquiring knowledge
and skills appropriate to this area.
Therefore, the book is designed especially for those who made the first steps in
programming and offers characteristics that lead to learning the C programming
language (a strong, portable and popular language, used to develop applications
in various domains). Some of the basic concepts of programming are discussed
before presenting the specific aspects of the C language. Therefore it will be
much easier to learn and to use other programming languages, because the
knowledge base about structured programming already exists.
This book is carefully split into chapters. The programming concepts are gradually presented, in a natural order, so that the connection between a newly introduced notion and the previous notions is very clear and that the learning of a
new notion is made on the basis of the already explained concepts. This way, a
fast understanding and assimilation of the presented elements is guaranteed.
The first two chapters depict general aspects, which apply to all programming
languages. Several basic notions of this domain are presented in the first chapter. The second chapter shows a graphic way of solving problems through
10
Chapter 1
Programming basics
The computer is able to execute different operations and to offer solutions for a
huge number of problems that have to be solved with its help. It only needs to
be programmed as such. In other words, the computer executes everything it is
asked for, with the imperative condition that it understands what the requirements are. Therefore, a certain means of communication between human
and computer is needed, and this means is the programming languages.
The concepts presented in this book are meant to facilitate the transmission of
basic informatics and structured programming knowledge to those who are at
the beginning of this road. The book can also be useful to those who have some
experience in this domain, helping them to consolidate and to organize the
knowledge they already have.
Information is a widely used concept, lately; its meanings are closely related to:
control, communication, perception, data, knowledge, representation, patterns.
In the computer world data and knowledge are not relate strictly to the word
information; they are connected to this word, heaving also specific significations. Thus, data represents the raw material. After being processed, data becomes information, which is interpreted (given a special meaning) and therefore
becomes knowledge. Figure 1.1.1 is a suggestive graphical representation of the
connection between these three notions that can create a pyramidal shape based
on data (the largest amount), consolidated by information (in the middle of the
pyramid) and crowned by knowledge.
KNOWLEDGE
INFORMATION
DATA
Figure 1.1.1 Pyramidal representation of data, information, and knowledge
12
1 Programming basics
The C programming language was invented by Dennis RITCHIE in 1972.
Although many years have passed since then, this language is still widely used
because of its advantages [CH96], [GP00]:
it is a high level language (it can be easily used thanks to its syntax); nevertheless, it provides the power and the flexibility of a machine language because it maintains some features of an assembly language;
it is highly efficient, being created for writing the operating systems (its a
programming language projected by the UNIX operating systems programmers [BK03]);
it is strong; the C programs can produce a large number of computations in
a few steps;
it is succinct due to the use of a large number of operators (some of them
are mathematical operators, others replace particular commands;
it is portable (can be installed on many different computers);
it is popular because of its force and its portability, being used by an impressive number of programmers;
it is in permanent development, being the subject of additions and extensions.
All these characteristics make the C programming language a language that any
programmer must know. Using the tools of the C language, the development of
the programs can be done in an efficient way, resulting high quality final products.
The features of the C programming language allow and encourage structured
programming. This kind of programming is based on a theorem, which states
that any algorithm can be implemented using only three control structures
(figure 1.1.2):
sequence first an entity of a program is executed, and then the next entity;
in other words, parts of a code sequence are executed one after another,
without jumps over certain parts (figure 1.1.2 a);
selection only one of two alternatives is executed, based on the value of a
condition (figure 1.1.2 b);
iteration an entity of a program is repeatedly executed as long as a condition is true (figure 1.1.2 c).
13
a) Sequence
b) Selection
c) Iteration
Figure 1.1.2 The three control elements that support the structured programming
Representation
Implementation
Even though the implementation, the last phase of the problem solving process,
seems to be the most important, the other two phases are not to be neglected
either. The preliminary analysis of the input data and of the requirements is
essential for finding a correct solution. It is also very important to create a wellstructured program and an explicit flow of executed elements. In order to provide a correct solution for a problem, it is recommended to have a graphical
representation of the algorithm that is being used. This is achieved using some
elements that form a so-called logical diagram. Each step that is executed to
solve a problem is represented by an image with a geometric aspect and a short
text that explains what has to be done in that certain step. Details regarding the
graphical representation of a problem can be found in the chapter that presents
the logical diagrams.
14
Chapter 2
Logical diagrams
2.1 The elements of a logical diagram
First steps in structured programming will be made using logical diagrams, a
very good method to improve the reasoning. The logical diagrams are not connected to a specific programming language. They are graphical representations
of programs, providing an explicit idea about them. A logical diagram is the
simplest way of expressing an algorithm. If a graphical representation of that
algorithm is available, then the program that has to implement it will be easily
written.
The logical diagrams might seem archaic. Nevertheless, they are essential when
a program is developed, being very useful, especially for the beginners in programming. It is said that an image is worth a thousand words; the logical diagrams are exactly the image of a program. Writing the program, after its graphical representation is made, is only routine work [GP00].
A logical diagram is made by several graphical symbols; any algorithm can be
represented using these symbols. The elements that can be used in a logical
diagram are hereby presented.
The START element marks the beginning of the program:
START
Write a
Write This is my
first program
STOP
Figure 2.1.1 A logical diagram that uses the output element
Read a
The logical diagram from figure 2.1.2 uses the input element to read the name
of a person; that name is then displayed with an output element.
START
Read name
STOP
Figure 2.1.2 A logical diagram that uses the input and the output elements
16
2 Logical diagrams
The processing element executes operations and it is used when the data is
processed (computations or assignments):
For example:
b=2*a
A lot of problems can be solved by using the processing element. The following
logical diagram calculates the sum and the product of two numbers (figure 2.1.3). An input element is used to read the numbers. Then, in a processing
element, the sum and the product are calculated. These are displayed at the end
of the diagram with an output element.
START
Read a,b
sum=a+b
product=a*b
STOP
Figure 2.1.3 The logical diagram for calculating the sum and the product of two numbers
Even more complex problems can be solved with the processing element. For
example, the first degree equation: ax+b=0. First, two numbers a and b,
representing the coefficients, are read. Then, the x value is calculated and displayed. The figure 2.1.4 presents a first version of logical diagram that solves
the first degree equation.
17
START
Read a,b
x=-b/a
Write x
STOP
Figure 2.1.3 Logical diagram for solving the first degree equation (the first version)
As it can be seen, this logical diagram created to solve the first degree equation
has a drawback: it doesnt cover the case where the a coefficient is zero (in
which case the division cannot be executed). From the mathematical point of
view, the equation ax+b=0 is solved as follows:
The value of the a coefficient is verified:
if a is not zero, then x=b/a;
else, the equation becomes b=0 and the value of the b coefficient must be
verified:
o if b is not zero, then the expression b=0 is false, so no solutions for
the unknown variable x;
o if b is zero, then the expression b=0 is true and any real number is
solution for the equation (this means that the unknown variable x
has an infinite number of solutions).
In order to solve this problem, another element is necessary: the one given
below.
The decisional element evaluates conditions and it is used when a decision
must be made based on two alternatives. The element has to contain a question
with two possible answers: yes or no.
18
2 Logical diagrams
For example
NO
YES
NO
a0
YES
The first degree equation can now be correctly solved using the decisional
element and the algorithm described above. The logical diagram presented in
figure 2.1.5 follows exactly the stages of this algorithm.
START
Read a,b
NO
YES
a0
NO
x=-b/a
YES
b0
Write x
Write No solutions
Write Infinite number
of solutions
STOP
Figure 2.1.5 Logical diagram for solving the first degree equation (the second version)
19
Read L
S=L*L
Write S
STOP
But what happens if the user, by mistake or by ignorance, enters a negative side
for the square? The value is unacceptable, because a dimension cannot be negative. Therefore, the logical diagram from the figure 2.2.1 doesnt properly
function for all cases and has to be modified. This problem could be partially
20
2 Logical diagrams
solved if the L value is verified before calculating the surface. If the side is
strictly positive (higher than zero), the surface can be calculated and displayed;
otherwise, an error message will be shown (figure 2.2.2).
START
Read L
NO
YES
L>0
S=L*L
Write
Incorrect value
Write S
STOP
Figure 2.2.2 The surface of a square (the second version)
There are cases when the surface (or something similar) must necessarily be
calculated. In other words, the user must be forced to enter a valid value (in this
case, a positive value). This is realized by a repetitive structure (figure 2.2.3).
The user has to reenter the required value as long as this is not valid. Therefore,
the program will continue, calculating the surface, only after a positive value is
entered.
21
START
Write
Incorrect value.
Enter a positive
value.
Read L
NO
L>0
YES
S=L*L
Write S
STOP
Figure 2.2.3 The surface of a square (the complete version)
2.2.2 The following problem is also an example of repetitive structure. The user
enters n numbers (n has to be a natural number). The average of these numbers
will be calculated and displayed (figure 2.2.4). In order to solve this problem, n
must have a positive value. A repetitive structure (similar to that used for the
squares surface) will be used to validate the n value. After a positive number is
read, the average can be calculated. It represents the sum of the entered elements divided by the number of elements. Therefore, a variable called sum,
with the initial value zero, is used (its obvious that the sum is zero before
entering any value). In addition to this, at any time during the programs execution, it is necessary to know how many numbers were already read. In order to
do this, another variable, called counter, is used; it also has the initial value
zero. Then, each number can be read. This is realized in another repetitive
structure. Each time a number is read, it is added to the sum and the counter is increased by one. The loop is repeated as long as the counter is less
22
2 Logical diagrams
than n. When the condition becomes false, the repetitive structure is left and the
execution of the program continues, calculating the average, which is then
displayed.
START
Read n
NO
n>0
YES
counter=0
sum=0
Read number
sum=sum+number
counter=counter+1
YES
counter<n
NO
average=sum/n
Write average
STOP
Figure 2.2.4 The average of n numbers
23
Read x
x=x+1
Write x
STOP
2.
START
Read x
NO
x>0
YES
Write Positive
Write Negative
STOP
24
2 Logical diagrams
3.
START
Read x
NO
YES
x>0
Write Positive
Write Negative
Write Zero
STOP
B. Considering the following logical diagrams, specify what actions they perform.
4.
START
Read xA,xB,yA,yB
AB
xB
xA
Write AB
STOP
25
yB
yA
Read a3,a2,a1,a0
Write
a3x3+a2x2+a1x+a0
b2=3a3
b1=2a2
b0=a1
Write b2x2+b1x+a0
STOP
6.
START
Read n
r = n modulo 10
Write r
STOP
26
2 Logical diagrams
7.
START
Read n
NO
n>0
YES
counter=1
p=1
counter=counter+1
p=p*counter
YES
counter<n
NO
Write p
STOP
x,ifx
|x|,ifx
0;
0.
and x
28
2 Logical diagrams
o if a is equal to zero, then the equation becomes bx+c=0 and the
value of the b coefficient must be verified:
16. Calculate the surface and the length of a circle with R radius.
Suggestion: The following formulas can be used: surface=R2 and
length=2R. The radius value must be validated (it has to be positive).
17. Display the first n Fibonacci numbers.
Suggestion: Fibonacci numbers list is a repetitive structure example. The
list is represented by a sequence of numbers defined using the following
formula:
F n
0,ifn
1,ifn
F n 1
F n 2 ,ifn
0;
1; ,wheren
1.
0, 1, 2, 3,
Therefore, the first two numbers are known (0 and 1) and each of the
following numbers is calculated as sum of the preceding two numbers.
Thus, the first 10 Fibonacci numbers are:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34.
29
Chapter 3
Data and data types
3.1 General concepts
As seen in the first chapter of this book, the computer stores and processes data;
these have different meanings and are essential for solving all kinds of problems. There are two categories of data:
the ones that can be modified (can change their value) during the execution
of the program, called variables;
the ones that maintain their initial value, without the possibility of changing
it, called constants.
Both variables and constants, before being used in a program, must be declared.
The variables have a name, a type and, optional, an initial value. The constants
have a name, a type and, mandatory, an initial value. Through this declaration,
variables and constants receive memory space.
The name of a variable or of a constant is made of several characters (letters,
digits, special characters), following certain rules. In order to do this, a programmer should know the available set of characters. These can be found in
Appendix 1. When the name of a variable or of a constant is set, several restrictions should be considered [CH96]:
the first character of the name should be a letter or an underscore (e.g.
name or _name);
following the first character, any combination of digits and letters (excepting non alphanumeric characters as #, $ or space) can be used (e.g. names
like variable1, word2new can be used, but var$ is not a valid name);
the C programming language is case sensitive; this means that it makes the
difference between uppercases (capital letters) and lowercases (small letters); this feature of the language should be considered when a variable or a
constant is declared and used (e.g. name1 and Name1 are different variables);
there are several reserved words that cannot be used as names for variables
or constants; a complete list of these words (also known as keywords) can
be found in Appendix 2.
Types meaning
Dimension
Range
char
character
8 bits
-128 127
int
integer
16 bits
-32.768 32.767
float
real
point)
(floating
32 bits
double
real
(floating
point,
double
precision)
64 bits
Data types are often accompanied by the so-called modifiers, which specify the
length of the memory space allocated to an element. These are:
short short;
long long;
signed with sign;
unsigned without sign.
Table 3.1.3 contains the C data types, together with the potential modifiers (this
is how the derived types resulted) [HS98], [DL06].
32
Types meaning
Dimension
Range
unsigned char
character
sign
8 bits
0 255
char or signed
char
8 bits
-128 127
unsigned int
16 bits
0 65.535
16 bits
-32.768 32.767
unsigned short
int
8 bits
0 255
short int or
signed short int
8 bits
-128 127
unsigned
int
long
32 bits
0 4.294.967.295
long int or
signed long int
32 bits
-2.147.483.648
float
32 bits
without
2.147.483.647
3,4 e-38
3,4 e+38
double
long double
64 bits
80 bits
33
1,7 e-308
1,7 e+308
3.4 e-4932
3.4 e+4932
3.1.2 Variables
When a variable is declared, the type of the information stored by that variable
must be specified. The variable must also have a name. The general form of an
instruction that declares variables is:
type var1,var2, , varn;
where var1, var2, , varn are the variables names and type is the name
of one of the types presented in table 3.1.3 or a user-defined type. Variables are
separated by comma, and the declaration is ended with semicolon.
Examples:
int number1, number2, sum;
double average;
When a variable is declared, it can also receive an initial value, which can be
modified during the execution of the program. For example:
int counter=0;
The previous instruction declares an integer variable, with the name counter
and the initial value zero.
3.1.3 Constants
If a program repetitively uses a value, then that value should be declared as
constant. It receives a name and it can be used throughout the program with that
name. Its similar to Mathematics where the surface of a circle is calculated
using the constant , instead of the value 3.14159265
The use of constants in a program has several advantages [CH96]. The most
important are related to the fact that due to the constants code becomes easy to
understand and easy to modify. If a program uses the constant, then is obvious that it represents the ratio between the circumference of a circle and its
34
3.1.4 Operators
Variables and constants can be included in different operations to obtain new
values. In order to do this, operators will be used. Variables, constants and
operators will form expressions. Depending on the type of the operation that
involves operators, these are divided into several categories. Those most frequently used will be discussed below [CH96], [DL06], [GP00].
relational operators when applied, the result is 1 if the comparison is
true and 0 otherwise:
< less than (a<b);
<= less than or equal to (a<=b);
35
37
y /2 z,
Operators
unary
++, , (type)
multiplicative
*, /, %
additive
+,
relational
equality
==, !=
logical AND
&&
logical OR
||
conditional
?:
assignment
The operators precedence has a very important role when the value of an expression is calculated and knowing the order of applying operators is mandatory. For example, the expression (1||1&&0) has the value 1 because operator
&& is applied before operator || [PT12]. If the order was the other way
around, then the result would change.
3.1.5 Expressions
Similar to Mathematics, in a programming language expressions are operations
made on operands (variables, constants or other expressions) using operators.
38
!a
a&&b
a||b
For example:
the expression (7>=5)&&(0!=10) contains two true expressions connected through the logical AND operator; the final expression is true,
so the result will be 1;
the expression (7==0)&&(3<4) is made of a false expression (the first
one) and a true expression (the second one), connected through a logical AND operator; the result is false, meaning 0;
the expression (7==0)||(3<4) contains the same two parts as the previous expression (a true one and a false one), connected this time
through the logical OR operator; therefore the value 1 will be obtained
(the final expression is true because at least one of the expressions is
true, as can be seen in table 3.1.5 also);
the expression !(7==0) is true because a false expression is negated.
40
int a, x;
x = 7;
a = ++x;
After these three lines of code are Because x is incremented before the
executed the results are a=7 and x=8 assignment, in this second case the
because x is incremented after the results are a=8 and x=8.
assignment.
42
49
Chapter 4
A first C program
4.1 Stages of a C program implementation
A program is a list of instructions that specify what a computer has to do. In
fact, a program represents the implementation of the algorithm that solves a
certain problem. The instructions that form a program may refer to: reading
information from the keyboard or from a file, writing information on the screen
or in a file, making arithmetic and logical operations, comparing entities.
The first step in making a program is writing it (and obviously saving it) using a
text editor. The result is a source file that will have the extension .c (e.g. program.c). But a source code has no meaning for the computer. It must still
undergo some changes.
Thus, the next step in the development of a program is the source file compilation; this means that the program will be translated from the programming
language used to write it (C, in this case) to the language of the computer machine, language that is called machine-code [NR01]. This process is performed
by a compiler. If the program has errors, these will be displayed and must be
solved. The line that contains each error is emphasized and a short message
explains the possible cause of the error. Once the program is successfully compiled, an object file is created a file with the same name as the source file, but
with the extension .obj (e.g. program.obj)
Next follows the linking phase performed by a linker (or link editor). It connects the object code previously created with object codes of library files, of
input/output drivers and/or of the operating systems programs [NR01]. The
result is a new file, an executable file. This has the same name as the source
file, but the extension is .exe (e.g. program.exe). The executable file can
be run, obtaining the results for which the program was created.
Figure 4.1.1 is a graphical representation of the steps followed in a C program
development, from the code writing, to the results. It can be observed that the
source file represents the input data for the compiler and the object file is the
input for the link editor.
4 A first C program
Editing
Source file
Correcting
errors
Displaying
errors
YES
Compiling
Errors?
NO
Object file
Linking
Executable file
Running
Results
#include <stdio.h>
10
4
void main(void)
11
Figure 4.2.1 The structure of a C program
Though the program in figure 4.2.1 has a single objective (to display on the
screen a simple message), it needs several tools in order to accomplish this task.
Their role is hereby presented.
1. #include
it is called preprocessor directive;
it specifies that together with the source code of the current program, another program/file must be considered in order to have a
proper functioning of the application;
usually the files that are included through this directive are library
files and contain a number of functions that are used in the program.
52
4 A first C program
2. <stdio.h>
the name of the file that is intended to be included;
it must be framed by angle brackets (number 10 in figure 4.2.1);
in this case the standard input/output library is included; it contains
functions that are used to read and to write data; the current program
needs to include this library because it has to display a text on the
screen (this is done using a function that is described in the included
library).
3. main
is the name of a function;
in this case it is the name of the most important function of a C program (main()), but it can also be any other function.
4. void or the name of a data type written in front of a functions name
represents the type of a function (in fact, the type of the value returned
by that function);
the main() function from the presented example doesnt return anything; for this reason, in front of its name stands the word void (as
shown in the chapter presenting data types, void can be considered
an empty data type);
caution: if nothing is written in front of a functions name, then that
function must return an integer value.
5. (void) or a list of comma delimited variables, each one preceded by its
type
the arguments of that function;
the list is enclosed by parentheses and is placed after the name of the
function, as shown by number 11 in figure 4.2.1;
if the function doesnt have arguments (as the current case), then the
word void will be used to specify this.
6. { and }
the curly brackets mark the beginning and the end of a function or of a
block of instructions;
53
4 A first C program
(marked by number 6) and parentheses () (marked by number 11). Square
brackets [] are also used (as shown in some of the following chapters). These
must be well understood and used correctly. In some cases, if they are not correctly used, then some compilation errors will be displayed and the program can
be corrected. In other cases, the compiler doesnt report an error (though these
symbols are not placed according to what the flow of instructions must execute), but the program will not generate correct results.
Comments in the C programming language
Comments can also be included in a C program. These are sequences of text
written in natural language, used by the programmer to mark some sections of
the program or to give some explanations, so that the written source code is as
explicit as possible. Comments are marked accordingly, are ignored by the
compiler and are not executed when the program is run.
The C programming language offers the possibility to use two types of comments:
single line comment is marked by two oblique lines (slashes) // that must
be placed at the beginning of the line;
multi line comment begins with /* and ends with */.
Several comments are inserted in the program that was previously presented, in
order to illustrate how to use them. Thus, the program 4.2.2 resulted.
Program 4.2.2
#include <stdio.h> //standard input/output library
void main(void){
/*The following function is used to display a
message on the screen. It receives the text of
the message as argument.*/
printf("This is a first C program.");
}
4 A first C program
x=-b/a
}
2. void main(void)
//this function increments the age
int age=18;
age++;
}
3. void main(void){
/*this function gives initial values to the
coefficients of the first degree equation and
calculates the value of the unknown x
float x,a=2,b=-4;
x=-b/a;
}
4. void main(void){
float x=3,y=4,z=5;
surface=(x*y)/2;
}
B. Considering the following programs, specify the value of the expressions
that are calculated.
5. void main(void){
int a, b;
float E1, E2;
a=7; b=2;
E1=a/b;
E2=(float)a/b;
}
6. void main(void){
int a, b, E;
a=7; b=3;
E=a++ + ++b;
}
7. void main(void){
int a, b, E;
a=7; b=3;
E=a>b;
}
57
58
Chapter 5
Library functions
The C programming language is a very simple language. It only has few instructions that can be used to solve different problems. But these instructions
are not always enough. For instance, the C programming language doesnt
provide any method to read information from the keyboard or from a file, to
display them on the screen or to write them in a file, to process strings, to work
with mathematical functions and so on. For this reason, all C compilers also
include a standard library of functions that implement the most frequently used
tasks. This library contains several header files that gather certain categories of
functions. The programmer can use (or can call) any library function; however,
he is forced to specify, at the beginning of the program, in a #include directive, the name of the header file which contains the function that is used in the
program.
In the following paragraphs some of the most frequently used library functions
are described [BH92], [SL12]. These are gathered in several categories, according to the domain they are applied in.
5 Library Functions
In program 5.1.4 the function puts()receives as argument directly the string
that must be displayed. It is also possible to send a string variable that was
previously declared, as argument to the function.
Programul 5.1.4
#include <stdio.h>
void main(void){
puts("This is a programming course.");
}
61
c character;
s string;
\b moves the cursor (the point where the printing begins) back with one character, deleting that character;
\ prints apostrophe;
5 Library Functions
The program from the example 5.1.6 calls function printf() in order to print
the value of the variable weight, which was previously declared and received
an initial value. Once the program is run, the text The suitcase is 17
kg will be displayed on the screen. It can be observed that the value of the
variable weight was inserted in the text where the descriptor %d appears.
Program 5.1.6
#include <stdio.h>
void main(void){
int weight=17;
printf("The suitcase is %d kg.", weight);
}
Function printf()also allows the use of some expressions as arguments.
Example 5.1.7 prints the sum of two numbers, sum that is calculated when
function printf() is called. The result is a real number (float), displayed
with two decimals precision. These features are specified by the format descriptor %.2f. Once the program is executed, the text The sum is: 7.50 is
displayed on the screen.
Program 5.1.7
#include <stdio.h>
void main(void){
float x=3.5, y=4;
printf("The sum is: %.2f.", x+y);
}
When using function printf(), it is possible to print more than one argument, as in example 5.1.8. The text that is displayed after the execution of the
program is The student is 177 cm and 80.7 kg. The value of the
weight is truncated due to the setting from the format descriptor %.1f.
Program 5.1.8
#include <stdio.h>
void main(void){
int h=177;
float w=80.73;
printf("The student is %d cm and %.1f kg.", h,w);
}
63
5 Library Functions
printf("Enter a character ");
c=getchar();
printf("The read character is: %c.", c);
}
Another function, int getch(void) from the header file conio.h, can be
also used to read a character from the keyboard. It returns the read character.
This function is often used to force the program to wait until a key is pressed (in
fact, the execution of the program is interrupted; the break will be finished
when the user presses a key). The read character is not used by the program, but
this trick is very good when some information is displayed and must be seen
before it is deleted or before the execution of the program is ended.
The program example 5.1.11 prints a simple text on the screen and then calls
the function getch() in order to avoid the ending of the programs execution
immediately after the text is printed; so, the execution is ended only when the
user specifies this by pressing a key. It can be observed that this program needs
two header files: stdio.h for the function printf() and conio.h for the
function getch().
Program 5.1.11
#include <stdio.h>
#include <conio.h>
void main(void){
printf("Press any key to continue.");
getch();
}
5 Library Functions
address of the first element of the string is given directly by the name of the
string.
In program 5.1.13 a couple of information about a person is read name (defined as string) and age. At the end, this information is displayed on the screen.
Warning: the addressing operator should not be omitted if a variable is not a
string; in the example one can observe that the variable age needs this operator
when it is read and stored.
Program 5.1.13
#include <stdio.h>
#include <conio.h>
void main(void){
char name[100];
int age;
printf("Enter the name ");
scanf("%s", name);
printf("Enter the age ");
scanf("%d",&age);
printf("%s is %d years old.", name,age);
getch();
}
If, for instance, the information entered by the user when the program is run is
Ann for the name and 7 for the age, then the message Ann is 7 years
old will be displayed on the screen. Function getch(), at the end of the
program, is used to determine the program to wait for the pressing of a key
before it ends its execution.
5 Library Functions
Two other functions, floor() and ceil(), are also part of this library; they
are used to find the largest integer that is smaller than or equal to the argument
and the smallest integer that is larger than or equal to the argument, respectively. The prototypes of these two functions are hereby presented.
double floor(double x);
double ceil(double x);
In other words, floor() makes a down rounding and ceil() makes an up
rounding of the argument. Both functions return the found integer as a
double. For example:
floor(6.3)=6
ceil(6.3)=7
floor(-1.73)=-2
ceil(-1.73)=-1
floor(0.5)=0
ceil(0.5)=1
floor(-0.5)=-1
ceil(-0.5)=0
floor(7)=7
ceil(7)=7
Example 5.2.1 shows how some of the mathematical functions presented in this
paragraph can be used in a program. During the program, a couple of variables
x and y receive different values and are used as arguments for several function
calls; the values that are returned are printed immediately or are firstly stored in
a variable f.
It can be observed the use of the constant M_PI for the trigonometric functions.
This constant has the value3.1415 and is part of the math.h library.
Program 5.2.1
#include <stdio.h>
#include <conio.h>
#include <math.h>
void main(void){
double x, y, f;
x=3; f=exp(x);
printf("\nexp(%.2f) = %.2f",x,f);
x=2; y=3;
printf("\n%.0f to the %.0f=%.0f",x,y,pow(x,y));
x=49;
printf("\nsquare root of %.1f is %.2f",x,sqrt(x));
69
5 Library Functions
Program 5.3.1 illustrates how these two functions can be used. A string is read
from the keyboard and then the integer and the real number represented by this
string are printed.
Program 5.3.1
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void main(void){
char str[20];
printf("Enter the string: ");
scanf("%s", str);
printf("Converted to integer: %d", atoi(str));
printf("\nConverted to real: %f", atof(str));
getch();
}
When the program is run, the user is asked to enter a string. If, for instance, the
string is 14.7, then the program will print:
Converted to integer: 14
Converted to real: 14.700000
If the user enters a non-numerical value (for instance abc2,7), then the printed
result will be:
Converted to integer: 0
Converted to real: 0.000000
5 Library Functions
If the program is repetitively run, it can be observed that the generated number
is the same. If this case is not accepted in a program, then the function void
randomize(void); must be called before; this will initialize the generator
of random numbers making the connection to the system clock, which, obviously, is modifying continuously. This way, function random() that is called
will not start from the same number. Program 5.4.3 is a complete example of
random number generator.
Program 5.4.3
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void main(void){
clrscr();
randomize();
printf("%d",random(100));
getch();
}
Both functions, random() and randomize(), are part of the stdlib.h
header file.
5.4.3 void exit(int status);
The call of this function causes the ending of the program. If there are other
instructions after exit(), these will not be executed. The function doesnt
return anything and receives as argument the exit status of the program, status
that is sent to the calling process (usually the operating system). Typically, the
value zero of the argument status indicates a normal exit and a non-zero
value is connected to a certain error. In order to use this function, the
stdlib.h header file must be included in the program.
Example 5.4.4 calls function exit() to quit the program after the first message (The program is ending here.) is displayed. The instruction
that prints the second message (This message wont be displayed.) is not executed.
Program 5.4.4
#include <stdio.h>
73
5 Library Functions
int a,b,x;
scanf("%d",&a); scanf("%d",&b);
x=a+b;
printf("The result is: " %5d,x);
}
5. #include <stdio.h>
void main(void){
int a;
float b,x;
a=7; b=3.54;
x=a+b;
printf("The result is: %5.2d",x);
}
6. #include <stdio.h>
void main(void){
int a,b,x;
a=7; b=3;
x=a+b;
printf("The result is: x=%4.1f",x);
}
7. #include <stdio.h>
#include <math.h>
void main(void){
float a=-49.7,x;
x=sqrt(a);
printf("The result is: %.2f",x);
}
B. Considering the following programs, specify what will be printed on the
screen after these programs are executed.
8. #include <stdio.h>
void main(void){
float x=39;
printf("%.1f",x/4);
}
9. #include <stdio.h>
#include <conio.h>
void main(void){
75
76
5 Library Functions
16. The default alignment when function printf() is used to display
something is:
a) to the left; b) centered; c) to the right; d) justified; e) all answers are wrong.
17. Which of the following format descriptors (used in the printf()
function) are wrong?
a) %-7s; b) %7.3f; c) %d; d) %c; e) all answers are wrong.
18. What type of variables are read by the call of the function
scanf("%d%c", &x,a);?
a) a real number and a char; b) an integer and a char; c) an integer and a string; d) a real number and a string; e) the instruction contains an error.
D. Write programs to solve the following problems.
19. Calculate and display the sum of two real numbers whose values are
read from the keyboard.
20. Transform the dimension of an angle from degrees into radians (180=
radians). Suppose that the number entered by the user is valid.
21. Use the mathematical functions sqrt, log, exp, pow, fabs. Check
what happens during the execution of the program if the arguments sent
to these functions are wrong (for instance, square root of a negative
number).
22. Find and display the last digit of an integer.
23. Print on the screen (using a single instruction) the following text lines:
"C language" \ Dennis RITCHIE
#1972
77
Chapter 6
Instructions
According to the previous chapters, C programs contain several entities: preprocessor directives, declarations of variables and different mechanisms used to
execute the actions for which the program was created. The latter are called
instructions [HS98], [BH92] and may be subject to the following classification:
simple instructions: assignments and function calls;
compound instructions:
o associative: blocks of instructions; they group two or more instructions that have some connection in the logic of the programs execution; these blocks of instructions are delimited using open curly bracket { at the beginning of the block and close
curly bracket } at the end of the block;
o alternative: if, switch; these instructions are used when, according to a condition, only certain branches of the program can
be executed;
o repetitive: for, while, do while; these are used when one
or more instructions have to be repeated.
Compound instructions are used to control how the program behaves when it is
run. Two jump instructions are presented within: break and continue.
The names of the instructions are keywords in the C programming language;
this means that these words can only be used for the purpose for which they
were created. It is not possible to define variables, constants, data types or
functions with the names of these instructions. The list of keywords of the C
programming language is available in Appendix 2.
The instructions are components of the C programming language. They are not
part of any library, therefore is not necessary to include any header file when
they are used.
6 Instructions
80
6 Instructions
false
EXPRESSION
Instructions
block 2
true
Instructions
block 1
6 Instructions
else
printf("Failed");
getch();
}
If the branches of if or else need more than one instruction, then these must
be grouped in a block using curly brackets. In example 6.2.2 the exam and
laboratory marks are read. If both of them are greater than or equal to 5, then
the final mark is calculated and displayed. Otherwise, only a message is printed.
Program 6.2.2
#include <stdio.h>
#include <conio.h>
void main(void){
float em, lm, fm;
clrscr();
printf("Mark for the exam: "); scanf("%f", &em);
printf("Mark for the lab: "); scanf("%f", &lm);
if ((em>=5)&&(lm>=5)){
printf("The student passed");
fm=(2*em+lm)/3;
printf("\nThe final mark is: %.2f", fm);
}
else
printf("The student failed");
getch();
}
The else part of the if instruction is optional; this means that it is possible to
write instructions that dont execute anything if the evaluated expression is
false. Program 6.2.3 is an example in this way. A temperature sensor whose
value is read from the keyboard is considered, as well as a variable that causes
the air conditioning (that is initially stopped) to be turned on. If the read temperature is greater than 25 degrees, then the message The air conditioning was turned on is displayed and the variable sw is set. The
else branch is missing, so the program doesnt execute any action if the temperature is less than or equal to 25 degrees.
Program 6.2.3
#include <stdio.h>
83
to
6 Instructions
When cascading checks are required, then the if-else-if structure can be
used. This is in fact an if instruction on the else branch of another if instruction. Program 6.2.5 is an example of this kind of use. According to the
average mark of a student, which is read from the keyboard (the variable av), a
scholarship is granted (the variable sch). The value of the scholarship is set
after some cascading tests.
Program 6.2.5
#include <stdio.h>
#include <conio.h>
void main(void){
float av, sch;
clrscr();
printf("The average mark=");
scanf("%f", &av);
if (av>=9.5)
sch=1000;
else if (av>=8.5)
sch=800;
else if (av>=8)
sch=500;
else
sch=0;
printf("The scholarship is: %f", sch);
getch();
}
85
var = val1
true
Sequence of
instructions 1
false
var = val2
true
Sequence of
instructions 2
false
var = valN
true
Sequence of
instructions N
false
Sequence of
instructions
6 Instructions
The variable is successively compared to each constant marked by a case
instruction. When a constant matches the value of the variable, then the sequence of instructions of that case branch is executed until a break instruction is encountered or until the switch instruction is ended. The default
branch is dedicated to the case when the value of the variable doesnt match any
of the considered constants. This is an optional branch; if it is not present and
the variable is not equal to any constant of the list, than the entire switch
ensemble will not generate any action.
Regarding the comparison made between the variable and the constants of the
list, this cannot be any relational expression, but only an equality check. In
other words, the switch instruction cannot verify if a variable is less or greater than a certain value, but only if the variable has exactly that value.
The constants of the list must be unique. It is not possible to have more than one
case branch with the same constant. These constants must also be integers or
chars (which are automatically converted to integers).
Break is a jump instruction. When it is encountered inside a switch instruction, a jump to the first instruction that follows the switch is executed. If
there are several nested instructions, then break will only affect the switch
instruction it belongs to, not a possible other instruction containing this
switch. Therefore, break acts only at the level on which it stands.
Usually, the switch instruction is used to process the users options when
he/she selects something from a menu. Program 6.2.6 is an example in this way.
The user has a menu with several mathematical operations (1 for addition, 2 for
subtraction, 3 for multiplication and 4 for division). He enters the values for the
variables x and y and then presses the key associated to his option. Inside a
switch instruction this option (which is an integer number) is compared to the
four possible values. If it is one of these, then the related operation is executed
and the result is displayed; after this, because of the presence of break instruction, a jump to the instruction that follows the switch (getch(), in this
case) is made. If the user enters a number that is not 1, 2, 3, or 4, then the
instruction of the default branch is executed, displaying an error message,
which informs the user that the option he entered doesnt exist.
Program 6.2.6
#include <stdio.h>
#include <conio.h>
87
break;
break;
break;
break;
The break instruction, which is placed at the end of the case branches, is not
mandatory. It closes the sequence of instructions that belongs to a constant. If it
is omitted, then the instructions belonging to the next branches are executed,
until a break instruction is encountered or the switch instruction is ended.
Example 6.2.7 emphasizes this aspect. The user enters the value of an integer
variable x and has the possibility to increment it once (the option 1), to increment it twice (the option 2), to decrement it once (the option 3) or to decrement
it twice (the option 4).
Inside the switch instruction, the case branch that firstly appears is that for
the option 2 (double increment). On this branch there is a single instruction for
increment. However, the result that is displayed is correct. This is because the
break instruction of this branch is missing; therefore the instructions of the
next branch (those belonging to the option 1) are executed. There is also an
instruction that increments the variable, followed by a break; this makes the
switch instruction end and the result to be displayed. If the user chooses
option 1, the variable is normally incremented because that case branch
doesnt have anything special.
88
6 Instructions
Options 3 and 4 are not implemented yet and it is required that when the user
chooses one of these options, the message Unimplemented option is
displayed. The case branch that belongs to option 3 doesnt have any instruction (not even break); this emphasizes another important aspect: a case
branch can be empty. In this case, the instructions from the following branches
will be executed: the message regarding the option that is not implemented is
displayed (this message is also displayed if the user chooses option 4).
Program 6.2.7
#include <stdio.h>
#include <conio.h>
void main(void){
int option, x;
clrscr();
printf("x="); scanf("%d",&x);
printf("\n1 - Single increment");
printf("\n2 - Double increment");
printf("\n3 - Single decrement");
printf("\n4 - Double decrement");
printf("\nEnter your option ");
scanf("%d", &option);
switch(option){
case 2: x++;
case 1: x++; break;
case 3:
case 4: printf("Unimplemented option"); break;
default: printf("\nWrong option");
}
printf("\nx=%d", x);
getch();
}
If break instructions are not used on some case branches, then the instructions belonging to different branches are executed together. This increases the
efficiency of a program because redundancy is avoided (it is not necessary to
write twice some code lines). But the programmer must be very careful with
these aspects. They are very useful, but they can also produce improper functionalities of the programs if they are not correctly used.
89
Initialization
EXPRESSION
false
true
Block of
instructions
Action
90
6 Instructions
The general form of the for instruction is:
for(initialization;expression;action)
//block of instructions
The for instruction usually has a variable of control; through this variable, it
establishes how many times the loop is repeated. The initial value of this variable is set in an assignment made in the first step executed by the for instruction: initialization.
The expression that is then evaluated determines when to stop the repeating
of the loop. The block of instructions is executed as long as the expression is
true (the result of its evaluation is not zero).
The action that is performed at the end of each iteration specifies how the
control variable is changed as the loop repeats. Usually this action increments
the value of the control variable, but other kind of operations are also possible.
All these three entities of the for instruction are optional. If the expression is
missing, it is considered that it is true.
The entities are separated by semicolon. This is required even if the entities are
not present.
The program from example 6.3.1 calculates the sum of the first 100 natural
numbers. The control variable i receives the initial value 1, and the loop is
repeated until i becomes greater than 100. At the end of each iteration the
value of i is incremented. Because the loop contains a single instruction (addition of i to the partial sum), the curly brackets are not mandatory. The sum is
displayed after the for instruction is ended. The sum must receive an initial
value before its first use and this value is 0 (the identity element for addition).
If a product is calculated, then the initial value would be 1 (the identity element
for multiplication).
Program 6.3.1
#include <stdio.h>
#include <conio.h>
void main(void){
int i,s=0;
clrscr();
for(i=1;i<=100;i++)
s=s+i;
91
6 Instructions
#include <conio.h>
void main(void){
int i,n;
clrscr();
n=0;
for(i=0;i<n;i++)
printf("%d ",i);
printf("The final value of i is: %d",i);
getch();
}
The for instruction can use two or more control variables. Their initializations
and changes must be separated by comma. The expression that is evaluated
must not necessarily refer to the control variables. Program 6.3.4 emphasizes
these aspects. It uses two variables i and j and displays their values during 10
iterations. The expression is a test performed only on variable i.
Program 6.3.4
#include <stdio.h>
#include <conio.h>
void main(void){
int i,j;
clrscr();
for(i=0,j=0;i<10;i++,j=j-i)
printf("%d %d\n",i,j);
getch();
}
As stated earlier in this chapter, the three elements that form the definition of
the for instruction are not mandatory. Some of them (even all of them) can
miss. The following examples emphasize this aspect.
It is possible to have a for instruction, which doesnt contain the action that
modifies the control variable. In program 6.3.5 the value of this variable is read
from the keyboard inside the loop. The value 1/i is calculated and displayed as
long as the user enters numbers that are not equal to zero.
Program 6.3.5
#include <stdio.h>
#include <conio.h>
93
6 Instructions
tively reads a character from the keyboard and stops only when the user enters
the letter 'z'.
Program 6.3.7
#include <stdio.h>
#include <conio.h>
void main(void){
char c;
clrscr();
for(;;){
c=getchar();
if(c=='z') break;
}
}
If some delays must be inserted in a program, then a for instruction with empty body can be used. Program 6.3.8 creates a delay; after the definition of the
instruction for follows a semicolon, meaning that it doesnt contain anything,
so it doesnt do anything, excepting it increments the control variable until this
reaches the threshold. In order to have a noticeable delay, the control variable
must have large values; for this reason it was declared as long int.
Program 6.3.8
#include <stdio.h>
#include <conio.h>
void main(void){
long int i;
clrscr();
printf("Wait!");
for(i=0;i<500000000;i++);
printf("\nThis was a delay.");
getch();
}
true
EXPRESSION
Block of
instructions
false
6 Instructions
#include <math.h>
void main(void){
float x=0;
clrscr();
printf("The square root is calculated\n.");
printf("Negative number -> end of the program.\n");
while (x>=0){
printf("Square root of %f is %f", x, sqrt(x));
printf("\nEnter a number ");
scanf("%f",&x);
}
}
Together with repetitive instructions a jump instruction is frequently used:
continue. This forces the program to execute the next iteration, ignoring the
lines of code that come after it until the end of the loop. It influences only the
iterative cycle that contains it and doesnt affect other outside instructions.
Program 6.3.10 reads numbers from the keyboard until the user enters the value
zero. If the read number is negative, it is transformed into a positive one and a
message informs the user about this. If the number is already positive, then a
jump to the next iteration is made using the continue instruction. This is also
an example where the variable x receives an initial value, which provides that
the loop is executed at least ones (this value will be overwritten anyway with
the first number entered by the user).
Program 6.3.10
#include <stdio.h>
#include <conio.h>
#include <math.h>
void main(void){
int x=1;
clrscr();
while (x!=0){
printf("Enter a number ");
scanf("%d",&x);
if (x>0) continue;
x=-x;
printf("The number was transformed.\n");
}}
97
98
6 Instructions
Block of
instructions
EXPRESSION
true
false
6 Instructions
printf("x="); scanf("%d",&x);
printf("%.2f",exp(x)); break;
}
getch();
}while(option==1||option==2);
}
e
x y,x
ln |x y|
2 y,x
Program 6.4.2
#include <stdio.h>
#include <conio.h>
#include <math.h>
101
102
6 Instructions
Program 6.4.4
#include <stdio.h>
#include <conio.h>
void main(void){
float a,b,c,max;
clrscr();
printf("a="); scanf("%f", &a);
printf("b="); scanf("%f", &b);
printf("c="); scanf("%f", &c);
max=a;
if(b>max) max=b;
if(c>max) max=c;
printf("MAX:%.2f",max);
getch();
}
6.4.5 The coefficients of a first degree equation, two numbers a i b, are read
from the keyboard. Then the equation is solved and the result is displayed (see
also the logical diagram used to solve this problem in chapter 2).
Program 6.4.5
#include <stdio.h>
#include <conio.h>
void main(void){
float a,b,x;
clrscr();
printf("a=");scanf("%f", &a);
printf("b=");scanf("%f", &b);
if(a==0)
if(b==0)
printf("An infinite number of solutions");
else
printf("The equation doesnt have solutions");
else{
x=-b/a;
printf("The result is: %5.2f", x);
}
getch();}
103
6.4.6 This program displays all natural numbers i[a,b] that can be divided
by n. The values for a, b and n are read from the keyboard. If a and b are not
in an ascending order, they are reversed using an auxiliary variable.
Program 6.4.6
#include <stdio.h>
#include <conio.h>
void main(void){
int i, n, a, b, aux;
clrscr();
printf("a="); scanf("%d", &a);
printf("b="); scanf("%d", &b);
printf("n="); scanf("%d", &n);
if(b<a){ //if it is not the correct order
aux=a; a=b; b=aux; //they are reversed
}
for(i=a;i<=b;i++) //the [a,b] range is scanned
if(i%n==0) //if the number is divisible by n
printf("%d ",i); //it is printed
getch();
}
6.4.7 The program reads n integer numbers and calculates the average of the
positive ones. Since the numbers are integers, a type conversion is required
when the average is calculated.
Program 6.4.7
#include <stdio.h>
#include <conio.h>
void main(void){
int i, n, sum=0, count=0, x;
float average;
clrscr();
printf("n="); scanf("%d", &n);
for(i=1;i<=n;i++){
printf("\nx="); scanf("%d",&x);
if(x>0){
104
6 Instructions
/*if the number is positive, it is added to the
sum and the variable that counts the number of
positive elements is incremented*/
sum=sum+x;
count++;
}
}
if(count==0)
printf("There are no positive numbers!");
else{
average=(float)sum/count;
printf("The average is: %.2f",average);
}
getch();
}
105
6 Instructions
be left only if the number is valid. Second, the numbers must be in descending
order; if not so, they must be reversed. After these two conditions are accomplished, the greatest common divisor can be determined.
Program 6.4.10
#include <stdio.h>
#include <conio.h>
void main(void){
int m, n, r, aux;
clrscr();
do{
printf("M="); scanf("%d", &m);
}while(m<=0);
do{
printf("N="); scanf("%d", &n);
}while(n<=0);
if (m<n){
aux=m;
m=n;
n=aux;
}
/*Here starts the Euclids algorithm*/
r=m%n;
while (r!=0){
m=n;
n=r;
r=m%n;
}
printf("\nThe greatest common divisor: %d", n);
getch();
}
6 Instructions
else if((a>0)&&(b>0))
y=a*b;
printf("x=%d, y=%d", x, y);
}
11. #include <stdio.h>
#include <conio.h>
void main(void){
int i;
clrscr();
for(i=1;i<0;i++)
printf("%d ",i);
getch();
}
12. #include <stdio.h>
#include <conio.h>
#include <math.h>
void main(void){
float r;
clrscr();
do{
printf("r="); scanf("%f",&r);
}while(r<=0);
printf("%.2f", 2*M_PI*r);
getch();
}
C. Choose the correct answer (one only).
13. Which of the following operators cannot be used in a comparison?
a) >=; b) <=; c) +=; d) ==; e) all answers are wrong.
14. Which of the following instructions is an alternative one?
a) while; b) if; c) break; d) for; e) all answers are correct.
15. After the instruction for(i=0; i<5; i++) is executed, the variable
i will have the value:
a) 0; b) 1; c) 4; d) 5; e) 6.
16. Which of the following instructions is a repetitive one?
109
6 Instructions
f(x)=max{7x2-3,|25-x|}.
27. Calculate and display the roots of the second degree equation (the coefficients a, b and c are real numbers and they are read from the keyboard).
28. The values of the three real numbers a, b and c are read from the keyboard; they represent the sides of a triangle. Calculate and display the
surface of the triangle. Herons formula will be used:
A
s s
a s
b s
112
Chapter 7
Arrays
An array is a homogeneous collection of variables; therefore the elements that
form an array must have the same type. Each element of an array has allocated
its own memory space. In C programming language arrays are made of adjacent
memory locations; the first element of an array has the smallest memory address and the last one has the greatest memory address [HS98].
Within an array, each element is identified and accessed through one or more
indexes. These indexes can only have integer values [DL06]. In C programming
language the numbering of indexes starts at 0 and each index is written inside
square brackets.
When an array is declared, it receives a name and it is associated to a data type.
The array can have one or more dimensions. Therefore they can be classified in:
single-dimensional arrays are the programming version of mathematical
vectors and are also used to represent strings (sequences of characters);
two-dimensional arrays represent the mathematical matrices and are organized on rows and columns;
multi-dimensional arrays are rarely used because they need a huge adjacent memory space and a lot of time is consumed to access their elements;
the dynamic memory allocation is usually used for this kind of variables
[HS98].
The following paragraphs describe the arrays with one and two dimensions
because they are most commonly used. Strings are closely related to this subject; they are in fact single-dimensional arrays of elements that have the type
char. Their description is made separately, in one of the next chapters.
-3
12
-9
n-2
n-1
114
7 Arrays
7 Arrays
for(i=0;i<n;i++){//reading the elements
printf("v[%d]=", i);
scanf("%d", &v[i]);
}
for(i=0;i<n;i++)//displaying the array
printf("%d ", v[i]);
for(i=0;i<n;i++)//calculating the sum
sum=sum+v[i];
printf("\nThe sum is: %d", sum);
getch();
}
m-1
-3
11
-7
-1
17
.
.
.
.
.
n-1
7 Arrays
int matr[3][4]={
{1, 9, 12},
{-7, 40, 3},
{3, -2, 8}
};
This kind of initialization of the elements of a matrix is a very simple procedure, but it could be improper for two-dimensional arrays with large dimensions
or when the values must be read or calculated. For these reasons, mostly, the
elements of a matrix receive their values through some instructions during the
execution of the program.
a) horizontal
b) vertical
Figure 7.2.2 Traversing a matrix
7 Arrays
In a vertical traversing, the outside for refers to the columns and the inside one
refers to the rows. Therefore, the index of the row is the one that changes more
often (unlike the horizontal traversing, where the index of the columns was the
one that was changed more often). The following example performs a vertical
traversing of a matrix and displays the elements in the accessing order.
for(j=0;j<m;j++)
for(i=0;i<n;i++)
printf("%3d ", a[i][j]);
It can be observed that the two fors used for the traversing were inverted,
compared to the horizontal traversing. This is because the traversing is made on
column, not on row.
If the matrix is
1 2 3 4
5 6 7 8
then
1 5 2 6 3 7 4 8
will be displayed on the screen (because of the vertical traversing).
121
There are cases when only these parts of a matrix must be traversed, not the
entire two-dimensional array. The following sequences of code show how to
execute these types of specific traversing of a square matrix a that contains
integer numbers. The index of the row is represented by the variable i and that
of the column is represented by the variable j. The accessed elements are displayed in order to be identified.
traversing the main diagonal the elements belonging to the main diagonal
have the index of the row equal to the one of the column; therefore a single
for instruction is enough to access them; an element of the main diagonal
has the coordinates i and j;
for(i=0;i<n;i++)
printf("%3d ", a[i][i]);
traversing the upper triangle of the main diagonal for the elements placed
above the main diagonal the index of the row, i, belongs to the range
[0,n) and the index of the column, j, starts from i+1 and goes to n-1;
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
printf("%3d ", a[i][j]);
traversing the lower triangle of the main diagonal at the elements placed
below the main diagonal, the index i also goes from 0 to n-1 and the index
j starts from 0 and stops before the element placed on the main diagonal
(the one on the column i);
122
7 Arrays
for(i=0;i<n;i++)
for(j=0;j<i;j++)
printf("%3d ", a[i][j]);
traversing the secondary diagonal the rows must be traversed downside up
(in the range [n,0)); between the index of the row and the one of the column there is a well-defined connection; therefore, in this case a single for
cycle is enough for the traversing; the elements of the secondary diagonal
have the coordinates i-1 and n-1;
for(i=n;i>0;i--)
printf("%3d ", a[i-1][n-i]);
traversing the upper triangle of the secondary diagonal for the elements
placed above the secondary diagonal both indexes start from 0; the i stops
before n and the j before n-i-1;
for(i=0;i<n;i++)
for(j=0;j<n-i-1;j++)
printf("%3d ", a[i][j]);
traversing the lower triangle of the secondary diagonal at the elements
placed below the secondary diagonal the index of row, i, also traverses the
range [0,n); the index of column, j, starts from n-i and stops at n-1.
for(i=0;i<n;i++)
for(j=n-i;j<n;j++)
printf("%3d ", a[i][j]);
There is considered a square matrix of 4 rows and 4 columns with the initial
values:
1
9 10 11 12
13 14 15 16
When the sequences of code previously presented are run, these will print:
for the main diagonal: 1 6 11 16;
123
7 Arrays
7 Arrays
int fibo[20];
int i;
clrscr();
/*the first two elements of the vector receive initial values (these values are known)*/
fibo[0]=0; fibo[1]=1;
/*the values of the next elements are calculated*/
for(i=2;i<20;i++)
fibo[i]=fibo[i-1]+fibo[i-2];
/*all the elements are displayed*/
for(i=0;i<20;i++)
printf("%d ", fibo[i]);
getch();
}
7.3.4 The minimum value in a two-dimensional array. At the beginning, the
value of the first element is considered the minimum. Then the entire matrix is
traversed, comparing the minimum with each element of the matrix; if a value
less than the minimum is found, then the minimum is changed.
Program 7.3.4
#include <stdio.h>
#include <conio.h>
void main(void){
int a[50][50], n, m, i, j, min;
clrscr();
printf("Number of rows: ");
scanf("%d", &n);
printf("Number of columns: ");
scanf("%d", &m);
for(i=0;i<n;i++)//reading the elements
for(j=0;j<m;j++){
printf("a[%d][%d]=", i, j);
scanf("%d", &a[i][j]);
}
for(i=0;i<n;i++){//printing the matrix
for(j=0;j<m;j++)
printf("%3d ", a[i][j]);
printf("\n");
127
7 Arrays
getch();
}
7.3.6 The number of odd elements placed below the main diagonal of a twodimensional array is found and these elements are displayed. Only that triangle
is analyzed (not the entire matrix), using a specific sequence of code: the index
of rows traverses the range [0,n), and the index of columns has values in the
range [0,i).
Program 7.3.6
#include <stdio.h>
#include <conio.h>
void main(void){
int a[50][50], n, i, j, count=0;
clrscr();
printf("Number of rows: ");
scanf("%d", &n);
for(i=0;i<n;i++)
for(j=0;j<n;j++){
printf("a[%d][%d]=", i, j);
scanf("%d", &a[i][j]);
}
for(i=0;i<n;i++){
for(j=0;j<n;j++)
printf("%3d ", a[i][j]);
printf("\n");
}
printf("The odd elements are: ");
for(i=0;i<n;i++)
for(j=0;j<i;j++)
if(a[i][j]%2!=0){
count++;
printf("%d ", a[i][j]);
}
printf("\nThere are %d odd elements", count);
getch();
}
129
7 Arrays
}
printf("The second matrix is:\n");
for(k=0;k<p;k++){
for(j=0;j<m;j++)
printf("%3d",b[k][j]);
printf("\n");
}
for(i=0;i<n;i++)//the product matrix is initialized
for(j=0;j<m;j++)
c[i][j]=0;
for(i=0;i<n;i++)//calculating the product matrix
for(j=0;j<m;j++)
for(k=0;k<p;k++)
c[i][j]=c[i][j]+a[i][k]*b[k][j];
printf("The product matrix is:\n");
for(i=0;i<n;i++){
for(j=0;j<m;j++)
printf("%3d",c[i][j]);
printf("\n");
}
getch();
}
132
7 Arrays
a) are integer numbers; b) are consecutive numbers; c) start from
the value zero; d) identify an element of the array; e) all of them.
11. When a single-dimensional array is declared, one must be specify:
a) the name; b) the type; c) the number of the elements; d) the
answers a, b and c are correct; e) all answers are wrong.
12. What is the action performed by the instruction a[7]=7;?
a) verifies if a variable a is equal to 7; b) assigns the value 7 to the
element with the index 7 of the single-dimensional array a; c) verifies
if the element a[7] is equal to 7; d) declares a vector of 7 elements
and gives initial value to its first element; e) all answers are wrong.
13. What is the effect of the line of code float average[20][10];?
a) declares a two-dimensional array of maximum 20 rows and 10
columns, containing real numbers; b) declares a single-dimensional
array with maximum 200 real numbers; c) declares a singledimensional array and initialize two of its elements with the values 20
and 10; d) performs a type conversion of the values 20 and 10 from
int to float; e) calculates the average between 20 and 10.
14. Which of the following statements regarding element a[2][3] of a
matrix is true?
a) it is placed on the second row and on the third column; b) it is
placed on the second column and on the third row; c) it is placed on
the third row and on the fourth column; d) it is placed on the third column and on the fourth row; e) all answers are wrong.
D. Write programs to solve the following problems.
15. Calculate and display the sum of odd elements in a single-dimensional
array.
16. Display in reverse order (from right to left) the elements of a vector.
17. Calculate and display the average grade of a student whose marks are
stored in a single-dimensional array. The average will be calculated only
if all the marks are greater than or equal to 5.
18. Determine the index of the first occurrence of a given value in a singledimensional array of n integer elements.
133
134
Chapter 8
Strings
A string variable stores a sequence of characters. C programming language
doesnt have a data type dedicated to strings (as Java and Pascal have the
string type). In C the strings are represented using single-dimensional arrays
that contain in each location a character and that have in their last location the
character '\0', which marks the end of the string. Because the basic element
of a string is the character, this chapter starts by presenting several aspects
connected to characters; then the features of the strings are described in detail.
8.1 Characters
The data type char is used in order to declare a character. This type has 8 bits;
therefore 28, meaning 256 characters can be represented. Each character is
stored as an integer number in the range [0, 255], number that is the ASCII code
related to that character [CH96]. Appendix 1 contains the most used characters
together with their ASCII codes.
When a character variable must be declared, the keyword char is used, followed by the name of that new variable. If the variable requires an initial value,
then that value must be enclosed by apostrophes (not quotation marks). The
following instruction declares a variable with the name ch and gives it the
ASCII value of the letter A.
char ch='A';
For input/output actions made on character variables the functions getchar() and putchar() can be used. If a formatted manner is required for
these variables, it can be performed through the functions printf() and
scanf(), using the format descriptor %c. The following instruction displays
on the screen the variable ch, previously declared; therefore the letter A will be
printed.
printf("%c",ch);
The characters can be analyzed and processed through several functions that are
part of the header file <ctype.h>. Some of these functions are hereby presented (each function receives a character as argument).
8 Strings
option=getch();
}while(tolower(option)!='n');
}
8.2 Strings
A string is a sequence of characters that ends with '\0' (character that has the
ASCII code 0) and enclosed in double quotes ("This is a string"). The
double quotes specify that it is a string and the compiler adds the terminator for
strings [CH96]. The null character from the end of a string exists only in the
computers memory; the programmer is not required to worry about it too
much. The string from above can have the following memory representation:
T
t r
n g
\0
8 Strings
The string processing (copying, concatenating, comparing) is made through
several functions that are part of the header file <string.h>. Some of these
functions are hereby presented.
int strlen(const char *s);
It returns the length of the string s (the number of characters), not counting the
terminating null character. Program 8.2.2 shows how this function can be used.
Once the program is run, values 14 and 17 (the lengths of the two strings) will
be displayed on the screen.
Program 8.2.2
#include <stdio.h>
#include <conio.h>
#include <string.h>
void main(void){
char name[]="Dennis Ritchie";
int l;
clrscr();
l=strlen("Bell Laboratories");
printf("%d, %d", strlen(name), l);
getch();
}
char *strcpy(char *dest, const char *src);
The function is used to make assignments between two strings, copying the
source string src into the destination string dest. It returns the destination
string and assumes that it is long enough to store the source string (if not, the
program can have an improper behavior, even if it doesnt have compilation
errors). This function is necessary because in C programming language the
assignments of strings cannot be made by simple instructions as str1=str2.
Program 8.2.3 is a short example that uses this function. The text abcdefg
will be displayed on the screen. It can be noted that strcpy() function modifies the content of the destination string (the initial content of this string is
lost), but keeps the source string unchanged (actually, the source string is declared as a constant in the functions prototype).
Program 8.2.3
#include <stdio.h>
#include <conio.h>
139
8 Strings
o 0 if strings s1 and s2 are identically;
o a positive value if string s1 is greater than string s2.
Program 8.2.5 compares the password entered by the user to the password that
was set through the program; a message is displayed accordingly. The passwords are stored into strings.
Program 8.2.5
#include <stdio.h>
#include <conio.h>
#include <string.h>
void main(void){
char pass[20]="Secret!";
char user_pass[20];
clrscr();
gets(user_pass);
if(strcmp(pass, user_pass)==0)
printf("Welcome!");
else
printf("Incorrect password");
getch();
}
char *strchr(const char *s, int c);
This function searches the char c into the string s. If it finds the character, it
returns a pointer to the characters first occurrence into the string; else, it returns the null value.
char *strrchr(const char *s, int c);
The character c is also searched into the string s, but the traversing is made
from right to left; therefore the function returns the address of the characters
last occurrence (or the null value if string s doesnt contain the character c).
char *strstr(const char *s1, const char *s2);
The function looks for string s2 into string s1. It returns a pointer to the address of s2 into s1 or null if s2 in not part of s1.
Program 8.2.6 is an example of using the previously described three functions.
"C Programming" string is considered and three substrings are extracted
from it; the first one begins where the char 'r' occurs for the first time, the
141
8 Strings
It is similar to the function strcmp(), but it doesnt distinguish between
lowercases and uppercases; therefore it is not case sensitive (the strings "ABC"
and "abc" will be considered identical by this function).
int strnicmp(const char *s1,const char *s2, int n);
It is similar to the function strncmp(), but it doesnt distinguish between
lowercases and uppercases; therefore it is not case sensitive.
Conversion functions these are used to transform a string into another data
type (usually a number) and vice versa. These functions are part of the
header file <stdlib.h>.
o int atoi(const char * str );
This function transforms the string received as argument into an integer number. First, the function ignores the spaces from the beginning of the string (if
there are such spaces); then it interprets a possible plus or minus sign; finally
the function transforms the next characters into an integer number (if these
characters have such a meaning). When a character that cannot be interpreted as
a number is encountered, the function stops, returning the already created number and ignoring the rest of the string. If the string doesnt begin with a sequence of characters that can be transformed into an integer, then the function
returns zero.
o long int atol(const char * str );
It is similar to the function atoi(), but it returns a value of type long int.
o double atof(const char * str );
It is similar to the function atoi(), but transforms the string (or a part of it)
into a real number (of type double).
o char *itoa(int val, char * str, int base);
This is not a standard function, but it is accepted by some compilers. Using this
function, an integer number is transformed into a string. The number is the first
argument of the function. The string obtained through the conversion is returned by the function and it is also stored into the second argument of the
function. The third argument specifies the base to be used in conversion (for
instance, 10).
Program 8.2.7 uses the functions atoi() and itoa() to convert a string into
an integer and two integers into strings (the third string is the base 2 representa143
8 Strings
the for the variable flag is unchanged (its value is still 1), then all the characters of the string are symmetrical with respect to the middle of the string,
therefore the string is a palindrome; otherwise, not.
Program 8.2.8
#include <stdio.h>
#include <conio.h>
#include <string.h>
void main(void){
char str[25];
int flag=1;
int i, n;
clrscr();
printf("Enter the string: ");
gets(str);
n=strlen(str);
for(i=0;i<n/2;i++)
if(str[i]!=str[n-i-1]){
flag=0;
break;
}
if(flag)
printf("The string is palindrome.");
else
printf("The string is not palindrome.");
getch();
}
8 Strings
10. There are considered two strings a="abra" and b="cadabra". After the execution of the instruction strcat(a,b);, the variables a
and b will have the following values:
a) a="abra", b="cadabra"; b) a="abra si cadabra",
b="cadabra"; c) a="abracadabra", b="cadabra"; d)
a="abra
cadabra", b="cadabra"; e) a="abra",
b="abracadabra".
11. There are considered two strings s1="abc" and s2="abc" and two
integer variables a=0 and b=0. The following sequence of code is executed: if(strcmp(s1,s2)==0) a++; else b+=1;. What
will be the values of the variables a and b after this execution?
a) a=0, b=0; b) a=1, b=0; c) a=1, b=1; d) a=0, b=1; e)
all answers are wrong.
12. Which of the following functions should be used to determine the length
of a string?
a) strlength(); b) length(); c) String.Len(); d)
strlen(); e) len().
13. Which of the following actions is possible with two strings s1 and s2?
a) s=s1+s2; b) s=s1-s2; c) s=s1*s2; d) s=s1/s2; e)
all answers are wrong.
14. A string is:
a) a data type; b) an array of characters; c) an operator; d) a
function; e) a program.
15. The function that concatenates two strings is:
a) strcat(); b) strconcatenate(); c) concatenate(); d) strconc(); e) conc().
16. Which of the following functions is case sensitive?
a) strcpy(); b) strcat(); c) strlen(); d) strcmp();
e) stricmp().
17. Which of the following instructions copies a string s1 to a string s2?
147
148
Chapter 9
Pointers
Pointers are essentials in C programming; they are connected to arrays and
strings (described in two previous chapters) and also to functions, user-defined
types and files, which will be explained in the following chapters. The dynamic
memory allocation is also closely related to pointers. A good programmer must
be able to manage this kind of variables.
Pointers are considered as some of the strongest features of C programming
language. On the other hand, they are also a very dangerous tool available to
anyone. The pointers that are uninitialized or that have incorrect values could
lead to errors that are very difficult to be located in a program or could even
cause dysfunctions of the operating system [HS98], [CH96].
.
..
65528
9.5
.
..
65520
mark
*p
65528
..
.
150
9 Pointers
In order to access the value of the mark one can either use the mark variable
directly or the dereferenced pointer *p. Therefore, the following two instructions have the same result: they display the mark on the screen.
printf("%.2f", mark);
printf("%.2f", *p);
Program 9.1.1 provides the entire example. It can be noted that both the variable mark and the pointer p have the same type, in order to make possible the
assignment p=&mark. Pointers must have a type related to the variables they
indicate. This means that it is unnatural to have an int pointer that stores the
address of a float variable (though any address can be assigned to a pointer).
Program 9.1.1
#include <stdio.h>
#include <conio.h>
void main(void){
float mark, *p;
clrscr();
p=&mark;
mark=9.5;
printf("%.2f",mark);
printf("\n%.2f",*p);
getch();
}
152
9 Pointers
9 Pointers
Because pointers are frequently used together with strings, another example
from this area is hereby presented (program 9.3.3). The program searches for
the first occurrence of a character in a string and displays the index of this
occurrence. In order to do this, a string str is declared using the classical way
(array of characters); it stores the text "C Programming". Another string,
ptr, is declared as pointer. It receives the address of the first occurrence of the
character 'r' that is stored in the variable c. If the address of the beginning of
the string (meaning str) is subtracted from the address of the first occurrence
of the character in the string (meaning ptr) then the result is the number of
locations between these two addresses, which is in fact exactly the index of the
first occurrence of the character c in the string str. If the character stored in
the variable c doesnt belong to the string str, then the pointer ptr will have
the value NULL and a message will be displayed accordingly.
Program 9.3.3
#include <stdio.h>
#include <conio.h>
#include <string.h>
void main(void){
char str[20];
char *ptr, c = 'r';
clrscr();
strcpy(str, "C Programming");
ptr = strchr(str, c);
if (ptr)
printf("\'%c\' has the index: %d", c, ptr-str);
else
printf("The character was not found");
getch();
}
The use of pointers doesnt end here. The following chapters describe the connections between pointers and functions (pointers are especially used to send
parameters by address), user-defined types (for instance, structures can be
accessed through pointers) or files (the connection to a file is made through a
pointer).
155
9 Pointers
11. Which of the following statements is false?
a) & is the addressing operator; b) * is the dereference operator;
c) * can be used to multiply two pointers; d) & cannot be used to multiply two pointers; e) all answers are wrong.
12. Which of the following sequences is the address of a variable indicated
by the pointer p?
a) p; b) &p; c) *p; d) &&p; e) none of them.
13. Which of the following sequences is the value of a variable indicated by
the pointer p?
a) p; b) &p; c) *p; d) &&p; e) none of them.
14. There is considered the sequence of code float *p1, *p2, x=3,
y=4; p1=&x; p2=&y;. Which of the following instructions cannot
be executed?
a) p1=p1+7.25; b) p1=p1+7; c) p1=p1-7; d)
if(p1==p2); e) all these instructions are correct.
D. Write programs to solve the following problems.
15. Two marks are read from the keyboard (the mark for the exam and the
mark for the lab); they are stored in pointer variables. Display the final
mark (the mark for the exam is 2/3 of the final mark and the mark for
the lab is 1/3 of the final mark).
16. The elements of a vector with integer numbers are read from the keyboard. Traverse this vector using a pointer and display the value of its
first negative element.
17. The first name and the last name of a student are read in two variables
char *. Create a third string (also a pointer of type char) that contains the first name followed by the second name (separated through a
space).
18. A text t and two words w1 and w2 are read from the keyboard. Display
the string that is obtained by replacing in text t all the occurrences of
w1 with w2.
157
Chapter 10
User-defined functions
A complex problem is not usually solved by a single group of instructions
placed in the main() function. This would imply the writing of a very long
and intricate program and, on the other hand, an unnecessary duplication of
some sections of code that perform the same task (eventually using different
input data). In order to avoid these disadvantages, the problem that must be
solved is split into several sub-problems; separated sections of code are written
for each sub-problem that has distinct features. These sections of code are in
fact the functions.
A C program can contain two types of functions:
predefined functions (or library functions)
o this are already implemented to solve simple and well-defined
problems;
o they are part of the standard library of the C programming language; therefore, a preprocessor directive #include followed
by the name of the header file that contains a certain function is
necessary when that function is used in a program;
o examples: mathematical functions (math.h): sqrt(), exp();
functions that perform input/output actions (stdio.h, conio.h): printf(), scanf(); functions used to process
strings (string.h): strlen(), strcpy();
user-defined functions
o these are written by the developer of a program;
o their use makes the program clearer, easier to correct, maintain
and modify and allows code reusability.
Therefore, functions are an important feature of the C programming language,
representing the location where the entire activity of a program takes place
[HS98]. Splitting programs into small units (functions) is the best solution in
structuring these programs. Functions are easier to handle and can be used in
various configurations [CH96].
10 User-defined functions
A function is a sequence of code that has a name and that performs a certain
task. A C program must have at least one function (the main() function,
without which a program cannot be executed), but it can contain many other
functions.
10 User-defined functions
float average(int n){
int i;
float sum=0;
for(i=1;i<=n;i++)
sum=sum+i;
return sum/n;
}
About return
If a function has to return a value, then its body must contain at least one return instruction followed by the value that is returned (as in case of the function average previously presented). The general form for this instruction is:
return [expression];
When the instruction return is executed, the function that contains it is immediately left and the execution of the program goes back to the instruction that
caused the call of the function. If the function returns a value, then the expression that follows after return is executed and the result is sent outside. If return is not followed by an expression, a variable or a value or even
is missing, then the function is left without returning a value (of course, this is
the case of a void function). The following function receives as argument a
string and displays it in reverse order, without returning anything:
void reverse(char *s){
int i;
for(i=strlen(s)-1;i>=0;i--)
printf("%c",s[i]);
}
A function may contain several return instructions; the first one that is encountered will be executed. These multiple return instructions emerge on
different branches of conditional instructions (for instance if else) and
using them distinct values are returned, accordingly to the path followed by the
execution of the program. The following function receives as argument a real
number (a float one) and returns its sign (-1 if the number is negative, 0 if it
is zero or 1 if it is positive):
161
About arguments
The arguments (or the parameters of a function) are enclosed by parentheses
and are placed right after the name of a function in its prototype and in its definition. Data is transmitted from outside to function through these arguments.
They can be used in the function as any other variable that was declared inside
that function. Each argument has a name and a type. The type that is specified
in the prototype must be identical to the one used when the function is called;
the name can be different. The following function returns the product of two
integer numbers received as argument:
int product(int x, int y){
return x*y;
}
If a function doesnt accept arguments, then its prototype and its definition will
have the type void instead of the list of arguments. The following function
doesnt receive arguments (it returns the sum of the first 5 natural numbers):
int sum(void){
int i, s=0;
for(i=1;i<=5;i++)
s=s+i;
return s;
}
162
10 User-defined functions
10 User-defined functions
10 User-defined functions
printf("Error: division by zero!");
getch();
}
One of the major advantages of functions is that these are written once and
could be used (called) many times, generating different results if different parameters are sent to them. In program 10.1.4, function signum() is called
three times.
Program 10.1.4
#include <stdio.h>
#include <conio.h>
int signum(float x){
if(x<0) return -1;
else
if(x==0) return 0;
else return 1;
}
void main(void){
clrscr();
printf("\n%d", signum(-7.17));
printf("\n%d", signum(0));
printf("\n%d", signum(70));
getch();
}
10 User-defined functions
char str[20], ch;
int found;
clrscr();
printf("Enter the string: ");
gets(str);
printf("Enter the character: ");
scanf("%c", &ch);
found=search(str,ch);
if(found)
printf("The character was found");
else
printf("The character doesnt exist");
getch();
}
169
10 User-defined functions
m=(a+b)/n;
return m;
}
void main(void){
float n1=5, n2=10, result;
//n1, n2, result local variables
clrscr();
n=2;
result=calculate(n1,n2);
//n1, n2 actual parameters
printf("The average is: %.2f", result);
getch();
}
It is advisable to use local variables and parameters rather than global variables
whenever is possible. For instance, a function that calculates the sum of two
numbers can be developed in several ways:
version 1 the function can only be used to calculate the sum of the global
variables x and y:
int x, y;
int sum(void){
return x+y;
}
version 2 the function receives two numbers as arguments; it is more
general and because it is parameterized, it can be used to calculate the sum
of any two numbers:
int sum(int x, int y){
return x+y;
}
If a local variable has the same name as a global variable, all the instructions
that access the variable within the function where the local variable is declared
refer only to the local variable and do not affect the global variable [HS98].
Program 10.1.8 emphasizes this aspect. Once it is run, on the screen is displayed:
x in main: 10
171
172
10 User-defined functions
If nothing else is specified, then the local variables are destroyed when the
function ends its execution. This is because they are considered by default
automatic.
There is the possibility to keep the content of a variable between two executions
of the function that created it. The variable can be accessed only by that function and its content is maintained until the execution of the entire program ends.
In other words, a static local variable gives the possibility to store information
in a private way (because this information is available only to the function
where the variable is defined) and also in a permanent way (the information is
available during the entire execution of the program) [BK03]. This is performed
using the keyword static in front of the variables declaration:
static int counter=0;
Program 10.1.9 emphasizes the difference between static and automatic variables. The functions increment1() and increment2() increment and
display the value of a counter that receives the initial value 0 at the beginning
of these functions. They are repetitively called 10 times in the main() function. The difference between these two functions is the manner of declaring the
local variable counter. Within function increment1() it remains automatic, but within function increment2() it is declared static; this will maintain the value of the variable counter, belonging to the function increment2(), from an execution to the next one.
Once the program is executed, on the screen will be displayed:
Automatic variable:
1 1 1 1 1 1 1 1 1 1
Static variable:
1 2 3 4 5 6 7 8 9 10
The counter variable receives the initial value 0 at the beginning of each
function. It must be specified that if a variable is declared static, this line is
executed only when the function is called for the first time (this is the reason
why the value of the variable is not altered when the function is recalled).
Program 10.1.9
#include <stdio.h>
#include <conio.h>
173
10 User-defined functions
function, but because it is only a copy of the value used in the functions call,
these changes have no effect on the actual parameter.
Program 10.1.10 creates and initializes a variable x within the main() function and then sends this value to the function pass_val() that increments the
received argument. Variable x is displayed at return from the function in order
to see that its value is not changed.
Program 10.1.10
#include <stdio.h>
#include <conio.h>
void pass_val(int x){
x++;
}
void main(void){
int x=10;
clrscr();
pass_val(x);
printf("x=%d", x); //it is displayed x=10
getch();
}
Programs that pass the parameters by value are more compact and have fewer
global variables (within functions the formal parameters are similar to local
variables) [BK03]. Using this way of passing the arguments, the functions dont
have access to the original variable, but only to their copies.
Nevertheless, sometimes the changing of actual parameters is required; in this
case they must be passed by address. The address of a variable is sent in the
functions call. The parameter is declared as pointer in the functions prototype
and the variable is indirectly accessed through this pointer [BK03]. This way
the changes are made right on the original variable.
Program 10.1.11 emphasizes the passing of arguments by address. The code is
very similar to the one used for the passing by value. The first difference that
should be noticed emerges at the call of the function pass_adr() that receives as argument the address of the variable x (&x). The second aspect is connected to the prototype of the function, where x is declared as pointer (*x).
Finally, the third thing regards the way of handling the variable x within the
175
10 User-defined functions
Program 10.1.12
#include <stdio.h>
#include <conio.h>
void doubles(int n, int v[]){
int i;
for(i=0;i<n;i++)
v[i]=v[i]*2;
}
void main(void){
int v[100], i;
clrscr();
for (i=0;i<10;i++) v[i]=i; //0 1 2 3 4 5 6 7 8 9
doubles(10,v);
for(i=0;i<10;i++)
printf("%d ", v[i]); //0 2 4 6 8 10 12 14 16 18
getch();
}
A two-dimensional array (a matrix) is passed as argument in a similar way.
Program 10.1.13 is an example of this matter. There is a difference: the function
that receives the matrix as argument (modifies()) requires information
regarding the maximum number of columns of the matrix (100), besides the
real number of rows (n, which is 2 in this case) and of columns (m, which is 3
in this case) used by the matrix.
Program 10.1.13
#include <stdio.h>
#include <conio.h>
void modifies(int n, int m, int a[][100]){
int i, j;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
a[i][j]++;
}
void main(void){
177
10.2 Recursion
The recursion is the process of defining an entity using the same entity [HS98].
A function is recursive if it is called directly or indirectly by itself [BK03].
One of the simplest examples of recursion is the factorial of an integer number
n. It is the product of all integer numbers between 1 and n (including n) and
from the mathematical point of view is written n!. For instance, 4 factorial is
4!=1x2x3x4=24.
The implementations of both recursive and iterative (non-recursive) versions
are hereby presented (program 10.2.1). The function iterative_factorial() is very simple; it traverses the numbers between 1 and
n and multiply each number i with the already calculated product of its previous numbers.
For the recursive version of the factorial, the function recursive_factorial() is called by itself. For instance, if factorial of 3 must be
calculated:
n has the initial value 3, therefore the instruction on the else branch is
executed; the result will be 3 multiplied with the value returned by a new
call of the function, this time with the parameter n-1, which is 2;
n is 2, therefore the result is 2*recursive_factorial(1);
178
10 User-defined functions
n is 1, therefore result=1 (the true branch of the if instruction is
executed) and this third call of the function ends, returning the value 1 to
the second call;
the second call of the function calculates result=2*1=2 and returns this
value to the first call of the function;
the first call calculates result=3*2=6 and returns it where the function
was initially called (in main()).
Program 10.2.1
#include <stdio.h>
#include <conio.h>
int iterative_factorial(int n){
int i, result=1;
for(i=1;i<=n;i++)
result=result*i;
return result;
}
int recursive_factorial(int n){
int result;
if(n==1)
result=1;
else
result=n*factorial_recursiv(n-1);
return result;
}
void main(void){
int n;
clrscr();
printf("n="); scanf("%d", &n);
printf("Iterative: %d", iterative_factorial(n));
printf("\nRecursive: %d", recursive_factorial(n));
getch();
}
Generally, a recursive function has an if instruction that determines whether
the last call of the function was encountered or it must be called again. Without
179
10 User-defined functions
10 User-defined functions
int i, j;
printf("Writing - matrix %s\n", name);
for(i=0;i<n;i++){
for(j=0;j<m;j++)
printf("%3d ", mat[i][j]);
printf("\n");
}
}
void sum
(int n,int m,int m1[][50],int m2[][50],int m3[][50]){
int i, j;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
m3[i][j]=m1[i][j]+m2[i][j];
}
void main(void){
int a[50][50], b[50][50], s[50][50];
int n_a, m_a, n_b, m_b;
clrscr();
read(&n_a, &m_a, a, "a");
read(&n_b, &m_b, b, "b");
clrscr();
write(n_a, m_a, a, "a");
write(n_b, m_b, b, "b");
if((n_a!=n_b)||(m_a!=m_b))
printf("Incorrect number of rows or columns!");
else{
sum(n_a, m_a, a, b, s);
write(n_a, m_a, s, "sum");
}
getch();
}
10.3.3 The implementation of some mathematical expressions. The user can
choose, through a repetitive menu, which expression to evaluate. Each expression is implemented within a separated function. Functions receive parameters
183
<stdio.h>
<conio.h>
<stdlib.h>
<math.h>
184
10 User-defined functions
float square(float sd){
if(sd>0)
return sd*sd;
else
return 0;
}
float circle(float r){
if(r>0)
return M_PI*r*r;
else
return 0;
}
int triangle(float sd, float *s, float *h){
if(sd>0) {
*s=sd*sd*sqrt(3)/4;
*h=sd*sqrt(3)/2;
return 1;
}
else
return 0;
}
int menu(void){
int o;
printf("1-Square-surface\n");
printf("2-Circle-surface\n");
printf("3-Equilateral triangle-surface, height\n");
printf("0-Exit\n");
printf("Your option: ");
scanf("%d", &o);
return o;
}
void main(void){
int option;
float side, radius;
float s, h;
while(1){
185
10 User-defined functions
The first version uses three variables: f1 with the initial value 0, f2 with the
initial value 1 and f3 that is calculated as f1+f2. At the end of each iteration
f1 takes the value of f2 and f2 the value of f3. The function fibo_var(),
which implements this version, receives as argument the variable n and doesnt
return anything.
The second version is probably the simple one; it stores the numbers within a
single-dimensional array. The first two elements of this vector receive the initial
values 0 and 1 respectively and the following elements are calculated as the
sum of the previous two elements. The function fibo_arr() receives as
argument the variable n and doesnt return anything.
The third version calculates each element in a recursive way. Thus, the function
fibo_rec() is called for each number that must be displayed. If n is greater
than 2, then the function calls itself again.
Program 10.3.4
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void fibo_var(int n){
int i, f1=0, f2=1, f3;
if(n==1)
printf("%d ", f1);
else if(n==2)
printf("%d %d ", f1, f2);
else{
printf("%d %d ", f1, f2);
for(i=3;i<=n;i++){
f3=f1+f2;
printf("%d ", f3);
f1=f2;
f2=f3;
}
}
}
void fibo_arr(int n){
int i, v[100];
187
10 User-defined functions
printf("%d ",fibo_rec(i));
break;
case 0: exit(0);
default: printf("Wrong option!");
}
getch();
}
}
10 User-defined functions
printf("a="); scanf("%d",&a);
printf("b="); scanf("%d",&b);
calculate(a,b);
printf("a=%d, b=%d",a, b);
}
7. #include <stdio.h>
void calculate(int x){
x++;
}
void main(void){
int x;
printf("x="); scanf("%d",&x);
calculate(x)=100;
}
8. #include <stdio.h>
int calculate(int x, int y){
return x+y;
}
void main(void){
int sum, a=2, b=3;
sum=calculate(a+b);
}
9. #include <stdio.h>
int calculate(void){
int counter=0;
//counts how many times the function is called
counter++;
return counter;
}
void main(void){
int i, c;
for(i=1;i<=10;i++) c=calculate();
printf("Number of calls: %d",c);
}
10. #include <stdio.h>
int calculate(int x){
if(x==1) return 1;
else return x*calculate();
191
10 User-defined functions
}
void main(void){
int y=1;
calculate(y);
printf("%d %d",x,y);
}
15. #include <stdio.h>
int x;
int calculate(int a){
x=++a;
return a;
}
void main(void){
int y=1,z;
z=calculate(y);
printf("%d",z);
}
16. #include <stdio.h>
void calculate(int x, int *y){
x++;
(*y)++;
}
void main(void){
int a=1, b=1;
calculate(a,&b);
printf("%d %d",a,b);
}
17. #include <stdio.h>
#include <conio.h>
void function(void){
char c;
printf("\nA letter or / to finish ");
c=getch();
if(c!='/'){
function();
putch(c);
}
}
void main(void){
193
10 User-defined functions
26. There is considered a vector of real numbers. Write a function that returns the maximum value.
27. Two natural numbers are read from the keyboard. Write a function that
finds and returns the greatest common divisor of these two numbers
(Euclids algorithm).
28. Write a function that verifies if a number n received as argument is
prime or not.
29. Perform the product of two matrices (with user defined functions).
30. Write a function that counts how many times a character c occurs within a string s.
31. Three real numbers (a, b and c) are read within main() function and
are passed to another function that verifies if they can be the sides of a
triangle (a+b>c, a+c>b and b+c>a); the function returns 1 if the
numbers can form a triangle and 0 otherwise.
32. Write a function that receives as argument a vector of real numbers,
representing the coefficients of a polynomial function (f(x)=anxn+an-1xn1
+ +a1x+a0) and a number x and returns the value of that function for
the number x.
33. Write a function that receives as argument a vector of real numbers,
representing the coefficients of a polynomial function (f(x)=anxn+an-1xn1
+ +a1x+a0) and creates, in another vector, the coefficients of the
functions derivative.
195
Chapter 11
User-defined types
Besides the standard data types (char, int, float, double), C programming language provides several mechanisms for creating customized data types
(user-defined types). Two of these mechanisms are the subject of this chapter:
the structure an entity that gathers several variables that are related from a
logical point of view, under a single name;
the enumeration a list of named integer constants.
typen varn;
} list_of_variables;
where:
11 User-defined types
structure_name is an optional label; the new data type can be used to
declare variables through this label;
var11, var12, var2, , varn are the members of the structure;
type1, type2, , typen represent the types of the structures members;
the variables that have the same type can be defined in a single instruction,
separated by comma (,);
the variables that dont have the same type are defined in different instructions, separated by semicolon (;);
the members are declared within a block enclosed by curly brackets ({});
list_of_variables is also optional and can contain one or more
variables;
the structures definition ends with semicolon (;), because it is an instruction, on the whole;
though both structure_name and list_of_variables are optional, they cannot be omitted in the same time; at least one of them should be
present, otherwise the structures definition has no sense (since neither variables are declared, nor the structure receives a name to be used later).
A first example of a structure, quite simply, is represented by the coordinates of
a point in a plane. The structure can be defined as:
struct point{
int x;
int y;
};
or as:
struct point{
int x, y;
};
The members of a structure can have different types, as shown in the following
example that defines several features of a student:
struct student{
197
11 User-defined types
stud1.mark=9.75;
strcpy(stud1.name,"Ritchie");
printf("%s %.2f",stud1.name,stud1.mark);
The name of a member variable can be identical with the name of a usual variable (non-member) without creating conflicts; the difference between the two
variables is made by the context where they are accessed [BK03] (the member
variable is always preceded by the name of the structure variable that contains
it). Based on the same reasoning, a member of a structure can have the same
name with a member of another structure (this is not recommended; it could be
used only if the elements have a very close meaning for instance, the radius
can be a variable that belongs to a structure that describes a circle and also to
one that describes an arc).
Program 11.1.1 is a complete example where the structure student is used.
The structure is global (it is defined outside any function) in order to extend its
visibility on the entire program (because this program contains a single function
main() the structure could also be defined within this function). A variable s of type student is defined and some of its features are read (id, name,
exam mark, laboratory mark). The final mark is calculated and displayed. The
program is very simple, being only an exercise of defining and using a structure.
Program 11.1.1
#include <stdio.h>
#include <conio.h>
struct student{
int id;
char name[20];
float exam, lab, final;
};
void main(void){
struct student s;
clrscr();
printf("Id: ");
scanf("%d",&s.id);
printf("The name: ");
199
11 User-defined types
cle that contains a member of type point, representing the coordinates of the
circles center, and a member of type float, representing the radius of the
circle:
struct circle{
struct point center;
float radius;
}c;
Three names are required to access the coordinates of the circles center: the
coordinates name (x), the centers name (center) and the circles name (c):
c.center.x=10;
Program 11.1.3
#include <stdio.h>
#include <conio.h>
struct point{
int x;
int y;
};
struct circle{
struct point center;
float radius;
};
void main(void){
struct circle c;
clrscr();
c.center.x=10;
c.center.y=20;
c.radius=5.37;
printf("center: (%d,%d)",c.center.x,c.center.y);
printf("\nradius: %.2f",c.radius);
getch();
}
A structure can also contain an array (with one or more dimensions):
struct vector{
201
11 User-defined types
int i;
v_st.max=v_st.v[0];
for(i=1;i<n;i++)
if(v_st.v[i]>v_st.max)
v_st.max=v_st.v[i];
}
void main(void){
clrscr();
read();
write();
maximum();
printf("\nMax: %d", v_st.max);
getch();
}
11 User-defined types
struct point A={3,4}, B={10,4};
clrscr();
printf("AB=%.2f", distance(A,B));
getch();
}
Program 11.1.7 passes by address a structure variable. A point A is declared and
initialized within main(). This point must be moved to other coordinates. In
order to have a real movement, the point must be passed by address to the function that performs this movement. The new coordinates are passed by value. On
return from the function the new location of the point is displayed to verify that
the movement was made. It is found that the values of the structures variables
were changed.
Program 11.1.7
#include <stdio.h>
#include <conio.h>
struct point{
int x;
int y;
};
void move(struct point *a, int new_x, int new_y){
(*a).x=new_x;
(*a).y=new_y;
}
void main(void){
struct point A={3,4};
clrscr();
move(&A,10,14);
printf("A(%d,%d)", A.x,A.y);
getch();
}
205
<stdio.h>
<conio.h>
<string.h>
<ctype.h>
struct count_vowels{
char vowel;
int counter;
};
struct count_vowels v[5]={
{'e',0},
{'a',0},
206
11 User-defined types
{'i',0},
{'o',0},
{'u',0}};
void count(char *text){
int i, j;
for(i=0;i<5;i++)
for(j=0;j<strlen(text);j++)
if(tolower(text[j])==v[i].vowel)
v[i].counter++;
}
void display(void){
int i;
for(i=0;i<5;i++)
printf("\n%c: %d",v[i].vowel,v[i].counter);
}
void main(void){
char text[50];
clrscr();
printf("Enter the text: ");
gets(text);
count(text);
display();
getch();
}
208
11 User-defined types
constn_name=valn;
} list_of_variables;
where:
enum is the key word used to define the enumeration;
enumeration_name is an optional label associated to the enumeration;
const1_name, const2_name, , constn_name are the names of the
constants that form the enumeration;
val1, val2, , valn are the values associated to the constants; these
values are optional; if they are present, they should be integers; if they are
omitted, then it is considered that the value associated to a constant is the
value associated to the previous constant plus 1 and the value 0 is associated by default to the first constant (if nothing else is specified);
list_of_variables is an optional way of declaring variables using the
enumeration that has just been defined.
As example, an enumeration that contains the days of a week is considered:
enum day {Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday};
and two variables of this type:
enum day today, tomorrow;
The variable of enumeration type can be used in instructions as:
today=Sunday;
if(today==Sunday) tomorrow=Monday;
209
fourth=4,
fifth,
Program 11.2.1 defines, within an enumeration, the three colors of the traffic
light. The values 0, 1 and 2 are, by default, associated to these colors. An
integer number (0, 1 or 2) is randomly generated in main() and then it is
passed to the function traffic_light().When submitting, the number is
identified with one of the three constants of the enumeration. The function only
generates a command (simulated by a text message) according to the color of
the traffic light received as argument. The command is returned and displayed
by main() function.
Program 11.2.1
#include
#include
#include
#include
#include
<stdio.h>
<conio.h>
<stdlib.h>
<time.h>
<string.h>
enum color{RED,YELLOW,GREEN};
char *traffic_light(enum color tl_color){
210
11 User-defined types
char *command;
switch(tl_color){
case RED:
strcpy(command,"Stop!");
break;
case YELLOW:
strcpy(command,"Stop if possible!");
break;
case GREEN:
strcpy(command,"Pass!");
break;
}
return command;
}
void main(void){
clrscr();
randomize();
printf("%s",traffic_light(random(3)));
getch();
}
11 User-defined types
9. #include <stdio.h>
#include <conio.h>
#include <string.h>
struct polygon{
char name[20];
int sides;
};
void modify(struct polygon pol){
strcpy(pol.name,"heptagon");
pol.sides=7;
}
void main(void){
struct polygon p={"square",4};
clrscr();
modify(p);
printf("The %s has %d sides", p.name, p.sides);
getch();
}
10. #include <stdio.h>
#include <conio.h>
#include <string.h>
struct polygon{
char name[20];
int sides;
};
void modify(struct polygon *pol){
strcpy((*pol).name,"heptagon");
(*pol).sides=7;
}
void main(void){
struct polygon p={"square",4};
clrscr();
modify(&p);
printf("The %s has %d sides", p.name, p.sides);
getch();
}
11. #include <stdio.h>
#include <conio.h>
enum boolean{false,true};
213
214
11 User-defined types
a) a list of integer constants; b) a list of variables of the same type;
c) a waiting list; d) a list of variables that can have different types;
e) all answers are wrong.
19. What will be printed on the screen once the following program is executed?
#include <stdio.h>
void main(void){
enum season{spring=1,summer,autumn,winter};
enum season now=autumn;
printf("%d",now);
}
a) autumn; b) 3; c) 2; d) 4; e) the program contains an error.
D. Write programs to solve the following problems.
20. A bouquet of flowers must be created. It may contain several types of
flowers and several flowers of each type (for example: 5 roses, 3 fern
leaves, and a bamboo). Simulate the content of a bouquet. Suggestion:
the bouquet can be an array of structure variables, the structure containing two fields: the name of a flower and the number of flowers with that
name used for the bouquet.
21. Calculate, using Herons formula, the surface of a triangle that is described by three points whose coordinates are read from the keyboard.
Suggestion: there will be used a structure of type point (with the two
coordinates); then structures of type segment (two points) or triangle
(three points) can be used. The lengths of the three segments that form
the triangle are calculated. Then the surface can be found with Herons
formula A
s s a s b s c , where a, b and c are the lengths
of the sides and s is the semi-perimeter.
22. Define a structure that describes a date through three fields (year,
month, and day). Write a function that compares two dates received as
argument. The function will have three versions:
a. it returns 0 if the dates are equals and 1 otherwise;
b. it returns 0 if the dates are equals, -1 if the first date is less than
the second and 1 if the first date is greater than the second;
215
216
Chapter 12
Files
The programs created in the previous chapters are operating on data stored in
RAM (Random Access Memory). This data is lost at the end of the programs.
The files are a method of storing data on disk. Thus, data is maintained and it is
available even after the execution of the current program. Therefore, a file is a
collection of data, it has a name and a location. The management of files is
performed by the operating system.
The connection between a C program and a file is made through a stream. This
stream is created once the file is opened and it is destroyed when the file is
closed. Some other operations can be performed between these two actions:
reading data from a file (this is an input action that brings data from disk to
RAM), processing this data and writing it into the file (an output action that
transfers the data from RAM back to disk).
Although there are many types of files (documents, images, databases, programs), all of them are represented by two basic types associated with two
streams [HS98], [CH96]:
text sequence of characters organized by lines;
binary sequence of 1s and 0s.
Meaning
Opens a file only for reading. The file must exist; otherwise, the
function returns NULL. After the opening action, the position
indicator (the file pointer) is placed at the beginning of the file.
218
12 Files
r+
Opens a file for reading and writing. If the file doesnt exist, the
function returns NULL; if it exists, a writing without repositioning the file pointer will alter the prior content of the file, because this opening places the position indicator at the beginning
of the file.
w+
Opens a file for reading and writing. If the file doesnt exist, it
is created; if it exists, its content is overwritten.
a+
Opens a file for reading and writing. If the file doesnt exist, it
is created; if it exists, the appending is made at the end of the
prior content (because the opening places the position indicator
at the end of the file).
219
12 Files
if the program crashes, then the automatic closing of the files is not executed; in this case the files that were not explicitly closed could remain
opened, being temporary inaccessible to other programs.
The following instruction closes in a correct manner the file that was previously
opened by fopen():
fclose(f);
221
String input/output
Functions fgets() and fputs() are used to read and to write, respectively,
a string from/into a file. Their prototypes are:
char *fgets(char *s, int n, FILE *f);
int fputs(const char *s, FILE *f);
Function fgets() reads characters from the file indicated by pointer f and
stores them into string s. The reading stops when n-1 characters were read or
when the end of the line is reached. If the reading stops because the end of the
line was reached, meaning that the new line character was read, then this character will be part of the string too. The terminator \0 is added at the end of
222
12 Files
the string s. The function returns the string s or NULL if the position indicator
is at the end of the file or if an error occurs.
Function fputs() writes string s into the file indicated by pointer f. The last
written character is returned or EOF if an error occurs.
Program 12.1.2 considers an input file (courses.txt) that contains on each
row the name of a discipline from the curricula, written on maximum 40 characters. Each discipline is read into string s and the user is asked to enter the
name of the teacher, which is then concatenated to the name of the discipline.
The resulted string is written into the output file (tutors.txt). The program
finishes when the end of the input file is reached and the function fgets()
returns NULL.
Program 12.1.2
#include <stdio.h>
#include <conio.h>
#include <string.h>
void main(void){
FILE *fin, *fout;
char s[80],teacher[30];
clrscr();
if((fin=fopen("courses.txt","r"))==NULL){
printf("Error: input file.");
getch();
return;
}
if((fout=fopen("tutors.txt","w"))==NULL){
printf("Error: output file.");
getch();
return;
}
while((fgets(s,40,fin))!=NULL){//file reading
printf("Teacher for: %s", s);
gets(teacher); //keyboard reading
strcat(s,teacher);
strcat(s,"\n");
fputs(s, fout); //file writing
}
223
Formatted input/output
If a formatted reading or writing is needed, then functions fscanf() and
fprintf() will be used. These are similar to functions scanf() and
printf() that are used for the reading/writing of the standard devices (keyboard and screen); for this reason they will not be detailed once again here. The
single difference is an extra parameter that specifies the file pointer. The prototypes of the functions that perform formatted input/output actions on a file are:
int fscanf(FILE *f, const char* format [, addr,...]);
int fprintf(FILE *f, const char* format [, arg,...]);
Function fscanf() returns EOF if the end of the file is reached and function
fprintf() returns EOF if a writing error occurs.
A first example of using these two functions (program 12.1.3) considers a file
that contains several numbers separated by space (numbers.txt). The numbers are read, their average is calculated and the result is displayed on the
screen and it is also written into another file (result.txt). If the input file is
empty, a message is displayed accordingly.
Program 12.1.3
#include <stdio.h>
#include <conio.h>
void main(void){
FILE *f,*g;
int n, sum=0,counter=0;
float average;
clrscr();
//the input file is opened
if((f=fopen("numbers.txt","r"))==NULL){
printf("Error input file");
getch();
return;
}
//the numbers are read from the file
224
12 Files
while(fscanf(f,"%d",&n)!=EOF){
printf("%d ",n);//they are displayed
sum=sum+n;//their sum is calculated
counter++;//they are counted
}
if(counter==0) printf("The file is empty");
else{
average=(float)sum/counter;
printf("\nThe average is: %.2f", average);
//the output file is created/opened
if((g=fopen("result.txt","w"))==NULL){
printf("Error output file");
getch();
return;
}
//the average is written into the result file
fprintf(g,"Average: %.2f",average);
}
getch();
fclose(f); fclose(g);
}
Program 12.1.4 is an example of both using formatted input/output functions
and opening a file to append information at the end of its content. The first
name and the last name of a student are read from the keyboard and then they
are appended to the content of a text file (students.txt).
Program 12.1.4
#include <stdio.h>
#include <conio.h>
void main(void){
FILE *f;
char first_name[20], last_name[20];
clrscr();
//opens the file for appending
if((f=fopen("students.txt","a"))==NULL){
printf("Error output file");
getch();
return;
225
RITCHIE 10.00
Brian
KERNIGHAN
9.90
Clint
HICKS
9.75
Herbert
SCHILDT
9.85
Program 12.1.5
#include <stdio.h>
#include <conio.h>
struct student{
char fname[21];
char lname[21];
float mark;
};
226
12 Files
void main(void){
FILE *in, *out;
struct student s;
int flag=0;
clrscr();
if((in=fopen("students.txt","r"))==NULL){
printf("Error input file");
getch();
return;
}
if((out=fopen("marks.txt","w"))==NULL){
printf("Error output file");
getch();
return;
}
//the names are read from file in
//the marks are read from the keyboard
//everything is written into file out
while(fscanf(in,"%s%s",s.fname,s.lname)!=EOF){
printf("\n%s %s",s.fname,s.lname);
printf("\nThe mark: "); scanf("%f",&s.mark);
fprintf(out,"%20s %20s %5.2f\n", s.fname,
s.lname, s.mark);
//the flag shows that at least one row was read
flag=1;
}
if(flag==0) printf("The file is empty");
getch();
fclose(in); fclose(out);
}
227
12 Files
the value that must be changed is read, therefore the file pointer should be
moved back in order to overwrite that information.
File students.txt is considered. The features of a student (id,
first_name, last_name, mark) are written in a formatted manner: the id
on 5 characters, empty space, the first name on 20 characters, empty space, the
last name on 20 characters, empty space and the mark on 5 characters (two of
them allocated to the decimal part). Program 12.1.6 changes the mark of a
student. Field id is used to uniquely identify a student. The input file looks like
this:
LM214
Dennis
RITCHIE 10.00
LM209
Brian
KERNIGHAN
9.90
LM205
Clint
HICKS
9.75
LM237
Herbert
SCHILDT
9.85
The id of the searched student is read within main() and then function modify() is called. The file is opened with the mode r+, which allows both reading and writing and doesnt remove the content of the file when this is opened.
Data of each student is read (within a while instruction) and is stored into a
variable of type structure. The id of the student from the file (s.id) is compared to the id of the searched student (specified through the argument
searched received by modify() function). If these two strings are identical, then the mark of this student must be changed. The new mark is read from
the keyboard and the file pointer is repositioned. It must be moved back with 5
characters towards its current position; this is performed through the instruction
fseek(f,-5,SEEK_CUR);. Then the new mark is written (also in a formatter manner) over the old one. If the file is empty or the student is not found,
according messages are displayed.
Program 12.1.6
#include <stdio.h>
#include <conio.h>
#include <string.h>
struct student{
char id[6];
char first_name[21];
char last_name[21];
float mark;
229
12 Files
void main(void){
char id[6];
clrscr();
printf("The id of the searched student: ");
scanf("%s", id);
modify(id);
}
12 Files
//the features of each student are read
while(fscanf(f,"%s%s%s%f", s.id, s.first_name,
s.last_name, &s.mark)!=EOF){
if(strcmp(s.id,searched)==0){
printf("\n%s %s %s %.2f",s.id, s.first_name,
s.last_name, s.mark);
found=1;
}
else
/*if this is not the searched student, its
features are written into the temporary file*/
fprintf(g,"%5s %20s %20s %5.2f\n", s.id,
s.first_name, s.last_name, s.mark);
flag=1;
}
if(flag==0) printf("The file is empty");
else
if(found==0) printf("The student was not found");
getch();
fclose(f); fclose(g);
//the initial file is removed
remove("students.txt");
/*the temporary file is renamed with the name of
the initial file*/
rename("temp.txt", "students.txt");
}
void main(void){
char id[6];
clrscr();
printf("The id of the searched student: ");
scanf("%s", id);
delete(id);
}
234
12 Files
In order to see the entire information
from the file, it is opened in mode r.
The file is traversed line by line, until
its end (EOF). Variable flag is used
to identify the case when the file is
empty. It has the initial value 0; if at
Figure 12.2.3 List
least one line is read from the file, the
flag receives the value 1. At the end
of the function this variable is checked and if it still has the value 0, then this
means that the file is empty and the user is notified through a message about
this situation.
The third option displays the students
that have the average mark greater
than or equal to a value specified by
the user (sch_mark). The file is
opened (r), it is traversed line by line
and the average mark of each student
Figure 12.2.4 Students with scholarship
(s.mark) is compared to the value
that is required to obtain scholarship. Variable flag is used here, too, in order
to point out that the file is empty. Another variable, found, is used to determine if there is at least one student with scholarship. If at the end of the function variable found still has its initial value 0, this means that no students with
the required mark were found.
If the user chooses the forth option,
he/she is asked to specify a group; all
the students that belong to that group
are displayed. The file is opened in
mode r and it is traversed line by line.
Figure 12.2.5 Students of a group
The students that have their group
(s.group) identical to the one specified by the user (group) are displayed. In order to identify the cases when the
file is empty or a certain group doesnt exist, variables flag and found are
used here, too.
235
236
12 Files
Function main() only displays the menu (in a repetitive manner) and, according to the users option, executes one of the implemented functions. The entire
program is hereby presented.
Program 12.2.1
#include
#include
#include
#include
#include
<stdio.h>
<conio.h>
<stdlib.h>
<string.h>
<ctype.h>
struct student{
char id[6];
char fname[21];
char lname[21];
int group;
float mark;
};
int menu(void){
int option;
printf("1-Add\n");
printf("2-List\n");
printf("3-Scholarship\n");
printf("4-Group\n");
printf("5-Search\n");
printf("6-Modify\n");
printf("7-Delete\n");
printf("0-Exit\n");
printf("Your option: ");
scanf("%d",&option);
return option;
}
void add(void){
FILE *f;
struct student s;
if((f=fopen("students.txt","a"))==NULL){
printf("Error - file cannot be opened");
getch();
237
12 Files
return;
}
printf("Mark for scholarship: ");
scanf("%f", &sch_mark);
while(fscanf(f,"%s%s%s%d%f", s.id, s.fname,
s.lname, &s.group, &s.mark)!=EOF){
if(s.mark>=sch_mark){
printf("%s %s %s %d %.2f\n", s.id, s.fname,
s.lname, s.group, s.mark);
found=1;
}
flag=1;
}
if(flag==0) printf("Empty file");
else if(found==0)
printf("No students with scholarship");
fclose(f);
getch();
}
void gr(void){
FILE *f;
struct student s;
int flag=0, found=0;
int group;
if((f=fopen("students.txt","r"))==NULL){
printf("Error - file cannot be opened");
getch();
return;
}
printf("Group: ");
scanf("%d", &group);
while(fscanf(f,"%s%s%s%d%f", s.id, s.fname,
s.lname, &s.group, &s.mark)!=EOF){
if(s.group==group){
printf("%s %s %s %d %.2f\n", s.id, s.fname,
s.lname, s.group, s.mark);
found=1;
}
flag=1;
239
12 Files
char searched[6];
char answer;
if((f=fopen("students.txt","r+"))==NULL){
printf("Error - file cannot be opened");
getch();
return;
}
printf("Id of the searched student: ");
scanf("%s", searched);
while(fscanf(f,"%s%s%s%d%f", s.id, s.fname,
s.lname, &s.group, &s.mark)!=EOF){
if(strcmp(s.id, searched)==0){
printf("%s %s %s %d %.2f\n", s.id, s.fname,
s.lname, s.group, s.mark);
found=1;
printf("Do you modify the group (Y/N)?");
answer=getch();
if(toupper(answer)=='Y'){
printf("\nNew group: ");
scanf("%d",&s.group);
}
printf("Do you modify the average mark (Y/N)?");
answer=getch();
if(toupper(answer)=='Y'){
printf("\nNew average mark: ");
scanf("%f",&s.mark);
}
fseek(f,-7,SEEK_CUR);
fprintf(f,"%1d %5.2f",s.group,s.mark);
}
flag=1;
}
if(flag==0) printf("Empty file");
else if(found==0)
printf("The student doesn't exist");
fclose(f);
getch();
}
void del(void){
241
12 Files
while(1){
clrscr();
o=menu();
switch(o){
case 1: add(); break;
case 2: list(); break;
case 3: scholarship(); break;
case 4: gr(); break;
case 5: search(); break;
case 6: modify(); break;
case 7: del(); break;
case 0: exit(0);
default: printf("Wrong option!"); getch();
}
}
}
12 Files
fprintf(f,"Programming");
fscanf(f,"%s",word);
printf("%s",word);
fclose(f);
}
C. Choose the correct answer (one only).
10. How many arguments does function fopen() have?
a) 0; b) 1; c) 2; d) 3; e) the number of arguments is undefined.
11. Which should be the value of mode argument of function fopen() if a
text file must be opened for reading?
a) "r"; b) "w"; c) "a"; d) "r+"; e) "r-".
12. Function fopen() returns:
a) a structure; b) constant EOF if the end of the file is reached; c)
the name of the file; d) the content of the file; e) a pointer of type
FILE.
13. Which function should be used to print in a formatted manner an argument into a file?
a) fscanf(); b) fprintf(); c) printf(); d) fgets();
e) all answers are wrong.
14. Which of the following letters cannot be used within mode argument of
function fopen()?
a) a; b) b; c) c; d) r; e) w.
15. Once fscanf() function reaches the end of a file, it returns:
a) EOF; b) NULL; c) SOS; d) nothing; e) all answers are
wrong.
16. Argument whence of function fseek() can have the value:
a) SEEK_SET; b) SEEK_CUR; c) SEEK_END; d) the answers
a, b and c are correct; e) all answers are wrong.
17. The argument of function fclose() is:
a) the name of the file (including the path, if necessary); b) the file
pointer returned by function fopen(); c) the content of the file;
245
12 Files
e. search a product by its name all products that have the specified name are displayed (for instance, it is possible to have two
products with the name bread, but with different features: one
could be rice bread, 500g and the other corn bread, 300g);
f. display the cheapest product the user enters a name; the minimum is only searched for that category (for instance, if the user
enters bread, the cheapest bread is displayed);
g. display the products that need supply products with the quantity zero;
h. modify the price and/or the quantity of a product the product is
identified by id;
i. delete a product identified by id;
j. exit.
247
Appendix 1
The set of characters (together with their ASCII codes)
This appendix contains the usual characters, together with their ASCII codes.
There are totally 256 characters. Besides the characters listed here, there is a set
of 32 characters (from 0 to 31), associated to the control codes (for instance, 9
stands for horizontal tab and 10 for new line) and also a second part of the
domain (codes from 128 to 255), which differs from one computer to another
(, , ).
blank
&
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<
>
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
249
Appendix 2
The keywords of the C programming language
The following table contains the keywords of the standard C language. These
keywords cannot be used as names for variables, constants, functions or userdefined types because they are already in use.
Keyword
Description
auto
break
case
char
const
continue
default
do
repetitive instruction
double
else
enum
extern
float
for
repetitive instruction
goto
if
alternative instruction
int
long
register
return
short
signed
sizeof
static
struct
switch
alternative instruction
typedef
251
union
unsigned
void
volatile
while
repetitive instruction
252
Appendix 3
Answers to questions and exercises
Chapter 2 Logical diagrams
A. 1. The x value was displayed using a decisional element instead of an output
element. 2. The condition x>0 is verified by a processing element; a decisional
element should be used. 3. A decisional element has two branches, not three.
B. 4. The diagram calculates and displays the distance between two points, the
coordinates of which are read. 5. The coefficients of a third degree polynomial
function are read, the function is displayed, the coefficients of its derivative are
calculated and the derivative is displayed. 6. The logical diagram calculates and
displays the last digit of an integer number n (the last digit of an integer is the
reminder of the division of that number to 10). 7. The diagram calculates and
displays n! (factorial); at the beginning, n is validated as a positive number.
C. 8. e). 9. c) it is possible to create a repetitive structure using a decisional
element within a loop, but a repetitive element doesnt exist. 10. b). 11. d). 12.
a). 13. c).
Chapter 3 Data and data types
A. 1. Because alpha is a constant, it cannot change its value. The instruction
alpha=beta+10; could only be executed if alpha would be a variable, not
a constant. 2. In C programming language, double is a keyword and cannot be
used as a variables name. 3. The increment operator (++) can only be applied
to integers; therefore, its impossible to execute x++; because x is a float
variable. 4. Variable x wasnt declared. 5. Variable y is declared as unsigned
int, therefore it cannot have a negative value. 6. Variable x must be declared
before it is used, not after. 7. The multiplication operator (*) is missing; the
correct expression is: e=x+2*y-z;. 8. The modulo operator can only be
applied to integer numbers, therefore the expression y=x%2; cannot be executed because x is float. 9. Digits are not allowed at the beginning of the
variables names; therefore, variables 1_mark and 2_mark dont have correct names.
258
262
References
[BH92]
[BK03]
[CH96]
[GP00]
[HS98]
[NR01]
[PT12]
[SL12]