You are on page 1of 111

C PROGRAMMING

CHARACTERISTICS
 Correctness- The extent to which a program
satisfies its specification and fulfills the
customer’s mission objectives .

 Reliability- The extent to which a program can


be expected to perform its intended function
with required precision .

 Efficiency- The amount of computing resources


and code required by a program to perform its
function.
 Integrity-The extent to which the access to data
by unauthorized persons, can be controlled.
 Usability- The effort required to learn, operate,
prepare input, and interpret output of the
program.
 Maintainability -The effort required to locate and
fix an error in a program.
 Flexibility- The effort required to modify an
operations program.
 Testability-The effort required to test a program
to ensure that it performs its intended function.
How to achieve the good
programming goals
 Analyze the program carefully.
 Break the program into small modules called building
blocks.
 Use meaningful names for variables and functions.
 Follow uniform naming conventions.
 Let each block do only its specified task and nothing
else.
 Every building block should have a header information
block.
 At least 30 % of the statements should be commented.
 Comments should be short and enlightening
DATA TYPES AND OPERATORS
 char : A single byte, capable of holding
one character in the local character set.
 int : An integer, typically reflecting the
natural size of integers on the host
machine.
 float : A single precision floating point.
 double: Double precision floating point. To
accept and print a double in a program
 In addition there are a number of qualifiers that
con be applied to these basic types.
‘short’ and ‘long’ to integers
These qualifiers provide different lengths of
integers, ‘short’ is often 16 bits and ‘long’ 32
bits, and
int either 16 or 32 bits depending on the
compiler.
‘signed’ and ‘unsigned’ to integer or character
and ‘long double’ specifies extended precision
floating point.
OPERATORS

 Arithmetic operators.
 Relational operators and logical operators.
 Increment and decrement operators .
 Bitwise operators.
 Assignment operator
 Ternary operator or conditional operator.
Arithmetic operators

 The arithmetic operators in C are


 ‘+’, addition
 ‘-’, subtraction
 ‘*’ , multiplication
 ‘/’, division.
 There is a ‘%’ operator called modulus
operator.
Relational operators
 The relational operators are
 ‘>‘ (greater than ),
 ‘<‘ ( lesser than ),
 ‘>=‘ (greater than or equal to),
 '<=‘ (lesser than or equal to),
 ‘==‘ (equal to) and
 ‘!=‘ (not equal to)
 The result of two values connected by these
operators is either true (non-zero) or false (O).
Logical operators

 The logical operators are


 ‘&&’ (and) and
 ‘II’ (inclusive or) .
 Expressions connected by logical operators
are evaluated from left to right and
evaluation is stopped as soon as truth or
falsehood of the result is known.
Increment and decrement
operators
 Two unusual operators ‘++’ and ‘ – ’ are
provided by C for incrementing and
decrementing variables

 The ‘++’ operator (incrementing operator) when


used with the variable adds 1 to the variable .
 The ‘--’ operator (decrementing operator) when
used with the variable subtracts 1 from the
variable .
 The incremental operators can be used
either as prefix operators, where the
operation is done before the value of the
variable is used, or as postfix operators
where the operation is done after the
value of the variable is used
Assignment Operator

 The assignment operator is ‘=‘ .This


operator copies the value on the right-
hand side into the variable or the address
on the left hand side .The result of the
operation has a value, which is the value
that is transferred and which can be used
in other expressions.
Conditional operator
 Conditional expressions are a shorthand
way of selecting one out of the two values
based on the value of another expression.
The syntax is :
exp1 ? exp2 : exp3
 If expression exp1 is true than the result
is value of expression exp2 otherwise it is
the value of expression exp3.
CONTROL FLOW STATEMENTS

 Control flow statements in a language


specify the computational order in the
program.
 The commonly used control flow
statements in ‘C’ are

 conditional : if-else, else-if, switch


 Loops: for, while, do-while.
If-Else
 This is used to express decisions.
 The if statement has the following syntax,
If (expression)
statement1 ;
else
statement2 ;
 The expression is evaluated, if it is true,
