0% found this document useful (0 votes)
65 views

C Programming

Uploaded by

Ĺalam Šainaťh
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
65 views

C Programming

Uploaded by

Ĺalam Šainaťh
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 373

C Programming

C Programming ver 2.0 Page 1


Chapter 1
Introduction

C Programming ver 2.0 Page 2


Objectives

In this session, you will learn to:


• Describe the evolution of the C programming language
• Describe C as a second-generation as well as a third-
generation language
• State the data types in C
• Write simple C functions for input and output
• Write C functions that employ conditional constructs
• Write C functions that employ iterative constructs

C Programming ver 2.0 Page 3


The Genesis of C

• Multics (Multiplexed Information and Computing


Service) is a mainframe timesharing operating system
begun in 1965.

• Multics started out as a joint venture between MIT,


General Electric, and Bell Labs. It was a research project,
and was an important influence on operating system
development.

• By 1969, Bell Labs management, and even the researchers


came to believe that the promise of Multics could be
fulfilled only too late, and too expensively.

C Programming ver 2.0 Page 4


The Genesis of C

• Even before the GE-645 Multics machine was removed


from the premises of Bell Labs, an informal group, led by
Ken Thompson, had begun investigating alternatives.

• In 1969, Ken Thompson and Dennis Ritchie designed a


file system for the Bell Labs in order to provide a more
convenient environment for programming.

• This file system evolved into an early version of the UNIX


Operating System.

C Programming ver 2.0 Page 5


The Genesis of C

• This file system was implemented on a PDP-7 computer,


and in 1971, on a PDP-11 computer.

• Not long after Unix first ran on the PDP-7 in 1969, Doug
McIlroy created the system’s first high-level language, an
implementation of McClure’s TMG (TransMoGrifiers).

• TMG is a language for writing compilers in a top-down,


recursive-descent style that combines context-free syntax
notation with procedural elements.

C Programming ver 2.0 Page 6


The Genesis of C

• Challenged by McIlroy’s feat in reproducing TMG,


Thompson decided that Unix – possibly it had not even
been named yet – needed a systems programming language.

• In a rapidly scuttled attempt at Fortran, he created, instead,


a language of his own, which he called B.

• Language B was in turn influenced by BCPL (Basic


Control Programming Language) of Martin Richards. Its
name most probably represents a contraction of BCPL.

C Programming ver 2.0 Page 7


The Genesis of C

• In 1971, Dennis Ritchie made extensions to language B,


and also rewrote its compiler to generate PDP-11 machine
instructions instead of threaded code.

• Thus, the transition from B to C was contemporaneous


with the creation of a compiler capable of producing
programs fast and small enough to compete with assembly
language.

• By early 1973, the essentials of modern C were complete.

C Programming ver 2.0 Page 8


The Genesis of C

• The language and compiler were strong enough to permit


the rewriting of the Unix kernel for the PDP-11 in C
during the summer of 1973.

• Also, during this period, the compiler was retargeted to


other nearby machines, particularly the Honeywell 635,
and IBM 360/370.

• Because the language could not live in isolation, the


prototypes for the modern libraries of the C language were
developed.

C Programming ver 2.0 Page 9


Nature of the C Language

• From its evolution, it was natural for C to exhibit the


powerful low-level features of second generation languages
like pointers, bit manipulation etc.

• It also supports conditional constructs, loop constructs, a


rich list of operators, and a variety of data types that is so
typical of any third generation language.

• The combined features of second and third generation


language make C a very powerful and a flexible language.

C Programming ver 2.0 Page 10


Nature of the C Language

• These features of C make it possible to use the language


for systems programming like development of compilers,
interpreters, operating systems, graphics and general
utilities.

• It is also ideal for a host of applications in the commercial


environment.

• Much of the Unix operating system has been written in the


C language.

C Programming ver 2.0 Page 11


Block Structured Nature of C

• The basic unit of code in C is written as a C function, that


can in turn be used as building blocks to write more C
functions, thus facilitating modular programming.

• C provides all features of structured programming such as


writing programs as functions, functions returning values,
functions defining its own local variables etc.

• C language offers only a handful of functions that form the


core of the language; rest of the functions, available as part
of the language libraries, are developed using the core
functions, thus expanding the scope of the language.

C Programming ver 2.0 Page 12


Block Structured Nature of C

• This promotes functionally cohesive code and therefore,


facilitates reusability.

• Thus standalone functions can be written as part of a


library that can be deployed in other applications.

C Programming ver 2.0 Page 13


The C Language: Features

• Pointers: In addition to referencing a memory location


through a variable name, the C language allows reference to
a memory location by its internal address, or byte number
called a pointer.

• Memory Allocation: Generally, in most programming


languages, memory is assigned to a variable name at the
time of definition. C allows dynamic allocation of memory;
i.e., a C program can request the operating system to release
memory for the use of the program at the time of execution.

C Programming ver 2.0 Page 14


The C Language: Features

• Recursion: In C, a function can call itself. Such functions


are called recursive functions.

• Bit Manipulation: C allows manipulation of data in its


lowest form of storage; i.e., it is possible to manipulate the
bits within a byte using bit shift operators (right bit shift,
left bit shift operators), and the bitwise or |, bitwise
exclusive or ^, and the bitwise and & operator.

C Programming ver 2.0 Page 15


The C Language: Features

• Keywords: There are only 32 keywords, i.e., reserved


words that cannot be used as a variable declaration. The
C99 has introduced five additional keywords.

• Library Functions: C is accompanied by a number of


library functions to carry out various commonly used
operations. These functions are not part of the language,
but are supplied as a part of C compiler. Features which
tend to be computer-dependent are generally written as
library functions.

C Programming ver 2.0 Page 16


The Hello World Program

/* Comment statements */ /* The Hello World program */


Preprocessor directives # include <stdio.h>
main() main()
{ {
Program statements; printf(“Hello World\n”);
} }

C Programming ver 2.0 Page 17


Factored Code: An Example

/* Comment statements */ /* A sample C program */


Preprocessor directives # include <stdio.h>
Function prototypes; int sum();
global variable declarations; int a=10, b=20;
main() main()
{ {
local variable declarations; int c;
Program statements; c = sum();
} printf(“%d+%d = %d \n”,a,b,c);
}
[Additional functions ….] int sum()
{
return(a+b);
}

C Programming ver 2.0 Page 18


The C Language Data Types

• In C, all variables must be declared before they are used,


usually at the beginning of a function, before any
executable statements.

• A declaration announces the properties of variables; it


consists of a type name, and a list of variables.

• The type of a variable actually determines the type of


operations that can be performed on a variable of that type.

C Programming ver 2.0 Page 19


Fundamental Data Types

• Fundamental data types are data types implemented at the


lowest level, i.e., those which are used for actual data
representation in memory.

• The fundamental data types are:


– char – for characters and strings
– int – for integers
– float – for numbers with decimals

• Since the fundamental data types are implemented at the


machine level, their storage requirement is machine-
dependent.

C Programming ver 2.0 Page 20


Fundamental Data Types

• The type int means that the variables listed are integers. The
range of both int and float depends on the machine you are
using; 16-bits ints, which lie between -32768 and +32767, are
common, as are 32-bit ints.

• Floating point variables on the other hand, are those that have a
decimal part. A float number is typically a 32-bit quantity, with
at least six significant digits, and magnitude between about 10-38
and 1038.

• Character variables, on the other hand, occupy a single byte of


storage.

C Programming ver 2.0 Page 21


Variations on Fundamental Data Types

• C provides several other data types besides int and float,


including:
• short: short integer
• long: long integer
• double: double-precision floating point

• The size of these variables is also machine-dependent.

C Programming ver 2.0 Page 22


Defining Data

• The general format for defining a variable of a data type is


[data type] [variable name]

• All data is normally defined at the beginning of a function.

• The definition:
char var;
defines a memory location of size one byte, of character type,
referred to as var.

C Programming ver 2.0 Page 23


Defining Data

Data Definition Data Memory Size Value


Type Defined Assigned
char x, y char x 1 byte -
y 1 byte -

int m; int m 4 bytes 22


int a, m=22;
a 4 bytes -

float num float num 4 bytes -


float num1= 9.67 float num1 4 bytes 9.67

C Programming ver 2.0 Page 24


Defining Data

• The definition:
• char var; defines a variable location called var, which is one
byte in size, and can therefore hold only one character.

• To define a memory location that can store characters in


contiguous locations as in a name, and addressable by one
variable name, you would need to use the following definition:
• char name[10];

• The above definition defines a memory location called name


containing 10 contiguous bytes for storing up to 9 valid
characters.

C Programming ver 2.0 Page 25


The Standard C Environment

• The C environment assumes the keyboard to be the


standard input device referred to as stdin

• The VDU is assumed to be the standard output device


referred to as stdout

• The VDU also serves as the standard error device, and is


referred to as stderr

C Programming ver 2.0 Page 26


Input/Output Functions

• C supports Input/Output operations through functions


written in C, and that are part of the standard C library
along with other functions.

• These input/output functions may be incorporated into any


program by a programmer.

• Any input or output operation happens as a stream of


characters. The standard I/O functions are available for
character-based I/O, or for string-based I/O.

C Programming ver 2.0 Page 27


Buffered I/O

• The standard I/O functions are buffered, i.e., each device


has an associated buffer through which any input or output
operation takes place.

• After an input operation from the standard input


device has occurred, care must be taken to clear the
standard input buffer. Otherwise, the previous contents
of the buffer may interfere with subsequent input.

• After an output operation, the buffer need not be cleared


since subsequent output data will flush the previous buffer
contents.

C Programming ver 2.0 Page 28


Character-Based I/O

• The function getch( ) is used to accept a character from


standard input. By default, it accepts characters from the
keyboard, and returns the character input from the
keyboard.

• The function putch( ) displays the character on to standard


output. It takes one argument, namely, the character to be
output.

• The function fflush( ) clears the buffer associated with the


particular device.

C Programming ver 2.0 Page 29


Character-Based I/O: An Example

• #include <conio.h>
• #include <stdio.h>
• main( )
• {
• char ch;
• ch = getch( );
• fflush(stdin);
• putch(ch);
• }

C Programming ver 2.0 Page 30


Character-Based I/O

• The macro getchar( ) by default accepts a character from


the keyboard. Hence, it does not need any parameters.

• The macro putchar( ) is used to display the character on to


standard output. It takes the character to be output as an
argument.

C Programming ver 2.0 Page 31


Character-Based I/O: An Example

• #include <stdio.h>
• main( )
• {
• char ch;
• ch = getchar( );
• fflush(stdin);
• putchar(ch);
• }

C Programming ver 2.0 Page 32


String-Based I/O

• The function gets( ) accepts as a parameter, a string


variable, or a string literal (enclosed in double quotes)
from the keyboard.

• The function puts( ) accepts a string variable, or a string


literal to be displayed to standard output.

• After displaying the output, the puts( ) function causes the


cursor to be positioned at the beginning of the next line.

C Programming ver 2.0 Page 33


String-Based I/O

• #include <stdio.h>
• #include <conio.h>
• main( )
• {
• char str[11];
• puts("Enter a string of maximum 10 characters");
• gets(str);
• fflush(stdin);
• puts(str);
• }

C Programming ver 2.0 Page 34


Conditional Constructs

• The C language provides different conditional constructs


for evaluating a condition in a program.

• The relational operators required for evaluating the


conditions are similar to those in other third-generation
languages, though the symbols are different.

C Programming ver 2.0 Page 35


Conditional Constructs

• Relational Operators:

Operator Meaning
== Equal to

!= Not equal to

< Less than

> Greater than

<= Less than or equal to

>= Greater than or equal to

C Programming ver 2.0 Page 36


The if-else Construct

• The following function checks whether the character start


• entered by the user is a star (*) character.
• #include <stdio.h>
• #include <conio.h> ch = ‘ ‘
• main( )
• {
• char ch; Input ch
• ch = getchar( );
• fflush(stdin);
• if (ch == '*') is ch = ‘*’ Print *
• puts ("You have entered the star character");
• else
• puts ("You have not entered the star character");
Not a *
• }

stop

C Programming ver 2.0 Page 37


The if-else Construct

• The earlier function can also be alternately written as:


• #include <stdio.h>
• #include <conio.h>
• main( )
• {
• char ch;
• ch = getchar( );
• fflush(stdin);
• if (ch == '*')
• puts ("You have entered the star character");
• else
• puts ("You have not entered the star character");
• }

Copyright C Programming ver 2.0 Page 38


Cascading if-else Construct

• The cascading if-else construct is also known as the


multiple if-else construct.

• On the first condition evaluating to false, the else part of


the first condition consists of another if statement that is
evaluated for a condition.

• If this condition evaluates to false, the else part of this if


condition consists of another if statement that is evaluated
for a condition, and so on.

Copyright C Programming ver 2.0 Page 39


Cascading if-else Construct

• #include <stdio.h>
• main( )
• {
• char chr;
• chr = getchar( );
• if (chr == '0')
• puts("You entered the number 0");
• else if (chr == '1')
• puts("You entered the number 1");
• else if (chr == '2')
puts("You entered the number 2");

Copyright C Programming ver 2.0 Page 40


Cascading if-else Construct

• else if (chr == '3')


• puts("You entered the number 3");
• else if (chr == '4')
• puts("You entered the number 4");
• else if (chr == '5')
• puts("You entered the number 5");
• else if (chr == '6') no
• puts("You entered the number 6"); ”
• else if (chr == '7')
yes
• puts("You entered the number 7");
• else if (chr == '8') no

• puts("You entered the number 8");
• else if (chr == '9') yes
• puts("You entered the number 9"); no
• else ”
• puts("You did not enter a number"); yes
• }

Copyright C Programming ver 2.0 Page 41


Nested if Construct

• A nested if statement is
encountered if the statement to be
executed after a condition
evaluates to true is another if
statement.

no
• Both the outer if statement and the ye

s
inner if statement have to evaluate
ye
to true for the statement following s
no

the inner if condition to be


executed.

Copyright C Programming ver 2.0 Page 42


Nested if Construct: Example

• The following program determines whether the character entered is an


uppercase or a lowercase alphabet.
• #include<stdio.h>
• main( )
• {
• char ch;
• ch = getchar( );
• fflush(stdin);
• if (ch >= 'A')
• if (ch <= 'Z')
• puts ("Its an Uppercase alphabet");
• else if (ch >= 'a')
• if (ch <= 'z')

Copyright C Programming ver 2.0 Page 43


Nested if Construct: Example

• puts ("It’s a lowercase alphabet");


• else
• puts ("Input character > z");
• else
• puts ("Input character greater than Z but less than a");
• else
• puts ("Input character less than A");
• }

Copyright C Programming ver 2.0 Page 44


Using Braces to Improve Readability

• #include< stdio.h>
• main( )
• {
• char ch;
• ch = getchar( );
• fflush(stdin);
• if (ch >= ‘A’)
• {
• if (ch <= ‘Z’)
• puts (Its an Uppercase alphabet”);
• else if (ch >= ‘a’)
• {
• if (inp <= ‘z’)
• puts (“It’s a lowercase alphabet”);
• else
• puts (“Input character > z”);
• }

Copyright C Programming ver 2.0 Page 45


Using Braces to Improve Readability

• else
• puts (“Input character greater than Z but less than a”);
• }
• else
• puts (“Input character less than A”);
• }

Copyright C Programming ver 2.0 Page 46


The switch-case Conditional Construct

• The switch-case conditional construct is a more structured


way of testing for multiple conditions rather than resorting
to a cascading, or a multiple if statement.

• A switch-case statement makes for better readability, and


hence makes code better understandable.

• The switch-case statement is used in situations where


based on the value of a variable, certain actions need to be
taken.

Copyright C Programming ver 2.0 Page 47


The switch-case Conditional Construct

• switch ( ) specifies the variable name which has to be


compared with the specified cases. The variable may be an
integer, or a character variable.

• The case statements specify values which may be integer,


or character constants. They also specify the action to be
taken if the value specified in the case statement matches
with the value of the switch variable.

• After the action for a particular case value is specified, the


break statement is used to bring control out of the switch
block of statements, and to the statement immediately
following the switch block.
Copyright C Programming ver 2.0 Page 48
The switch-case Conditional Construct

• If the break statement is not specified after the statements


associated with each case statement, then all the
statements associated with the other case statements will
be executed.

• This will be in addition to the statements associated with


the case statement whose value evaluated to the value of
the variable specified in the switch statement.

