C Programming Through Examples
C Programming Through Examples
Page 1
Chapter 1
Introduction
Page
2
The Genesis of C
Page 3
Striking features:
• C is case sensitive. All commands must be lower case
• Starting point of every C program is identified by
word main()
• Braces ({...}) are used to enclose a block of
statements to be treated as a unit
• Comments are enclosed in /* and */ delimiters
• End of each statement must be marked with a
semicolon ( ; )
C Program – Hello World!
Page 14
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.
The definition:
char var;
defines a memory location of size one byte, of character
type, referred to as var.
Defining Data
Page 21
Page 21
Defining Data
Page 22
The definition:
char var; defines a variable location called var, which is
one byte in size, and can therefore hold only one
character.
Keywords in C Programming
#include <conio.h>
#include <stdio.h>
main( )
{
char ch;
ch = getch( );
fflush(stdin);
putch(ch);
}
Character-Based I/O
Page 29
#include <stdio.h>
main( )
{
char ch;
ch = getchar( );
fflush(stdin);
putchar(ch);
}
String-Based I/O
Page 31
#include <stdio.h>
#include <conio.h>
main( )
{
char str[11];
puts("Enter a string of maximum 10 characters");
gets(str);
fflush(stdin);
puts(str);
}
Conditional Constructs
Page 33
Relational Operators:
Operator Meaning
== Equal to
!= Not equal to
Page 34
The if-else Construct
Page 35
The following function checks whether the character start
entered by the user is a star (*) character.
#include <stdio.h>
#include <conio.h> ch = ‘ ‘
main( )
{ Input ch
char ch;
ch = getchar( );
fflush(stdin); is ch = ‘*’ Print *
if (ch == '*')
puts ("You have entered the star character");
else Not a *
puts ("You have not entered the star character");
}
stop
The if-else Construct
Page 36
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");
}
Cascading if-else Construct
Page 37
#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");
Cascading if-else Construct
Page 39
A nested if statement is
encountered if the statement to
be executed after a condition
evaluates to true is another if
statement.
condition to be executed.
Nested if Construct: Example
Page 41
else
puts (“Input character greater than Z but less than a”);
}
else
puts (“Input character less than A”);
}
The switch-case Conditional Construct
Page 45
#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); } }
Iterative Constructs – The do…while
loop
Page 53
#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);
}
}
Control of Loop Execution
Page 58
Operator Notation
NOT !
AND &&
OR ||
Page 61
The Logical AND Operator
Page 62
a && b;
a b a && b a || b
0 0 0 0
0 1 0 1
1 0 0 1
1 1 1 1
Page 68
Formatted I/O
Page 69
An example:
printf(“%c\n”, var);
The conversion characters and their meanings are:
Between the % character and the conversion character, there may be:
Page 73
Data Conversion Using Format String
Page 74
#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);
}
Formatted Input
Page 75
#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);
}
String Input Using scanf( )
Page 77
#include<stdio.h>
main( )
{
char string[40];
printf("Enter a string of maximum 39 characters");
scanf("%s", string);
fflush(stdin);
printf("%s", string);
}
Unary Operators
Unary operators, as the name suggests, works on one
Page 78
operand or variable.
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 (a > b)
z = a;
else
z = b;
x = x * y; can be written as x *= y;
x = x / y; can be written as x /= y;
Page
96
One-Dimensional Arrays
Page 97
a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9]
Page 98
Character Arrays
Page 99
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]
Array Initialization
Page 101
#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};
}
Array Processing
Page 103
#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];
}
Array Initialization Using a for Loop
Page 104
#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);
}
}
Array Manipulation Using Subscripts
Page 105
#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]);
}
Array Manipulation Using Subscripts
Page 106
#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);
}
Array Manipulation Using Subscripts
Page 109 #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);}
Array Addressing
Page 110
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.
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
Page 111
Array Addressing
Page 112
Chapter 3
Two-Dimensional Arrays
Two-Dimensional Arrays
Page 116
row 0
row 1
row 2
reg A
reg B
reg C
Declaring a Two-Dimensional Array
Page 120
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] */
Initializing Two-Dimensional Arrays
Page 121
/* 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;
}
}
Processing Two-Dimensional Arrays
Page 125
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;
}
}
Two-Dimensional Character Arrays
Page 130
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”
};
Printing Two-Dimensional Character
Arrays
Page 133
int i;
for( i = 0; i < 11; i ++)
{
printf(“%s”, team_india[i]);
}
}
Printf(“%c”, team_india[10][6] would print the character ‘P’ from the string
“Pathan”
Page
134
Page 135
Chapter 4
Pointers
Objectives
Page 136
two-dimensional arrays
Distinguish between arrays and pointers
22 value
1000 address
Pointer – Definition
Page 139
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. */
Pointer – Declaration & Initialization
Page 141
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.
#include<stdio.h>
main( )
{
int x, y, *pointer;
x = 22;
pointer = &x;
y = *pointer; /* obtain whatever pointer is pointing to */
}
Pointers - Variations on a theme
Page 144
pointer2
1000
Pointers - Variations on a Theme
Page 146
1000 22
p2 y
2000 44
1000 44
pointer2
y
1000 44
Printing Using Pointers
Page 148
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.
char *string; /* string is now a explicit pointer variable that can point to a
character */
char *string = “Hello”;
printf(“%s”, string);
Two-dimensional Character Arrays Using Pointers
Page 155
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
Pointer Arithmetic
Page 159
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
Pointer Arithmetic
Page 161
100
100 104 108
4 8 12
Page 162
Pointer Arithmetic
Page 163
p
104
100 104 108
4 8 12
Pointer Arithmetic
Page 164
Page 169
String Handling Functions Using
Pointers
Page 170
Chapter 5
The Function Call Mechanism
Objectives
Page 174
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;
}
Call by Value
Page 181
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;
}
Passing Arrays to Functions
Page 184
fn(int num_list[10]); or
fn(int *num_list)
Returning a Value From a Function
Page 186
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.
Returning a Value From a Function
Page 188
#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);
}
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.
Memory
Register Area
Code Area
RAM
Data Area
Code Area
Page 200
code area
global/static area
stack
free space
heap
Procedure Activation Record
Page 204
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
. . .
. . .
}
. }
}
A View of the Runtime Stack
Page 212
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)
Access to Variables
Page 213
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.
Variable Length Data
Page 217
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.
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
Command Line Arguments
Page 225
/* 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);
}
Static Variables
Page 231
#include<stdio.h>
main( )
{
char var;
while ((var = getchar( )) != ‘*’)
{
if ((var >= ‘A’) && (var <= ‘Z’))
{
uppercase_count( );
}
}
}
uppercase_count( )
{
static int counter = 0;
counter ++;
}
Static and Global Variables – A
Comparison
Page 233
Page 237
Standard String Handling Functions
Page 238
Chapter 6
File Input/Output
Objectives
Page 247
ftell( )
rewind( )
feof( )
Files
Page 248
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.
“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
Page 253
File Access Modes
Page 254
Page 254
Character-based File I/O
Page 255
#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);
}
Variation to Console-Based I/O
Page 257
#include<stdio.h>
main( )
{
char ch;
while ( (ch = fgetc( stdin)) != EOF)
{
fputc (ch, stdout);
}
}
Nuggets on FILE Type Pointers
Page 258
The function fseek( ) is used for repositioning the current position in a file
opened by the function fopen( ).
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
Page 272
The fseek( ) function
Page 273
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
Page 273
The fseek( ) function
Page 274
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
Page 274
The fseek( ) function
Page 275
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
Page 275
The rewind( ) Function
Page 276
Structure of SALARY.DAT
employee number salary
Page 278
Updating Data in a File
Page 279
/* 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( );
}
Updating Data in a File
Page 280
Chapter 7
User-Defined Data Types
Objectives
Page 284
struct empdata
{
int empno;
char name[10];
char job[10];
float salary;
};
Declaring a Structure
Page 291
struct empdata
{
int empno;
char name[10];
char job[10];
float salary;
} emprec; /* emprec is a variable of structure type empdata */
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.
Accessing Elements of a Structure
Page 295
#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;
Passing Structures to Functions
Page 297
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]
}
Array of Structures
Page 299
fread( ) will return the actual number of records read from the file.
This feature can be checked for a successful read.
An odd feature of the fread( ) function is that it does not return any
special character on encountering end of file.
Byte 0 Byte 1
ch
Unions
Page 307
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;
}
Typedef Statements
Page 321
Chapter 8
Recursion
Introduction
Page 324
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.
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.
The Factorial Function
Page 329
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 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
Evolving a Recursive Definition
for the Factorial
Page 337
int fact(n)
int n;
{
int x, y;
if ( n == 0)
return (1);
else
{
x = n-1;
y = fact(x);
return ( n * y);
}
}
Mechanics of Recursion
Page 343
Since execution has not yet left the first call of fact( ),
the first allocation of these variables remains.
2 * *
3 * *
3 2 *
4 * * 4 3 * 4 3 *
n x y n x y n x y n x y
Mechanics of Recursion
Page 354
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
Mechanics of Recursion
Page 355
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.
Function Pointers
Page 356