statement l is executed . If it is false, and if
there is an ‘else’ part (the else part being
optional) statement2 is executed instead.
Else-if

 A multiway decision is written using else-


if.
if (expression 1)
statement1;
else if(expression2)
statement2;
else if(expression3)
statement3 ;
else
statement4;
Switch
 The switch statement is a multiway
decision based on a single expression.
switch (expression)
case constant_expression : statements
case constant_expression : statements
case constant_expression : statements
default : statements
While

 The while loop has the form :


while ( expression )
statements ;

 where statements will be executed as long


as expression evaluates to a non-zero
value
FOR STATEMENT
 The for statement has the following syntax
:
for( expression 1; expression2 ;
expression3)
statements ;
 Expression l and expression3 are
assignments and expression2 is a
relational expression. Ali three expressions
are optional ; however the semicolons are
not.
 The for statement is equivalent to the
following while loop :

expression 1 ;
while ( expression 2)
statement ;
expression 3 ;
Do-While

 The do-while loop in C provides a loop


termination at the end of the loop. Its
syntax is
do
statement
while( expression );
 ‘while’ statement will be executed at least
once and then as long as expression
remains non-zero thereafter.
Break

 The 'break’ statement provides an early


exit from ‘for’, ‘while’ and ‘do’ loops, just
as from ‘switch’
 A break, causes the innermost loop or
switch to be exited immediately.
Continue
 The continue statement will result in
the next iteration of the enclosing
‘for’, ‘while’ or ‘do’ loop to execute.
 The continue statement applies only

to loops and not to switch.


Goto
 C does contain the goto statement but since its
use is not looked upon with favor, it will not be
discussed in detail . Goto abandons processing
in same deeply nested structure such as coming
out of two or more loops at once which is not
possible by ‘break’
 Its syntax is :
goto NAME;
NAME : statement
 The goto statement transfers control directly to
the statement !hat has NAME as its label.
FUNCTIONS
 In programming we normally break a task into
separate functions because it is easier to deal
with smaller tasks that may be independent of
other parts of the program. A normal C program
is a collection of functions. The main program,
called main, is a function that may invoke other
functions.
 A function will process information passed to it
from the, calling portion of the program, and
return a single value. Information is passed to
the function via special identifiers called
‘arguments’ also called ‘parameters’ and
returned via the ‘return’ statement.
Call by Value

 C passes arguments to functions by value.


That is, C makes a copy of the argument
and passes the copy to the function. If the
function modifies a parameter, the
function is modifying only a copy of the
original argument.
Call by Reference
 Often we want the function to have access
to the original argument in the invoking
function instead of its copy. In this case
we pass the argument by reference; that
is, we pass the address of the argument
as a parameter for the function. Since the
function has the address of the actual
argument, it can change the value of this
argument.
STORAGE CLASSES

 Automatic Variables
 External Variables
 Static Variables
Automatic Variables

 These variables are always declared within


a function and are local to the function in
which they are declared. Their scope is
confined only to that function. Any
variable declared within a function is an
automatic variable unless a different
storage-class is included within the
declaration
External Variables
 These variables are not confined to single
functions. Their scope extends from the
point of definition through the remainder
of' the program. They are also called
global variables, They can be accessed
from any function that falls within the
scope of the, entire program. They are
permanent so they retain values from one
function invocation to the next.
Static Variables
 The variables which retain their values
throughout the life of the program are
called static variables. lf a function is
exited and re-entered later the static
variables defined within that function, will
retain their farmer values.
 Static variables are defined within
individual functions and have same scope
as automatic variables.
Pointers

 What is a pointer?
A pointer is a group of memory
locations that stores the address of
another memory location.
 The operators used here are the unary
operators “ * ” and “ & ”.
 The unary operator “ * ” is the indirection
or dereferencing operator ; when applied
to a pointer , it accesses the object the
pointer points to .
 The unary operator “ & ” gets the address
of the memory location where a variable
resides.
 e.g. &a gets the memory address of the