• This is because when one of the case statements is


evaluated as true, the action statements are executed until a
break statement sends control out of the switch block of
statements, or the switch block comes to an end.
Copyright C Programming ver 2.0 Page 49
The switch-case Conditional Construct

• The default statement is optional, and is used for handling


situations where none of the case statements are evaluated
as true.

• The case and default statements can occur in any order.


• #include <stdio.h>
• main( )
• {
• char chr;
• chr = getchar( );
• fflush (stdin);

Copyright C Programming ver 2.0 Page 50


The switch-case Conditional Construct

• switch ( chr)
• {
• case '0' : puts( "you entered 0");
• break;
• case '1' : puts( "you entered 1");
• break;
• case '2' : puts( "you entered 2");
• break;
• case '3' : puts( "you entered 3");
• break;
• case '4' : puts( "you entered 4");
• break;
• case '5' : puts( "you entered 5");
• break;
• case '6' : puts( "you entered 6");
• break;

Copyright C Programming ver 2.0 Page 51


The switch-case Conditional Construct

• case '7‘ : puts( "you entered 7");


• break;
• case '8' : puts( "you entered 8");
• break;
• case '9' : puts( "you entered 9");
• break;
• default : puts ("You did not enter a number");
• }
• }

Copyright C Programming ver 2.0 Page 52


Iterative Constructs - The while Loop

• In a while loop, the loop condition is


written at the top followed by the body
of the loop. false
Evaluate Condition

• Therefore, the loop condition is true


evaluated first, and if it is true, the loop
body is executed. Execute body of loop

• After the execution of the loop body,


the condition in the while statement is
evaluated again. This repeats until the
condition becomes false.

Copyright C Programming ver 2.0 Page 53


Iterative Constructs - The while Loop

• #include <stdio.h>
• /* function to accept a string and display it 10 times */
• main( )
• {
• int counter=0;
• char message[10];
• gets( message);
• fflush( stdin);
• while (counter <= 9)
• {
• puts( message);
• putchar ('\r');
• counter = counter + 1;
• gets( message);
• fflush (stdin); } }

Copyright C Programming ver 2.0 Page 54


Iterative Constructs – The do…while loop

• In this loop construct, the body of the loop


comes first followed by the loop condition at
the end.
Execute body of loop
• Therefore, when this loop construct is used, the
body of the loop is guaranteed to execute at
least once.

false
• The loop is entered into straightaway, and after Evaluate Condition
the first execution of the loop body, the loop
condition is evaluated. true

• Subsequent executions of the loop body would


be subject to the loop condition evaluating to
true.

Copyright C Programming ver 2.0 Page 55


Iterative Constructs – The do…while loop

• /* This is an example of a do-while loop */


• #include <stdio.h>
• main()
• {
• int i;
• i = 0;
• do {
• printf("The value of i is now %d\n",i);
• i = i + 1;
• } while (i < 5);
• }

Copyright C Programming ver 2.0 Page 56


Iterative Constructs – The for loop

• The for loop construct is by far the most powerful and


compact of all the loop constructs provided by C.

• This loop keeps all loop control statements on top of the


loop, thus making it visible to the programmer.

• The for loop works well where the number of iterations of


the loop is known before the loop is entered into.

Copyright C Programming ver 2.0 Page 57


Iterative Constructs – The for loop

• The header of the loop consists of three parts separated by


semicolons:
– The first part is executed before the loop is entered. This is usually
the initialization of the loop variable.
– The second is a test. The loop is terminated when this test returns a
false.
– The third part is a statement to be run every time the loop body is
completed. This is usually an increment of the loop counter.

Copyright C Programming ver 2.0 Page 58


Iterative Constructs – The for loop

• #include <stdio.h>
• /* this function displays a message 10 times */
• main( )
• {
• int i;
• char message[10];
• gets (message);
• fflush(stdin);
• for( i = 0; i <= 9; i = i + 1)
• {
• puts( message);
• }
• }

Copyright C Programming ver 2.0 Page 59


Control of Loop Execution

• A loop construct, whether while, or do-while, or a for loop


continues to iteratively execute until the loop condition
evaluates to false.

• But there may be situations where it may be necessary to


exit from a loop even before the loop condition is
reevaluated after an iteration.

• The break statement is used to exit early from all loop


constructs (while, do-while, and for).

Copyright C Programming ver 2.0 Page 60


Control of Loop Execution

• The continue statement used in a loop causes all


subsequent instructions in the loop body (coming after the
continue statement) to be skipped.

• Control passes back to the top of the loop where the loop
condition is evaluated again.

• In case of a continue statement in a for loop construct,


control passes to the reinitialization part of the loop, after
which the loop condition is evaluated again.

Copyright C Programming ver 2.0 Page 61


Summary

In this session, you learnt to:


• Describe the evolution of the C programming language
• Describe C as a second-generation as well as a third-
generation language
• State the data types in C
• Write simple C functions for input and output
• Write C functions that employ conditional constructs
• Write C functions that employ iterative constructs

Copyright C Programming ver 2.0 Page 62


Copyright C Programming ver 2.0 Page 63
Chapter 2
One-Dimensional Arrays

Copyright C Programming ver 2.0 Page 64


Objectives

In this session, you will learn to:


• Write compound conditions employing the logical
operators
• Write functions that perform formatted input/output
• Declare, initialize, manipulate, and address one-
dimensional arrays

Copyright C Programming ver 2.0 Page 65


Writing Compound Conditions Using Logical
Operators

Operator Notation

NOT !

AND &&

OR ||

Copyright C Programming ver 2.0 Page 66


The Logical AND Operator

• The result of a logical AND operation is true if both


operands are true.

• It has the general form:


• expression1 && expression2

• Which evaluates to 1 (true) if both expression1 and


expression2 are 1 (true); otherwise evaluates to false even
if one of them evaluates to 0 (false).

Copyright C Programming ver 2.0 Page 67


The Logical AND Operator

• Some examples of valid AND expressions are:

• a && b;

• (a < b) && (c < d)

Copyright C Programming ver 2.0 Page 68


The Logical OR Operator

• The result of a logical OR operation is false only if both


the operands are false.

• It has the general form:


• expression1 || expresssion2

• which evaluates to 1 (true) if either or both expressions


are 1, otherwise evaluates to 0 (false).

Copyright C Programming ver 2.0 Page 69


The Logical OR Operator

• Some examples of valid OR expressions:


• a || b
• (a < b) || (c < d)

• Some examples of invalid OR expressions:


• a || /* one operand missing */
• a | | b /* space not allowed */

Copyright C Programming ver 2.0 Page 70


The Logical NOT Operator

• C also includes the operator ! that negates the value of a


logical expression; i.e., it causes an expression that is
originally true to become false, and vice-versa.

• This operator is referred to as the logical negation, or


complement, or logical NOT.

• It has the general form:


• !expression
• which evaluates to 1 (true) if the expression is 0, otherwise
evaluates to 0 (false)

Copyright C Programming ver 2.0 Page 71


The Logical NOT Operator

• For example, the expression !(k == 4) is true if the value of


k is not equal to 4, and false otherwise.

• Some examples of valid ! expressions:


• !a
• !(x + 7)

• Some examples of invalid ! expressions:


• a! /* out of order */

Copyright C Programming ver 2.0 Page 72


Logical Expressions

Values of Logical Expressions

a b a && b a || b

0 0 0 0

0 1 0 1

1 0 0 1

1 1 1 1

Copyright C Programming ver 2.0 Page 73


Formatted I/O

• C provides standard functions for performing formatted


input and output. These functions accept as parameters a
format string and a list of variables.

• The format string consists of a specification for each of


the variables in terms of its data type, called the
conversion character, and width of input or output.

Copyright C Programming ver 2.0 Page 74


Formatted Output

• The function printf( ) is used for formatted output to


standard output based on a format string.

• The format string, along with the data to be output, are


the parameters to the printf( ) function.

• The syntax of the printf( ) function is:


• printf( “format string”, var1,var2…..)

• Format string is a string containing the format


specification introduced by the character %, and ended by
a conversion character.

Copyright C Programming ver 2.0 Page 75


Formatted Output

• An example:
• printf(“%c\n”, var);
• The conversion characters and their meanings are:

Conversion character Meaning


d The data is converted to decimal
c The data is treated as a character
s The data is a string, and characters
from the string are printed until a null
character is reached, or until the
specified number of characters have
been exhausted
f The data is output as float or double
with a default precision of 6

Copyright C Programming ver 2.0 Page 76


Formatted Output

• Between the % character and the conversion character, there may be:

A minus sign Implying left adjustment of data
A digit Implying the minimum width in which the data is to be output. If
the data has larger number of characters than the specified width,
the width occupied by the output is larger. If the data consists of
fewer characters than the specified width, it is padded to the
right (if minus sign is specified), or to the left (if no minus sign
is specified). If the digit is prefixed with a zero, the padding is
done with zeroes instead of blanks
A period Separates the width from the next digit.
A digit Specifying the precision, or the maximum number of characters
to be output
l To signify that the data item is a long integer, and not an integer.

Copyright C Programming ver 2.0 Page 77


Formatted Output

Format String Data Output


%2d 4 |4|
%2d 224 |224|
%03d 8 |008|
%-2d 4 |4 |
%5s Sherlock Holmes | Sherlock Holmes|
%15s Sherlock Holmes | Sherlock Holmes |
%-15s Sherlock Holmes | Sherlock Holmes |
%f 22.44 |22.440000|

Copyright C Programming ver 2.0 Page 78


Data Conversion Using Format String

• A variable of a data type can be output as another data


type using the conversion character.

• #include<stdio.h>
• main( )
• {
• int number = 97;
• printf("Value of num is %d\n", number);
• printf("The Character equivalent of %d is %c\n", number, number);
• }

Copyright C Programming ver 2.0 Page 79


Formatted Input

• The function scanf( ) is used for formatted input, and


provides many of the conversion facilities of printf( ).

• The syntax of the function scanf( ) is:


• scanf( format string, var1, var2….)

• The scanf( ) function reads and converts characters from


standard input according to the format string, and stores
the input in memory locations specified by the other
arguments.

Copyright C Programming ver 2.0 Page 80


Formatted Input

• #include<stdio.h>
• main( )
• {
• char name[10];
• int age = 0;
• char gender = ' ';
• scanf ("%7s %c %2d", name, &gender, &age);
• fflush(stdin);
• printf( "% s %c %d", name, gender, age);
• }

C Programming ver 2.0 Page 81


String Input Using scanf( )

• Remember that while accepting strings using scanf( ), a


space is considered as a string terminator. Hence, scanf( )
cannot be used to accept strings with embedded spaces.

• #include<stdio.h>
• main( )
• {
• char string[40];
• printf("Enter a string of maximum 39 characters");
• scanf("%s", string);
• fflush(stdin);
• printf("%s", string);
• }

C Programming ver 2.0 Page 82


One-Dimensional Arrays

• An array can be defined as a collection of elements of


identically typed data items that are stored contiguously in
memory.

• Each array element shares the same name as the array


name, but distinguishes itself from other elements in the
array using a subscript, or an index.

• The subscript, or the index of each array element is


determined based on the number of offset positions it is
from the starting position. The starting offset is taken as 0.

Copyright C Programming ver 2.0 Page 83


Array Representation

• The declaration int a[10]; defines an array a of size 10, as a block of 10


contiguous elements in memory.

a

a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9]

Copyright C Programming ver 2.0 Page 84


Character Arrays

• To define a character array for storing a string of n characters, we


would need to define a character array of size n+1 characters.

• This is because all character arrays are terminated by a NULL


character (‘\0’).

• To define a character array called name for storing a ten-character


name, we will define the array as:
• Char name[11];

• where name[0] through name[9] will contain the characters


comprising the name, and name[10] will store the NULL character.

Copyright C Programming ver 2.0 Page 85


Representation of a Character Array

name

a b c d e f g h i j \0
name[0] name[1] name[2] name[3] name[4] name[5] name[6] name[7] name[8] name[9] name[10]

Copyright C Programming ver 2.0 Page 86


Array Initialization

• Since an array is a set of elements located at contiguous


memory locations, its initialization involves moving
element by element, or one data at a time into the array.

• An array is initialized by specifying each element in an


initialization list separated by commas.

• The size of the array, in this case, may or may not be


specified. The number of elements stored in the array
determines its size.

Copyright C Programming ver 2.0 Page 87


Array Initialization Syntax

• A character array needs a string terminator, the NULL


character (‘\0’) as the last character, whereas integer and
float arrays do not need a terminator.

• #include<stdio.h>
• main( )
• {
• char array1[ ] = {‘A’, ‘R’, ‘R’, ‘A’, ‘Y’, ‘\0’};
• char array2[ ] = {“ARRAY”};
• char dayofweek[ ] = {‘M’, ‘T’, ‘W’, ‘T’, ‘F’, ‘S’, ‘S’, ‘\0’};
• float values[ ] = {100.56, 200.33, 220.44, 400.22, 0};
• }

Copyright C Programming ver 2.0 Page 88


Array Processing

