Bit 2201 Programming Methodology Programming in C
Bit 2201 Programming Methodology Programming in C
DEPARTMENT OF INFORMATION
TECHNOLOGY
PROGRAMMING IN C
Contents
Introduction....................................................................................................................................................1
1.3 Translators.............................................................................................................................................4
2.1 Variables.............................................................................................................................................22
2.6.1 auto..............................................................................................................................................32
2.6.2 extern...........................................................................................................................................32
2.6.3 register.........................................................................................................................................34
2.6.4 static.............................................................................................................................................34
2.7 Constants............................................................................................................................................35
4.1 Introduction........................................................................................................................................53
4.4 Looping................................................................................................................................................64
5.1 Introduction........................................................................................................................................46
5.2.1 Recursion......................................................................................................................................51
6.1 Introduction........................................................................................................................................57
6.3 Strings.................................................................................................................................................73
Revision Exercises.....................................................................................................................................91
8.1 Introduction........................................................................................................................................77
8.8 Unions.................................................................................................................................................91
Revision Exercises.....................................................................................................................................95
9.1 Introduction........................................................................................................................................98
Revision Exercises...................................................................................................................................136
Bibliography................................................................................................................................................149
Index...........................................................................................................................................................150
Introduction
The basic aim of this study guide is to teach C programming in as clear and simple
manner as possible.
You will explore the world of C from the basic concepts to other facets of the language.
Explanations, examples, exercises and tip notes are used. The guide uses an easy – to
learn approach. You will find the guide comprehensive, concise and practical –
oriented. To help grasp the concepts of the language, a number of real - life situation
examples have been used.
You will find revision questions at the end of every chapter so that you can test
your proficiency in what is covered.
Finally, the model examination papers at the end of the guide shall test
your preparedness for the final examination.
Objectives
Understand what is structured programming
Identify the steps of developing a program
Explain the characteristics of C.
Understand the components of a C program
Identify various types of program errors
Create and compile a program
Add comments to a program.
Programming
Programming is a creation of a set of commands or instructions which directs a computer in
carrying out a task.
Programming Language
A programming language is a set of words, symbols and codes that enables humans to
communicate with computers.
The fifth generation programming language or visual programming language, is also known as
natural language. Provides a visual or graphical interface, called a visual programming
environment, for creating source codes. Fifth generation programming allows people to interact
with computers without needing any specialized knowledge. People can talk to computers and the
voice recognition systems can convert spoken sounds into written words. Prolog and Mercury are
the best known fifth-generation languages.
1.3 Translators
All software packages or programs are written in high-level languages, for example, C++, Visual
Basic and Java. The translation of high level languages to machine language is performed by a
translator.
Program
Have you ever wondered how your computer runs your favourite software?
Your favourite software is a program that consists of several instructions that perform its operation.
A programmer will write a source code which consists of the instructions needed to run a program.
Then the compiler or interpreter with assembler will translates the source code into machine
language which is made of a sequence of bits (eg. 01100011). The computer will load the machine
code and run the program.
Assembler
An assembler is a computer program for translating assembly language — essentially, a mnemonic
representation of machine language — into machine language. For example in intel 80836, the
assembly language for the ’no operation’ command is NOP and its machine code representation is
10010000.
Interpreter
The interpreter will read each code converts it to machine code and executes it line by line until the
end of the program. Examples of interpreter-based language are BASIC, Logo and Smalltalk.
Compiler
The source code (in text format) will be converted into machine code which is a file consisting of
binary machine code that can be executed on a computer. If the compiler encounters any errors, it
records them in the program-listing file. When a user wants to run the program, the object program
is loaded into the memory of the computer and the program instructions begin executing. A
compiled code generally runs faster than programs based on interpreted language. Several
programming languages like C++, Pascal and COBOL used compilers as their translators.
2. Design program
The programmer decides how the program will go about its implementation, what should the
user interface be like, how should the program be organized, how to represent the data and
what methods to use during processing. At this point, you should also be thinking generally
although some of your decisions may be based on some general characteristics of the C
language.
routines. The end result is an executable file that the computer can understand.
The compiler also checks errors in your program and reports the error to you for correction.
The object code can never be produced if the source code contains syntax
errors.
Linking is the process where the object code, the start up code, and the code for library routines
used in the program (all in machine language) are combined into a single file - the executable
file.
Efficiency
C is a concise language that allows you to say what you mean in a few words.
The final code tends to be more compact and runs quickly.
Portability
C programs written for one system can be run with little or no modification on other
systems.
Power and flexibility
C has been used to write operating systems such as Unix, Windows.
It has (and still is) been used to solve problems in areas such as physics and
engineering.
Programmer orientation
C is oriented towards the programmer’s needs.
It gives access to the hardware. It lets you manipulate individual bits of memory.
It also has a rich selection of operators that allow you to expand programming
capability.
1. Constant.
2. Variable.
3. Data Type.
4. Operators.
5. Control Structures.
Constants
Constant is a data container that stores information. The value will never change (remains
constant) at any time during the course of a program.
Declare is the official term used in programming to announce to the program the
condition of statement in programming.
Variables
Variable is a data container that stores information. The value inside may change at any time
during the course of a program.
Data Types
Data types refer to an extensive system for declaring variables of different types.
int
float
double
char
Operator
An operator is a symbol that tells the compiler to perform specific mathematical or logical
manipulations. C language is rich in built-in operators and provides the following types of
operators:
Arithmetic Operators
Relational Operators
Logical Operators
Bitwise Operators
Assignment Operators
Misc Operators
Control Structures
Control structures represent the forms by which statements in a program are executed. Three
structures control program execution:
Sequence
Selection or decision structure
Iteration or looping structure
Functions
Declaration statements
Comments
Expressions
Input and output statements
1. Keywords
These are reserved words that have special meaning in a language. The compiler recognizes a
keyword as part of the language’s built – in syntax and therefore it cannot be used for any other
purpose such as a variable or a function name. C keywords must be used in lowercase
otherwise they will not be recognized.
Examples of keywords
auto break case else int void default
do double if sizeof long
float for goto signed unsigned
register return short union continue struct
switch typedef const extern volatile while
char enum static
Sample Program
This program will print out the message: This is a C program.
#include<stdio.h>
main()
{
printf("This is a C program \n");
return 0;
}
Though the program is very simple, a few points are worthy of note.
10
Every C program contains a function called main. This is the start point of the program.
#include<stdio.h> allows the program to interact with the screen, keyboard and file system of
your computer. You will find it at the beginning of almost every C program.
main() declares the start of the function, while the two curly brackets show the start and finish
of the function. Curly brackets in C are used to group statements together as in a function, or in
the body of a loop. Such a grouping is known as a compound statement or a block.
printf("This is a C program \n"); prints the words on the screen. The text to be printed is
enclosed in double quotes. The \n at the end of the text tells the program to print a new line as
part of the output.
Most C programs are in lower case letters. You will usually find upper case letters used in
preprocessor definitions (which will be discussed later) or inside quotes as parts of character
strings.
C is case sensitive, that is, it recognizes a lower case letter and it's upper case
equivalent as being different.
#include<stdio.h>
main()
{
int num; /* define a variable called num */
num = 1; /* assignment */
printf(“ This is a simple program ”);
printf(“to display a message. \n”);
printf (“My favorite number is %d because ”, num);
printf(“ it is first.\n ”);
return 0;
11
2. Functions
All C programs consist of one or more functions, each of which contains one or more
statements. In C, a function is a named subroutine that can be called by other parts of the
program. Functions are the building blocks of C.
All C statements must end with a semicolon. C does not recognize the end of a line as a
terminator. This means that there are no constraints on the position of statements within a line.
Also you may place two or more statements on one line.
Although a C program may contain several functions, the only function that it must have is
main( ).
The main( ) function is the point at which execution of your program begins. That is, when your
program begins running, it starts executing the statements inside the main( ) function, beginning
with the first statement after the opening curly brace. Execution of your program terminates
when the closing brace is reached.
Another important component of all C programs is library functions. The ANSI C standard
specifies a minimal set of library functions to be supplied by all C compilers, which your
program may use. This collection of functions is called the C standard
library. The standard library contains functions to perform disk I/O (input / output), string
manipulations, mathematics, and much more. When your program is compiled, the code for
12
One of the most common library functions is called printf( ). This is C‟s general purpose
output function. Its simplest form is
printf(“string – to – output”);
The printf( ) outputs the characters that are contained between the beginning and ending
double quotes.
For example, printf(“ This is a C program “);
The double quotes are not displayed on the screen. In C, one or more characters enclosed
between double quotes is called a string. The quoted string between printf( )‟s parenthesis is
called an argument to printf( ). In general, information passed to a function is called an
argument. In C, calling a library function such as printf( ) is a statement; therefore it must end
with a semicolon.
To call a function, you specify its name followed by a parenthesized list of arguments that
you will be passing to it. If the function does not require any arguments, no arguments will
be specified, and the parenthesized list will be empty. If there is more than one argument, the
arguments must be separated by commas.
In the above program, line 7 causes the message enclosed in speech marks “ ” to be
printed on the screen. Line 8 does the same thing.
The \n tells the computer to insert a new line after printing the message. \n is an
example of an escape sequence.
Line 9 prints the value of the variable num (1) embedded in the phrase. The %d
instructs the computer where and in what form to print the value. %d is a type specifier
used to specify the output format for integer numbers. Line 10 has the same effect as line 8.
Line11 indicates the value to be returned by the function main( ) when it is executed. By
default any function used in a C program returns an integer value (when it is called to execute).
13
Therefore, line 3 could also be written int main( ). If the int keyword is omitted, still an
integer is returned.
Then, why return (0); ? Since all functions are subordinate to main( ), the function does not
return any value.
Note:
(i) Since the main function does not return any value, line 3 can alternatively be written
as : void main( ) – void means valueless. In this case, the statement return 0; is not
necessary.
(ii) While omitting the keyword int to imply the return type of the main( ) function does
not disqualify the fact that an integer is returned (since int is default), you should
explicitly write it in other functions, especially if another value
other than zero is to be returned by the function.
A preprocessor directive performs various manipulations on your source file before it is actually
compiled. Preprocessor directives are not actually part of the C language, but rather instructions
from you to the compiler
The preprocessor directive #include is an instruction to read in the contents of another file and
include it within your program. This is generally used to read in header files for library
functions.
Header files contain details of functions and types used within the library. They must be included
before the program can make use of the library functions.
Library header file names are enclosed in angle brackets, < >. These tell the preprocessor to
look for the header file in the standard location for library definitions.
4. Comments
14
Comments are non – executable program statements meant to enhance program readability
and allow easier program maintenance, i.e. they document the program. They can be used in
the same line as the material they explain (see lines 4, 6, 7 in sample program).
A long comment can be put on its own line or even spread on more than one line. Comments
are however optional in a program. The need to use too many comments can be avoided by
good programming practices such as use of sensible variable names, indenting program
statements, and good logic design. Everything between the opening /* and closing */ is
ignored by the compiler.
5. Declaration statements
In C, all variables must be declared before they are used. Variable declarations ensure that
appropriate memory space is reserved for the variables, depending on the data types of the
variables. Line 6 is a declaration for an integer variable called num.
An assignment statement uses the assignment operator “=” to give a variable on the operator‟s
left side the value to the operator‟s right or the result of the expression on the right. The
statement num =1; (Line 6) is an assignment statement.
7. Escape sequences
Escape sequences (also called back slash codes) are character combinations that begin with a
backslash symbol (\) used to format output and represent difficult-to-type characters.
One of the most important escape sequences is \n, which is often referred to as the new line
character. When the C compiler encounters \n, it translates it into a carriage return.
main()
15
main()
printf(“\a”);
return 0;
Remember that the escape sequences are character constants. Therefore to assign one to a
character variable, you must enclose the escape sequence within single quotes, as shown in
this fragment.
Char ch;
ch = „\t ‟ /*assign ch the tab character */
16
\a alert/bell
\b backspace
\n new line
\v vertical tab
\t horizontal tab
\\ back slash
\0 null
17
Note:
The compiler may suggest that other program line statements have errors when they may not.
This will be the case when a syntax error in one line affects directly the execution of other
statements, for example multiple use of an undeclared variable. Declaring the variable will
remove all the errors in the other statements.
Runtime errors occur when a program with no syntax errors asks the computer to do something
that the computer is unable to reliably do. Common examples are:
18
results will come out of them and the programmer will find it difficult to debug such errors.
Examples include a data overflow caused by an attempt to assign a value to a field or memory
space smaller than the value requires, division by zero, etc.
Ensure that your program logic design is clear and correct. Avoid starting to code before
the logic is clearly set out since good logic will reduce coding time as well as result in
programs that are easy to understand, error free and easily maintainable.
Declare all variables before using them in any statements.
Use sensible names for variables. Use of general names such as n instead of net_sal
for net salary makes variables vague and may make debugging difficult. This
however depends on the programmer‟s ingenuity.
Use a variable name in the case that it was declared in.
Never use keywords in uppercase.
Terminate C declarations, expressions and I/O statements with a semi colon.
Restrict your variables names to eight characters. The compiler may truncate part of a
variable name and possibly give it the meaning of another variable e.g. Shakespeare and
Shakespencil.
Always save your program every time you make changes.
Proof read your program to check for any errors or omissions
Dry run you design with some simple test data before running the code, then
compare the two.
main()
19
n = 5;
n2 = n *n
n3 = n2 * n2;
return 0;
4. Provide the meaning of the following keywords, giving examples of their use in C
programs.
(i) void
(ii) return
(iii) extern
(iv) struct
(v) static
5. C is both “portable and “efficient”. Explain.
6. C is a “case sensitive‟ language. Explain.
20
21
Objectives
2.1 Variables
A variable is a memory location whose value can change during program execution.
In C, a variable must be declared before it can be used. Variables can be declared at
the start of any block of code.
A declaration begins with the type, followed by the name of one or more variables.
For example,
int high, low, results[20];
22
23
It is conventional to avoid the use of capital letters in variable names. These are
used for names of constants. Some old implementations of C only use the first 8
characters
of a variable name. Most modern ones don't apply this limit though. The rules
governing variable names also apply to the names of functions.
C supports five basic data types. The table below shows the five types, along with the
C
keywords that represent them. Don‟t be confused by void. This is a special
purpose data type used to explicitly declare functions that return no value.
Type Meaning Keyword
Character Character data char
Integer Signed whole number int
Float floating-point numbers float
Double double precision floating- double
point numbers
Void Valueless void
Integer variables may hold signed whole numbers (numbers with no fractional part).
Typically, an integer variable may hold values in the range –32,768 to 32,767 and
are 2 bytes long.
You can use printf( ) to display values of characters, integers and floating - point
values. To do so, however, requires that you know more about the printf( ) function.
For example:
printf(“This prints the number %d ”, 99);
displays This prints the number 99 on the screen. As you can see, this call to the
printf( ) function contains two arguments. The first one is the quoted string and the
other is the constant 99. Notice that the arguments are separated from each other by a
comma.
In general, when there is more than one argument to a function, the arguments are
separated from each other by commas. The first argument is a quoted string that may
contain either normal characters or formal specifiers that begin with a percent (%)
sign.
Normal characters are simply displayed as is on the screen in the order in which they
are encountered in the string (reading left to right). A format specifier, on the other hand
informs printf( ) that a different type item is being displayed. In this case, the %d,
means that an integer, is to be output in decimal format. The value to be displayed is to
be found in the second argument. This value is then output at the position at which the
format specifier is found on the string.
If you want to specify a character value, the format specifier is %c. To specify a floating-
point value, use %f. The %f works for both float and double. Keep in mind that the
values matched with the format specifier need not be constants, they may be variables
too.
Code Format
%c Character
%s String of characters
Examples
1. The program shown below illustrates the above concepts. First, it declares a
variable called num. Second, it assigns this variable the value 100. Finally, it uses
printf( ) to display the value is 100 on the screen. Examine it closely.
#include<stdio.h>
main()
int num;
num = 100;
return 0;
2. This program creates variables of types char, float, and double assigns each
a value and outputs these values to the screen.
#include<stdio.h>
main()
char ch;
float f;
double
d; ch =
„X‟;
f = 100.123;
d = 123.009;
printf(“ ch is %c “,
ch); printf(“ f is %f
“, f); printf(“ d is %f
“, d); return 0;
}
Exercises
There are several ways to input values through the keyboard. One of the easiest is to
use another of C‟s standard library functions called scanf( ).
To use scanf( ) to read an integer value from the keyboard, call it using the general
form:
scanf(“%d”, &int-var-name);
Where int-var-name is the name of the integer variable you wish to receive the value.
The first argument to scanf( ) is a string that determines how the second argument will
be treated. In this case the %d specifies that the second argument will be receiving an
integer value entered in decimal format. The fragment below, for example, reads an
integer entered from the keyboard.
int num;
scanf(“%d”, &num);
The & preceding the variable name means “address of‟. The values you enter are put
into variables using the variable’s location in memory. It allows the function to place a
value into one of its arguments.
When you enter a number at the keyboard, you are simply typing a string of digits. The
scanf( ) function waits until you have pressed <ENTER> before it converts the string
into the internal format used by the computer.
The table below shows format specifiers or codes used in the scanf() function and their
meaning.
Code Meaning
%c Read a single character
%s Read a string
Examples
1. This program asks you to input an integer and a floating-point number and displays
the value.
#include<stdio.h>
main()
{
int num;
float f;
printf(“ \nEnter an integer: “);
scanf( “%d “, &num);
printf(“\n Enter a floating point number: “);
scanf( “%f “, &f);
printf( “%d ”, num);
printf( “\n %f ”, f);
return 0;
}
2. This program computes the area of a rectangle, given its dimensions. It first
prompts the user for the length and width of the rectangle and then displays the
area.
#include<stdio.h>
main()
{
int len, width;
printf(“\n Enter length: “);
scanf (“%d “, &len);
Exercises
Variables declared outside all functions are called global variables and they may be
accessed by any function in your program. Global variables exist the entire time
your program is executing.
Variables declared inside a function are called local variables. A local variable is
known to and may be accessed by only the function in which it is declared. You need
to be aware of two important points about local variables.
(i) The local variables in one function have no relationship to the local variables
in another function. That is, if a variable called count is declared in one
function,
another variable called count may also be declared in a second function – the two
2.6.1 auto
It is used to declare automatic variables. Automatic variables are simply local variables,
which are auto by default. You will never see auto used in any C program.
2.6.2 extern
As the size of a program grows, it takes longer to compile. C allows you to break down
your program into two or more files or functions. You can separately compile these files
and then link them together. In general, global data may only be declared once.
Because global data may need to be accessed by two or more functions that form the
program, there must be a way of informing the compiler about the global data used by
the program.
File 1
#include<stdio.h>
int count;
void f1 (void);
main()
{
int i;
f1 ( ); /* Set count‟s value */
for( i =0; i <count; i++)
printf(“%d”);
return 0;
}
File 2
#include<stdlib.h>
void f1(void)
{
count = rand ( ); /* Generates a random number */
}
If you try to compile the second file, an error will be reported because count is
not defined. However, you cannot change File 2 as follows:
#include<stdlib.h>
int count;
void f1(void)
{
count = rand (); /* Generates a random number */
}
Note: stdlib.h is a header file that contains certain standard library functions. rand()
function is one of them and is used to generate a random number between . Others
are abort() – to abort a program, abs() – to get the absolute value ,malloc() for
dynamic memory allocation ,free() to free memory allocated with malloc(), qsort()to
sort an array, realloc() to reallocate memory, et al.
If you declare count a second time, the linker will report a duplicate-symbol error, which
means that count is defined twice, and the linker doesn‟t know which to use.
The solution to this problem is C‟s extern specifier. By placing extern in front of
count‟s declaration in File 2, you are telling the compiler that count is an
integer declared elsewhere. In other words, using extern informs the compiler
about the existence and type of the variable it precedes but does not cause
storage for that variable to be allocated. The correct version for File 2 is:
#include<stdlib.h>
extern int count;
void f1(void)
{
count = rand ( ); /* Generates a random number */
}
2.6.3 register
When you specify a register variable, you are telling the compiler that you want
access to that variable as fast as possible. In other words, using register variables
minimizes access time.
No matter what storage method used, only a given number of variables can be
granted the fastest possible access time. For example, the CPU has a limited number
of registers. When fast-access locations are exhausted, the compiler is free to convert
register variables into regular variables. For this reason, you must choose carefully
which variables you modify with register.
One good choice is to make a frequently used variable such as the variable that
controls a loop, into a register variable. The more times a variable is accessed,
the greater the increase in performance when its access time is decreased.
2.6.4 static
The static modifier causes the contents of a local variable to be preserved between
function calls. Also, unlike normal local variables, which are initialized each time a
function is entered a static variable is initialized only once. For example, take a look at
the following program:
#include<stdio.h>
void f(void);
main()
{
int i;
for (i =0; i < 10; i ++)
f( );
return 0;
}
void f (void)
{
static int count = 0;
count ++;
printf(“Count is %d \n”, count);
}
which displays the following output.
count is 1
count is 2
count is 3
count is 4
count is 5
count is 6
count is 7
count is 8
count is 9
count is 10
Visibly from above, count retains its value between function calls.
2.7 Constants
A constant is a value that does not change during program execution. In other words,
constants are fixed values that may not be altered by the program.
Integer constants are specified as numbers without fractional components. For example
–10, 1000 are integer constants.
Floating - point constants require the use of the decimal point followed by the
number‟s fractional component. For example, 11.123 is a floating point constant. C
allows you to use scientific notation for floating point numbers. Constants using
scientific notation must follow this general form:
number E sign exponent
The number is optional. Although the general form is shown with spaces between the
component parts for clarity, there may be no spaces between parts in an actual number
. For example, the following defines the value 1234.56 using scientific notation
123.456E1
Character constants are usually just the character enclosed in single quotes; 'a', 'b', 'c'.
ch = „z‟;
Note:
There is nothing in C that prevents you from assigning a character variable a value
using a numeric constant. For example the ASCII Code for „A „ is 65. Therefore, these
two assignments are equivalent.
char ch;
ch = “A‟;
ch = 65;
Directly
Here the constant value is inserted in the expression, as it should typically be.
For example:
Area = 3.14 * Radius * Radius;
The value 3.14 is used directly to represent the value of PI which never requires
changes in the computation of the area of a circle
This process is generally referred to as macro substitution. The general form of the
#define statement is;
Notice that this line does not end in a semi colon. Each time the macro - name is
encountered in the program, the associated string is substituted for it. For example,
consider the following program.
#include<stdio.h>
#define PI
3.14 main()
{
scanf(“%f”, &radius);
return 0;
Note:
At the time of the substitution, the text such as 3.14 is simply a string of characters
composed of 3, ., 1 and 4. The preprocessor does not convert a number into any sort
of internal format. This is left to the compiler.
The macro name can be any valid C identifier. Although macro names can appear in
either uppercase or lowercase letters, most programmers have adopted the
convention of using uppercase for macro names to distinguish them from variable
names. This makes it easy for anyone reading your program to know when a macro
name is being used.
Macro substitutions are useful in that they make it easier to maintain programs. For
example, if you know that a value, such as array size, is going to be used in several
places in your program, it is better to create a macro for this value. Then, if you ever
need to change this value, you simply change the macro definition. All references will
be automatically changed when the program is recompiled.
In an assignment statement in which the type of the right side differs from that on the
left, the type of the right side is converted into that of the left. When the type of the left
side is larger than the right side, this process causes no problems. However, when
the type of the left side is smaller than the type of the right, data loss may occur.
When converting from a long double to a double or from a double to float, precision
is lost. When converting from floating point value to an integer value, the fractional part
is lost, and if the number is too large to fit in the target type, a garbage value will result.
#include<stdio.h>
main()
int i;
float f;
f = 1234.0098;
i = f;
return 0;
1. Discuss four fundamental data types supported by C, stating how each type is
stored in memory.
2. Distinguish between a variable and a constant.
3. Suggest, with examples two ways in which constant values can be used in C
expression statements.
4. Give the meaning of the following declarations;
(i) char name[20];
(ii) int num_emp;
(iii) double tax, basicpay;
(iv) char response;
An operand is a data item that is acted upon by an operator. Some operators act upon
two operands (binary operators) while others act upon only one operand (unary
operators).
Examples
(i) x + y ; x, y are operands, + is an addition operator.
(ii) 3 * 5; 3, 5 are constant operands, * is a multiplication operator.
(iii) x % 2.5; x, 5 are operands, % is a modulus (remainder) operator.
(iv) sizeof (int); sizeof is an operator (unary), int is an operand.
Note:
(i) There exists no exponential operators in C.
(ii) The operands acted upon by arithmetic operators must represent
numeric values, that is operands may be integers, floating point
quantities or characters (since character constants represent integer
values).
(iii) The % (remainder operator) requires that both operands be integers.
Thus;
5%3
int x = 8;
int y = 6 ; x % y are valid while;
8.5 % 2.0 and
float p = 6.3, int w = 7 ; 5 %p , p % w are invalid.
(iv) Division of one integer quantity by another is known as an
integer division. If the quotient (result of division) has a decimal
part, it is truncated.
(v) Dividing a floating point number with another floating point number, or a
floating point number with an integer results to a floating point quotient
.
Exercise
Note:
(i) c1 and c2 are character constants
(ii) ASCII codes for 9 is 57, P = 80,T = 84.
If one or both operands represent negative values, then the addition, subtraction,
multiplication, and division operators will result in values whose signs are determined
by their usual rules of algebra. Thus if a b, and c are 11, -3 and –11 respectively, then
a +b =8
a – b = 14
a * b = -33
a / b = -3
a % b = -2
c % b = -2
c/b=3
Note:
(i) If both operands are floating point types whose precision differ (e.g. a float and a
double) the lower precision operand will be converted to the precision of the
other operand, and the result will be expressed in this higher precision. (Thus if
an expression has a float and a double operand, the result will be a double).
(ii) If one operand is a floating-point type (e.g. float, double or long double) and the
other is a character or integer (including short or long integer), the character or
integer will be converted to the floating point type and the result will be expressed
as such.
(iii) If neither operand is a floating-point type but one is long integer, the other will be
converted to long integer and the result is expressed as such. (Thus between an
int and a long int, the long int will be taken).
(iv) If neither operand is a floating type or long int, then both operands will be
converted to int (if necessary) and the result will be int (compare short int and long
int)
(i) i+f
(ii) i+c
(iii) i + c-„w‟
(iv) ( i + c) - ( 2 * f / 5)
Note: Whichever type of result an expression evaluates to, a programmer can convert
the result to a different data type if desired. The general syntax of doing this is:
The order of executing the various operations makes a significant difference in the
result. C assigns each operator a precedence level. The rules are;
(i) Multiplication and division have a higher precedence than addition and subtraction,
so they are performed first.
(ii) If operators of equal precedence; (*, /), (+, -) share an operand, they are executed in
the order in which they occur in the statement. For most operators, the order
(associativity) is from left to right with the exception of the assignment ( = ) operator.
(Division follows)
Note that it is possible for the programmer to set his or her own order of evaluation by
putting, say, parenthesis. Whatever is enclosed in parenthesis is evaluated first.
include<stdio.h >
main()
int score,top;
score = 30;
return 0;
Try changing the order of evaluation by shifting the parenthesis and note the change in
the top score.
Exercise
2
The roots of a quadratic equation ax + bx + c = 0 can be evaluated as:
2
x1 = (-b + (b - 4ac))/2a
2
x2 = (-b + (b - 4ac))/2a
2
where a, b ,c are double type variables and b = b * b , 4ac = 4 * a * c, 2a = 2 * a.
Write a program that calculates the two roots x1 x2 with double precision, and displays
the roots on the screen.
#define SEC_PER_MIN 60
main()
{
return 0;
sizeof returns the size in bytes, of its operand. The operand can be a data type e.g.
sizeof (int), or a specific data object e.g. sizeof n.
If it is a name type such as int, float etc. The operand should be enclosed
in parenthesis.
main()
int n;
sizeof n, sizeof(int)) ;
return 0;
Assignment expressions that make use of the assignment operator (=) take the form;
identifier = expression;
where identifier generally represents a variable, constant or a larger expression.
Examples of assignment;
a = 3 ;
x = y ;
pi = 3.14;
sum = a + b ;
area_circle = pi * radius * radius;
Note
(i) You cannot assign a variable to a constant such as 3 = a ;
(ii) The assignment operator = and equality operator (= =) are distinctively
different. The = operator assigns a value to an identifier. The equality
operator (= =) tests whether two expressions have the same value.
(iii) Multiple assignments are possible e.g. a =b = 5 ; assigns the integer value
5 to both a and b.
(iv) Assignment can be combined with +, -, /, *, and %
Assuming i is an integer, the expression (i < 0) is evaluated and if it is true, then the
result of the entire conditional expression is zero (0), otherwise, the result will be
100.
These are operators that act on a singe operand to produce a value. The operators
may precede the operand or are after an operand.
Examples
A logical expression represents conditions that are either true (represented by integer 1)
or false (represented by 0).
Example
Consider a, b, c to be integers with values 1, 2,3 respectively. Note their results
with relational operators below.
Expression Result
a<b 1 (true)
The two operators act upon operands that are themselves logical expressions
to produce more complex conditions that are either true or false.
Example
Suppose i is an integer whose value is 7, f is a floating point variable whose value is
5.5
and C is a character that represents the character „w‟,
then;
Further suppose that c1, c2, c3 are character-type variables assigned the values E,
5 and ? respectively.
4.1 Introduction
Basically, program statements are executed in the sequence in which they appear in
the program.
In reality, a logical test using logical and relational operators may require to be used
in order to determine which actions to take (subsequent statements to be executed)
depending on the outcome of the test. This is selection. For example:
The if statement provides a junction at which the program has to select which path
to follow. The general form is :
if(expression)
statement;
Examples
(i) if (x<y)
printf(“x is less that y”);
if(expression)
{
block of statements;
Example
if(salary>5000)
The if else statement lets the programmer choose between two statements as opposed
to the simple if statement which gives you the choice of executing a statement
(possibly compound) or skipping it.
Example:
if(x >=0)
x++;
else
statement;
else if (expression)
statement;
else if (expression)
statement;
else
statement;
Example
if(sale_amount>=10000)
else
#include<stdio.h >
#include<string.h >
main()
int marks;
strcpy(grade, “Credit”);
strcpy(grade, “Pass”);
strcpy(grade, “Fail”);
else
return 0;
The switch - break statements can be used in place of the if - else statements when
there are several choices to be made.
main()
int choice;
switch (choice)
{ /* Begin of switch* /
case 1: /* label 1* /
printf(“\n You typed 1”); break;
case 2: /* label 2* /
break;
case 3: /* label 3* /
break;
case 4: /* label 4* /
break;
default:
} /* End of switch*/
else
return (0);
} /* End of main*/
Explanation
The expression in the parenthesis following the switch is evaluated. In the example
above, it has whatever value we entered as our choice.
Then the program scans a list of labels (case 1, case 2,…. case 4) until it finds one that
matches the one that is in parenthesis following the switch statement.
If there is no match, the program moves to the line labeled default, otherwise the
program proceeds to the statements following the switch.
The break statement causes the program to break out of the switch and skip to the next
statement after the switch. Without the break statement, every statement from the
matched label to the end of the switch will be processed.
For example if we remove all the break statements from the program and then run the
program using the number 3 we will have the following exchange.
statement; optional
case constant 2:
statement; optional
…………
default: (optional)
statement; (optional)
}
Note:
(i) The switch labels (case labels) must be type int (including char) constants or
constant expression.
(ii) You cannot use a variable for an expression for a label expression.
(iii) The expressions in the parenthesis should be one with an integer value. (again
including type char)
#include<stdio.h>
main()
char ch;
scanf(“%c”, &ch);
switch (ch)
{ /*begin of switch*/
case `a`:
break;
case „b‟:
break;
case „c‟:
break;
case „d‟:
break;
default:
else
return 0;
} /* End of main */
Like the break statement the continue statement is a jump that interrupts the flow of a
program. It is used in loops to cause the rest of an iteration to be skipped and the next
iteration to be started.
Example
goto part2;
In principle you never need to use goto in a C statement. The if construct can be used
in its place as shown below.
Alternative 1 Alternative 2
if (a>14) if (a>14)
goto a; sheds=3;
sheds=2; else
goto b; sheds=2;
a: sheds=3; k=2*sheds;
b: k=2 * sheds;
4.4 Looping
The while statement is used to carry out looping instructions where a group
of instructions executed repeatedly until some conditions are satisfied.
General form:
while (expression)
statement;
The statement will be executed as long as the expression is true, the statement can
be a single or compound
/* counter.c */
main()
while (digit<=9)
digit++;
return 0;
Algorithm:
(i) Initialise an integer count variable to 1. It will be used as a loop counter. (ii)
Assign a value of 0 to the floating-point sum.
(iii) Read in the variable for n (number of values)
(iv) Carry out the following repeatedly (as long as the count is less or equal to n). (v)
Read in a number, say x.
(vi) Add the value of x to current value of sum.
(vii) Increase the value of count by 1.
(viii) Calculate the average: Divide the value of sum by n.
(ix) Write out the calculated value of average.
Solution
#include<stdio.h>
main()
int n, count = 1;
scanf(“%d”, &n);
while (count<=n)
printf(“x = “);
scanf(“%f”, &x);
sum+=x;
count++;
average = sum/n;
return 0;
(Note that using the while loop, the loop test is carried out at the beginning of each
loop pass).
It is used when the loop condition is executed at the end of each loop pass.
General form:
do
statement;
while(expression);
The statement (simple or compound) will be executed repeatedly as long as the value
of the expression is true. (i.e. non zero).
Notice that since the test comes at the end, the loop body (statement) must be
executed at least once.
Rewriting the program that counts from 0 to 9, using the do while loop:
/* counter1.c */
main()
do
digit++;
} while (digit<=9);
return 0;
Exercise: Rewrite the program that computes the average of n numbers using the
do while loop.
where:
expression3 is used to alter the value of the parameter index initially assigned by
expression and is usually a unary expression or assignment operator);
Example
Output
0
1
2
3
4
5
#include<stdio.h>
main()
int digit;
for(digit=0;digit<=9; digit++)
printf(“%d \n” , digit);
return 0;
#include<stdio.h>
main()
int n, count;
scanf(“%d”, &n);
for(count=1;count<=n;count++)
printf(“x = “);
scanf(“%f”, &x);
sum+=x;
}
average = sum/n;
return 0;
41
#include<stdio.h>
main()
int number;
for(num=1; num<=6;num++)
42
return 0;
You can count by any number you wish; two‟s threes, etc.
You can test some condition other than the number of operators.
Example
if (number>6)
if (number<12)
else
42
#include<stdio.h>
main()
sum=0.0;
scanf(“%d”, &n);
for(count=1;count<=n; count++)
printf(“x = “);
scanf(“%f”, &x);
sum+=x;
} /* End of inner loop */
average = sum/n;
return 0;
Purchase Amount >= Ksh. 10,000 - Give 10% discount on the amount.
Ksh. 5, 000 <= Purchase Amount < Ksh. 10,000 - Give 5% discount on the
amount. Ksh. 3, 000 <= Purchase Amount < Ksh. 5,000 - Give 3% discount on the
amount.
0 > Purchase Amount < Ksh. 3,000 - Pay full amount.
2. Write a program that asks for the customer‟s purchase amount, then uses if
statements to recommend the appropriate payable amount. The program should
cater for negative purchase amounts and display the payable amount in each
case.
3. In what circumstance is the continue statement used in a C program?
4. Using a nested if statement, write a program that prompts the user for a number
5.1 Introduction
A function is a self-contained program segment that carries out some specific well -
defined task. Every C program consists of one or more functions. One of these
functions must be called main. Execution of the program will always begin by carrying
out the instructions in main. Additional functions will be subordinate to main, and
perhaps to one another.
If a program contains multiple functions, their definitions may appear in any order,
though they must be independent of one another. That is, one function definition cannot
be embedded within another. A function will carry out its intended action whenever it is
accessed (whenever the function is called) from some other portion of the program. The
same function can be accessed from several different places within a program. Once
the function has carried out its intended action, control will be returned to the point from
which the function was accessed.
Generally the function will process information that is passed to it from the calling
portion of the program and return a single value. Information is passed to the function
via special identifiers called arguments (also called parameters), and returned via the
return statement. Some functions however, accept information but do not return
anything.
There are several advantages to this modular approach to program development; for
example many programs require that a particular group of instructions be accessed
repeatedly from several different places in the program. The repeated instructions can
be placed within a single function which can then be accessed whenever it is needed.
Moreover a different set of data can be transferred to the function each time it is
accessed . Thus the use of a function eliminates the need for redundant
programming of the same instructions.
Equally important is the logical clarity resulting from the decomposition of a program
into several concise functions where each function represents some well-defined part of
the overall problem. Such programs are easier to write and easier to debug and their
logical structure is more apparent than programs which lack this type of structure. This
is especially true of lengthy, complicated programs. Most C programs are therefore
modularised in this manner, even though they may not involve repeated execution of
some task. In fact the decomposition of a program into individual program modules is
generally considered to be good programming practice.
This use of functions also enables a programmer to build a customized library of
frequently used routines or of routines containing system-dependent features.
Each routine can be programmed as a separate function and stored within a special
library file. If a program requires a particular routine, the corresponding library
function can be accessed and attached to the program during the compilation
process. Hence a single function can be utilised by many different programs.
A function definition has two principle components; the first line (including the argument
declaration), and the body of a function. The first line of a function definition contains
the value returned by the function, followed by the function name, and (optionally) a set
of arguments separated by commas and enclosed in parenthesis. Each argument is
preceded by its associated type declaration. Any empty pair of parenthesis must follow
the function name if the function definition does not include any arguments.
Where data-type represents the data type of the item that is returned by the function.
functionname represents the function name , and type 1 , type 2 ,…….., type n
represents the data types of the arguments, argument 1, argument 2 ,
……..argument n .
The data types are assumed to be of type int if they are not shown explicitly. However,
the omission of the data type is considered poor programming practice, even if the
data items are integers.
The arguments are called formal arguments because they represent the names of
data items that are transferred into the function from the calling portion of the
program. They are also known as parameters or formal parameters. (The
corresponding arguments in the function reference are called actual arguments since
they define the data items that are actually transferred). The names of the formal
arguments need not be the same as the names of the actual arguments in the
calling portion of the program. Each formal argument must be of the same data type,
however, as the data item it receives from the calling portion of the program.
The remainder of the function definition is a compound statement that defines the
action to be taken by the function. This compound statement is sometimes referred to
as the body of the function. Like any other compound statement, this statement can
contain expressions statements, other compound statements, control statements and
so on. It should include one or more return statements in order to return a value to the
calling portion of the program. A function can access other functions. In fact it can
access itself (a process known as recursion).
Information is returned from the function to the calling portion of the program via a
return statement. The return statement also causes the program logic to return to
return (expression);
Only one expression can be included in the return statement. Thus, a function
can return only one value to the calling portion via return.
The function shown below calculates the functional of a given positive integer n. The
factorial is returned as a long integer quantity, since factorials grow in magnitude
very rapidly as n increases.
int i;
if (n >1 );
Notice the long int specification that is included in the first line of the function definition.
The local variable prod is declared to be a long integer within the function. It is
assigned an initial value of 1 though its value is recalculated within a for loop. The final
value of prod which is returned by the function represents the desired value of n
factorial (n!).
If the data type specified in the first line is inconsistent with the expression appearing in
the return statement, the compiler will attempt to convert the quantity represented by
the expression to the data type specified in the first line. This could result in a
compilation error or it may involve a partial loss in data (due to truncation).
Inconsistency of this
type should be avoided at all costs.
The following definition is identical to that in Example 1 except that the first line
does not include a type specification for the value that is returned by the function.
factorial (int n) /* calculate the factorial of n */
int i;
if (n > 1)
return (prod);
The function expects to return an ordinary integer quantity since there is no explicit type
declaration in the first line of the function definition. However the quantity being returned
is declared as a long integer within the function. This inconsistency can result in an error
(some compilers will generate a diagnostic error and then stop without completing the
compilation). The problem can be avoided however by adding a long int type
declaration to the first line of the function definition as Example 1 shows.
The keyword void can be used as a type specifier when defining a function that does
not return anything or when the function definition does not include any arguments.
The presence of this keyword is not mandatory but it is good programming practice to
make use of this feature.
Consider a function that accepts two integer quantities, determines the larger of the
two and displays it (the larger one). This function does not return anything to the calling
portion. Therefore the function can be written as;
int z;
z = (x >= y)? x : y;
The keyword void added to the first line indicates that the function does not
return anything.
(They are also known as actual parameters or arguments). In a normal function call,
there will be one actual argument for each formal argument. Each actual argument
must be of the same data type as its corresponding formal argument. Remember that it
is the value of each actual argument that is transferred into the function and assigned
into the corresponding formal argument.
There may be several different calls to the same function from various places within a
program. The actual arguments may differ from one function call to another. Within
each function call however the actual arguments must correspond to the formal
arguments in the functions definition; i.e. the number of actual arguments must be the
same as the number of formal arguments and each actual argument must be of the
same data type as its corresponding formal argument.
The following program determines the largest of three integers quantities. The program
makes use of a function that determines the larger of two integer quantities. The overall
strategy is to determine the larger of the first two quantities and then compare the
value with the third quantity. The largest quantity is then displayed by the main part of
the program.
#include<stdio.h>
int z;
z = (x > = y )? x : y;
return(z);
main()
int a , b , c ,d;
printf(“\n a = ”);
scanf(“%d”, &a);
printf(“\n b = ” );
scanf(“%d”, &b);
printf(“\n c = ”);
scanf(“%d”, &c);
/* Calculate and display the maximum value */
return 0;
The function maximum is accessed from two different places in main. In the first call
to maximum, the actual arguments are the variables a and b whereas in the second
call, the arguments are c and d. (d is a temporary variable representing the maximum
value of a and b).
In this statement, we see that one of the calls to maximum is an argument for the other
call. Thus the calls are embedded one within the other and the intermediary variable d
is not required. Such embedded functions calls are permissible though their logic may
be unclear. Hence they should generally be avoided by beginning programmers.
In the previous function examples, the programmer -defined function has always
preceded main. Thus when the programs are compiled, the programmer-defined
function will have been defined before the first function access. However many
programmers prefer a top drawn approach in which main appears ahead of the
programmer-defined function definition. In such a situation, the function access
(within main) will precede the function definition. This can be confusing to the
compiler unless the compiler is first alerted to the fact that the function being
accessed will be defined later in the program. A function prototype is used for this
purpose
Function prototypes are usually written at the beginning of a program ahead of any
programmer-defined function (including main) The general form of a function
prototype is;
Where data_type represents the type of the item that is returned by the
function, function_name represents the name of the function, type 1, type 2, …
…., type n represent the types of the arguments 1 to n.
Note that a function prototype resembles the first line of a function definition (although
a definition prototype ends with a semicolon).
The names of the argument within the function prototype need not be declared else
where in the program since these are “dummy” argument names that are recognised
only within the prototype. In fact, the argument names can be omitted (though it is not
a good idea to do so). However the arguments data types are essential.
In practice, the argument names usually included are often the same as the names of
the actual arguments appearing in one of the function calls. The data types of the
actual arguments must conform to the data types of the arguments within the prototype.
Function prototypes are not mandatory in C. They are desirable however because
they further facilitate error checking between the calls to a function and the
corresponding function definition.
Here is a complete program to calculate the factorial of a positive integer quantity. The
program utilises the function factorial defined in example 1 and 2. Note that the
function definition precedes main.
#include<stdio.h>
main()
int n;
int i;
if (n >1)
prod *= i;
return (prod);
The programmer-defined function makes use of an integer argument (n) and two
local variables (an ordinary integer and a long integer). Since the function returns a
long integer, the type declaration long int appears in the first line of the function
definition.
5.2.1 Recursion
Recursion is the process by which a function calls itself repeatedly until a special
condition is satisfied.
Or generally,
This is to say that in the factorial example, the calculation of n is expressed in form of
a previous result (condition (i) is satisfied).
51
main()
int n;
printf (“n = ” );
return 0;
52
/* Function definition */
return (1);
else
The functional factorial calls itself recursively with an actual argument that decreases in
magnitude for each successive call. The recursive call terminates when the value of
the actual argument becomes equal to 1.
int a, b, c;
……
c =function1(a,b);
……
{
int z;
……
z = ……
return(z);
(b) main()
{
int a;
float b;
long int c;
……
c = funct1(a,b);
……
}
int func1(int x, float y)
long int z;
……
……
z = ……
return (z);
#include<stdio.h>
main()
int a,count;
a = func(count);
printf(“%d”,a);
return 0;
int func(int x)
int y;
y = x * x;
return(y);
6.1 Introduction
It is often necessary to store data items that have common characteristics in a form
that supports convenient access and processing e.g. a set of marks for a known
number of students, a list of prices, stock quantities, etc. Arrays provide this facility.
Example
Because the array is declared as type float, each element can be assigned a float
value such as debts[5] = 32.54;
Other examples;
int emp_no[15]; /*An array to hold 15 integer employee numbers */
char alpha [26]; /*an array to hold 26 characters */
An array definition
comprises; (i) Storage
class (optional) (ii) Data
type
(iii) Array name
(iv) Arraysize expression (usually a positive integer or symbolic constant). This
is enclosed in square brackets.
Examples:
float table[50]
[50];
char page[24]
[80];
Static double records[100][60]
[255];
Example
Two-dimensional array representing sales ( „000 tonnes for a product in four months
for
five years).
Yr1 Yr2 Yr3 Yr4 Yr5
Month 1 23 21 27 23 22
Month 2 24 20 19 18 20
Month 3 26 23 26 29 24
Month 4 27Downloaded by Abdinoor
25 Maalim (maalimabdinoor3@gmail.com)
24 23 25
lOMoARcPSD|34868190
Because the array is defined inside main, its an automatic array. The first element
marks[0] is assigned the value of 30 , marks[1] as 40 and so on.
An external array is one defined outside a function.
They
(i) are known to all functions following them in a file e.g. from above, both main ( )
and feed ( ) can use and modify the array SOWS.
(ii) Persist (retain values) as long as the program runs. Because they are not
defined in any particular function, they don‟t expire when a particular function
terminates.
----------
----------
int feed(int n)
{
---------
---------
(iii) A static array is local to the function in which it is declared but like an external
array, it retains its values between function calls and is inititialised to zero by default.
Example
Like other types of variables, you can give the elements of arrays initial values. This
is accomplished by specifying a list of values the array elements will have. The
The value list is a comma separated list of constants that are type compatible with the
base type of the array. The first constant will be placed in the first position of the
array, the second constant in the second position and so on. Note that a semi colon
follows the }.
In the following example, a five – element integer array is initialised with the squares
of the number 1 though 5.
This means that i[0] will have the value 1 and i[4] will have the value 25.
You can initialise character arrays in two ways. First, if the array is not holding a
null -terminated string, you simply specify each character using a comma
separated list. For example, this initialises a with the letters „A‟, „B‟, and „C‟.
If the character array is going to hold a string, you can initialise the array using
a quoted string, as shown here.
Notice that no curly braces surround the string. They are not used in this form of
initialisation. Because strings in C must end with a null, you must make sure that the
array you declare is long enough to include the null. This is why name is 6
characters long, even though “Peter” is only 5 characters. When a string constant is
used, the compiler automatically supplies the null terminator.
For example, here the array sqr is initialised with the values 1 though 9, using
row order.
};
This initialisation causes sqr[0][0] to have the value 1, sqr[0][1] to contain 2, sqr[0][2]
If you are initialising a one-dimensional array, you need not specify the size of the
array, simply put nothing inside the square brackets. If you don‟t specify the size, the
compiler simply counts the number of initialisation constants and uses that that value
as the size of the array.
Arrays that don‟t have their dimensions explicitly specified are called unsized arrays.
An unsized array is useful because it is easier for you to change the size of the
initialisation list without having to count it and then change the array dimension
dimension. This helps avoid counting errors on long lists, which is especially
important when initialising strings.
If at a later date, you wanted to change the prompt to “Enter your last name: “ , you
would not have to count the characters and then change the array size.
For multi dimensional arrays, you must specify all but the left dimension to allow C
to index the array properly. In this way you may build tables of varying lengths with
the compiler allocating enough storage for them automatically.
For example, the declaration of sqr as an unsized array is shown here.
int sqr[][3] = {
1, 2, 3,
4, 5, 6,
7, 8, 9
};
The advantage to this declaration over the sized version is that tables may be
lengthened or shortened without changing the array dimensions.
#include<stdio.h>
#define MONTHS 12
main()
int index;
return 0;
Explanation
By defining days [ ] outside the function, we make it external. We initialise it
with a list enclosed in braces, commas are used to separate the members of the
list.
Inside the function the optional declaration extern int days [ ]; uses the keyword
extern to remind us that days array is defined elsewhere in the program as an
external array. Because it is defined elsewhere we need not give its size here.
(ommitting it has no effect on how the program works)
Note:
The number of items in the list should match the size of the array.
Single operations which involve entire arrays are not permitted in C. Operations
such as assignment, comparison operators, sorting etc must be carried out on an
element- by-element basis. This is usually accomplished within a loop where each
pass through the loop is used to process one array element. The number of
passes through the loops will therefore be equal to the number of array elements to
be processed.
#include<stdio.h>
main()
int n, count;
float list[100];
/* Read in a value of n */
scanf(“ %d “, &n);
printf(“ \n”);
printf(“ i = %d x = ”,
count+1); scanf(“ %f “,
&list[count]);
sum+=list[count];
}
avg = sum/n;
d = list[count] – avg;
list[count], d);
return 0;
} /* End of program */
Output
The average is 2
Exercise
Assuming that the number of values in the list is already known to be 3, and that the
list
values are 5, 6, 8, rewrite the above program without having to request input from
the keyboard.
Arrays are especially useful when you want to sort information. For example, this
program lets the user enter up to 100 numbers and then sorts them. The sorting
algorithm is the bubble sort. The general concept of the bubble sort is the
repeated comparisons and, if necessary exchanges of adjacent elements. This is a
little, like bubbles in a tank of water with each bubble, in turn, seeking its own level.
#include<stdio.h>
main()
int item[100];
int a, b, t;
int count;
/ * Read in the numbers */
printf(“ How many numbers? “);
scanf(“ %d “, &count);
for (a = 0; a < count; a ++)
t = item[b – 1];
item[b –1] = item[b];
item[b] = t;
printf(“ %d “, item[t]);
return 0;
#include<stdio.h>
main()
printf(“CAT %d\n”,cols+1);
for(rows=0;rows<STUDENT; rows++)
for(cols=0;cols<CATS;cols++)
return 0;
6.3 Strings
In C, one or more characters enclosed between double quotes is called a string. C has
no built-in string data type. Instead, C supports strings using one dimensional
character arrays. A string is defined as a null terminated character array. In C, a null is
0. This fact means that you must define the array is going to hold a string to be one
byte larger than the largest string it is going to hold, to make room for the null.
To read a string from the keyboard you must use another of C‟s standard library
functions, gets( ), which requires the STDIO.H header file. To use gets( ), call it using
the name of a character array without any index. The gets( ) function reads characters
until you press <ENTER>. The carriage return is not stored, but it is replaced by a null,
which terminates the string. For example, this program reads and writes a string
entered at the keyboard.
#include<stdio.h>
main()
char str[80];
int i;
gets(str);
The gets( ) function performs no bounds checking, so it is possible for the user to
enter more characters that gets( ) is called with can hold. Therefore be sure to call it
with an array large enough to hold the expected input.
In the previous program, the string that was entered by the user was output to the
screen a character at a time. There is however a much easier way to display a
string, using printf( ). Here is the previous program rewritten..
#include<stdio.h>
main()
char str[80];
gets(str);
printf(str);
return 0;
}
If you wanted to output a new line, you could output str like this:
This method uses the %s format specifier followed by the new line character and
uses the array as a second argument to be matched by the %s specifier.
The C standard library supplies many string-related functions. The four most important
are strcpy( ), strcat( ), strcmp( ) and strlen( ). These functions require the header
file STRING.H.
It copies the contents of from to to. The contents of from are unchanged. For example,
this fragment copies the string “hello‟ into str and displays it on the screen.
char str[80];
strcpy(str, “hello”);
printf(“%s”, str);
The strcpy( ) function performs no bounds checking, so you just make sure that the
array on the receiving end is large enough to hold what is being copied, including
the null terminator.
The strcat( ) function adds the contents of one string to another. This is called
concatenation. Its general form is
It adds the contents of from to to. It performs no bounds checking, so you must
make sure to is large enough to hold its current contents plus what it will be
receiving. This fragment displays hello there.
char str[80];
strcpy(str, “hello”);
strcat(str, “there”);
printf(str);
The strcmp( ) function compares two strings. It takes this general form.
strcmp(s1, s2);
It returns 0 if the strings are the same. It returns less than 0 if s1 is less than s2 and
greater than 0 if s1 is greater than s2. The strings are compared lexicographically; that
is in dictionary order. Therefore, a string is less than another when it would appear
before the other in a dictionary. A string is greater than another when it would appear
after the other. The comparison is not based upon the length of the string. Also, the
comparison is case-sensitive, lowercase characters being greater than uppercase. This
fragment prints 0, because the strings are the same.
The strlen( ) function returns the length , in characters, of a string. Its general form
is strlen(str);
#include<string.h>
#include<stdio.h>
main()
int i;
gets(str1);
gets(str2);
i = strcmp(str1, str2);
if ( ! i)
else if (i < 0)
else
strcat(str1, str2);
strcpy(str1, str2);
return 0;
Note:
You can use scanf( ) to read a string using the %s specifier, but you probably won‟t
need to. Why? This is because when scanf( ) inputs a string, it stops reading that
string when the first white space character is encountered. A white space character is
a space, a tab, or a new line. This means that you cannot use scanf() to read input like
the following string.
Because there is a space after the word This, scanf( ) will stop inputting the string
at that point. That is why gets( ) is generally used to input strings.
MARY 45 78 70 89
ALEX 89 65 56 90
MOSES 67 56 72 76
CAROL 70 90 68 56
A pointer is a variable that holds the memory address of another variable. For
example, if a variable called p contains the address of another variable called q, then p
is said to point to q.
Therefore if q were at location 100 in memory, then p would have the value 100.
Here, type is the base type of the pointer. The base type specifies the type of the
object that the pointer can point to. Notice that an asterisk precedes the variable name.
This tells the computer that a pointer variable is being created. For example, the
following statement creates a pointer to an integer.
int *p;
C contains two special pointer operators: * and &. The & operator returns the address
of the variable it precedes. The * operator returns the value stored at the address that it
precedes. The * pointer operator has no relationship to the multiplication operator,
which uses the same symbol). For example, examine this short program.
#include<stdio.h>
main()
int *p, q;
First, the line int *p, q; defines two variables: p, which is declared as an integer
pointer, and q, which is an integer. Next, q is assigned the value 100.
In the next line, p is assigned the address of q. You can verbalize the & operator as
“address of.“ Therefore, this line can be read as: assign p the address of q. Finally,
the value is displayed using the * operator applied to p. The * operator can be
verbalized as “at address”.
Therefore the printf( ) statement can be read as “print the value at address q,” which is
100. When a variable value is referenced through a pointer, the process is called
indirection. It is possible to use the * operator on the left side of an assignment
statement in order to assign a variable a new value using a pointer to it. For
example, this program assigns a value q indirectly using the pointer p.
#include<stdio.h>
main()
int *p, q;
return 0;
Note: The type of the variable and type of pointer must match.
For example
e.g. char line[100], *p;
We may refer to the first two elements of the array line using
line[0] = „a‟;
line[1] = ‟b‟; and for each assignment, the compliler calculates the
address.
Another way to perform the assignments is to use a printer. First, we must initialize the
pointer p to point to the beginning of the array.
i.e. p = &line [0];
Since an array‟s name is a synonynm to the array‟s starting addres, we can use:
p = line;
We can now perform the assignments:
*p = „a‟; and *(p+1) = „b‟;
#include<stdio.h>
main()
return 0;
Output
(a) Assignment
One can assign an address to a pointer by:
(i) Using an array name or
(ii) Using the address operator
p+ +; first increments p and then obtains the value at the new location. To
increment what is pointed to by a pointer, you must use (p)+ +;
Incrementing a pointer to an array involves moving to the next element of an
array. Thus, from the above array example, p1+ + makes the pointer point to the
next
element, x[1]. Therefore p1++ becomes 20.
For example, assume an integer pointer called p contains the address 200. After the
statement p++ executes, p will have the value 202, assuming integers are 2 bytes
long. If p had been a floating point value (4 bytes long), then the resultant value
contained in p would be 204.
Pointer arithmetic with character appears normal when character pointers are used.
Because characters are 1 byte long, an increment increases the pointer value by
one, decrement decreases it by one.
int *p;
……
……
p = p + 200;
th
causes p to point to the 200 integer past the one to which p was
You may not perform any other type of arithmetic operations. You may not
divide, multiply,or take modulus of a pointer. But you may subtract a pointer from
another to find the number of elements separating them.
Pointers may be arrayed like any other data type. For example the following
statement declares an integer pointer array that has 20 elements.
int *pa[20];
The address of an integer variable myvar is assigned to the ninth element of the
array as folows;
pa[8]= &myvar;
Because pa is an array of pointers, the only value that the array elements may hold
are addresses of integer variables. To assign the integer pointed to by the third
element of pa the value 50, use the statement;
*pa[2] = 50;
Program that uses a for loop that counts from 0 to 9. It puts in the numbers using
a pointer.
#include<stdio.h>
main()
int i,*p;
p = &i;
#include<stdio.h>
main()
pv = &v;
u2 = 2 * (*pv + 5 );
return 0;
Output
u1 = 16, u2 = 16.
Explain why.
Note
Never use a pointer of one type to point to an object of a different type.
For example:
int q;
float *fp;
Do not use a pointer before it has been assigned the address of a variable.
May cause program to crash.
For example:
main()
int *p;
Revision Exercises
1. Write an appropriate declaration for each of the following situations;
(a) Declare two pointers whose objects are the integer variables i and j.
(b) Declare a function that accepts two integer arguments and returns a long integer.
Each argument will be a pointer to an integer quantity.
(c) Declare a one-dimensional floating point array using pointer rotation.
(d) Declare a function that accepts another function and returns a pointer to a
int *p;
p = temp;
8.1 Introduction
Suppose you want to write a program that keeps tracks of students [Name, Marks] i.e.
a variety of information to be stored about each student. This requires;
An array of strings (for the Names).
Marks in an array of integers.
A data form or type containing both the strings and integers and somehow keep
the information separate is required. Such a data type is called a structure.
A structure is an aggregate data type that is composed of two or more related elements.
Unlike arrays, each element of a structure can have its own type, which may differ
from the types of any other elements.
struct student
char name[SIZE];
int marks;
};
The above describes a structure made up of a character array name, and int variable
marks.
Explanation
The keyword struct announces to the computer that what follows is a structure
data type template.
The tag follows: which is a shorthand label that can be used later to refer to
this structure. In the above example, the tag name is student.
A list of structure members enclosed in a pair of braces. Each member is described
by its own declaration. For example; the name portion is a character array of SIZE
elements.
Note: Members of a structure can be any data types including other structures.
int acc_number;
char acc_type;
78
float balance;
};
The structure template doesn‟t tell the computer how to represent the data. Having
set up the template we can declare a structure variable as follows;
The computer creates a variable mystudent following the structure template. It allocates
space for a character array of SIZE elements and for an integer variable.
One can declare as many variables of type student as possible. For example,
struct student mystudent, student1, x, y, z; etc.
Note: One can combine the process of defining the structure template and the process
of defining a structure variable as follows;
struct student
char name;
int marks;
}mystudent;
typeN elementN;
}variable list;
A structure can be initialized like any other variable - external, static or automatic. This
will depend on where the structure is defined.
Example
static struct student mystudent =
“Fred Otieno”,25;
};
Each member is given its own line of initialization and a comma separator, one member
initialization from the next.
Individual structure members are accessed using a period (.) - structure member
operator.
For example mystudent.marks which means the marks portion of struct mystudent.
Note: You can use mystudent.marks exactly the way you use other integer variables.
For example, you can use gets(mystudent.name);
or
scanf(“%d”, &mystudent.marks);
80
Note: Although mystudent is a structure, mystudent.marks is an int type and is like any
other integer variable. Therefore;
The use of scanf(“%d”.........) requires the address of an integer and that is what
&mystudent.marks does.
struct student stud1;, then it is possible to read the name and marks into
the variable using the statements;
gets(stud1.name)
scanf(“%d”, &stud1.marks);
#define SIZE 40
struct student
{
char name[SIZE];
int marks;
};
main()
81
scanf(“%s”, mystudent.name);
printf(“Enter the marks obtained \n”);
scanf(“%d”, &mystudent.marks);
printf(“%s: got %d “, mystudent.name, mystudent.marks);
return 0;
One student can be described by one structure variable of type student, 2 students
by two variables, 3 students by three variables, n students by n such structure
variables, etc.
#include<stdio.h>
#define SIZE 40
#define MAXSTU 30
struct student
{
char name[SIZE];
int marks;
};
main()
int count;
scanf(“%s”, mystudent[count].name);
scanf(“%d”, &mystudent[count].marks);
return 0;
The immediate application that comes to mind is database management. For example,
to maintain data about employees in an organization, books in a library, items in a
store, financial transactions in a company, etc.
Their use however, stretches beyond database management. They can be used for a
variety of applications like:
Checking the memory size of the computer.
To program the above applications, you need thorough knowledge of internal details
of the operating system
Using enumerated data type can also help reduce programming errors.
Example
We could invent a data type called mar_status (for marital status) which can have
four possible values - single, married, widowed or divorced. (Do not confuse these
names
with variable names; they are only possible values for marital status).
The format of the enum definition is similar to that of a structure. The example can
be implemented as follows:
enum mar_status
{
single,
married,
divorced,
widowed
};
We cannot use the values that are not in the original declaration. Thus the
expression,
person1 = unknown;
would cause an error.
Internally, the compiler treats the enumerators as integers. Each value on the list
of permissible values corresponds to an integer, starting with 0. Thus in our
example, single is stored as 0, married is stored as 1, divorced as 2 and widowed
as 3.
enum mar_status
{
single = 100,
married = 200,
divorced = 300,
widowed = 400
};
enum mar_status person1, person2;
#include<string.h>
#include<stdio.h>
main()
{
enum emp_dept
{
assembly,
manufacturing,
accounts,
stores
};
struct employee
{
char name[30];
int age;
float bs;
enum emp_dept department;
};
struct employee e;
strcpy(e.name, “Rodgers Okumu”);
e.age = 30;
e.bs = 20000.50;
e.department = manufacturing;
if(e.department == accounts)
printf(“Rodgers is an accountant”);
else
printf(“Rodgers is not an accountant”);
return 0;
}
Explanation
We first defined the data type enum emp_dept and specified the four possible values,
namely assembly, manufacturing, accounts and stores. Then we defined a
variable department of the type enum emp_dept in a structure. The structure
employee has three other elements containing employee information.
The program first assigns values to the variables in the structure. The statement,
e.department = manufacturing;
assigns the value manufacturing to e.department variable. This is much more
informative to anyone reading the program than a statement like,
e.department = 1;
A weakness of using enum variables is shown in the next part of the program. There
is no way to use enumerated variables in input/output functions like
printf( ) and scanf( ).
The printf( ) function is not smart enough to perform the translation and hence the
The typedef feature allows users to define new data types that are equivalent to
existing data types. Once a user defined type has been established, then new
variables, arrays, structures, etc. can be declared in terms of this new data type.
For example,
typedef int age;
In this declaration, age is a user defined data type which is equivalent to type
int. Hence the declaration:
age male, female; - is equivalent to writing int male,male;
In other words, male and female are regarded as variables of type age, though they
are actualy integer type variables.
typedef struct
char name[SIZE];
int marks;
student student1,student2;
typedef struct
int month;
int day;
int year;
}date; /*date is a user defined data type*/
typedef struct
int acc_number;
char acc_type;
char name[30];
float balance;
date lastpayment;
}BankAcct; /*BankAcct is a user defined type */
BankAcct customer[100];
8.8 Unions
A union is a single memory location that stores two or more variables. Members within
a union all share the same storage area, whereas each member within a structure is
assigned its own unique storage area.
Thus, unions are used to conserve memory. They are useful for applications
involving multiple members, where values need not be assigned to all members at a
time.
The similarity between structures and unions is that both contain members
whose individual data types may differ from one another.
Format of a union
union tag
{
member 1;
member 2;
…..
…..
member n;
};
Or
union tag
{
member 1;
member 2;
…..
…..
member n;
}variable list;
union id{
char color[12];
int size;
}shirt, blouse;
Explanation
(i) There are two union variables shirt and blouse. Each variable can represent
either a 2 character string (colour) or a integer quantity (size) at any one time.
The
12-character string will require more storage area within the computer‟s memory
than the integer quantity.
Therefore a block of memory large enough for the 12-character string will
be allocated to each union variable.
union id{
char color[12];
int size;
};
struct clothes
char manufact[20];
float cost;
union id descr;
}shirt,blouse;
Explanation
char manufact[20];
float cost;
union
char color[12];
int size;
}descr;
};shirt, blouse;
Revision Exercises
double balance;
struct s_type
int a;
char b;
float bal;
}myvar,*p;
p = &myvar;
p.a = 10;
5. Set up a suitable structure for an invoice that should hold the following details:
Element Type
Invoice number integer
Customer number integer
Invoice date structure
(with three integer elements; day, month, year)
Customer address string (20 characters)
Item structure
[with product code (integer), unit price (float)
quantity (float) , amount (double)]
Invoice Total double
6. How is a structure different from a union?
(b) Using a user defined type named invoices set up the structure template in
(a) above. Show how you can set two simple structure variables invoice1,
invoice2 using the new type.
8. (a) Declare a structure card which stores the following library information.
Student Number (int)
Student Name (25 characters)
Course Code (int)
Telephone (12 characters)
Address (14 Characters)
(b) Set up a structure called card1 using typedef. It should store similar data items to
card.
9.1 Introduction
Disk input/output (I/O) operations are performed on entities called files.
Although C does not have any built – in method of performing file I/O, the standard C
library contains a very rich set of I/O functions.
High-level Disk I/O functions are more commonly used in C programs, since they are
easier to use than low-level disk I/O functions.
The low-level disk I/O functions are more closely related to the computer‟s operating
system than the high-level disk I/O functions.
Low-level disk I/O is harder to program than high-level disk I/O. However, low-level disk
I/O is more efficient both in terms of operation and the amount of memory used by the
program.
There are two types of streams; text and binary. A text stream is used with ASCII
characters. When a text stream is being used, some character translations take
place. For example, when the new line character is output, it is converted into a
carriage return/line feed sequence. For this reason, there may not be a one-to-one
correspondence between what is sent to the stream and what is written to the file.
A binary stream is used with any type of data. No character translations will occur, and
there is a one-to-one correspondence between what is sent to the stream and what is
actually contained in the file.
One final concept you need to understand is that of the current location. The current
location also referred to as the current position is the location is a file where the next file
access will begin. For example, if a file is 100 bytes long and half the file has been
read, the next read operation will occur at location 50, which is the current location.
The link between our program and the operating system is a structure called FILE
(which has been defined in the header file stdio.h.
If the open operation is successful, what we get back is a pointer to the structure FILE.
That is why we make the following declaration before opening the file,
FILE *fp;
Each file we open will have its own file structure. The file structure contains information
about the file being used, such as its current size, memory location, access modes, etc.
FILE *fp;
Fp = fopen(“myfile.txt”, “r”);
Meaning? fp is a pointer variable, which contains address of the structure FILE which
has been defined in the “stdio.h” header file.
fopen( ) will open a file “myfile.txt” in „read‟ mode, which tells the C compiler that we
would be reading the contents of the file.
Legal values for modes that can be used with fopen() are summarised below.
“r” Searches file. If the file exists, loads it into memory and sets up a pointer which
points to the first character in it. If the file doesn‟t exist it returns
NULL. Operation possible - reading from the file.
“w” Searches file. If the file exists, its contents are overwritten. If the file
doesn’t exist, a new file is
created; Returns NULL if unable to open file.
“a” Searches file. If the file exists, loads it into memory and sets up a pointer which
points to the first character in it. If the file doesn‟t exist, a new file is created.
Returns NULL if unable to open file.
“r+” Searches file. If the file exists, loads it into memory and sets up a pointer which
points to the first character in it. Returns NULL if unable to open file.
Operations possible – Reading existing contents, writing new contents, modifying
contents of the file.
“w+” Searches file. If the file exists, its contents are destroyed. If the file doesn‟t exist,
a new file is created. Returns NULL if unable to open file.
file.
“a+” Searches a file. If the file exists, loads it into memory and sets up a pointer
which points to the first character in it. Returns NULL if unable to open file.
Note
The header file “stdio.h” defines the macro NULL which is defined to be a null pointer.
It is very important to ensure that a valid file pointer has been returned You must
check the value returned by fopen( ) to be sure that it is not NULL.
For example, the proper way to open a file called myfile.txt for text input is
shown below.
FILE *fp;
fp = fopen(“myfile.txt”, “r”);
if (fp = = NULL)
{
printf(“Error opening file \n”);
exit();
}
For example,
A character declared as char ch; may be used to read the contents of a file as
below: ch = fgetc(fp);
fgetc( ) function reads the character from current pointer position , advances the
pointer position so that it now points to the next character, and returns the character
that is
read, which we collected in the variable ch. Note that once the file has been opened,
we no longer refer to the file by its name, but through the file pointer fp.
fclose(fp);
This deactivates the file and it can no longer be accessed using fgetc( ),
Note: The fgetc( ) function reads the next byte from the file described by fp and
returns an integer. The reason that it returns an integer is that if an error occurs,
fgetc( )
returns EOF (A macro has been defined in the file stdio.h), which is an integer
value. The fgetc( ) also returns EOF when the end of file is reached.
The fputc( ) returns the character written if successful or EOF if an error occurs.
Historical note: The traditional names for fgetc( ) and fputc( ) are getc( ) and putc(
). The ANSI standard still defines these names, and they are essentially
interchangeable with fgetc( ) and fputc( ). One reason the names were added was
for consistency. All other ANSI file system functions names begin with „f‟ and so the
„f‟ was added to the getc( ) and the putc( ). The traditional names are still supported
by the ANSI standard. If you see programs that use getc( ) and putc( ), do not worry,
they are essentially
different names for fgetc( ) and fputc( ).
1. The program demonstrates the four file – system functions you have learned so
far. First, it opens a file called MYFILE for output. Next, it writes the string “This
is a file system test” to the file. Then it closes the file and reopens it for read
operations. Finally, it displays the contents of the file on the screen and closes
the file.
#include <stdio.h>
#include <stdlib.h>
p = str;
while *p)
{
if(fputc(*p, fp)= = EOF)
{
printf(“Error writing file \n”);
exit(1);
}
p++;
}
fclose(fp);
Note:
The exit( ) function is used to terminate execution of a program.
The reason that you might want to use putchar( ) rather than printf( ) with the
%c specifier to output a character is that putchar( ) is faster and more efficient.
In this version, the return value of fgetc( ) is assigned to int. The value of this integer
is then checked to see if the end of the file has been reached. For most compiler,
however, you can simply assign the value returned by fgetc( ) to a char and still check
for EOF as is shown in the following version.
#include <stdio.h>
#include <stdlib.h>
{
FILE *fp;
char ch, *p;
while *p)
{
if(fputc(*p, fp)= = EOF)
{
printf(“Error writing file \n”);
exit(1);
}
p++;
}
fclose(fp);
The reason this approach works with most C compilers is that when a char is
being compared with an int, the char value is automatically elevated to an
equivalent int value.
There is however, even a better way to code this program. For example, there is no
need for a separate comparison step because the assignment and the comparison
can be performed at the same time within the if, as shown here.
#include <stdio.h>
#include <stdlib.h>
while *p)
{
if(fputc(*p, fp)= = EOF)
{
printf(“Error writing file \n”);
exit(1);
}
p++;
}
fclose(fp);
The feof( ) function returns non - 0 if the file associated with fp has reached the end
of file. Otherwise, it returns 0. This method works for both text and binary files.
The ferror( ) function returns non -0 if the file associated with fp has experienced
an error, otherwise, it returns 0.
Using the feof( ) function, this code fragment shows how to read the end of a file.
FILE *fp;
.
.
. while(!
feof(fp))
fgetc(fp);
This code works for any kind of file and is better in general than checking for
EOF. However, it does not provide for error checking. Error checking is added
here:
FILE *fp;
.
.
. while(!
feof(fp))
{
fgetc(fp);
if ferror(fp))
{
Instead of printing the error message using printf( ), we can use the standard
library function perror( ) which prints the error message specified by the compiler.
Similar to fgetc( ) and fputc( ), fgets( ) and fputs( ) read strings from and writes stings to
a file respectively.
main()
{
FILE *fp;
char str[80];
fp = fopen(“POEM.TXT”, “w”);
if(fp==NULL)
{
printf(“Cannot open file \n“);
exit(1);
}
printf(“\n Enter a few lines of text: \n“);
while(strlen(gets(str)) > 0)
{
fputs(str, fp);
fputs(“\n”);
}
fclose(fp);
return 0;
}
Notice that each string is terminated by hitting the <ENTER> key. To terminate the
execution of the program, hit <ENTER> at the beginning of a line. This creates a
string of zero length., which the program recognises as the signal to close the file and
exit.
We have set up a character array (str) to receive the string; the fputs( ) function then
writes the contents of the array to the disk. Since fputs( ) does not automatically add a
new line character to the end of the string, we must do this explicitly to make it easier
to read the string back from the file.
/* Reads strings from the file and displays them on the screen */
#include <stdio.h>
#include <stdlib.h>
main()
{
FILE *fp;
char str[80];
fp = fopen(“POEM.TXT”, “r”);
if(fp = = NULL)
{
printf(“Cannot open file \n“);
exit(1);
}
while(fgets(str,79, fp)!= NULL)
printf(“%s”, str);
fclose(fp);
return 0;
}
The function fgets( ) takes three arguments. The first is the address where the string
is stored and the second is the maximum length of the string. The argument prevents
fgets( ) from reading in too long a string and overflowing the array. The third pointer as
usual, is the pointer to the structure FILE. When all the lines from the file have been
read, we attempt to read one more line, in which case fgets( )returns a NULL.
The functions fprintf( ) and fscanf( ) operate exactly like printf( )and scanf( )
except that they work with files.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
main( )
{
FILE *fp;
char another =‟Y‟;
char name[40];
int age;
float bs;
fp=fopen(“EMPLOYEE.DAT“,”w”);
if(fp==NULL)
{
printf(“Cannot open file”);
exit(1);
}
while(another==‟Y‟)
{
printf(“\n Enter name, age and basic salary \n”);
scanf(“%s%d%f”, name,&age,&bs);
fprintf(fp, ”%s%d%f\n”, name,&age,&bs);
The key to this program is the function fprintf( ), which writes the values of the three
variables to the file. This function is similar tom printf( ), except that a FILE pointer
is included as the first argument.
As in printf( ), we can format the data in a variety of ways, by using fprintf(). In fact
all the format conventions of printf() function work with fprintf()as well.
Why use the fflush( ) function? The reason is to get rid of peculiarity of scanf().
After supplying data for one employee, we would hit the <ENTER> key. What scanf()
does is it assigns name, age and salary to appropriate variables and keeps the enter
key unread in the keyboard buffer. So when it is time to supply Y or N for the
question
„Another employee (Y/N)?‟, getch( ) will read the enter key from the buffer thinking
the user has entered the <ENTER> key. To avoid this problem we use the function
fflush(). It is designed to remove or „flush out‟ any data remaining in the buffer. The
argument to fflush() must be the buffer which we want to flush out here we use „stdin‟,
which means buffer related with standard input device, the key board.
Suppose we want to read back the names, ages and basic salaries of different
employees which we stored through the earlier program into the
EMPOYMENT.DAT” file. The following program does just this:
#include <stdio.h>
#include <stdlib.h>
main()
{
FILE *fp;
char name[40];
int age;
float bs;
fp=fopen(“EMPLOYEE.DAT”,”r”);
if (fp==NULL)
{
printf(“cannot open file”);
exit(1);
}
while(fscanf(fp,”%s%d%f”, name,&age,&bs)!=EOF)
printf(“%s %d %f\n”, name, &age, &bs);
fclose (fp);
return 0;
}
James 34 1550.000000
Mary 24 1200.000000
Peter 26 2000.000000
This program uses the fscanf( ), function to read the data from disk. This function is
similar to scanf( ) ,except that as with fprintf( ), a pointer to FILE is included as the
first argument.
So far we have seen programs which write characters, strings or number to a file. if
we desire to write a combination of these, that is a combination of dissimilar data
types, what should we do? Use structures.
main()
{
FILE *fp;
char another =‟Y‟;
struct emp
{
char name[40];
int age;
float bs;
};
struct emp e;
fp = fopen(“EMPLOYEE.DATA”,”w”);
if(fp==NULL)
{
printf(“cannot open file”);
exit(1);
}
while(another==‟Y‟)
{
printf(“\n Enter name, age and basic salary: ”);
scanf(“%s%d%f“, e.name,&e.age,&e.bs);
fprintf(fp, “%s %d %f\n”,e.name,e.age,e.bs);
printf(“\n Add another record (Y/N)? ”);
fflush(stdin),
another=getche();
}
fclose(fp);
return 0;
}
In the above program, we are just reading data into a structure using scanf( ) and
dumping it into disk file using fprintf( ). The user can input as many records as he
desires. The procedure ends when the user supplies „N‟ for the question „Add
another record (Y/N)?‟.
Before we can eliminate these disadvantages, let us first complete the program
that reads employee records created by the above program.
main()
{
FILE *fp;
struct emp
{
char name[40];
int age;
float bs;
};
struct emp e;
fp = fopen(“EMPLOYEE.DATA”,”w”);
if(fp==NULL)
{
printf(“cannot open file”);
exit(1);
}
while(fscanf(fp, “%s%d%f”,e.name,&e.age,&e.bs)!= EOF)
printf(“\n %s %d %f”, e.name,e.age,e.bs);
fclose(fp);
return 0;
}
John 34 1250.000000
Anne 21 1300.000000
Rodgers 34 1400.000000
Let us now see a more efficient way of reading/writing records (structures). This
makes use of two functions fread( ) and fwrite( ).
/*Receiving records from the key board & writing them to a file in a
binary mode*/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
main( )
{
FILE *fp;
char another = ‟Y‟;
struct emp
{
char name[40];
int age;
float bs;
};
struct emp e;
fp=fopen(“EMP.DAT”,”wb”);
if(fp==NULL)
{
printf(“cannot open file”);
exit(1);
}
while (another ==‟Y‟)
{
printf(“\n Enter name, age and basic salary: ”);
scanf(“%s%d%f”, e.name,&e.age,&e.bs);
fwrite(&e,sizeof(e), 1, fp);
printf(“ \n Add another record (Y/N)? ”);
fflush(stdin);
another=getche( );
}
fclose(fp);
return 0;
}
Most of this program is in similar to the one that we wrote earlier, which used fprintf()
instead of fwrite( ). Note, however, that the file “EMP.DAT” has now been opened in
binary mode.
The information obtained about the employee from the key board is placed in the
structure variable e. then, the following statement writes to the structure to the
file:
fwrite(&e,sizeof9e),1,fp);
Here, the first argument is the address of the structure to be written to the disk.
The second argument is the size of the structure in bytes. Instead of counting the bytes
occupied by the structure ourselves, we let the program do it for us by using the
sizeof() operator which gives the size of variable in bytes. This keeps the program
unchanged in event of change in the elements of the structure. The third argument is
the number of
such structures that we want to write at one time. In this case, we want to write only
one structure at a time. Had we had an array of structures, for example, we might want
have wanted to write the entire array at once.
/*Read the records from the binary file and display them on VDU*/
#include <stdio.h>
#include <stdlib.h>
main( )
{
FILE *fp;
struct emp
{
char name[40];
int age;
float bs;
};
struct emp e;
fp=fopen(“EMP.DAT”, “rb”);
if(fp==NULL)
{
printf(“cannot open file”);
exit(1);
}
fclose(fp);
return 0;
}
Here the fread() function causes the data read from the disk to be placed in
the structure variable e. The format of fread() is same as that of fwrite().
The function fread() returns the number of records read. Ordinarily, this should
correspond to the third argument, the number of records we asked for - 1 in this case.
If we have reached the end of file, since fread() cannot read anything, it returns a 0.
Note: You can now appreciate that any database management application in C must
make use of fread() and fwrite() functions, since they store numbers more efficiently,
and make writing/reading of structures quite easy. Note that even if the number
belonging to the structures increases, the format of fread() and fwrite()remains
same.
The following application uses a menu driven program. It has a provision to Add,
Modify, List and Delete records, the operations that are common in any
database management.
The following comments would help you in understanding the program easily.
Addition of records must always take place at the end of existing records in the file,
much in the same way you would add new records in a register manually.
Listing records means displaying the existing records on the screen. Naturally,
records should be listed from the first record to last record.
In modifying records, first we must ask the user which record he intends to modify.
Instead of asking the record number to be modified, it would be more meaningful to
ask for the name of the employee whose record is to be modified. On modifying
the record, the existing record gets overwritten by the new record.
In deleting records, except for the record to be deleted, rest of the records must first
be written to a temporary file, then the original file must be deleted, and the
temporary file must be renamed back to original.
Observe carefully the way the file has been opened, first for reading and writing, and
if this fails(the first time you run this program it would certainly fail, because that time
there is no data file existing), for writing and reading. It is imperative that file should be
opened in binary mode.
Note that the file is being opened only once and being closing only once, which is
quite logical.
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<string.h>
main( )
{
FILE *fp,*ft;
char another, choice;
struct emp
{
char name[40];
int age;
float bs;
};
struct emp e;
char empname[40];
fp=fopen(“EMP.DAT”, “rb+”);
if (fp==NULL)
{
fp=fopen(“EMP.DAT”, “wb+”);
if(fp==NULL)
{
choice=getche();
switch(choice)
{
case „1‟:
fseek(fp,0,SEEK_END);
another = ‟Y‟;
while(another==‟Y‟)
{
printf(“\n Enter name,age and basic sal. ”);
scanf(“%s %d %f”,e.name, &e.age, &e.bs);
fwrite(&e,sizeof(e), 1, fp);
printf(“\n Add another Record(Y/N) ”);
fflush(stdin);
another = getche( );
}
break;
case „2‟:
rewind(fp);
while (fread(&e,sizeof(e),1,fp)==1)
printf(“%s %d %f\n”,e.name,e.age, e.bs);
break;
case ‟3‟:
another = ‟Y‟;
while (another==‟Y‟)
{
printf(“\n Enter name of employees to modify ”);
scanf(“%s”,empname);
rewind(fp);
while(fread(&e, sizeof(e), 1,fp)==1)
{
if(strcmp(e.name,empname)==0)
{
printf(“\nEnter new name, age & bs ”);
scanf(“%s %d %f”, e.name, &e.age, &e.bs);
fseek(fp, -sizeof(e), SEEK_CUR);
fwrite(&e, sizeof(e), 1, fp);
break;
}
ft = fopen(“TEMP.DAT”, “wb”);
rewind(fp);
while(fread(&e, sizeof(e),1,fp)==1)
{
if (strcmp(e.name,empname)!=0)
fwrite(&e, sizeof(e), 1, ft);
}
fclose(fp);
fclose(ft);
remove(“EMP.DAT”);
rename(“TEMP.DAT”,”EMP.DAT”);
fp = fopen(“EMP.DAT”, “rb+”);
case ‟0‟:
fclose(fp);
exit(1);
}
}
}
To understand how this program works, you need to be familiar with the concept
of pointers.
The rewind () function places the pointer to the beginning of the file, irrespective
of where it is present right now.
Note that pointer movement is of utmost importance since fread always reads that
record where the file pointer is currently placed. Similarly, fwrite() always writes
the record where the file pointer is currently placed.
The fseek() function lets us move the file pointer from one place to another. In the
program above, to move the pointer to the previous record from its current position,
we used the function,
fseek(fp,-sizeof(e), SEEK_CUR);
Here, -sizeof (e) moves the pointer back by sizeof(e) bytes from the current position.
SEEK_CUR is a macro defined in “stdio.h”
Similarly, the following fseek() would place the pointer beyond the last record in the
file. in fact –sizeof (e) or 0 are just the offsets which tell the compiler by how many
bytes
should the pointer be moved from a particular position. The third argument could be
either SEEK_END, SEEK_CUR or SEEK_SET all these act as reference from which
the pointer should be offset. SEEK_END means move the pointer from the end of
the file, SEEK_CUR means move the file in reference to its current position and
SEEK_SET means move the pointer with reference to the beginning of the file.
if we wish to know where the pointer is positioned right now, we can use the function
ftell(). It returns this position as a long int which is an offset from the beginning of the
file. the value returned by ftell() can be used in subsequent calls to fseek(). A
sample call to ftell( ) is shown below:
position=ftell(fp);
Revision Exercises
fp = fopen(strcpy(str,”ENGINE.C”), “W”);
fclose(fp);
return 0;
}
(b)
#include<stdlib.h>
#include<stdio.h>
main( )
{
FILE *fp;
char c;
fp = fopen(strcpy(str,”ENGINE.C”), “W”);
fclose(fp);
fp = fopen(“TRY.C”,”r”);
if(fp=NULL)
{
printf(“Cannot open file”);
exit(1);
}
while((c = getch(fp)) ! = EOF)
putch(c);
fclose(fp);
return 0;
}
(c)
#include<stdio.h>
main( )
{
FILE fp,*fs,*ft;
char str[80];
fp = fopen(“TRIAL.C”, “r”);
while(fgets(str,80,fp) != EOF)
puts(str);
return 0;
}
INSTRUCTIONS:
Question One
(a) What do you understand by „structured programming‟?
(3 marks)
(4 marks)
(b) C language is said to be both portable and efficient. Explain.
Question Two
(a) Distinguish between a simple variable and an array variable.
(b) Discuss four fundamental data types in C, giving examples and stating
their conventional storage requirements.
(12 marks)
(c) (i) What is a symbolic constant?
(2 marks)
(ii) What is the advantage of using symbolic constants over direct constants?
(1 mark)
(d) What is a storage class? Explain how any two of storage classes are used in C.
(3 marks)
(7 marks)
(ii) Write a declaration statement that would create a 5-element array variable
named invoice_file from the structure type in b(i).
(2 marks)
(c) How is a structure different from a union? (2 marks)
(d) (i) What is a user defined data type? (2 marks)
(ii) Using a user defined type named invoices set up the structure template
in b(i) above. Show how you can set two simple structure variables
invoice1, invoice2 using the new type.
(4 marks)
Question Four
(a) Outline the stages of developing a working program in C. (14 marks)
(ii) A program may compile successfully but fail to generate desired results.
Why?
(2 marks)
(c) Kelly encountered the following error messages on compiling a program:
(i) Misplaced else
(ii) Statement missing
What advice would you offer him to debug the above errors?
(2 marks)
Question Five
(a) (i) C programs are basically made up of functions, one of which is called main.
State three advantages offered by functions in C programs.
(3 marks)
(ii) What is a function prototype?
(2 marks)
(b) Write a program that requests two integers values and outputs the larger
value on the screen. Use a function to perform the comparison of the two
integers to determine the larger one. The main function should pass the
entered values to this function.
(10 marks)
(c) Suggest the output of the following program.
#include <stdio.h>
int mult(int);
main()
{
int a, count;
for(count=1; count <=5; count++)
{
a = mult(count);
printf(“\n %d”, a);
}
}
Question Six
(a) Muajiri Company Ltd uses the following PAYE (Pay As You Earn) percentage tax
rates for all its employees salary categories.
(The rates are exclusive of the upper boundary salary figures for categories
2,3,4,5,6) The following standard deductions apply to all employees.
N.S.S.F = Ksh. 80.00
N.H.I.F = Ksh. 200.00
The overtime rate is Ksh. 300 for the first 50 hours an employee has
worked overtime. Any extra overtime hour is paid at Ksh. 350.
At the end of the month, the payroll clerk runs a payroll program though which
he enters each employee‟s basic salary into the computer and overtime hours
worked as recorded in a claims form filled by the employee. The computer in
turn adds up the basic salary and the overtime pay (if any) to get the gross pay.
The computer then determines the PAYE amount payable from the gross pay.
Finally the employee‟s net pay is calculated using the formula:
Required:
Write a program that performs the above mentioned payroll activities for a
single employee and outputs the following on the screen:
- Gross pay
- PAYE amount
- Net pay
(15 marks)
delta + = pica;
printf(“ \n %d “, delta);
}
pica++;
}
}
(5 marks)
Question Seven
(a) Give the meaning of each of the following terms, giving examples.
(i) Escape sequence
(ii) Recursion
(iii) Binary operator
(iv) Conditional expression
(8 marks)
(b) Interpret the following statements:
(i) float sigma(int p, float s);
(ii) double *meta(float n, float m);
(iii) char char_value, *pc; pc = &char_value;
(iv) int nums[] = {34, 45, 67, 90, 57};
(4 marks)
(c) s and t are integers with values 500 and 800 and stored at memory locations
1200 and1205 respectively. ps and pt are integer pointers to s and t
respectively. Give the results of:
(i) *ps + *pt
(ii) *ps++
(iii) (*pt)++
(3 marks)
(d) Write a program using a for loop that counts down from 10 down to 0, displaying
only the even numbers in this range. The numbers should be displayed using
a pointer.
(5 marks)
Question Eight
(a) State with examples, four types of operators used in C.
(4 marks)
(b) List three types of unary operators. Give an expression in each case to
show how they are used.
(6 marks)
(c) The following table shows Kenya‟s average exports (in tonnes) of
five
commodities over four years.
1974 1975 1976 1977
TEA 18000 19450 23890 28820
COFFEE 20000 27000 29000 33452
SISAL 3400 4501 3890 3973
SUGAR 6500 7200 8100 8805
FRUITS 12780 13210 14300 15302
Bibliography
nd
Gottfried, Byron S. Schaum’s Outlines programming in C, 2 Ed. Tata McGraw Hill
1996.
rd
Kanetkar, Yashavant. Let us C, 3 Ed. New Delhi: BPB 1999.
st
Kanetkar, Yashavant. Working with C.1 Ed. New Delhi: BPB 1994.
nd
Schild, Herbert. Teach Yourself C 2 Ed. Osborne McGraw-Hill 1994.
st
Waite, Mitchel. Prata, Stephen. C Step by Step 1 Ed. The Waite Group 1989.
Index
M
G
MSDOS, 1
getc, 99 Multi dimensional arrays, 62
getchar, 100
N
getche, 106, 109, 111, 114, 115
Nesting, 47
gets, 70, 71, 74
NULL, 97, 98, 100, 101, 102, 104, 105,
106, 107, 108, 110, 112, 113, 117
H
Header file, 8, 72 O
Object code, 2, 3, 4
I
One-dimensional array, 62, 64, 65
if else statement, 36 Operand, 27, 28, 29, 31, 32
if statement, 35, 36, 49 Operator, 9, 27, 29, 30, 31, 32, 34, 45,
47, 76, 77, 78, 85, 122
P 116
short, 2, 5, 15, 29, 58, 76
perror, 104
signed, 4, 14, 15
Pointer, 76, 80
sizeof, 4, 27, 31, 32
Preprocessor directive,
Source code, 2, 3
8 putc, 99
Start up code, 4
putchar, 100, 101, 103
static, 5, 12, 20, 22, 23, 62, 63, 64, 78,
R 85
Recursion, 57, 122 stdin, 106, 107, 109, 111, 114, 115
register, 5, 20, 22 Storage class, 20, 118
S
SEEK_CUR, 114,
strcat, 72, 73
strcmp, 72, 73
strcpy, 38, 72,
74 stream, 96,
97
structure, 35, 39, 40, 41, 47, 50, 74,
83,
84, 85, 86, 87, 91, 92, 93, 94, 95,
119 switch, 5, 13, 39, 40, 41
Symbolic constant, 24, 27
T
Type modifier, 15
Type specifier, 7, 14,
53 typedef, 5, 90, 91,
95
U
Unary Operators,
32
Union, 5, 91, 92, 93, 94,
119 unsigned, 4, 14, 15,
18, 58
while statement, 42