variable a .
Declaration of pointers
 Pointers are declared using following syntax :

 char a[10],ch;

 int *p;i=NULL /* pi is a pointer to


integer, initialized to null so
that it does not point to any arbitrary
memory location */

 char *pca= a; /* pca is a pointer to char ,
initialised to point to the first
element of array a[10] i.e a[0]*/

 float *pf; /* un-initialized pointer .


Often the
cause of errors. */
 char *pc=&ch; /* pc is a pointer to char ,
initialized to point to ch
*/

 the unary operator “&” gives the
address of an object
 It cannot be applied to expressions,
constants or register variables.
 Examples :
 int x=1,y=2; /* x and y are integers
and initialised to 1 and 2 respectively
*/
 int *ip; /* ip is a pointer to int
or *ip is an integer */
 ip = &x; /* ip now points to x */
 y = *ip; /* The value of y is now
1(the value of x) */
 *ip = 0; /* x is now zero (since ip
was pointing to x) */
 a “pointer to void” is used to hold any
type of pointer but cannot be
dereferenced itself .
Precedence of Address and
Dereferencing Operators

 “&” and dereferencing “*” operators


have equal precedence.
 they associate from right to left.
 You have to be careful when you mix
“*” with “++” or “--” in a pointer
expression.
 The unary operators “*” and “&” bind
more tightly than arithmetic operators ,
so the assignment
 y = *ip + 1
 takes whatever ip points at , adds 1 ,
and assigns the result to y . This can be
understood as

 Before y = *ip + 1 After y = *ip
+1

 ip y 4000 ip y 4000

4000 5 2 4000 3
2
Difference between pointers
and ordinary variables
 For ordinary variables the C compiler
allocates memory on its own at
compilation time.
 memory location by assigning the
address of some other variable to the
pointer or by allocating memory when
the program runs.
 Allocation of memory is done by using
the C function “ malloc ”. The syntax of
malloc is:
 pointer=(datatype *) malloc (size of
memory to be allocated)
 e.g. to allocate 10 bytes of memory to
the pointer to integer *ip:
 ip=(int *) malloc (10);
 e.g. to free the memory allocated to the
pointer to integer *ip:
 free(ip);
C Memory model
 The C language views a program’s
memory as being divided into three pieces
:
 Text Area : The area for the program
code(instructions).
 Data Area : For static variables and data.
 Dynamic Area : For the automatic
variables ,for dynamic allocation and for
function call bookkeeping.
 The following diagram shows a conceptual
model of the memory layout for a C
program.
 Text
 Data
 Dynamic
 Besides the instructions which make up
the program , other items may also be
placed into the text area. Constant
items such as strings , jump tables for
switch statements , and floating point
constants are occasionally also allocated
in the text area. The text section is not
modifiable.
 Data objects which have a lifetime that
persists for the entire program are placed
in the data area. In many implementations ,
strings , floating point constants , and switch
tables are also placed in this area.
 The data area is sometimes divided into
two sections , an area for explicitly initialised
data and an area for “uninitialised” global and
static data.
 The dynamic area includes automatic
variables , function housekeeping
information , and storage which is used
when objects are created using the
memory allocation routines.
 The dynamic area is often
divided into two sections . The first is the
stack .
 The stack is the area where automatic
variables are dynamically allocated for
each function when the function is
invoked.
 The stack is also the area where , in
almost all systems , the actual
arguments are pushed for function calls.
 Function housekeeping information is also
pushed onto the stack when the called
function is entered. The stack is also the area
where compiler-generated temporaries (used
during complex computations and some
optimizations) are kept.

 The second part of the dynamic data area is


the heap , where user controlled dynamic
space allocations take place.
 A simplified memory model can be considered
for the understanding of pointer concepts as
below:
 Stack : The definition given earlier holds true
here too.
 Heap: This definition will be slightly modified .
It is the entire memory not allocated to the
stack and not in use by the Operating System .
Memory from the heap is allocated by the
Operating System .
 The pointer concepts can best be understood by the following example