• #include<stdio.h>
• main( )
• {
• char array1[ ] = {‘A’, ‘R’, ‘R’, ‘A’, ‘Y’, ‘\0’};
• char array2[ ] = {“ARRAY”};
• char dayofweek[ ] = {‘M’, ‘T’, ‘W’, ‘T’, ‘F’, ‘S’, ‘S’, ‘\0’};
• float values[ ] = {100.56, 200.33, 220.44, 400.22, 0};
• int i = 0;
• printf( “String 1 is %s\n”, array1);
• printf( “String 2 is %s\n”, array2);
• for( i = 0; dayofweek[i] != ‘\0’; i = i +1)
• printf ( “The Day %d in a week is %c\n”, i + 1, dayofweek[i];
• for( i = 0; values[i] != 0; i = i +1)
• printf ( “The amount %d in a week is %f\n”, i + 1, values[i];
• }

Copyright C Programming ver 2.0 Page 89


Array Initialization Using a for Loop

• #include<stdio.h>
• main( )
• {
• int i, num[50];
• for (i = 0; i < 50; i = i + 1)
• {
• num[i] = 0;
• num[i] = i + 1;
• printf("%d\n",i);
• }
• }

Copyright C Programming ver 2.0 Page 90


Array Manipulation Using Subscripts

• #include<stdio.h>
• /* displays each element of the array on a new line */
• main( )
• {
• int i;
• char array[11];
• printf( "enter a string of maximum 10 characters\n");
• gets(array);
• fflush(stdin);
• for (i = 0; array[i] != '\0'; i = i +1)
• printf("Element %d is %c\n", i +1, array[i]);
• }

Copyright C Programming ver 2.0 Page 91


Array Manipulation Using Subscripts

• /* this function finds the length of a character string */


• #include <stdio.h>
• main( )
• {
• int i = 0;
• char string[11];
• printf(“Enter a string of maximum ten characters\n”);
• gets(string);
• fflush( stdin);
• for(i =0; string[i] != ‘\0’; i = i + 1)
• ;
• printf(“The length of the string is %d \n”, i);
• }

Copyright C Programming ver 2.0 Page 92


Array Manipulation Using Subscripts
• /* this function converts a string to upper case */
• #include <stdio.h>
• main( )
• {
• char string[51];
• int i = 0;
• printf("Enter a string of maximum 50 characters\n");
• gets(string);
• fflush(stdin);
• while (string[i] != '\0')
• {
• if(string[i] >= 'a' && string[i] <= 'z')
• { string[i] = string[i] - 32;
• i = i + 1; }
• }
• printf("The converted string is %s\n", string); }

Copyright C Programming ver 2.0 Page 93


Array Manipulation Using Subscripts
• #include <stdio.h>
• main( )
• {
• int i, start_pos, no_of_chars;
• char string[101], substring[101];
• printf("Enter a string of upto 100 characters\n");
• gets(string); fflush( stdin);
• printf("Enter start position\n");
• scanf("%d", &start_pos); fflush(stdin);
• printf("Enter no. of characters to extract\n");
• scanf("%d", &no_of_chars); fflush(stdin);
• start_pos = start_pos -1;
• for (i = 0; i < no_of_chars; i = i + 1, start_pos = start_pos + 1)
• substring[i] = string[start_pos];
• substring[i] = '\0';
• printf("The substring is %s\n", substring);
• }

Copyright C Programming ver 2.0 Page 94


Array Manipulation Using Subscripts
• #include<stdio.h>
• main( )
• {
• int total=0, int_array[20], i = -1;
• do
• {
• i = i + 1;
• printf("Enter number(0 to terminate)\n");
• scanf("%d", &int_array[i]);
• }while (int_array[i] != 0);
• i = 0;
• while (int_array[i] != 0)
• {
• printf("Element number %d is %d\n", i + 1, int_array[i]);
• total = total + int_array[i]; i = i + 1;
• }
• printf("The sum of the numbers in the array is %d \n", total);}

Copyright C Programming ver 2.0 Page 95
Array Addressing

• In the declaration:
• char string[11);
• the name of the array refers to the starting address of the
area that gets allocated for storing the elements of the array.

• Thus, string contains the address of string[0].

• In the aforesaid declaration, string refers to the starting


position of the array, and the subscript refers to the offset
position from the starting position.

Copyright C Programming ver 2.0 Page 96


Array Addressing

string

100

100 101 102 103 104 105 106 107 108 109 110

a b c d e f g h i j \0

0 1 2 3 4 5 6 7 8 9 10

Copyright C Programming ver 2.0 Page 97


Array Addressing

• In the previous declaration, string represents the starting


point of the array, and the subscript refers to the offset
position from the starting point.

• To arrive at the address of the particular element, the


compiler applies the following simple formula:
– starting address of the array + ( offset position * size of data
type)

– Address of element 4 = 100 + ( 3 * 1) = 100 +3 = 103

Copyright C Programming ver 2.0 Page 98


Summary

• In this session, you learnt to:


• Write compound conditions employing the logical operators
• Write functions that perform formatted input/output
• Declare, initialize, manipulate, and address one-dimensional
arrays

Copyright C Programming ver 2.0 Page 99


Copyright C Programming ver 2.0 Page 100
Chapter 3
Two-Dimensional Arrays

Copyright C Programming ver 2.0 Page 101


Objectives

In this session, you will learn to:


• Apply the unary, binary, ternary, compound assignment
operators, increment, and decrement operators
• Use character arithmetic, and understand the rules of
conversion between different data types
• Declare, initialize, manipulate and print from a two-
dimensional array

Copyright C Programming ver 2.0 Page 102


Unary Operators

• Unary operators, as the name suggests, works on one operand


or variable.

• The ++ and the -- operators are examples of unary operators.

• When these operators prefix an operand, they are referred to as


prefix operators, and when they are suffixed to an operand,
they are referred to as postfix operators.

• Prefix and postfix operators, when used in an expression, can


have totally different results, and hence it is necessary to know
their workings.

Copyright C Programming ver 2.0 Page 103


Unary Operators

• Incrementing and decrementing by 1 is such a ubiquitous


operation that C offers the prefix and postfix
implementations of the ++ and the -- operators.

• The expression i = i + 1; can also be written as i++.

• When used as a standalone statement, writing i++, or ++i does


not make any difference at all.

• It is only when they are used as part of an expression that


the prefix and the postfix operators can have totally
different results.

Copyright C Programming ver 2.0 Page 104


Unary Operators

• Consider the following two statements:


• total = i++;
• total = ++i;

• The first statement total = i++; is equivalent to:


• total = i;
• i++;
• This is equivalent to assigning to total the current value of
i, and then incrementing i.

Copyright C Programming ver 2.0 Page 105


Unary Operators

• The second statement total = ++i; is equivalent to:


• i = i + 1;
• total = i;

• This is equivalent to first incrementing the value of i, and


then assigning the incremented value of i to total.

• The same principle holds true when working with the


unary -- operators.

Copyright C Programming ver 2.0 Page 106


Binary Operators

• Binary operators as the name suggests, works on two


operands.

• The binary operators in C (as in other programming


languages) are:
– The add ( + ) operator
– The subtract ( - ) operator.
– The multiply (* ) operator
– The divide ( / ) operator
– The modulo ( % ) operator

Copyright C Programming ver 2.0 Page 107


Binary Operators

• Examples of binary operators:


• int x, y, z;
• x = 27;
• y = x % 5; /* y set to 2 */
• z = x / 5 /* z set to 5 and not 5.4 */

Copyright C Programming ver 2.0 Page 108


Type Conversions

• When an operator has operands of different types, they are


converted to a common type according to a small number
of rules.

• In general, the only automatic conversions are those that


convert a “narrower” operand into a “wider” one without
losing information, such as converting an integer into
floating point

Copyright C Programming ver 2.0 Page 109


Type Conversions

• Expressions that might lose information, like assigning a longer


integer type to a shorter, or a floating-point type to an integer, may
draw a warning, but they are not illegal.

• A char is just a small integer, so chars may be freely used in


arithmetic expressions. This permits considerable flexibility in
certain kinds of character transformations.

• Implicit arithmetic conversions work much as expected. In general,


if an operator like +, or * that takes two operands (a binary
operator) has operands of different types, the “lower” type is
promoted to the “higher” type before the operation proceeds.
Copyright C Programming ver 2.0 Page 110
Type Conversion

The following informal set of rules will suffice:


• If either operand is long double, convert the other to long double.
• Otherwise, if either operand is double, convert the other to
double.
• Otherwise, if either operand is float, convert the other to float.
• Otherwise, convert char and short to int.
• Then, if either operand is long, convert the other to long.

• Conversions take place across assignments; the value of the


right side is converted to the type of the left, which is the type
of the result.

Copyright C Programming ver 2.0 Page 111


Type Conversions

• Consider the following assignments:


• int i;
• char c;
• i = c;

• In the aforesaid assignment, the data type on the right (char) is converted
to the data type on the left (int), which is the type of the result.

• If x is float and i is int, then x = i and i = x both cause conversions; float


to int causes truncation of any fractional part. When a double is
converted to float, whether the value is rounded, or truncated is
implementation-dependent.

Copyright C Programming ver 2.0 Page 112


Explicit Type Conversion

• Finally, explicit type conversions can be forced (“coerced”)


in any expression, with a unary operator called a cast.

• In the construction (type name) expression, the expression is


converted to the named type by the conversion rules above.

• The precise meaning of a cast is as if the expression were


assigned to a variable of the specified type, which is then
used in place of the whole construction.

Copyright C Programming ver 2.0 Page 113


Explicit Type Conversion

• Consider the following example:


• int i, j;
• double d;
• d = i / j; /* double assigned the result of the division of two
integers */

• The problem with the above assignment is that the fractional


portion of the above division is lost, and d is effectively
assigned the integer quotient of the two integers i and j.

Copyright C Programming ver 2.0 Page 114


Explicit Type Conversion

• To resolve this, the variable i can be typecast into a double


as in: d = (double)i / j;

• int i is converted to a double using the explicit cast


operator. Since one of the operands is a double, the other
operand (j) is also converted to a double, and the result is a
double.

• The result is assigned to a double with no side effects. The


cast operator can be done only on the right-hand side
of an assignment.

Copyright C Programming ver 2.0 Page 115


Ternary Operators

if (a > b)
z = a;
else
z = b;

• The aforesaid statements evaluate z to the maximum of a


and b. The conditional expression, written with the ternary
operator “?:”, provides an alternate way to write this, and
similar constructions. In the expression
• expr1 ? expr2 : expr3

Copyright C Programming ver 2.0 Page 116


Ternary Operators

• If it is non-zero (true), then the expression expr2 is


evaluated, and that is the value of the conditional
expression.

• Otherwise expr3 is evaluated, and that is the value. Only


one of expr2 and expr3 is evaluated.

• Thus to set z to the maximum of a and b,


z = (a > b) ? a : b; /* assign z the maximum of a and b */

Copyright C Programming ver 2.0 Page 117


Compound Assignment Operators

• Compound assignment statements help in simplifying, and


writing simple code.

• So far, we have been writing statements such as:


sum = sum + num

• The same could be simplified as sum += num;

• The same applies to the other binary operators.

Copyright C Programming ver 2.0 Page 118


Compound Assignment Operators

• sum = sum – num; can be written as sum -= num;

• x = x * y; can be written as x *= y;

• x = x / y; can be written as x /= y;

• Compound assignment operators can be very useful if the


identifiers used for the operands is very long.

Copyright C Programming ver 2.0 Page 119


Two-Dimensional Arrays

• While a one-dimensional array can be visualized in one-


dimension as either a row of elements, or a column of
elements, a two-dimensional array needs to be visualized
along two dimensions, i.e., along rows and columns.

• To be precise, a two-dimensional array can be represented


as an array of m rows by n columns.

• A general way of representing or visualizing a two-


dimensional array is in the form of a two-dimensional grid.
But, in memory, even a two-dimensional array is arranged
contiguously as an array of elements.

Copyright C Programming ver 2.0 Page 120


Two-dimensional Arrays

col 0 col 1 col 2

row 0

row 1

row 2

r0,c0 r0,c1 r0,c2 r1,c0 r1,c1 r1,c0 r2,c0 r2,c1 r2,c2

Copyright C Programming ver 2.0 Page 121


Two-Dimensional Arrays

• The Scenario: Consider a situation where you want to


record the region-wise, product-wise figures of sales. The
regions are A, B and C. The products are X, Y and Z

• Sales data for the region-wise, product-wise breakup


should be shown as follows:

Copyright C Programming ver 2.0 Page 122


Two-Dimensional Arrays

Prod X Prod Y Prod Z

reg A

reg B

reg C

Copyright C Programming ver 2.0 Page 123


Declaring a Two-Dimensional Array

• Declaring a two-dimensional array involves two indices, or two


subscripts. There will be an extra set of square brackets[ ] to
indicate the second subscript, or the second index.

• To declare a two-dimensional array for accommodating sales data


for three regions and three products, we would come out with an
array declaration as in:

• int rp_array[3][3];
• /* this array would have nine elements starting at rp_array[0][0],
rp_array[1][1]…….and going on till rp_array[2,2] */

Copyright C Programming ver 2.0 Page 124


Initializing Two-Dimensional Arrays

• int rp_array[3][3] = {0,0, 0,


• 0, 0, 0,
• 0, 0, 0
• };

• To improve the legibility of the initialization, it can be


written as: int rp_array[3][3] = { {0,0, 0},
• {0, 0, 0},
• {0, 0, 0}
• };

Copyright C Programming ver 2.0 Page 125


Initializing Two-Dimensional Arrays Using the for
Loop
• /* r_counter is for referring to the rth region */
• /* p_counter is for referring to the pth product */
• for (r_counter = 0; r_counter < 3; r_counter ++)
• {
• for (p_counter = 0; p_counter < 3; p_counter ++)
• {
• rp_array[r_counter][p_counter] = 0;
• }
• }

Copyright C Programming ver 2.0 Page 126


Input to Two-Dimensional Arrays

• for (r_counter = 0; r_counter < 3; r_counter ++)


• {
• for (p_counter = 0; p_counter < 3; p_counter ++)
• {
• printf( “\nEnter sales data for Region %d and Product %d,
• r_counter + 1, p_counter + 1)
• scanf(“%d”, &rp_array[r_counter][p_counter]);
• fflush( stdin);
• }
• }

Copyright C Programming ver 2.0 Page 127


Processing Two-Dimensional Arrays

• /* Program for converting these sales figures into percentages of total sales. */
• main( )
• {
• int r_counter, p_counter, rp_array[3][3], total_sales = 0;
• float rp_array_perc[3][3];
• /* initialization of rp_array using the for loop */
• for (r_counter = 0; r_counter < 3; r_counter ++)
• {
• for (p_counter = 0; p_counter < 3; p_counter ++)
• {
• rp_array[r_counter][p_counter] = 0;
• }
• }

Copyright C Programming ver 2.0 Page 128


Processing Two-Dimensional Arrays

• /* input sales into rp_array using the for loop */


• for (r_counter = 0; r_counter < 3; r_counter ++)
• {
• for (p_counter = 0; p_counter < 3; p_counter ++)
• {
• printf( “\nEnter sales data for Region %d and Product %d,
• r_counter + 1, p_counter + 1)
• scanf(“%d”, &rp_array[r_counter][p_counter]);
• fflush( stdin);
• }
• }

Copyright C Programming ver 2.0 Page 129


Processing Two-Dimensional Arrays

• /* Determine total sales using the for loop */


• for (r_counter = 0; r_counter < 3; r_counter ++)
• {
• for (p_counter = 0; p_counter < 3; p_counter ++)
• {
• total_sales += rp_array[r_counter][p_counter];
• }
• }

Copyright C Programming ver 2.0 Page 130


Processing Two-Dimensional Arrays

• /* Determine percentage of individual sales data against total sales */


• for (r_counter = 0; r_counter < 3; r_counter ++)
• {
• for (p_counter = 0; p_counter < 3; p_counter ++)
• {
• rp_array_perc[r_counter][p_counter] = (( float) 100 *
• rp_array[r_counter][p_counter] ) / total_sales ;
• }
• }
• } /* end of main( ) */

Copyright C Programming ver 2.0 Page 131


The Preprocessor Phase

• The measure of the flexibility of any program is the ease


with which changes can be implemented.

• The preceding exercises involving two-dimensional arrays


is inflexible because the number of regions and products is
hard coded into the program, causing the size of the
array to be also hard coded.

• If changes in terms of the number of regions and products


were to be incorporated with the least amount of code
maintenance, the best solution would be the use of macros
referred to in C as #define.

Copyright C Programming ver 2.0 Page 132


The Preprocessor Phase
• The #define constitutes the preprocessor phase, wherein the value/s specified as
part of the macro or #define is substituted into the code prior to compilation.
This is also known as macro substitution.
• #include <stdio.h>
• #define RG 3
• #define PR 3
• main( )
• {
• int r_counter, p_counter, rp_array[RG][PR], total_sales = 0;
• float rp_array_perc[RG][PR];
• /* initialization of rp_array using the for loop */
• for (r_counter = 0; r_counter < RG; r_counter ++)
• {
• for (p_counter = 0; p_counter < PR; p_counter ++)
• {
• rp_array[r_counter][p_counter] = 0;
• }
• }

Copyright C Programming ver 2.0 Page 133


Two-Dimensional Character Arrays

• If you were to store an array of 11 names, with each name


containing up to a maximum of 30 characters, you would
declare it as a two-dimensional character array such as:
char name[11][31];

• Here, name[0] through name[9] would store character


strings representing names of 30 characters each.

• The first index represents the number of names, and the


second index represents the maximum size of each name.

Copyright C Programming ver 2.0 Page 134


Initializing Two-Dimensional Character Arrays

• char team_india [11][30] = { “Akash Chopra”,


• “Virendra Sehwag”,
• “Rahul Dravid”
• “Sachin Tendulkar”,
• “V.V.S. Laxman”,
• “Yuvraj Singh”,
• “Ajit Agarkar”,
• “Parthiv Patel”,
• “Anil Kumble”,
• “L. Balaji”,
• “Irfan Pathan”
• };

Copyright C Programming ver 2.0 Page 135


Printing Two-Dimensional Character Arrays

• main( )
• {
• char team_india [11][30] = { “Akash Chopra”,
• “Virendra Sehwag”,
• “Rahul Dravid”
• “Sachin Tendulkar”,
• “V.V.S. Laxman”,
• “Yuvraj Singh”,
• “Ajit Agarkar”,
• “Parthiv Patel”,
• “Anil Kumble”,
• “L. Balaji”,
• “Irfan Pathan”
• };

Copyright C Programming ver 2.0 Page 136


Printing Two-Dimensional Character Arrays

• int i;
• for( i = 0; i < 11; i ++)
• {
• printf(“%s”, team_india[i]);
• }
• }

• Particular elements can also be printed from a two dimensional array


by using the second subscript.

• Printf(“%c”, team_india[10][6] would print the character ‘P’ from the


string “Pathan”

Copright C Programming ver 2.0 Page 137


Copyright C Programming ver 2.0 Page 138
Chapter 4
Pointers

C Programming ver 2.0 Page 139


Objectives

At the end of this session, you should be able to:


• Declare, initialize, and manipulate pointers
• Use pointers for manipulating one-dimensional and two-
dimensional arrays
• Distinguish between arrays and pointers
• Use pointer arithmetic

C Programming ver 2.0 Page 140


Pointer – Definition

• When a variable is declared (such as int i = 22) in a


program, space is reserved in memory for the variable i.

• To be precise, each variable is assigned a particular


memory location referenced by its address.

• In our case, the integer i would be stored at a specific


memory location having the address, say, 1000 (addresses
are typically hexadecimal values).

• The declaration of i can be conceptualized as follows:

C Programming ver 2.0 Page 141


Pointer – Definition

i variable name i is a named location in memory that can hold


an integer and having the address 1000

22 value

1000 address

C Programming ver 2.0 Page 142


Pointer – Definition

• In C, it is possible to manipulate a variable either by its


name, or by its address. The address of a variable can be
stored in another variable (called a pointer variable), and
access can be had to the variable through this pointer
variable.

• A pointer can therefore be defined as a variable that


holds the address of another variable.

• If you want to define a pointer to hold the address of an


integer variable, then you must define the pointer as a
pointer to an integer.

C Programming ver 2.0 Page 143


Pointer – Declaration & Initialization

• It is in this sense that a pointer is referred to as a


derived data type, as the type of the pointer is based on
the type of the data type it is pointing to.

• For the earlier declaration of the integer variable i, its


pointer can be declared as follows:

• int i, *pointer_to_an_integer;
• i = 22;
• pointer_to_an_integer = &i; /* initializing the integer
pointer variable (pointer_to_an_integer) with the address of
the integer variable i. */

C Programming ver 2.0 Page 144


Pointer – Declaration & Initialization

• The ‘*’ operator precedes a pointer operand. In the preceding


declaration, int *pointer_to_an_integer; the ‘*’ operator preceding the
variable name marks it out as a pointer declaration, and the data type
of the pointer variable begins the pointer declaration.

• It is obvious from the preceding code snippet that the ‘&’ operator is
used to return the address of a variable. The returned address is stored
into a pointer variable of the appropriate type.

• It is critical, as a good C programmer, to initialize a


pointer as soon as it is declared.

C Programming ver 2.0 Page 145


Pointer – Declaration & Initialization

• the integer pointer variable (pointer_to_an_integer) being


initialized with the address of the integer variable i.

i variable name

pointer_to_an_integer 22 variable value

1000 1000 variable address

C Programming ver 2.0 Page 146


Dereferencing a Pointer

• Returning the value pointed to by a pointer is known as


pointer dereferencing. To deference the contents of a
pointer, the * operator is used.

• #include<stdio.h>
• main( )
• {
• int x, y, *pointer;
• x = 22;
• pointer = &x;
• y = *pointer; /* obtain whatever pointer is pointing to */
• }

C Programming ver 2.0 Page 147


Pointers - Variations on a theme

• pointer = &x; /* make pointer point to x */


• y = *ptr + 1; /* return the value of the variable pointed to by
pointer, add 1 to it, and store the result in y */
• *ptr = 0; /* set the value of the variable pointed to by
pointer to 0. In this case, the variable x is set to 0 through its
pointer */

C Programming ver 2.0 Page 148


Pointers - Variations on a Theme

• Consider the following code snippet:


• Int x, y, *pointer1, *pointer2;
• pointer1 = &x /* return the address of x into pointer1 */
• pointer2 = pointer1; /* assign the address in pointer1 to
pointer2. Hence, both the pointer variables, pointer1 and
pointer2, point to the variable x. */
i variable name

pointer1 22 variable value

1000 1000 variable address

pointer2
1000

C Programming ver 2.0 Page 149


Pointers - Variations on a Theme

• Consider the following code snippet:


• int x, y, *p1, *p2;
• x = 22;
• y = 44;
• p1 = &x; /* p1 points to x */
• p2 = &y /* p2 points to y */
• *p1 = *p2 /* make whatever p1 was pointing to (variable x
and hence the value 22) equivalent to whatever p2 is
pointing to. */

• Hence, both x and y will now have the value 44.


C Programming ver 2.0 Page 150
Pointers - Variations on a Theme

Before *p1 = *p2


p1 x

1000 22

p2 y

2000 44

After *p1 = *p2


pointer1 x

1000 44

pointer2
y
1000 44

C Programming ver 2.0 Page 151


Printing Using Pointers

• Consider the following code snippet:


• #include <stdio.h>
• main( )
• {
• int x, *p;
• x = 26;
• p = &x;
• printf("The value of x is %d\n", x);
• printf("The value of x is %d\n", *p);
• }

C Programming ver 2.0 Page 152


One-dimensional Character Arrays Using Pointers

• In the declaration:
• char string[11];
• the name of the array refers to the starting address of
the area that gets allocated for storing the elements of
the array.

• Thus, string contains the address of string[0].

• Since a pointer is a variable that contains the address of


another variable, it is evident that string is a pointer.

C Programming ver 2.0 Page 153


One-dimensional Character Arrays Using Pointers

• What is string pointing to? Seemingly, it points to a string,


but actually, string is pointing to a character at string[0].

• Recall that a string is just a sequence of characters


terminated by a null character (‘\0’).

• When the string name is passed down as a parameter to a


printf( ) function, it starts printing from the starting
address of the string till it encounters a null character
(‘\0’), which happens to be the string terminator.

C Programming ver 2.0 Page 154


Difference Between Pointers and Arrays

• There are subtle differences between pointers and arrays.

• Consider the following declaration:


• char string[10], *p;
• Both string and p are pointers to char.

C Programming ver 2.0 Page 155


Difference Between Pointers and Arrays

• However, string[10] has 10 bytes of contiguous


storage allocated for it.

• Thus, during execution, string is effectively a


pointer with a constant address, namely, the
address &string[0];

• And this address cannot be changed during the


life of the program

C Programming ver 2.0 Page 156


Difference Between Pointers and Arrays

• However, p is a pointer variable that can point to one


string at one point of time during the running of the
program, and can also point to another string at another
point of time during the running of the same program.

• p is a variable, and a variable by its very definition can


hold different values at different points of time during
program execution.

• Therefore, we can conclude that a string is a pointer


constant, whereas an explicit character pointer
declaration is a character pointer variable.

C Programming ver 2.0 Page 157


One-dimensional Character Arrays Using Pointers

• The one-dimensional character array declared earlier (char


string[11]) can be alternately declared as:

• char *string; /* string is now a explicit pointer variable that can point
to a character */
• char *string = “Hello”;
• printf(“%s”, string);

C Programming ver 2.0 Page 158


Two-dimensional Character Arrays Using Pointers

• Since a pointer to a character can be a pointer to a string, it


follows therefore that a two-dimensional character array
can be declared as an array of character pointers.

• Recall the declaration of the two dimensional character


array that you used earlier to store 11 names, each of
which could be a maximum of 30 characters. It was
written as: char team_india [11][30];

C Programming ver 2.0 Page 159


Two-dimensional Character Arrays Using Pointers

• This could be alternately declared as:


• char *team_india[11];

• team_india is now an array of 11 character pointers, each


of which in turn can point to a string. A pointer to a
character can be a pointer to a string as well.

• The flexibility with a declaration of an array of character


pointers is that each of the character pointers may point to
an array of unequal length, as against the declaration of a
two-dimensional character array in which each string is of
a fixed size.

C Programming ver 2.0 Page 160


Pointer Arithmetic

• The most common arithmetic operation using pointers is


incrementing by 1. Consider the following statement:

• char *p = “Sherlock H”;


• printf(“%s\n”, p);

• The initialization of the character pointer with the string


“Sherlock H” can be visualized as shown in the following
slide.

C Programming ver 2.0 Page 161


Pointer Arithmetic

100

100 101 102 103 104 105 106 107 108 109 110

S h e r l o c k H \0

0 1 2 3 4 5 6 7 8 9 10

C Programming ver 2.0 Page 162


Pointer Arithmetic

• Now, let us increment the pointer p by 1, as in:


• p++;

• p initially pointed to the base address of the string


“Sherlock H”, i.e., 100.

• After incrementing the pointer p by 1, it points to the next


element in the string or the character array, i.e., character
‘h’ after ‘S’.

• p now contains the address of the element ‘h’, i.e., 101

C Programming ver 2.0 Page 163


Pointer Arithmetic

101

100 101 102 103 104 105 106 107 108 109 110

S h e r l o c k H \0

0 1 2 3 4 5 6 7 8 9 10

C Programming ver 2.0 Page 164


Pointer Arithmetic

• But will the statement p++; always make p point to the


next memory location.

• The answer is an emphatic No.

• This depends upon the data type that p is pointing to.

• Consider the following piece of code:


• #include <stdio.h>
• main( )
• {

C Programming ver 2.0 Page 165


Pointer Arithmetic

• int int_array[3] = {4, 8, 22}; /* int_array is a constant pointer */


• int * p;
• p = int_array;
• printf (“%d”, p);
• p++;
• printf(“%d”, p);
• } The value of p afer being initialized
p with the address of int_array

100
100 104 108

4 8 12

C Programming ver 2.0 Page 166


Pointer Arithmetic

The value of p after pointer arithmetic


performed on p, i.e., p++

p
104
100 104 108

4 8 12

C Programming ver 2.0 Page 167


Pointer Arithmetic

• The key point to note is that when pointers are


incremented by 1, the size of the data type to which it is
pointing to (4 bytes in our case, since an integer needs 4
bytes of storage) is taken into account.

• To summarize, the operation p++; will result in the


following computation:
• New address of p = old address of p + size of data type

C Programming ver 2.0 Page 168


Pointer Arithmetic

• Consider the following declaration of a two-dimensional


integer array:
• int p[3][5] = {
• { 2, 4, 6, 8, 10},
• { 3, 6, 9, 12, 15},
• { 5, 10, 15, 20, 25}
• };

• The aforesaid declaration declares an array of three integer


pointers, each pointing to the first element of an array of 5
integers. This can be visualized as follows:

C Programming ver 2.0 Page 169


Pointer Arithmetic

p
100

200 204 208 212 216


100
200
2 4 6 8 10

300 304 308 312 316


104 300 3 6 9 12 15

400 404 408 412 416


108 400
5 10 15 20 25

C Programming ver 2.0 Page 170


Pointer Arithmetic

• Here, p points to the first element of the array of pointers.

• *p equals p[0], i.e., it returns the address 200. This address


points to the element at offset [0,0], i.e., element 2.

• Therefore, *(*p) returns the value 2.

• Since p is a pointer to another pointer, incrementing p by 1


makes it point to the next element in the array of pointers,
i.e., it now points to the element containing the address
300.

C Programming ver 2.0 Page 171


Pointer Arithmetic

• Hence, *(p + 1) returns the address 300.

• Therefore, * (*(p + 1)) returns the value at this address,


i.e., the element with the value 3. In other words, the
element at the offset [1,0].

• The following table gives various pointer expressions, and


their values:

C Programming ver 2.0 Page 172


Pointer Arithmetic

Pointer Resulting Variable Value


Expression Address
*(*p) 200 p[0][0] 2

*(*p+1) 204 p[0][1] 4

*(*(p + 1)) 300 p[1][0] 3

*(*(p+1)+1) 304 p[1][1] 6

*(*(p+1)+1)+1 304 p[1][1] + 1 6+1=7

C Programming ver 2.0 Page 173


String Handling Functions Using Pointers

• /* The following function determines the length of a string */


• #include <stdio.h>
• main( )
• {
• char *message = “Virtue Alone Ennobles”;
• char *p;
• int count;
• for (p = message, count = 0, p != ‘\0’, p++)
• count++;
• printf(The length of the string is %d\n”, count);
• }

C Programming ver 2.0 Page 174


String Handling Functions Using Pointers

• /* The following functions compares two strings */


• #include<stdio.h>
• main( )
• {
• char *message1 = “This is a test”;
• char *message2 = “This is not a test”;
• char *p1, *p2;
• for(p1=message1, p2=message2; (*p1 = = *p2) && (*p1 != ‘\0’) &&
(*p2 != ‘\0’); p1++, p2++)
• if ((*p1 = = ‘\0’) && (*p2 = = ‘\0’))
• printf(“The two strings are identical\n”);
• else
• printf(“The two strings are not identical\n”);
• }

C Programming ver 2.0 Page 175


Summary

In this session, you learnt to:


• Declare, initialize, and manipulate pointers
• Use pointers for manipulating one-dimensional and two-
dimensional arrays
• Distinguish between arrays and pointers
• Use pointer arithmetic

C Programming ver 2.0 Page 176


C Programming ver 2.0 Page 177
Chapter 5
The Function Call Mechanism

C Programming ver 2.0 Page 178


Objectives

• In this session, you will learn to:


• Write programs that invoke functions through a:
– Call by value
– Call by reference
• Define function prototypes
• Describe the function call mechanism
• Pass arguments to main( ) in the form of command-line
arguments
• Use the Auto, Static, and Extern storage qualifiers
• Use string handling functions, conversion functions, and
functions for formatting strings in memory

C Programming ver 2.0 Page 179


Advantages of Function

• Functions facilitate the factoring of code. Every C program


consists of one main( ) function typically invoking other
functions, each having a well-defined functionality.

• Functions therefore facilitate:


– Reusability
– Procedural abstraction

• By procedural abstraction, we mean that once a function is


written, it serves as a black box. All that a programmer
would have to know to invoke a function would be to
know its name, and the parameters that it expects.

C Programming ver 2.0 Page 180


Function Parameters

• Function parameters are defined as part of a function


header, and are specified inside the parentheses of the
function.

• The reason that functions are designed to accept


parameters is that you can embody generic code inside the
function.

• All that would be required by the function would be the


values that it would need to apply the generic code on the
values received by it through its parameters.

C Programming ver 2.0 Page 181


Function Parameters

• Consider the following printf( ) statement:


• printf(“%d”, i);

• This is actually a call to the printf( ) function with two


pieces of information passed to it, namely, the format
string that controls the output of the data, and the variable
that is to be output.

• The format string, and the variable name can be called the
parameters to the function printf( ) in our example.

C Programming ver 2.0 Page 182


Function Parameters

• Function parameters are therefore a mechanism wherein


values can be passed down to a function for necessary
processing, and the processed value returned back from the
function, as the case may be.

• It is important to remember that not all function need be


defined to accept parameters, though most functions do.

• This brings us now to the important concept of a


function returning a value, and also the return type of a
function.

C Programming ver 2.0 Page 183


Invoking Functions

• In C, functions that have parameters are invoked in one of


two ways:
– Call by value
– Call by reference

C Programming ver 2.0 Page 184


Call by Value

void swap(int,int );
main()
{ int a=10, b=20;
swap(a, b);
printf(“ %d %d \n”,a,b);
}
void swap (int x, int y)
{ int temp = x;
x= y;
y=temp;
}

C Programming ver 2.0 Page 185


Call by Value

• In the preceding example, the function main( ) declared and


initialized two integers a and b, and then invoked the function swap( )
by passing a and b as arguments to the function swap( ).

• The function swap( ) receives the arguments a and b into its


parameters x and y. In fact, the function swap( ) receives a copy of
the values of a and b into its parameters.

• The parameters of a function are local to that function, and hence, any
changes made by the called function to its parameters affect only the
copy received by the called function, and do not affect the value of
the variables in the called function. This is the call by value
mechanism.
C Programming ver 2.0 Page 186
Call by Reference

• Call by reference means that the called function should be


able to refer to the variables of the calling function directly,
and not create its own copy of the values in different
variables.

• This would be possible only if the addresses of the


variables of the calling function are passed down as
parameters to the called function.

• In a call by reference, therefore, the called function directly


makes changes to the variables of the calling function.

C Programming ver 2.0 Page 187


Call by Reference

• Consider the same swap( ) that we discussed earlier now rewritten


using a call by reference.
void swap( int *, int *);
main()
{ int a=10, b=20;
swap(&a, &b);
printf(“ %d %d \n”,a,b);
}
void swap (int *x, int *y)
{ int temp=*x;
*x=*y;
*y=temp;
}

C Programming ver 2.0 Page 188


Passing Arrays to Functions

• Arrays are inherently passed to functions through a call by


reference.

• For example, if an integer array named int_array of 10


elements is to be passed to a function called fn( ), then it
would be passed as:
• fn( int_array);

• Recall that int_array is actually the address of the first


element of the array, i.e., &int_array[0]. Therefore,
this would be a call by reference.

C Programming ver 2.0 Page 189


Passing Arrays to Functions

• The parameter of the called function fn( ) would can be


defined in one of three ways:

• fn( int num_list[ ]); or

• fn(int num_list[10]); or

• fn(int *num_list)

C Programming ver 2.0 Page 190


Returning a Value From a Function

• Just as data can be passed to a function through the


function’s parameters at the time of call, the function can
return a value back to the caller of the function.

• In C, functions can return a value through the return


statement. Consider the following example:
• #include<stdio.h>
• main( )
• {
• int i,j, value;
• scanf(“%d %d”, &i, &j);
• fflush(stdin);

C Programming ver 2.0 Page 191


Returning Value From a Function

• value = add(i, j);


• printf( “the total is %d\n”, value);
• }

• add( int a, int b)


• {
• return (a + b);
• }

• In the aforesaid example, the function add( ) sends back the value of
the expression (a + b) to the function main( ). The value returned to
main( ) from add( ) is stored in the variable value which appears on the
left hand side of the statement in which the function add( ) is called.

C Programming ver 2.0 Page 192


Returning a Value From a Function

• The return statement not only returns a value back to the


calling function, it also returns control back to the calling
function.

• A function can return only one value, though it can return


one of several values based on the evaluation of certain
conditions.

C Programming ver 2.0 Page 193


Function Prototype

• C assumes that a function returns a default value of int if


the function does not specify a return type.

• In case a function has to return a value that is not an


integer, then the function itself has to be defined of the
specific data type it returns.

• Consider the following code:


• #include <stdio.h>
• main( )
• {

C Programming ver 2.0 Page 194


Function Prototype

• Functions should be declared before they are used.

• Consider the situation where you want to use the pow( )


function, called the power function, one of many functions
in the mathematics library available for use by the
programmer.

• A function call such as pow(x, y) returns the value of x


raised to the power y.

• To elucidate further, pow(2.0, 3.0) yields the value 8.0

C Programming ver 2.0 Page 195


Function Prototype

• The declaration of the function is given by:


• double pow( double x, double y);

• Function declarations of this type are called function


prototypes.

• An equal function prototype is given by:


• double pow( double, double);

C Programming ver 2.0 Page 196


Function Prototype

• A function prototype tells the compiler the number and


data types of arguments to be passed to the function and
the data type of the value that is to be returned by the
function.

• ANSI C has added the concept of function prototypes to


the C language.

C Programming ver 2.0 Page 197


Function Prototype

• float add(float a, float b);


• float i, j, value;
• scanf(“%f %f”, &i, &j);
• fflush(stdin);
• value = add(i, j);
• printf( “the total is %d\n”, value);
• }

• float add(float a, float b)


• {
• return (a + b);
• }

C Programming ver 2.0 Page 198


Function Prototype

• #include <stdio.h>
• main( )
• {
• void add( float, float);
• float i, j, value;
• scanf(“%f %f”, &i, &j);
• fflush(stdin);
• add(i, j);
• printf( “the total is %d\n”, value);
• }

• void add(float a, float b)


• {
• printf(“%f”, a + b);
• return;
• }

C Programming ver 2.0 Page 199


Function Calls

• It is important for us to know what happens under the hood when a


function executes.

• A logical extension of the aforesaid point is the situation that arises


when a function calls another function.

• It is important to know how the CPU manages all this, i.e., knowing
where to look for when a function call is encountered, and having
executed the function, to also know where it has to return to.

• In short, we need to know the call mechanism, and the return


mechanism.

C Programming ver 2.0 Page 200


Function Calls – A Top Level Overview

• When a function call is encountered, it involves the


following steps:
1. Each expression in the argument list is evaluated.
2. The value of the expression is converted, if necessary, to
the type of the formal parameter, and that value is
assigned to the corresponding formal parameter at the
beginning of the body of the function.
3. The body of the function is executed.

C Programming ver 2.0 Page 201


Function Calls – A Top Level Overview

4. If the return statement includes an expression, then the


value of the expression is converted, if necessary, to the
type specified by the type specifier of the function, and
that value is passed back to the calling function.
5. If no return statement is present, the control is passed
back to the calling function when the end of the body of
the function is reached. No useful value is returned.

C Programming ver 2.0 Page 202


Function Calls & The Runtime Stack

• Runtime Environment: Runtime Environment is the


structure of the target computer’s registers and memory
that serves to manage memory and maintain the
information needed to guide the execution process.

• The C language uses a stack-based runtime environment,


which is also referred to as a runtime stack, or a call stack.

• Let us begin by understanding the internal memory


organization that comes into the picture whenever a
program needs to be executed.

C Programming ver 2.0 Page 203


Function Calls & The Runtime Stack

Memory

Register Area
Code Area
RAM
Data Area

C Programming ver 2.0 Page 204


Code Area

Entry point for procedure 1


Code for
Procedure 1
Entry point for procedure 2
Code for
Procedure 2
.
.
Entry point for procedure n
Code for
Procedure n

C Programming ver 2.0 Page 205


Data Area

• Only a small part of data can be assigned fixed locations


before execution begins
– Global and/or static data
– Compile-time constants
• Large integer values
• Floating-point values
– Literal strings

C Programming ver 2.0 Page 206


Dynamic Memory

• The memory area for the allocation of dynamic data can be


organized in many different ways.
• A typical organization divides the dynamic memory into
– stack area (LIFO protocol)
– heap area

C Programming ver 2.0 Page 207


Memory Organization

code area
global/static area
stack

free
free space
space

heap

C Programming ver 2.0 Page 208


Procedure Activation Record

• Procedure activation record


contains memory allocated for
the local data of a procedure or
function when it is called, or
activated. A Procedure Activation
Record or a Stack Frame
• When activation records are arguments
kept on stack, they are called
bookkeeping information
stack frames. Details depend on
(return address)
the architecture of target
machine and properties of the local data
language.
local temporaries
C Programming ver 2.0 Page 209
Registers

• Registers may be used to store temporaries, local variables,


or even global variables.
• When a processor has many registers, the entire static area
and whole activation records may be kept in the registers.
• Special purpose registers:
– Program counter (PC)
– Stack pointer (SP)

C Programming ver 2.0 Page 210


Calling Sequence

• The calling sequence is the sequence of operations that


must occur when a procedure or function is called.
– Allocation of memory for the activation record
– The computation and storing the arguments
– Storing and setting registers

C Programming ver 2.0 Page 211


Return Sequence

• The return sequence is the sequence of operations needed


when a procedure or function returns.
– The placing of the return value where it can be
accessed by the caller
– Readjustment of registers
– Releasing of activation record memory

C Programming ver 2.0 Page 212


Fully Static Runtime Environment

• The simplest kind of a runtime environment.


• All data are static, remaining in memory for the duration
of the program.
– All variables can be accessed directly via fixed addresses
• Each procedure has only a single activation record, which
is allocated statically prior to execution.
• Such environment can be used to implement a language in
which:
– There are no pointers or dynamic allocation,
– Procedures cannot be called recursively.
• Example: COBOL & FORTRAN

C Programming ver 2.0 Page 213


Stack-based Runtime Environment

• In a language in which recursive calls are allowed,


activation records cannot be allocated statically.

• Activation records are allocated in a stack-based fashion.

• This stack is called the stack of activation records (runtime


stack, call stack).

• Each procedure may have several different activation


records at one time.

C Programming ver 2.0 Page 214


Global Procedures

• In a language where all procedures are global (the C


language), a stack-based environment requires two things:
1. A pointer to the current activation record to allow access to local
variables.
– This pointer is called the frame pointer (fp) and is usually kept in a
register.
2. The position or size of the caller’s activation record
– This information is commonly kept in the current activation record as
a pointer to the previous activation record and referred as the control
link or dynamic link.
– Sometimes, the pointer is called the old fp
3. Additionally, there may be a stack pointer (sp)
– It always points to the top of the stack

C Programming ver 2.0 Page 215


Tracing Function Calls

• int z;
fn_a( int m ) fn_b( int n )
• main( )
• { { {
• int x; int y; int b;
• fn_a( );
• ….. . fn_b( ); …..
return instruction
• . ….. return instruction .
• .
. .
• .
• } . .
• . }
}

C Programming ver 2.0 Page 216


A View of the Runtime Stack

z
S Global static area
t Activation record of main
x
a
m
c
y
k
control link Activation record of call to fn_a( )
G return address
r n
o control link Activation record of call to fn_b( )
w return address
t fp b
sp
h Free Store (Heap)

C Programming ver 2.0 Page 217


Access to Variables

• In static environment, parameters and local variables can


be accessed by fixed addresses.
• In a stack-based environment, they must be found by offset
from the current frame pointer.
• In most languages, the offset for each local variable is still
statically computable by compiler.
– The declarations of a procedure are fixed at compile time and the
memory size to be allocated for each declaration is fixed by its
data type.

C Programming ver 2.0 Page 218


Calling Sequence

1. Compute the arguments and store them in their correct


positions in the new activation record (pushing them in
order onto the runtime stack)
2. Store (push) the fp as the control link in the new
activation record.
3. Change the fp so that it points to the beginning of the new
activation record (fp=sp)
4. Store the return address in the new activation record.
5. Jump to the code of the procedure to be called.

C Programming ver 2.0 Page 219


Return Sequence

1. Copy the fp to the sp


2. Load the control link into the fp
3. Jump to the return address
4. Change the sp to pop the arguments.

C Programming ver 2.0 Page 220


Variable Length-Data

• There is a possibility that data may vary, both in the


number of data objects and the size of each object.

• Two examples:
– The number of arguments in a call may vary from call to call.
– The size of an array parameter or a local array variable may vary
from call to call.

C Programming ver 2.0 Page 221


Variable Length Data

• The printf( ) function in C, where the number of arguments


is determined from the format string that is passed as the
first argument.
printf(“%d%s%c”, n, prompt, ch);
printf(“Hello, world!”);

• C compilers push arguments onto the stack in reverse


order.

• The first parameter (which tells how many more


parameters are) is always located at the fixed offset from
fp.

C Programming ver 2.0 Page 222


Local Temporaries

• Local temporaries are partial results of computations that


must be saved across procedure calls.
• Example:
x[i]=(i+j)*(i/k+f(i));
– Three partial results need to be saved: the address of x[i], the sum
i+j, and the quotient i/k.
• They can be stored
1. In the registers
2. As temporaries on the runtime stack prior the call to f.

C Programming ver 2.0 Page 223


Nested Declarations

• Nested declarations can be treated in a similar way to temporary expressions, allocating them
on the stack as the block is entered and deleting them on exit.

• void p (int x, double y)


• { char a;
• int i;
• { double x; // block A
• int y;
• …
• }
• { double x; // block B
• int j;
• …
• }
• { char *a; // block C
• int k;
• …
• }
• }

C Programming ver 2.0 Page 224


Passing Arguments to main( )

• Arguments are generally passed to a function at the time of


call. And function calls are initiated by main( ).

• Since main( ) is the first function to be executed, there is no


question of main( ) being called from any other function.

• So, if main( ) is not going to be invoked by any other


function, is it possible to pass arguments to main( ) given
the fact that arguments are generally passed to a function at
the time of invocation.

• The answer lies in understanding command-line arguments.

C Programming ver 2.0 Page 225


Command-Line Arguments

• The function main( ) can receive arguments from the


command line.

• Information can be passed to the function main( ) from the


operating system prompt as command line arguments.

• The command line arguments are accepted into special


parameters to main( ), namely, argc and argv. Their
declarations are as follows:
• main(int argc, char * argv[ ])

C Programming ver 2.0 Page 226


Command Line Arguments

• argc provides a count of the number of command line


arguments.

• argv is an array of character pointers of undefined size that


can be thought of as an array of pointers to strings.

• The strings are the words that make up the command line
arguments.

• Since the element argv[0] contains the command itself, the


value of argc is at least 1.

C Programming ver 2.0 Page 227


Command Line Arguments

• Consider a program called uppercase which converts a


string to uppercase. The program expects the string to be
entered at the command prompt.

• It should be noted that if the string accepted as a command


line argument has embedded spaces, it should be enclosed
in quotation marks.

• Assume the program is run by entering the following


command at the operating system prompt:
• Uppercase “Sherlock Holmes”

C Programming ver 2.0 Page 228


Command-Line Arguments

argv
argc = 3
100

argv[0]
200
u p p e r c a s e \0

argv[1] 300
S h e r l o c k H o l m e s \0

C Programming ver 2.0 Page 229


Command Line Arguments

• The program uppercase.c can be coded as follows:


• #include <stdio.h>
• main(int argc, char * argv[ ])
• {
• int i;
• for (i = 0; argv[1][i] != ‘\0’, i++)
• {
• if ((argv[1][i] >= ‘a’) && (argv[1][i] <= ‘z’))
• argv[1][i] = argv[1][i] – 32;
• }
• printf( “%s”, argv[1]);
• }

C Programming ver 2.0 Page 230


Storage Qualifiers

• The storage qualifier determines the lifetime of the storage


• associated with the identified variable.

• A variable also has a scope, which is the region of the


program in which it is known.

• The storage qualifiers in C are:


• auto
• static
• extern
• register

C Programming ver 2.0 Page 231


automatic Variables

• automatic variables are local to a block, and are discarded


on exit from the block.

• Block implies a function block, a conditional block, or an


iterative block.

• Declarations within a block create automatic variables if


no storage class specification is mentioned, or if the auto
specifier is used.

• Variable declarations, therefore, are by default, auto.

C Programming ver 2.0 Page 232


automatic Variables
• #include<stdio.h>
• main( )
• {
• char var;
• while ((var = getchar( )) != ‘*’)
• {
• if ((var >= ‘A’) && (var <= ‘Z’))
• {
• uppercase_count( );
• }
• }
• }
• uppercase_count( )
• {
• auto int counter = 0;
• counter ++;
• }

C Programming ver 2.0 Page 233


Global Variables

• Global variable is defined outside all functions.

• A typical convention of defining global variables is before


the main( ) function.

• A variable declared as global is visible to the function


main( ) as well as to any other functions called from main( ).

• A variable defined as global has file scope, that is, it is


visible to all the functions written within the scope of a
program file.

C Programming ver 2.0 Page 234


Global Variables

/* A sample C program */
# include <stdio.h>
int sum( ); /* function prototype */
int a=10, b=20; /* a and b are global variables, visible to main( ) as well as to sum( ) */
main()
{
int c;
c = sum();
printf(“%d+%d = %d \n”,a,b,c);
}
int sum()
{
return(a+b);
}

C Programming ver 2.0 Page 235


Static Variables

• Static variables may be local to a block or external to all


blocks, but in either case retain their values across exit
from, and reentry to functions and blocks.

• Within a block, including a block that provides the code


for a function, static variables are declared with the
keyword static.

• Let us rewrite the code for the example involving auto


variables to incorporate the declaration of static variables.

C Programming ver 2.0 Page 236


Static Variables

• #include<stdio.h>
• main( )
• {
• char var;
• while ((var = getchar( )) != ‘*’)
• {
• if ((var >= ‘A’) && (var <= ‘Z’))
• {
• uppercase_count( );
• }
• }
• }
• uppercase_count( )
• {
• static int counter = 0;
• counter ++;
• }

C Programming ver 2.0 Page 237


Static and Global Variables – A Comparison

• From the preceding example, it seems that static variables


are functionally similar to global variables in that they
retain their value even after exiting from a function in
which it has been defined as static.

• But an important difference is that while a global variable


has file scope, and is therefore visible to all functions
defined within that program file, a static variable is visible
only to the function in which it has been defined as static.

C Programming ver 2.0 Page 238


Extern Variables

• Variables declared as extern are useful especially when


building libraries of functions.

• This means that functions required to run a program can be


saved in separate program files, which can be compiled
separately, and linked up with the file containing the
function main( ) prior to running the program.

• In such a case, if the functions use the same global


variables, then their declarations would involve the use of
the extern qualifier

C Programming ver 2.0 Page 239


Extern Variables

• Program a.c • Program b.c


• int val /* global */ • compute( )
• main( ) • {
• { • extern int val; /* implies
• printf(“Enter value”); that val is defined in
• scanf(“%d”, &val); another program containing
a function to which the
• compute( ); /* function call current function will be
*/ linked to at the time of
• } compilation */
• }

C Programming ver 2.0 Page 240


Extern Variables

• From the preceding example, it is clear that though val is


declared global in the function main( ) in program a.c, it
has been declared again within the function compute( ),
which is defined in its own program file, b.c.

• However, the qualifier extern has been added to its


declaration.

• The extern qualifier in the function compute( ) in b.c


indicates to the compiler (when a.c and b.c are compiled
together) that the variable used in this program file has
been declared in another program file.

C Programming ver 2.0 Page 241


Standard String Handling Functions

• strcmp( ) – compares two strings (that are passed to it as parameters)


character by character using their ASCII values, and returns any of the
following integer values.
Return Value Implication Example
Less than 0 ASCII value of the character of i = strcmp(“XYZ”, “xyz”)
the first string is less than the
ASCII value of the corresponding
character of the second string

Greater than 0 ASCII value of the character of i = strcmp(“xyz”, “XYZ”)


the first string is less than the
ASCII value of the corresponding
character of the second string

Equal to 0 If the strings are identical i = strcmp(“XYZ”, “XYZ”)

C Programming ver 2.0 Page 242


Standard String Handling Functions

• strcpy( ) – copies the second string to the first string,


both of which are passed to it as arguments.

• Example: strcpy( string1, “XYZ”) will copy the string


“XYZ” to the string string1.

• If string1 were to contain any value, it is overwritten with


the value of the second string.

C Programming ver 2.0 Page 243


Standard String Handling Functions

• strcat( ) – appends the second string to the first string,


both of which are passed to it as arguments.

• Example: assume that the string realname contains the


value “Edson Arantes Do Nascimento”. If one were to
append the nickname “Pele” to the string realname, then it
can be done as follows:
– strcat(“Edson Arantes Do Nascimento”, “Pele”); will give the
string “Edson Arantes Do Nascimento Pele”

C Programming ver 2.0 Page 244


Standard String Handling Functions

• strlen( ) – This function returns the length of a string


passed to it as an argument. The string terminator, i.e.,
the null character is not taken into consideration.

• Example: i = strlen(“Johann Cryuff”); will return the value


value 13 into i.

C Programming ver 2.0 Page 245


String to Numeric Conversion Functions

• atoi( ) – This function accepts a string representation of an integer,


and returns its integer equivalent.

• Example: i = atoi(“22”) will return the integer value 22 into the


integer i.

• This function is especially useful in cases where main is designed to


accept numeric values as command line arguments.

• It may be recalled that an integer passed as a command line


argument to main( ) is treated as a string, and therefore needs to be
converted to its numeric equivalent.

C Programming ver 2.0 Page 246


String to Numeric Conversion Functions

• atof( ) - This function accepts a string representation of


a number, and returns its double equivalent.

• For example, if the string str contains the value “1234”,


then the following statement:
• i = atoi(str); will cause i to have the value 1234.000000

• To use the function atof( ) in any function, its prototype


must be declared at the beginning of the function where
it is used:
• double atof( )

C Programming ver 2.0 Page 247


Functions for Formatting Data in Memory

• sprintf( ) – this function writes to a variable in memory


specified as its first argument.

• The syntax of the function sprintf( ) is as follows:


• sprintf( string, format specification, data)

• Example: sprintf( str, “%02d-%02d-%02d”, 28, 8, 71) will


return the string 28-08-71 into str.

C Programming ver 2.0 Page 248


Functions for Formatting Data in Memory

• sscanf( ) – this function reads from a variable in memory,


and stores the data in different memory variables specified.

• The syntax of the function sscanf( ) is:


• Sscanf( string, format specification, variable list);

• Example: sscanf(str, “%2d%2s%s%d”, &day, suffix, mnth, &year)


• printf(“The day is : %d, suffix is %s, month is %s, year is %d\n”, day,
suffix, mnth, year);
• If the data in str is “29th July 1971”, the output will be:
• The day is 29, suffix is th, month is July, year is 1971

C Programming ver 2.0 Page 249


Summary

• In this session, you learnt to:


• Write programs that invoke functions through a:
– Call by value
– Call by reference
• Define function prototypes
• Describe the function call mechanism
• Pass arguments to main( ) in the form of command-line
arguments
• Use the Auto, Static, and Extern storage qualifiers
• Use string handling functions, conversion functions, and
functions for formatting strings in memory

C Programming ver 2.0 Page 250


C Programming ver 2.0 Page 251
Chapter 6
File Input/Output

Copyright C Programming ver 2.0 Page 252


Objectives

• In this session, you will learn to:


• Use pointers of type FILE when performing file I/O
• Perform Input/Output with files
• Use character-based file input/output functions
• Use string-based file input/output functions
• Perform random access on files using the functions
– fseek( )
– ftell( )
– rewind( )
– feof( )

Copyright C Programming ver 2.0 Page 253


Files

• A collection of logically related information


• Examples:
– An employee file with employee names, designation, salary etc.
– A product file containing product name, make, batch, price etc.
– A census file containing house number, names of the members,
age, sex, employment status, children etc.
• Two types:
– Sequential file: All records are arranged in a particular order
– Random Access file: Files are accessed at random

Copyright C Programming ver 2.0 Page 254


File Access

• The simplicity of file input/output in C lies in the fact that


it essentially treats a file as a stream of characters, and
accordingly facilitates input/output in streams of
characters.

• Functions are available for character-based input/output, as


well as string-based input/output from/to files.

• In C, there is no concept of a sequential or an indexed file.


This simplicity has the advantage that the programmer can
read and write to a file at any arbitrary position.

Copyright C Programming ver 2.0 Page 255


File Access

• The examples so far have involved reading from standard


input, and writing to standard output, which is the standard
environment provided by the operating system for all
applications.

• You will now look at the process that a program needs to


follow in order to access a file that is not already
connected to the program.

• Before a file can be read from, or written into, a file has to


be opened using the library function fopen( )

Copyright C Programming ver 2.0 Page 256


File Access

• The function fopen( ) takes a file name as an argument,


and interacts with the operating system for accessing the
necessary file, and returns a pointer of type FILE to be
used in subsequent input/output operations on that file.

• This pointer, called the file pointer, points to a structure


that contains information about the file, such as the
location of a buffer, the current character position in the
buffer, whether the file is being read or written, and
whether errors, or end of file have occurred.

Copyright C Programming ver 2.0 Page 257


File Access

• This structure to which the file pointer point to, is of type


FILE, defined in the header file <stdio.h>.

• The only declaration needed for a file pointer is exemplified


by:
• FILE *fp;
• FILE *fopen(char *name, char *mode);
• fp = fopen( “file name”, “mode”);

• Once the function fopen( ) returns a FILE type pointer stored


in a pointer of type FILE, this pointer becomes the medium
through which all subsequent I/O can be performed.
Copyright C Programming ver 2.0 Page 258
File Access Modes

• When opening a file using fopen( ), one also needs to mention the
mode in which the file is to be operated on. C allows a number of
modes in which a file can be opened.

Mode Access Explanation

“r” Read only mode Opening a file in “r” mode only


allows data to be read from the file

“w” Write only mode The “w” mode creates an empty file
for output. If a file by the name
already exists, it is deleted. Data can
only be written to the file, and not
read from it

Copyright C Programming ver 2.0 Page 259


File Access Modes

Mode Access Explanation


“a” Append mode Allows data to be appended to the end of the file,
without erasing the existing contents. It is therefore
useful for adding data to existing data files.
“r+” Read + Write This mode allows data to be updated in a file
mode
“w+” Write + Read This mode works similarly to the “w” mode, except
mode that it allows data to be read back after it is written.
“a+” Read + This mode allows existing data to be read, and new
Append mode data to be added to the end of the file.

Copyright C Programming ver 2.0 Page 260


Character-based File I/O

• In C, character-based input/output from and to files is


facilitated through the functions fgetc( ) and fputc( ).

• These functions are simple extensions of the


corresponding functions for input/output from/to the
terminal.

• The only additional argument for both functions is the


appropriate file pointer, through which these functions
perform input/output from/to these files.

Copyright C Programming ver 2.0 Page 261


A File Copy Program

• #include<stdio.h>
• main( )
• {
• FILE *fp1, *fp2;
• fp1 = fopen( “source.dat”, “r”);
• fp2 = fopen( “target.dat”, “w”);
• char ch;
• while ( (ch = fgetc( fp1)) != EOF)
• {
• fputc (ch, fp2);
• }
• fclose(fp1);
• fclose(fp2);
• }

Copyright C Programming ver 2.0 Page 262


Variation to Console-Based I/O

• #include<stdio.h>
• main( )
• {
• char ch;
• while ( (ch = fgetc( stdin)) != EOF)
• {
• fputc (ch, stdout);
• }
• }

Copyright C Programming ver 2.0 Page 263


Nuggets on FILE Type Pointers

• The important point to note is that in C, devices are also


treated as files. So, the keyboard and the VDU are also
treated as files.

• It would be interesting here to know what stdin, stdout,


and stderr actually are.

• stdin, stdout, and stderr are pointers of type FILE


defined in stdio.h. stdin is a FILE type pointer to standard
input, stdout is a FILE type pointer to standard output,
and stderr is a FILE type pointer to the standard error
device.

Copyright C Programming ver 2.0 Page 264


Nuggets on FILE Type Pointers

• In case fopen( ) is unsuccessful in opening a file (file may


not exist, or has become corrupt), it returns a null (zero)
value called NULL.

• NULL is defined in the header file stdio.h

• The NULL return value of fopen( ) can be used for error


checking as in the following line of code:
• if ((fp = fopen(“a.dat”, “r”)) = = NULL)
• printf(“Error Message”);

Copyright C Programming ver 2.0 Page 265


The exit( ) function

• The exit( ) function is generally used in conjunction with


checking the return value of the fopen( ) statement.

• If fopen( ) returns a NULL, a corresponding error message


can be printed, and program execution can be terminated
gracefully using the exit( ) function.

• if ((fp = fopen(“a.dat”, “r”)) = = NULL)


• {
• printf(“Error Message”);
• exit( );
• }

Copyright C Programming ver 2.0 Page 266


Line Input/Output With Files

• C provides the functions fgets( ) and fputs( ) for performing line


input/output from/to files.

• The prototype declaration for fgets( ) is given below:


• char* fgets(char *line, int maxline, FILE *fp);

• The explanations to the parameters of fgets( ) is:


– char* line – the string into which data from the file is to be read
– int maxline – the maximum length of the line in the file from which data
is being read
– FILE *fp – is the file pointer to the file from which data is being read

Copyright C Programming ver 2.0 Page 267


Line Input/Output With Files

• fgets( ) reads the next input line (including the newline)


from file fp into the character array line;

• At most maxline-1 characters will be read. The resulting


line is terminated with '\0'.

• Normally fgets( ) returns line; on end of file, or error it


returns NULL.

Copyright C Programming ver 2.0 Page 268


Line Input/Output With Files

• For output, the function fputs( ) writes a string (which


need not contain a newline) to a file:

– int fputs(char *line, FILE *fp)

• It returns EOF if an error occurs, and non-negative


otherwise.

Copyright C Programming ver 2.0 Page 269


File Copy Program Using Line I/O

• #define MAX 81;


• #include<stdio.h>
• main( )
• {
• FILE *fp1, *fp2;
• fp1 = fopen( “source.dat”, “r”);
• fp2 = fopen( “target.dat”, “w”);
• char string[MAX];
• while ( (fgets(string, MAX, fp1)) != NULL)
• {
• fputs (string, fp2);
• }
• fclose(fp1);
• fclose(fp2);
• }

Copyright C Programming ver 2.0 Page 270


Formatted File Input/Output

• C facilitates data to be stored in a file in a format of your


choice. You can read and write data from/to a file in a
formatted manner using fscanf( ) and fprintf( ).

• Apart from receiving as the first argument the format


specification (which governs the way data is read/written
to/from a file), these functions also need the file pointer as
a second argument.

• fscanf( ) returns the value EOF upon encountering end-of-


file.

Copyright C Programming ver 2.0 Page 271


Formatted File Input/Output

• fscanf( ) assumes the field separator to be any white space


character, i.e., a space, a tab, or a newline character.

• The statement printf(“The test value is %d”, i); can be


rewritten using the function fprintf( ) as:
– fprintf( stdout, “The test value is %d”, x);

• The statement scanf( “%6s%d, string, &i) can be rewritten


using the function fscanf( ) as:
– fscanf(stdin, “%6s%d”, string, &i);

Copyright C Programming ver 2.0 Page 272


Random Access

• Input from, or output to a file is effective relative to a


position in the file known as the current position in the file.

• For example, when a file is opened for input, the current


position in the file from which input takes place is the
beginning of the file.

• If, after opening the file, the first input operation results in
ten bytes being read from the file, the current position in
the file from which the next input operation will take place
is from the eleventh byte position.

Copyright C Programming ver 2.0 Page 273


Random Access

• It is therefore clear that input or output from a file results


in a shift in the current position in the file.

• The current position in a file is the next byte position from


where data will be read from in an input operation, or
written to in an output operation.

• The current position advances by the number of bytes read


or written.

• A current position beyond the last byte in the file indicates


end of file.

Copyright C Programming ver 2.0 Page 274


Random Access

• For example, when a file is opened for input, the current


position in the file from which input takes place is the
beginning of the file.

• If, after opening the file, the first input operation results in
ten bytes being read from the file, the current position in the
file from which the next input operation will take place is
from the eleventh byte position.

• This is sequential access, in which a file is opened, and you


start reading bytes from the file sequentially till end of file.
The same argument cab be extended to sequential write.

Copyright C Programming ver 2.0 Page 275


Random Access

• In sharp contrast to sequential access is random access that


involves reading from any arbitrary position in the file, or
writing to any arbitrary position in the file.

• Random access therefore mandates that we must have a


mechanism for positioning the current position in the file
to any arbitrary position in the file for performing input or
output.

• To facilitate this, C provides the fseek( ) function, the


prototype of which is as follows:

Copyright C Programming ver 2.0 Page 276


The fseek( ) Function

• The function fseek( ) is used for repositioning the current position in a file
opened by the function fopen( ).

• int rtn = fseek(file pointer, offset, from where)


• where,
• int rtn is the value returned by the function fseek( ). fseek( ) returns the value
0 if successful, and 1 if unsuccessful.
• FILE file-pointer is the pointer to the file
• long offset is the number of bytes that the current position will shift on a file
• int from-where can have one of three values:
– from beginning of file (represented as 0)
– from current position (represented as 1)
– from end of file (represented as 2)

Copyright C Programming ver 2.0 Page 277


The fseek( ) function

• Consider the following schematic representation of a file in terms of a


string of 30 bytes. The file contains records and fields that are not
delimited by any special character.

• fp = fopen(“employee.dat”, r)
employee.dat

1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0

current offset

Copyright C Programming ver 2.0 Page 278


The fseek( ) function

• Consider the following schematic representation of a file in terms of a


string of 30 bytes. The file contains records and fields that are not
delimited by any special character.

• fseek(fp, 10L, 0);


employee.dat

1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0

current offset

Copyright C Programming ver 2.0 Page 279


The fseek( ) function

• Consider the following schematic representation of a file in terms of a


string of 30 bytes. The file contains records and fields that are not
delimited by any special character.

• fgets(string, 7, fp);
employee.dat

1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0

current offset

Copyright C Programming ver 2.0 Page 280


The fseek( ) function

• Consider the following schematic representation of a file in terms of a


string of 30 bytes. The file contains records and fields that are not
delimited by any special character.

• fseek(fp, -10L, 2)
employee.dat

1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0

current offset

Copyright C Programming ver 2.0 Page 281


The rewind( ) Function

• The function, rewind( ) is used to reposition the current


position in the file (wherever it may be) to the beginning of
the file.

• The syntax of the function rewind( ) is:


– rewind (file-pointer);
– where file-pointer is the FILE type pointer returned by the
function fopen( ).

• After invoking rewind( ), the current position in the file is


always the first byte position, i.e., at the beginning of the
file.
Copyright C Programming ver 2.0 Page 282
Updating Data in a File

• A file that needs to be updated should be opened using


fopen( ) in the “r+” mode, i.e., opening a file for read and
write.

• The “r+” mode is useful for operations on files that need to


be updated.

• Consider a file, “SALARY.DAT” which contains the


following structure:

Copyright C Programming ver 2.0 Page 283


Updating Data in a File

Structure of SALARY.DAT
employee number salary

Copyright C Programming ver 2.0 Page 284


Updating Data in a File
• /* function to read the salary field (beginning at byte no. 5 and ending at
byte 10) for each record in the file, and increase it by 100 */
• #include<stdio.h>
• main( )
• {
• FILE *fp;
• char empno[5], salary[7];
• double fsalary, atof( );
• long int pos = 4L, offset = 4L;
• /* open the file SALARY.DAT in read-write mode */
• if ((fp = fopen( “SALARY.DAT”, “r+”)) = = NULL)
• {
• printf(“Error opening file SALARY.DAT”);
• exit( );
• }
Copyright C Programming ver 2.0 Page 285
Updating Data in a File

• while(( fseek( fp, offset, 1)) = = 0)


• {
• fgets(salary, 7, fp);
• f_salary = atof(salary) + 100;
• sprintf(salary, “%6.2f”, f_salary); /*convert f_salary to a string */
• fseek(fp, pos, 0); /* reposition at start of salary field */
• fputs(salary, fp); /* update salary field
• pos += 10; /* increment pos to starting byte of salary field for the next
record */
• }
• printf(“The file SALARY.DAT has been updated”);
• fclose(fp);
• }

Copyright C Programming ver 2.0 Page 286


The ftell( ) and feof( ) Function

• The prototype declaration for the function ftell( ) is:


– long ftell(FILE *fp)

• ftell returns the current file position for stream, or -1 on


error.

• The prototype declaration for the function feof( ) is:


– int feof(FILE *fp)

• feof returns non-zero if the end of file indicator for stream


is set.

Copyright C Programming ver 2.0 Page 287


Summary

• In this session you learnt to:


• Use pointers of type FILE when performing file I/O
• Perform Input/Output with files
• Use character-based file input/output functions
• Use string-based file input/output functions
• Perform random access on files using the functions
– fseek( )
– ftell( )
– rewind( )
– feof( )

Copyright C Programming ver 2.0 Page 288


Copyright C Programming ver 2.0 Page 289
Chapter 7
User-Defined Data Types

Copyright C Programming ver 2.0 Page 290


Objectives

• In this session, you will learn to:


• Trace down the genesis of user-defined data types
• Declare user-defined data types, namely
– Structures
– Unions
– Enumerations
• Use pointers to structures and unions
• Declare arrays of structures
• Pass structures to functions
• Use the typedef declaration for easier and compact coding
• Use the functions fread( ) and fwrite( ) to read and write
structures to and from files

Copyright C Programming ver 2.0 Page 291


User-Defined Data Types – The Genesis

• Consider a situation where your application needs to read


records from a file for processing.

• The general approach would be to read the various fields


of a record into corresponding memory variables.

• Computations can then be performed on these memory


variables, the contents of which can then be updated to the
file.

• But, this approach would involve manipulating the current


file offset for the relevant fields that need to be updated.

Copyright C Programming ver 2.0 Page 292


User-Defined Data Types – The Genesis

• Processing would become a lot more simpler if it were


possible to read an entire record into an extended variable
declaration, the structure of which would be the same as
the record in the file.

• This extended variable declaration in turn would be a


collection of variables of different data types, each
variable matching the data type of the fields in the record.

• The flexibility with such an arrangement is that the


collection of variables making up the extended variable
declaration can be referred to in the program using a single
name.
Copyright C Programming ver 2.0 Page 293
Structures – The Definition

• A structure is a collection of one or more variables,


possibly of different types, grouped together under a single
name for convenient handling.

• Structures help to organize complicated data, particularly


in large programs, because they permit a group of related
variables to be treated as a unit instead of as separate
entities.

• An example of a structure is the payroll record: an


employee is described by a set of attributes such as name,
address, social security number, salary, etc.

Copyright C Programming ver 2.0 Page 294


Structures – The Definition

• Some of these in turn could be structures: a name has


several components, as does an address.

• Other examples of structures are: a point is a pair of


coordinates, a rectangle is a pair of points, and so on.

• The main change made by the ANSI standard is to define


structure assignment - structures may be copied and
assigned to, passed to functions, and returned by functions.

• Automatic structures and arrays may now also be


initialized.

Copyright C Programming ver 2.0 Page 295


Structures – Defining a Type

• When we declare a structure, we are defining a type.

• A structure declaration results in the definition of a


template or a blueprint for a user-defined data type.

• Upon declaring a structure, the compiler identifies the


structure declaration as a user-defined data type over and
above the fundamental data types, or primitive data types
built into the compiler.

• A structure therefore is a mechanism for the extension


of the type mechanism in the C language.

Copyright C Programming ver 2.0 Page 296


Declaring a Structure

• The C language provides the struct keyword for declaring


a structure. The following is a structure declaration for
employee attributes.

• struct empdata {
• int empno;
• char name[10];
• char job[10];
• float salary;
• };

Copyright C Programming ver 2.0 Page 297


Declaring a Structure

• The keyword struct introduces a structure declaration,


which is a list of declarations enclosed in braces.

• An optional name called a structure tag may follow the


word struct, as with employee in the previous example.

• The tag names this kind of structure, and can be used
subsequently as a shorthand for the part of the declaration
in braces.

• A struct declaration defines a type.

Copyright C Programming ver 2.0 Page 298


Declaring a Structure - Conventions

• The variables named in a structure are called members. A


structure member or tag, and an ordinary (i.e., non-member)
variable can have the same name without conflict, since they
can always be distinguished by context.

• Furthermore, the same member names may occur in different


structures, although as a matter of style one would normally use
the same names only for closely related structure variables.

• Variables of a structure type may immediately follow the


structure declaration, or may be defined separately as follows:

Copyright C Programming ver 2.0 Page 299


Declaring a Structure Variable

• struct empdata {
• int empno;
• char name[10];
• char job[10];
• float salary;
• } emprec; /* emprec is a variable of structure type empdata */

• Or a structure can be declared separately as:


• struct empdata emprec;/* emprec is a variable of structure type
empdata */

Copyright C Programming ver 2.0 Page 300


Declaring a Structure

• Declaring a structure only defines a template or a blueprint for a


data type. It does not therefore result in the allocation of memory.

• Memory is allocated only when a variable of a structure type is


declared in the program.

• Till a variable of a structure type is created, a structure declaration


is only identified as a type, and no memory is allocated.

• Even for fundamental data types, the compiler does not allocate
memory for types. Rather, it allocates memory for implementations
of fundamental data types, in short, memory is allocated only for a
variable declaration.

Copyright C Programming ver 2.0 Page 301


Accessing Elements of a Structure

• Once a structure variable has been declared, the individual


members of the structure can be accessed by prefixing the
structure variable to the element of the structure.
• struct empdata {
• int empno;
• char name[10];
• char job[10];
• float salary;
• }
• struct empdata emprec;
• emprec.empno /* referring to the element of the structure variable
emprec */

Copyright C Programming ver 2.0 Page 302


Passing Structures to Functions

• #include<stdio.h>
• struct salesdata
• {
• int transaction_number;
• int salesman_number;
• int product_number;
• int units_sold;
• float value_of_sale;
• };
• main( )
• {
• struct salesdata salesvar;

Copyright C Programming ver 2.0 Page 303


Passing Structures to Functions

• printf(“enter transaction number :”);


• scanf(“%d”, &salesvar.transaction_number);
• fflush(stdin);
• printf(“enter salesman number :”);
• scanf(“%d”, &salesvar.salesman_number);
• fflush(stdin);
• printf(“enter product number :”);
• scanf(“%d”, &salesvar.product_number);
• fflush(stdin);
• printf(“enter units sold :”);
• scanf(“%d”, &salesvar.units_sold);
• fflush(stdin);

Copyright C Programming ver 2.0 Page 304


Passing Structures to Functions

• compute(&salesvar);
• .
• .
• .
• }
• compute( salesdata *salesptr)
• {
• static float product_unit_price = {10.0, 20.0, 30.0, 40.0};
• /*product unit price for products numbered 1 through 4 */
• salesptr-> value_of_sale = (float)salesptr-> units_sold *
• product_unit_price[salesptr->product_number – 1]
• }

Copyright C Programming ver 2.0 Page 305


Array of Structures

• Just as it is possible to declare arrays of primitive data


types, it should also be possible to declare arrays of
structures as well.

• Consider the structure declaration for the employee details


used earlier.
• struct empdata {
• int empno;
• char name[10];
• char job[10];
• float salary;
• };

Copyright C Programming ver 2.0 Page 306


Array of Structures

• If one were to define an array of structure variables, one


would do so as follows:

• struct empdata employee_array[4];

• The rationale for declaring an array of structures becomes


clear when one wants to improve I/O efficiency in a
program.

• Once an array of structures is defined, it is possible to read


in a block of records from a file using an appropriate
function (fread( )), the details of which you will see
shortly.
Copyright C Programming ver 2.0 Page 307
Writing Records On To a File

• The fwrite( ) function allows a structure variable to be


written on to a file.

• The following statement writes the structure variable


salesvar on to a file “SALES.DAT, which is pointed to by
the FILE type pointer fp:
• fwrite( &salesvar, sizeof(struct salesdata), 1, fp);

• The arguments to the function fwrite( ) are explained as


follows:

Copyright C Programming ver 2.0 Page 308


Writing Structures To a File

– Here &salesrec is the address of the structure variable to be


written to the file.
– The second parameter is the size of the data to be written, i.e., size
of the structure salesdata. The parameter to the sizeof( ) operator
is the structure label, or the structure type itself, and not a variable
of the structure type. The sizeof( ) operator can be used to
determine the size of any data type in C (fundamental as well as
user-defined data types.
– The third parameter of fwrite( ) is the number of structure
variables to be written to the file. In our statement, it is 1, since
only one structure variable is written to the file. In case, an array
of 4 structure variables is to be written to a file using fwrite( ), the
third parameter to fwrite( ) should be 4.
– The last parameter is the pointer to the file.

Copyright C Programming ver 2.0 Page 309


Reading Records from a File

• Records can be read from a file using fread( ). The


corresponding read statement using fread( ) for the earlier
fwrite( ) statement would be:
• fread(&salesvar, sizeof(struct salesdata), 1, fp);

• Here, the first parameter &salesvar is the address of the


structure variable salesvar into which 1 record is to be
read from the file pointed to by the FILE type pointer fp.

• The second parameter specifies the size of the data to be


read into the structure variable.

Copyright C Programming ver 2.0 Page 310


Reading Records from a File

• fread( ) will return the actual number of records read from the file. This
feature can be checked for a successful read.

• if ((fread( &salesvar, sizeof(struct salesdata), 1, fp)) != 1)


• error code;

• An odd feature of the fread( ) function is that it does not return any
special character on encountering end of file.

• Therefore, after every read using fread( ), care must be taken to check
for end of file, for which the standard C library provides the feof( )
function. It can be used thus:
• if(feof(fp))

Copyright C Programming ver 2.0 Page 311


Union
• Can hold objects of different types and sizes at different times
• Syntax similar to structure but meaning is different
• All members of union share same storage space
• Only the last data member defined can be accessed
• Means of conserving memory
• union declaration similar to struct declaration
eg. union u_type {
int i;
char ch;
};
union u_type cnvt;
Copyright C Programming ver 2.0 Page 312
Unions

• In cnvt, both integer i and character ch share the same


memory location. Of course, i occupies 2 bytes (assuming
2-byte integers, and ch uses only one byte.

Byte 0 Byte 1

ch

Copyright C Programming ver 2.0 Page 313


Unions

• To access a member of a union, use the same syntax that


you would use for structures: the dot and arrow operators.

• If you are operating on the union directly, use the dot


operator. If the union is accessed through a pointer, use the
arrow operator.

• For example, to assign the integer 10 to element i of cnvt,


write cnvt.i = 10;

Copyright C Programming ver 2.0 Page 314


Unions

• In the following code snippet, a pointer to cnvt is passed to a


function:
• void func1( union u_type *un)
• {
• un->i = 10; /* assign 10 to cnvt using function */
• }

• Using a union can aid in the production of machine-


independent (portable) code. Because the compiler keeps
track of the actual size of the union members, no unnecessary
machine dependencies are produced.

Copyright C Programming ver 2.0 Page 315


Unions

• Unions are used frequently when specialized type conversions


are needed because you can refer to the data held in the union
in fundamentally different ways.

• Consider the problem of writing a short integer to a disk file.


The C standard library defines no function specifically
designed to write a short integer to a file.

• While you can write any type of data to a file using fwrite( ),
using fwrite( ) incurs excessive overhead for such a simple
operation.
Copyright C Programming ver 2.0 Page 316
Unions

• However, using a union, you can easily create a function called


putw( ), which represents the binary representation of a short integer
to a file one byte at a time.

• The following example assumes that short integers are 2 bytes long.
First, create a union consisting of one short integer and a 2-byte
character array:
• union pw
• {
• short int i;
• char ch[2];
• };

Copyright C Programming ver 2.0 Page 317


Unions

• Now, you can use pw to create the version of putw( )


shown in the following program:
• #include <stdio.h>
• union pw
• {
• short int i;
• char ch[2];
• };

• int putw( short int num, FILE *fp);

Copyright C Programming ver 2.0 Page 318


Unions

• int main (void)


• {
• FILE *fp;
• fp = fopen( “test.tmp”, “wb+”);
• putw(1000, fp); /* write the value 1000 as an integer */
• fclose( fp );
• return 0;
• }

Copyright C Programming ver 2.0 Page 319


Unions

• int putw( short int num, FILE *fp)


• {
• union pw word;
• word.i = num;
• fputc( word.ch[0], fp); /* write first half */
• fputc( word.ch[1], fp); /* write second half */
• }

• Although putw( ) is called with a short integer, it can still


use the standard function fputc( ) to write each byte in the
integer to a disk file one byte at a time.

Copyright C Programming ver 2.0 Page 320


Enumeration

• Is a set of named integer constants that specify all the legal


values a variable of that type can have.

• The keyword enum signals the start of an enumeration type.

• The general form for enumeration is


• enum enum-type-name { enumeration list } variable_list;

• enum coin { penny, nickel, dime, quarter, half_dollar,


dollar};
• enum coin money;
Copyright C Programming ver 2.0 Page 321
Enumeration

• Given these declarations, the following types of statements


are perfectly valid:
• money = dime;
• if (money = = quarter)
• printf( “Money is a quarter. \n”);

• The key point to understand about an enumeration is that


each of the symbols stands for an integer value.

• As such, they may be used anywhere that an integer may


be used.

Copyright C Programming ver 2.0 Page 322


Enumeration

• Each symbol is given a value one greater than the symbol


that precedes it. The value of the first enumeration symbol
is 0. Therefore,
• printf( “%d %d”, penny, dime);
• displays 0 2 on the screen.

• You can specify the value of one or more of the symbols


by using an initializer.

• Do this by following the symbol with an equal sign and an


integer value.

Copyright C Programming ver 2.0 Page 323


Enumeration

• For example, the following code assigns the value of 100


to quarter:
• enum coin { penny, nickel, dime, quarter=100, half_dollar,
dollar};
• Now, the values of these symbols are:
• penny 0
• nickel 1
• dime 2
• quarter 100
• half_dollar 101
• dollar 102

Copyright C Programming ver 2.0 Page 324


Enumeration

• One common but erroneous assumption about enumerations


is that the symbols can be input and output directly. This is
not the case.

• For example, the following code fragment will not perform


as desired:
• money = dollar;
• printf( “%s”, money);

• Dollar is simply a name for an integer; it is not a string.

Copyright C Programming ver 2.0 Page 325


Enumeration

• For the same reason, you cannot use this code to achieve
the desired results:
• /* this code is wrong */
• strcpy (money, “dime”);

• That is, a string that contains the name of a symbol is not


automatically converted to that symbol.

• Actually creating code to input and output enumeration


symbols is quite tedious (unless you are willing to settle
for their integer values).

Copyright C Programming ver 2.0 Page 326


Enumeration

• For example, you need the following code to display, in words, the kind of
coins that money contains:
• switch (money)
• {
• case penny : printf( “penny”);
• break;
• case nickel : printf( “nickel”);
• break;
• case dime : printf( “dime”);
• break;
• case quarter : printf( “quarter”);
• break;
• case half_dollar : printf( “half_dollar”);
• break;
• case dollar : printf( “dollar”);
• break;
• }

Copyright C Programming ver 2.0 Page 327


Typedef Statements

• Creates synonyms (aliases) for previously defined datatypes


• Used to create shorter type names
• Format: typedef type new-type;
– Example: typedef struct Card * CardPtr;
defines a new type name CardPtr as a synonym for type
struct Card *
• typedef does not create a new datatype
• Only creates an alias

Copyright C Programming ver 2.0 Page 328


Summary

• In this session, you learnt to:


• Trace down the genesis of user-defined data types
• Declare user-defined data types, namely
– Structures
– Unions
– Enumerations
• Use pointers to structures and unions
• Declare arrays of structures
• Pass structures to functions
• Use the typedef declaration for easier and compact coding
• Use the functions fread( ) and fwrite( ) to read and write
structures to and from files

Copyright C Programming ver 2.0 Page 329


Copyright C Programming ver 2.0 Page 330
Chapter 8
Recursion

Copyright C Programming ver 2.0 Page 331


Objectives

• In this session, you will learn to:


• Define a recursive function
• Describe how to write a recursive function
• Describe recursive calls to a function using the runtime
stack
• Define, Declare, and Use Function Pointers

Copyright C Programming ver 2.0 Page 332


Introduction

• Many concepts typically in mathematics are defined by


presenting a process leading up to that concept. For
example,  is defined as ratio of the circumference of a
circle to its diameter.

• This is equivalent to the following set of instructions:


– Obtain the circumference of a circle
– Obtain its diameter
– Divide circumference by the diameter and call the result 
– Clearly, the process specified must terminate with a definite result.

Copyright C Programming ver 2.0 Page 333


The Factorial Function

• Another example of a definition specified by a process is


that of the factorial function.

• Given a positive integer n, n factorial is defined as the


product of all integers between n and 1.

• For example, 4 factorial equals 4 * 3 * 2 * 1 = 24.


0 factorial is defined as 1.

• In mathematics, the exclamation mark (!) is used to denote


the factorial function.

Copyright C Programming ver 2.0 Page 334


The Factorial Function

• You may therefore write the definition of this function as


follows:
• n! = 1 if n = = 0
• n! = n * (n-1) * (n-2) * ….. * 1 if n > 0.

• The dots are really a shorthand notation for all the numbers
between (n – 3) and (n – 2) multiplied together.

• To avoid the shorthand in the definition of n!, we would


have to list a formula for n! for each value of n separately,
as follows:

Copyright C Programming ver 2.0 Page 335


The Factorial Function

• 0! = 1
• 1! = 1
• 2! = 2 * 1
• 3! = 3 * 2 * 1
• 4! = 4 * 3 * 2 * 1

• It is cumbersome for you to list the formula for the factorial of each
integer.

• To avoid any shorthand, and to avoid an infinite set of definitions,


but yet to define the function precisely, you may present an
algorithm that accepts an integer n and returns the value of n!.
Copyright C Programming ver 2.0 Page 336
The Factorial Function

prod = 1
for (x = n; x > 0; x--)
{
prod *= x;
return (prod)
}

• Such an algorithm is iterative because it calls for the


explicit repetition of some process until a certain condition
is met.

• This function can be translated readily into a C function


that returns n! when n is input as a parameter.

Copyright C Programming ver 2.0 Page 337


The Factorial Function

• Pay closer attention to the definition of n! that lists a


separate formula for each value of n.

• You may note, for example, that 4! equals 4 * 3 * 2 * 1,


which equals 4 * 3!.

• In fact, for any n > 0, you see that n! equals n * (n – 1)!.

• Multiplying n by the product of all integers from n – 1 to 1


yields the product of all integers from n to 1.

Copyright C Programming ver 2.0 Page 338


The Factorial Function

• You may therefore define:


• 0! = 1
• 1! = 1 * 0!
• 2! = 2 * 1!
• 3! = 3 * 2!
• 4! = 4 * 3!

Copyright C Programming ver 2.0 Page 339


The Factorial Function

• Using the mathematical notation used earlier, you can write the
factorial of any number as:
• n! = 1 if n = = 0
• n! = n * (n – 1)! If n > 0

• This definition is interesting since it defines the factorial


function in terms of itself.

• This seems to be a circular definition and totally unacceptable


until you realize that the mathematical notation is only a
concise way of writing out the infinite number of equations
necessary to define n! for each n. 0! is defined directly as 1.
Copyright C Programming ver 2.0 Page 340
The Factorial Function

• Once 0! has been defined, defining 1! As 1* 0! is not


circular at all.

• Similarly once 1! factorial has been defined, defining 2! as


2 * 1! is equally straightforward.

• It may be argued that the latter notation is more precise than


the definition of n! as n * (n-1) * (n-2) * ….. * 1 for n > 0
because it does not resort to dots to be filled in by the
logical intuition of the reader.

Copyright C Programming ver 2.0 Page 341


The Factorial Function

• Such a definition, which defines a problem in terms of a


simpler case of itself, is called a recursive definition.

• Let us see how the recursive definition of the factorial


function may be used to evaluate 5!.

• The definition states that 5! Equals 5 * 4!.

• Thus, before you can evaluate 5!, you must first evaluate
4!. Using the definition once more, you find that 4! = 4 *
3!. Therefore, you must evaluate 3!.

Copyright C Programming ver 2.0 Page 342


The Factorial Function

• Repeating this process, you have:


• 5! = 5 * 4!
• 4! = 4 * 3!
• 3! = 3 * 2!
• 2! = 2 * 1!
• 1! = 1 * 0!
• 0! = 1

Copyright C Programming ver 2.0 Page 343


The Factorial Function

• From the aforesaid expression, it is obvious that each case


is reduced to a simpler case until we reach the case of 0!,
which is defined directly as 1.

• On the last line, you have a value that is defined directly


and not as the value of another number (line containing 0!
= 1).

• You may therefore backtrack from line 1 to line 6,


returning the value computed in one line to evaluate the
result of the previous line.

Copyright C Programming ver 2.0 Page 344


The Factorial Function

• This produces:

• 0! = 1
• 1! = 1 * 0! = 1 * 1 = 1
• 2! = 2 * 1! = 2 * 1 = 2
• 3! = 3 * 2! = 3 * 2 = 6
• 4! = 4 * 3! = 4 * 6 = 24
• 5! = 5 * 4! = 5 * 24 = 120

Copyright C Programming ver 2.0 Page 345


Evolving a Recursive Definition
for the Factorial
• You will now attempt to incorporate this process into an
algorithm. You want the algorithm to accept a non-negative
integer, and to compute in a variable fact the non-negative
integer that is n factorial.
• if (n == 0)
• fact = 1;
• else
• {
• x = n – 1;
• find the value of x!. call it y;
• fact = n * y;
• }

Copyright C Programming ver 2.0 Page 346


Evolving a Recursive Definition
for the Factorial
• This algorithm exhibits the process used to compute n! by
the recursive definition.

• The key to the algorithm is of course line 5 , where you are


told to find the value of x!.

• This requires re-executing the algorithm with input x,


since the method for computing the factorial is the
algorithm itself.

• To see that the algorithm eventually halts, note that at the


start of line 5, x equals n – 1.

Copyright C Programming ver 2.0 Page 347


Evolving a Recursive Definition
for the Factorial
• Each time the algorithm is executed, its input is one less
than the preceding time, so that 0 is eventually input to the
algorithm. At that point, the algorithm simply returns 1.

• This value is returned to line 5, which asks for the


evaluation of 0!.

• The multiplication of y (which equals 1) by n (which


equals 1) is then executed and the result is returned. This
sequence of multiplications and returns continues until the
original n! has been evaluated.

Copyright C Programming ver 2.0 Page 348


Properties of Recursive Definitions

• It is important to summarize what is involved in a


recursive definition or algorithm.

• One important requirement for a recursive algorithm to be


correct is that it does not generate an infinite sequence of
calls to itself.

• Clearly, any algorithm that does generate such a sequence


can never terminate.

Copyright C Programming ver 2.0 Page 349


Properties of Recursive Definitions

• For at least one argument or group of arguments, a


recursive function f must be defined in terms that do
not involve f.

• There must be a way out of the sequence of recursive


calls.

• For example, the non-recursive portion of the n! was 0!


that is equal to 1 and did not involve another recursive
definition.

Copyright C Programming ver 2.0 Page 350


C Program for a Factorial Function

• int fact(n)
• int n;
• {
• int x, y;
• if ( n == 0)
• return (1);
• else
• {
• x = n-1;
• y = fact(x);
• return ( n * y);
• }
• }

Copyright C Programming ver 2.0 Page 351


Mechanics of Recursion

• In the statement y = fact(x), the function fact( ) makes a


recursive call to itself.

• This is the essential ingredient of a recursive routine.

• The programmer assumes that the function being


computed has already been written, and uses it in its own
definition.

• However, the programmer must ensure that this does not


lead to an endless series of calls.

Copyright C Programming ver 2.0 Page 352


Mechanics of Recursion

• It is important to examine the execution of this function


when it is called by another program.

• For example, the calling program (main( )) contains the


statement: printf(“%d”, fact(4));

• When the calling function calls fact( ), the parameter n is


set equal to 4. Since n is not 0, x is set equal to 3.

• At that point, fact( ) is called a second time with an


argument of 3.

Copyright C Programming ver 2.0 Page 353


Mechanics of Recursion

• Therefore, the function fact( ) is reentered and the local


variables (x and y) and parameter (n) of the block are
reallocated.

• Since execution has not yet left the first call of fact( ), the
first allocation of these variables remains.

• Thus, there are two generations of each of these variables


in existence simultaneously in the stack for the first call,
and the second recursive call to the function fact( )
respectively.

Copyright C Programming ver 2.0 Page 354


Mechanics of Recursion

• From any point within the second execution of fact( ), only


the most recent copy of these variables can be referenced.

• In general, each time the function fact( ) is entered


recursively, a new set of local variables and parameters is
allocated on the stack, and only this new set may be
referenced within that call of fact( ).

• When a return from fact( ) to a point in a previous call


takes place, the most recent allocation of these variables is
freed from the stack when the function returns, and the
previous copy is reactivated (belonging to the previous
recursive call to the function fact( )).
Copyright C Programming ver 2.0 Page 355
Mechanics of Recursion

• This previous copy is the one that was allocated upon the
original entry to the previous call and is local to that call.

• This description suggests the use of a stack to keep the


successive generations of local variables and parameters.

• This stack is maintained by the C system and is invisible to


the programmer.

• Each time that a recursive function is entered, a new


allocation of its variables is pushed on top of the stack.

Copyright C Programming ver 2.0 Page 356


Mechanics of Recursion

• Any reference to a local variable or parameter is through


the current top of the stack.

• When the function returns, the stack is popped, the top


allocation is freed, and the previous allocation becomes
the current top of the stack to be used for referencing local
variables and parameters.

• You will now see how this mechanism is applied in


computing the factorial function.

Copyright C Programming ver 2.0 Page 357


Mechanics of Recursion

• The following figure contains a series of snapshots of the


stack for the variables n, x, and y as execution of the fact( )
function proceeds.

• Initially, the stacks are empty, as illustrated in (a).

• After the first call on fact( ) by the calling procedure, the


situation is as shown in (b) with n equal to 4. The variables
x and y are allocated but not initialized.

Copyright C Programming ver 2.0 Page 358


Mechanics of Recursion

• Since n does not equal 0, x is set to 3 and fact(3) is called


as shown in (c).

• The new value of n does not equal 0; therefore, x is set to 2


and fact(2) is called as shown in (d).

• This continues until n equals 0 as shown in(f).

• At that point, the value 1 is returned from the call to


fact(0).

Copyright C Programming ver 2.0 Page 359


Mechanics of Recursion

• Execution resumes from the point at which fact(0) was


called, which is the assignment of the returned value to the
copy of y declared in fact(1).

• This is shown by the status of the stack shown in figure


(g), where the variables allocated for fact(0) have been
freed and y is set to 1.

• The statement return (n * y) is then executed, multiplying


the top values of n and y to obtain 1, and returning the
value to fact(2) as shown in (h).

Copyright C Programming ver 2.0 Page 360


Mechanics of Recursion

• This process is repeated twice more, until finally the value


of y in fact(4) equals 6.

• The statement return (n * y) is executed one more time.

• The product 24 is returned to the calling function where it


is printed by the statement printf(“%d”, fact(4));

• Note that each time that a recursive routine returns, it


returns to the point immediately following the point from
which it was called.

Copyright C Programming ver 2.0 Page 361


Mechanics of Recursion

• Thus, the recursive call to fact(3) returns to the assignment


of the result to y within fact(4), but the call to fact(4)
returns to the printf( ) statement in the calling function.
(a) initially (b) fact(4) (c) fact(3) (c) fact(2)

2 * *
3 * *
3 2 *
4 * * 4 3 * 4 3 *

n x y n x y n x y n x y

Copyright C Programming ver 2.0 Page 362


Mechanics of Recursion

(e) fact(1) (f) fact(0) (g) y = fact(0) (h) y = fact(1)

0 * *

1 * * 1 0 *
1 0 1
2 1 * 2 1 *
2 1 * 2 1 1
3 2 * 3 2 *
3 2 * 3 2 *
4 3 * 4 3 *
4 3 * 4 3 *

n x y n x y n x y n x y

Copyright C Programming ver 2.0 Page 363


Mechanics of Recursion

(i) y = fact(2) (j) y = fact(3) Pritnf(“%d”, fact(4))

3 2 2

4 3 * 4 3 6

n x y n x y n x y

The stack at various times during execution. An asterisk indicates an uninitialized value.

Copyright C Programming ver 2.0 Page 364


Function Pointers

• Function Pointers are pointers, i.e. variables, which point


to the address of a function.

• You must keep in mind, that a running program gets a


certain space in the main-memory.

• Both, the executable compiled program code and the used


variables, are put inside this memory.

• Thus a function in the program code is, like e.g. a


character field, nothing else than an address.

Copyright C Programming ver 2.0 Page 365


Function Pointers

• It is only important how you, or better, your


compiler/processor, interpret the memory a pointer points to.

• When you want to call a function fn() at a certain point in


your program, you just put the call of the function fn() at that
point in your source code.

• Then you compile your code, and every time your program
comes to that point, your function is called.

• But what can you do, if you don't know at build-time which
function has got to be called? Or, invoke functions at runtime.
Copyright C Programming ver 2.0 Page 366
Function Pointers

• You want to select one function out of a pool of possible


functions.

• However you can also solve the latter problem using a


switch-statement, where you call the functions just like
you want it, in the different branches.

• But there's still another way: Use a function pointer!

• Consider the example on the following slide:

Copyright C Programming ver 2.0 Page 367


Declaring and Using Function Pointers

• How are function pointers used? As stated above they are typically
used so one function can take in other functions as a parameter.

• Consider the following example:


• #include <stdio.h>
• int compute( int, int (*comp)(int) );
• int doubleIt( int );
• int tripleIt( int );
• int main()
• {
• int x;
• x = compute( 5, &doubleIt );
• printf("The result is: %i\n", x );

Copyright C Programming ver 2.0 Page 368


Declaring and Using Function Pointers

• x = compute( 5, &tripleIt );
• printf("The result is: %i\n", x );
• return 0;
• }

• int compute( int y, int (*comp)(int) )


• { return comp( y );
• }
• int doubleIt( int y )
• { return y*2;
• }
• int tripleIt( int y )
• { return y*3;
• }

Copyright C Programming ver 2.0 Page 369


Declaring and Using Function Pointers

• Aside from main( ), this program has 3 functions.

• The functions doubleIt( ) and tripleIt( ) are just run of


mill functions that take in an integer, either double or triple
the value of the argument received, and return the value.

• The function of interest here is compute( ). It starts off


normal. It returns an int, and the first parameter is an int.

• But the second parameter is pretty strange looking. The


whole "int (comp*)(int)" is one parameter, which, in fact,
is the format of a function pointer.

Copyright C Programming ver 2.0 Page 370


Declaring and Using Function Pointers

• Basically it says compute( ) wants a pointer to a function


that takes one integer parameter, and returns an integer.
And it is going to refer to this function through the
parameter name comp.

• When compute( ) is called, it uses its parameter comp just


like a normal function. When a function pointer is passed
to a function, it can be used like a normal function.

• When compute( ) is called in main( ), the second


parameter is given the name of another function with an
ampersand.

Copyright C Programming ver 2.0 Page 371


Declaring and Using Function Pointers

• The ampersand is of course, the "address of" operator. So


this is passing the address of doubleIt( ) (and pointers are
really just addresses). So this is how compute( ) gets the
pointer to doubleIt( )

• It is important to note however, that if the return type of


the function doubleIt( ) and it's parameter list did not
match the ones for the function pointer comp, it could not
be used.

• When you pass a function pointer, the functions header


must match the header of the function pointer definition
exactly, or it cannot be used.
Copyright C Programming ver 2.0 Page 372
Summary

• In this session, you learnt to:


• Define a recursive function
• Describe how to write a recursive function
• Describe recursive calls to a function using the runtime
stack
• Define, Declare, and Use Function Pointers

Copyright C Programming ver 2.0 Page 373

You might also like