program:
#include<stdio.h>
int Y;
void main()
{
int X,*pX,**pX;
X = 10;
Y = 1000;
pX = &X;
ppX = &pX;
f1(pX);
printf(“%d”,*pX);
f2(pX);
printf(“%d”,*pX);
f3(ppX);
printf(“%d”,*pX);
f4(ppX);
printf(“%d”,*pX);
f5(ppX);
printf(“%d”,*pX);
}
MACROS
#include <stdio.h>
#define area length*width
main ( )
{
int length, width;
printf (“length = “);
scanf (“%d”, &length);
printf (“width = “);
scanf (“%d”, &width);
printf (“area = %d”, area);
}
 The scope of a macro definition extends
from its point of definition to the end of
the file.
 A macro defined in one file is not
recognized within another file.
 Multiline macros can be defined by
placing a backward slash (\) at the end
of each line except the last.
 This feature permits a single macro (i.e.,
a single identifier) to represent a
compound statement.
 A macro definition may include arguments,
which are enclosed in parentheses.
 The left parenthesis must appear immediately
after the macro name, i.e. there can be no
space separating the macro name from the left
parenthesis. When a macro is defined in this
manner, its appearance within a program
resembles a function call.
 Macros are sometimes used in place of
functions within a program.
 The use of a macro in place of a function
eliminates the time delays associated
with the function calls.
 If a program contains many repeated
functions calls, the time saving resulting
from the use of macros can become
significant.
 On the other hand a program that
contains several references to the same
macro may become unreasonably long.
 We are therefore faced with a tradeoff
between execution speed and size of the
compiled object program.
 The use of a macro is most advantageous in
applications where there are relatively few
function calls but the functions is called
repeatedly (e.g., a single function call within a
loop).
 When passing arguments to a macro, the
number of arguments will be checked, but
their data types will not. Thus, there is less
error checking than with a function call.
 A macro identifier is not associated with
an address, so that a macro cannot be
utilized as a pointer. Thus, a macro
identifier cannot be passed to a function
as an argument in the same sense that a
function can be passed to another
function as an argument . Moreover, a
macro cannot call itself recursively.
FILES

 Many applications require that


information be written to or read from an
auxillary storage device.
 Such information is stored on the device
in the form of a data file.Data files
allow us to store information
permanently and to access and alter the
information whenever necessary.
 There are two types of data files called
 stream-oriented(or standard) data files
and
 system-oriented(or low-level) data files.
Stream-oriented data files

 Opening and Closing a file


 FILE *ptvar;
 where FILE is of structure type which
establishes the buffer area and ptvar is a
pointer variable that indicates the
beginning of the buffer area.
 The pointer ptvar is referred to as stream
pointer.
 The library functions fopen and fclose
are used to open and close a file.
 fopen:syntax
 ptvar=fopen(file_name,file_type);
 file_type represents the manner in
which the data file will be utilized.
 The file_type must be one of the strings
as shown in the table:
 “r” Open an existing file for reading only.
 “w” Open a new file for writing only(if the
file exists it will be destroyed and a new
file will be created in it’s place)
 “a” Open an existing file for adding new
information at the end of the file.If the file
does not exist a new file is created.
 “r+” Open an existing file for both
reading and writing.
 “w+” Open a new file for both reading and
writing(if the file already exists it will be
destroyed and a new file will be created in
its place)
 “a+” Open an existing file for both
reading and appending.A new file will be
created if the file does not exist.
 Stream-oriented data files can be further
divided into two categories:
 1. Formatted data files
 2. Unformatted data files
 Formatted data files
 These files comprise of consecutive
characters.

 The following functions are available for


these files:
 1. int fgetc(FILE *stream)
 This reads a character from a data file.
 This function returns the: next character of
stream
 or
 EOF if end of file
 or
 error occurs.
 2. int fputc(int c,FILE *stream)
 This function writes a character ‘c’
to a data file .
 It returns: the character written
 or
 EOF if end of file for error
 A simple program
#include<stdio.h>
main()
{
FILE *fp;
/*define a pointer to a
predefined structure type
FILE */
char c;
fp=fopen(“test.dat”,”w”);
/*open the file for writing
only*/
do
{
c=getchar();
fputc(c,fp); /* write the
contents of c
into the file*/
}while(c!=‘\n’);
fclose(fp); /*close the data
file*/
fp=fopen(“test.dat”,”r”); /*open
the file for reading
only*/
if(fp==NULL)
printf(“cannot open file”);
do
{
c=fgetc(fp); /* read character
by character from file */
putc(c);
}while(c!=‘\n’);
fclose(fp);
}
 3. char *fgets(char *s,int n,FILE *stream)
 This function reads at most the next n-1
characters into the array s,stopping if a newline
is encountered ;the newline is included in the
array,which is terminated by ‘\0’.
 It returns: the array ‘s’
 or
 NULL if end of file
 or
 error occurs
 4. int fputs(const char *s,FILE *stream)
 This function writes the string ‘s’ on stream
 It returns non-negative
 or
 EOF for an error
 Like the above example for fgetc() and fputc()
these two functions can also be used.
 When data files contain records that include
various combinations of numeric and character
information the functions fscanf and fprintf can
be used.They are analogous to the scanf and
printf functions.

 int fscanf(FILE *stream,const char


*format,......)
 It permits formatted data to be read from a
data file.
 Consider an example
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int i;
printf("Input an integer: "); /*
read an integer from
the standard input
stream */
if (fscanf(stdin, "%d", &i))
printf("The integer read was: %i\n", i);
else
{
fprintf(stderr, "Error reading an integer from stdin.\n");
exit(1);
}
return 0;
}
 6.int fprintf(FILE *stream,const char
*format,.....)
 It permits formatted data to be
written to a data file.

 Consider an example:
#include <stdio.h>
int main(void)
{
FILE *stream;
int i = 100;
char c = 'C';
float f = 1.234;
stream = fopen("DUMMY.FIL", "w+"); /*
open a file for update */
fprintf(stream, "%d %c %f", i, c, f);
/* write some data to the
file */
fclose(stream); /* close the
file */
return 0;
}
 Unformatted data files
 These files comprise of blocks of data
containing contiguous bytes of
information.
 These blocks represent more complex
data structures such as arrays and
structures.
 Hence,it may be desirable to read the
entire block from the data file or write the
entire block to the data file rather than
reading or writing the individual
components within each block seperately.
 The library functions fread and fwrite are
intended to be used in situation of this type.
 1. size_t fread(void *ptr,size_t size,size_t
nobj,FILE *stream)

 fread reads from stream into the array ptr at


most non objects of size size.
 fread returns the number of objects read ;this
may be less than the number requested.
 feof and ferror must be used to determine
status.
 2. size_t fwrite(const void *ptr,size_t size,size_t
nobj,FILE *stream)

 fwrite writes from array ptr ,nobj objects of


size size on stream.
 It returns the number of objects written ;which
is less than nobj on error.
 End of file is detected using feof library .This
function returns a nonzero value (TRUE) if an
end-of-file condition has been detected and a
value of zero(FALSE) if an end-of-file is not
detected.
Data Structures
 Languages provides the intial level of
abstraction by giving
 you different fundamental data types so
that you can access data.
 A data type is a term which refers to the
kinds of data that variables may ‘hold’ in a
programming language.
 A data structure is a group of items in
which each item is identified by it’s own
identifier,each of which is known as a
member of the structure.The common
data structures available are :
stacks,queues,lists and trees.
STACK

 “The list that grows and shrinks at same


end”
 Stack uses LAST IN FIRST OUT.
 Functions necessary to implement a stack :

#include<stdio.h>
#define STACK_SIZE 20
int stack[STACK_SIZE]; /*space for stacking
integers*/
int top=-1; /*top_of_stack is
defined as global
variable for a global stack */
/*Function to check whether the stack is ‘full’ */
int stack_full()
{
if(top==STACK_SIZE)
return(1);
else
return(0);
}
 /* Function to check whether the stack is ‘empty’ */
int stack_empty()
{
if(top==-1)
return(1);
else
return(0);
}
/*Function to push or add an element on the stack.*/
void push(int number)
{
stack[++top]=number; /*add element on top of stack
*/
}
 /* Function to pop an element from the stack*/
int pop()
{
int number;
number=stack[top]; /*remove top element
from stack */
top--;
return(number);
}
QUEUE

 “List that grows from one end and shrinks


from the other”
 Queues use FIRST IN FIRST OUT.
 A queue is an ordered collection of items
from which items may be deleted at one
end (called the front of the queue) and
into which items may be inserted at the
other end (called the rear of the queue).
 /* Function to determine status of queue i.e. if
(FRONT = REAR) */
int is_q_empty()
{
if(rear==front)
return(1);
else
return(0);
}
 /*Function to determine status of queue i.e. if
(REAR > MAX) */
int is_q_full()
{
if(rear==n)
return(1);
else
return(0);
}
 /* Function to add an element to the
queue*/

void addq(int item)


{
if (!is_q_full())
q[++rear] = item;
}
 /* Function to delete an element from the
queue*/
int deleteq(void)
{
if (!is_q_empty())
return q[++front];
}
Circular Queue

 Is same as queue but when the rear


pointer reaches the end of the queue and
if there is space available at the front of
the queue then insertion of elements
begin from the front of the queue.
 /* Function to add an element to the circular
queue*/
void addsq(int item)
{
rear = (rear+1) % n; /* Advance Rear
Clockwise */
if (!is_q_full())
q[rear] = item; /* Insert In The
Queue */
}
 /* Function to delete an element from the
circular queue*/
int deleteq(void)
{
if (!is_q_empty())
{ front = (front + 1) % n; /* Advance Front
Clockwise*/
return q[front];
}
}
LINKED LISTS

 Linked list is used where arrays fall short.


This happens because rays are to be
declared before program starts
execution, i.e it is a static declaration.
 Lists can insert and delete new elements
at any arbitrary position.
 In 'C' a linked list can be very easily
structured, with the use of self
referential structures.
 A global pointer variable “list_header” is
used to point to the linked list.
 This list pointer should always point to
the starting node so that one can
traverse along the list in one direction.
typedef struct list
{
int data ; /*all the data fields*/
struct list *next ;
} List;
Pictorial representation of a linked
list
NULL

Head

Data Part Pointer Part


 Functions required to implement a linked list
are:
 1>empty_list()
 Checks whether the list is empty.
 2>list_node()
 Function to allocate a node and to initialize it.
 3>insert()
 To insert a node in the list.
 4>delete()
 To delete a node from the list.
 5>print()
 To print the contents of the list in sequential
order.
 6>free()
 To free all the elements of the list.
 Example source code for these operations
typedef struct list
{
int data ; /*all the data fields*/
struct list *next ;
} List;
 List *list_header=NULL;
 /*Function to check whether the list is
empty*/
int empty_list()
{
if(list_header == NULL)
return(1);
else
return(0);
}
 /*Function to allocate a node and to initialize
it*/
List *list_node(int no)
{
List *l;
l=(List *)malloc(sizeof(List));
l->num=no;
l->next=NULL;
return(l);
}
 /*Function to add a new node at the beginning
of the list */
void insert(int no)
{
List *l;
l=list_node(no);
l->next=list_header;
list_header=l;
}
 /*Function to delete first element from the list */
void delete(int *no)
{
List *temp;
*no=list_header->num;
temp=list_header->next;
free(list_header);
list_header=temp;
}
 /*Function to print the value of of every
node*/
void print()
{
List *t;
for(t=list_header;t!=NULL;t=t->next)
printf(“%d”,t->num);
}
 /*Function to free memory allocated dynamically*/
void free()
{
List *t,*tmp;
for(t=list_header;t!=NULL;t=t->next)
{
tmp=t->next;
free(t);
t=tmp;
}
}
DOUBLY LINKED LISTS
 To traverse in both directions in a link list, you
will have to keep one more reference for the
previous structure.
 For example:
struct double
{
int data;
struct double *next;
struct double *previous;
};

You might also like