C Programing Basics
C Programing Basics
Machine Language: A Binary Language composed of 0s and 1s that is specific to each computer. Assembly Language: Binary instructions are given abbreviated names called mnemonics which form the Assembly Language. Assembly Language is specific to a given machine. High Level Language: Programming language intended to be machine-independent is called High level language. Instructions are called as statements. Eg:FORTRON,PASCAL,C ..etc.
The C Language
C is a robust language whose rich set of built-in functions and operators can be used to write any complex program. C compiler combines the capabilities of an assembly language with features of high-level language and therefore it is well suited for writing both system software and business packages. Programs written in C are efficient and fast .This is due to its variety of data types and powerful operators.
C History
Developed between 1969 and 1973 along with Unix Ken Thompson created the B language in 1969 from Martin Richard's BCPL Dennis Ritchie of Bell Laboratories later converted B into C by retaining most of B's syntax in 1972 and wrote the first compiler. Designed for systems programming
Operating systems Utility programs Compilers Filters
Welcome to C Programming
#include <stdio.h>
Preprocessor used to share information among source files
Program mostly a collection of functions I/O performed by a library function: not included in the language main function special: the entry point void qualifier indicates function does not return anything
Pieces of C
Types and Variables
Definitions of data in memory
Expressions
Arithmetic, logical, and assignment operators in an infix notation
Statements
Sequences of conditional, iteration, and branching instructions
Functions
Groups of statements and variables invoked recursively
Variables are the quantities which may vary during the execution of a program Keywords are the words whose meaning explained to the C compiler. has already been
Identifiers are the user defined names given to variables,functions and arrays.
C variables
Variable names are names given to the memory locations of a computer where different constants are stored. These locations can contain integer,real or character constants. The rules of constructing variable names of all types are same.
A variable name is any combination of 1 to 8 alphabets, digits or underscores. The first character must be alphabet. No commas and blanks are allowed within the variable name. No special symbol other than an underscore can be used in a variable name. Eg: si_int, pop_e_89
C Data Type
Memory allocation is done by OS.
10
C Keywords
Keywords are the words whose meaning has already been explained to the C compiler. The keywords cannot be used as variable names . Doing so is trying to assign a new name to the keyword which is not allowed by the compiler. Keywords are also called as Reserved words. There are only 32 keywords available in C.
11
C Instructions
Type declaration :To declare the type of variables used in the program. Input/Output instructions: To perform the function of supplying input data to a program and obtaining the output results from it. Arithmetic instructions: To perform arithmetic operations b/n constants and variables. Control instructions: To control the sequence of execution of various statements.
12
C program
Any C program is basically a collection of functions that are supported by the C library.User defined functions can be added to the C library. The main( ) is a special function used by the C system to tell the computer where the program starts. The set of statements belonging to a function are enclosed within a pair of braces,{ }. Any Variable used in the program must be declared before using it. C program statements are written in lowercase letters and end with semicolon. Uppercase letters are used only for symbolic constants.
13
14
printf() statement
printf( ) is predefined ,standard C function for printing output. The general form of printf() is, printf(<format string>,<list of variables>); <format string> could be, %f for printing real values. %d for printing integer values. %c for printing character values. Eg: printf(%f,si); printf(%d,i);
15
scanf() statement
scanf( ) is a predefined,standard C function used to input data from keyboard. The general form of scanf() is scanf(<format string>,<address of variables>); Eg: scanf(%d,&n); scanf(%f,&interest); & is pointer operator which specifies the address of that variable.
16
Example Program
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 } Enter first integer 45 Enter second integer 72 Sum is 117
17
/*
#include <stdio.h>
Outline
int main() { int integer1, integer2, sum; /* declaration */
printf( "Enter second integer\n" ); /* prompt */ scanf( "%d", &integer2 ); sum = integer1 + integer2; printf( "Sum is %d\n", sum ); /* read an integer */ /* assignment of sum */ /* print sum */
return 0;
3. Print
Program Output
Arithmetic Operators. Logical Operators. Relational Operators. Bit wise Operators Assignment Operators. Increment & Decrement Operators. Conditional Operators.
Arithmetic Operators
Arithmetic operators:
19
M eaning of C condition
= not =
R elational O perators
x is equal to y x is not equal to y x is greater than y x is less than y x is greater than or equal to y x is less than or equal to y
20
21
Conditional/Ternary Operator
A Ternary operator pair ? :is available in C to construct conditional expression of the form expression1 ? expression2 : expression3 Eg: a=10; b=15; x=(a>b) ? a : b; x will be assigned to the value of b.
22
#include <stdio.h> main() { int number1, number2, greater; printf(\nEnter the first number ); scanf(%d,&number1); printf(\nEnter the second number); scanf(%d,&number2); greater=number1 > number2?number1 : number2; printf(\nThe greater number is %d,greater);
23
Logical Operators
The Logical AND Operator
a && b; (a < b) && (c < d)
24
Assignment Operators
25
Type Conversions
When an operator has operands of different types, they are converted to a common type according to a small number of rules. 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.
26
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.
27
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.
28
29
Bit-wise Operators
Bit-wise operators allow direct manipulation of individual bits within a word. These Bit-manipulations are used in setting a particular bit or group of bits to 1 or 0. All these operators work only on integer type operands.
Bit-Wise logical operators: Bit-Wise AND (&) Bit-Wise OR ( | ) Bit-Wise exclusive OR (^)
Size of operator
The sizeof is a compile time operator and,when used with an operator, it returns the number of bytes the operand occupies The operand may be a variable,a constant or a data type qualifier
Eg: int m,n, sum; m=sizeof(sum); n=sizeof(long int);
The sizeof operator is normally used to determine the lengths of arrays and structures It is also used to allocate memory space dynamically to variables during execution of a program
31
Control Structures
These are the statements which alter the normal (sequential)execution flow of a program. There are three types of Control Statements in C
32
if statement
The general form : if(test expression) { statementblock; } statement-x;
Entry
False Statement-x
33
if.else statement
The if.else statement is an extension of simple if statement. The general form is, if(test expression) { true-block statements; } else { False-block statements; } statement-x;
Entry False
True
Test expression?
True-block
False-block
Statement-x
34
start
ch =
Input ch
true
is ch = *
false
Print *
Not a *
stop
36
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); ..
else if (chr = = 9) puts(You entered the number 9);
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. Both the outer if statement and the inner if statement have to evaluate to true for the statement following the inner if condition to be executed.
ye s
no
ye s no
39
40
switch statement
The switch statement tests the value of a given variable(or expression) against a list of case values and when a match is found, a block of statements associated with that case is executed. The break statement at the end of each block signals the end of particular case and causes an exit from the switch statement, transferring the control to the statement-x. The default is an optional case. When present, it will be executed if the value of the expression does not match any of the case values. If default not present, no action takes place if all matches fail and control goes to statement-x.
41
switch (expression) { case value-1 : case-1 block break; case value-2 : case-2 block break; default : default block break; } statement-x;
42
Evaluate Condition
true
false
43
dowhile loop
The general form of do..while loop is
do { body of the loop } while (test-condition) ;
The do..while construct provides an exit-controlled loop as the testcondition is evaluated at the bottom of the loop and therefore the body of the loop is always executed at least once.
false
Evaluate Condition
true
45
46
for loop
The for loop is another entry-controlled loop that provides a more concise loop structure
for(initialization;test-condition;increment) { body of the loop }
47
48
50
goto statement
C supports goto statement to branch unconditionally from one point to another in a program. The goto requires a label in order to identify the place where the branch is to be made. A label is any valid variable name , and must be followed by a colon.
52
C Statements
Expression Conditional
if (expr) { } else {} switch (expr) { case c1: case c2: }
Iteration
while (expr) { } zero or more iterations do while (expr) at least one iteration for ( init ; valid ; next ) { }
Jump
goto label continue; break; return expr; go to start of loop exit loop or switch return from function
53
Arrays
An array is a group of related data items that share a common name. int a[10];
Data type Index(size)
The individual values are called elements. The elements are a[0] ,a[1] , a[2]a[9]. The elements are stored in continuous memory locations during compilation. The name of the array(a)contains the address of the first location i.e a[0]. The elements of the array are physically and logically adjacent. When an array is passed as an argument to a function,its address is actually passed.
54
Array Representation
int a[10];
/*defines an array a of size 10, as a block of 10 contiguous elements in memory */
Character Arrays
Char name[11]; To define a character array, need to define a array of size n+1 characters.This is because all character arrays are terminated by a NULL character (\0) where name[0] through name[9] will contain the characters comprising the name, and name[10] will store the NULL character
55
56
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. #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};
57
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];
}
58
gets(string); fflush( stdin); for(i =0; string[i] != \0; i = i + 1); printf(The length of the string is %d \n, i); }
59
}
62
Two-Dimensional Arrays
Declaration: type array_name[rowsize][columnsize]; Eg: int m[3][3]={0,0,0,1,1,1,2,2,2}; m[0][0] m[0][1] m[0][2] m[1][0] m[1][1] m[1][2] m[2][0] m[2][1] m[2][2]
63
Two-dimensional Arrays
col 2
col 0 row 0
col 1
row 1
row 2
r0,c0
r0,c1
r0,c2
r1,c0
r1,c1
r1,c0
r2,c0
r2,c1
r2,c2
64
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);
} }
/* 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];
66
} } /* end of main( ) */
67
68
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; }
69
The first index represents the number of names, and the second index represents the maximum size of each name.
70
Pointers
A pointer is a variable which holds the address of another variable in memory.The actual location of a variable in the memory is system dependent. Since pointer is a variable ,its value is also stored in the memory in another location. & operator(address of) is used to assign the address of a variable to a pointer variable. The declaration of a pointer takes the following form:
data type *ptr; Eg: int *pa; int a; pa=&a;
The asterisk(*)tells that pa is a pointer variable. pa needs a memory location. pa points to a variable a of type int
71
The actual location of a variable in the memory is OS dependent. Two bytes(in DOS )of memory is allocated to any type of pointer.
73
i pointer_to_an_integer 1000
74
22 1000
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 }
75
76
78
79
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
80
char *string = Hello; printf(%s, string); Two-dimensional Since a pointer to a character can be a pointer to a string, it follows that a two-dimensional character array can be declared as an array of character pointers. This could be alternately declared as: char *team_india[11];
81
Pointer Arithmetic
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.
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
82
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:
83
Pointer Arithmetic
p 100
200 100 200 2 300 104 300 3 204 4 304 6 208 6 308 9 212 8 312 12 216 10 316 15
404 10
408 15
412 20
416 25
84
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:
Pointer Expression
*(*p) *(*p+1) *(*(p + 1)) *(*(p+1)+1) *(*(p+1)+1)+1
Resulting Address
200 204 300 304 304
Variable
p[0][0] p[0][1] p[1][0] p[1][1] p[1][1] + 1
Value
2 4 3 6 6+1=7
85
86
87
Function - Introduction
Functions facilitate the factoring of code. Functions facilitate:
Reusability Procedural abstraction
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
88
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 this example.
89
Invoking Functions
In C, functions that have parameters are invoked in one of two ways:
Call by value Call by reference
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; }
90
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; }
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. 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)
91
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.
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.
93
Function Prototype
To elucidate further, pow(2.0, 3.0) yields the value 8.0
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); 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.
94
Function Prototype
#include <stdio.h> float add(float a, float b); main() { float i, j, value; scanf(%f %f, &i, &j); fflush(stdin); value = add(i, j);
printf( the total is %d\n, value);
#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);
95
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.
96
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.
97
Data Area
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
98
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
99
Memory Organization
heap
100
101
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)
102
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
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
103
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
1. 2. 3. 4.
Copy the fp to the sp Load the control link into the fp Jump to the return address Change the sp to pop the arguments.
104
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.
105
106
Global Procedures
In a language where all procedures are global (the C language), a stack-based environment requires two things:
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. The position or size of the callers 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 Additionally, there may be a stack pointer (sp) It always points to the top of the stack
107
.. . . . }
return instruction
. . . }
108
S t a c k G r o w t fp sp h
109
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.
110
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.
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!);
111
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.
112
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; } }
113
114
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[ ])
115
116
Command-Line Arguments
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
118
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.
119
#include<stdio.h> main( ) { char var; while ((var = getchar( )) != *) { if ((var >= A) && (var <= Z)) uppercase_count( ); } } uppercase_count( ) { auto int counter = 0; counter ++; }
Global Variables
Global variable is outside all functions. defined
/* A sample C program */ # include <stdio.h> /* function prototype */ int sum( );
/* a and b are global variables, visible to main( ) as well as to sum( ) */
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.
120
int a=10, b=20; main() { int c; c = sum(); printf(%d+%d = %d \n,a,b,c); } int sum() { return(a+b); }
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.
121
#include<stdio.h> main( ) { char var; while ((var = getchar( )) != *) { if ((var >= A) && (var <= Z)) uppercase_count( ); } } uppercase_count( ) { static int counter = 0; counter ++; }
122
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
123
Extern Variables
Program a.c int val /* global */ main( ) { printf(Enter value); scanf(%d, &val); compute( ); /* function call */ } Program b.c compute( ) { extern int val; /* implies that val is defined in another program containing a function to which the current function will be linked to at the time of compilation */ }
124
Implication
Example
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 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 If the strings are identical i = strcmp(XYZ, XYZ)
Greater than 0
Equal to 0
125
126
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.
127
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.
128
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( )
129
Example:
sprintf( str, %02d-%02d-%02d, 28, 8, 71)
will return the string 28-08-71 into str.
130
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
131
132
133
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.
134
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
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 4
n x y n
* 2 3
n x
* * *
y
* 3
n x
* *
y
3 4
*
x
*
y
135
Mechanics of Recursion
(e) fact(1)
(f) fact(0)
(g) y = fact(0)
(h) y = fact(1)
0 1 2 3 4 n x * 1 2 3 * * * * 1 2 3 4 n x
* 0 1 2 3
* * * *
1 2 3 4
0 1 2 3 x y
1 * * * 2 3 4 n 1 2 3 x 1 * * y
136
Mechanics of Recursion
(i) y = fact(2)
(j) y = fact(3)
Pritnf(%d, fact(4))
3 4 n x
2 3 y
2 * n 4 x 3 y 6 n x y
The stack at various times during execution. An asterisk indicates an uninitialized value.
137
Function Pointers
Function Pointers are pointers, i.e. variables, which point to the address of a function. Thus a function in the program code is, like e.g. a character field, nothing else than an address. 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.
138
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 switchstatement, where you call the functions just like you want it, in the different branches. Consider the example : How are function pointers used? As stated above they are typically used so one function can take in other functions as a parameter.
139
140
141
142
143
144
145
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; };
146
147
Or a structure can be declared separately as: struct empdata emprec;/* emprec is a variable of structure type empdata */
148
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 */
149
151
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. 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.
struct empdata { int empno; char name[10]; char job[10]; float salary; };
152
153
154
155
156
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 union u_type { int i; char ch; }; union u_type cnvt;
157
Unions
In cnvt, both integer i and character ch share the same memory location. Of course, i occupies 2 bytes (assuming 2byte integers, and ch uses only one byte.
Byte 0
Byte 1
ch
158
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 machineindependent (portable) code. Because the compiler keeps track of the actual size of the union members, no unnecessary machine dependencies are produced.
159
Unions - Example
union pw { short int i; char ch[2]; }; int main (void) { FILE *fp; fp = fopen( test.tmp, wb+); putw(1000, fp); /* write the value 1000 as an integer */ fclose( fp ); return 0; } 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 */ }
160
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;
161
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
162
Enumeration - Example
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; }
163
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 *
164
Hands-on: 2 hours
Purpose construct Structures, Unions & Enumeration and performing computation
165
Summary
In this module, we discussed: 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
166
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. The format string, along with the data to be output, are the parameters to the printf( ) function. Format string is a string containing the format specification introduced by the character %, and ended by a conversion character.
167
Formatted Output
An example: printf(%c\n, var); The conversion characters and their meanings are:
Conversion character d c s
Meaning The data is converted to decimal The data is treated as a character 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 has been exhausted The data is output as float or double with a default precision of 6
168
Formatted Output
Between the % character and the conversion character, there may be: A minus sign A digit Implying left adjustment of data Implying the minimum 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 Separates the width from the next digit. Specifying the precision, or the maximum number of characters to be output To signify that the data item is a long integer, and not an integer.
A period A digit l
169
Formatted Output
Format String %2d %2d %03d %-2d %5s %15s %-15s %f 4 224 8 4
Output
170
171
Formatted Input
The function scanf( ) is used for formatted input, #include<stdio.h> and provides many of the main( ) conversion facilities of { char name[10]; printf( ). 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.
int age; char gender;
scanf (%s%c%d, name, &gender, &age);
fflush(stdin);
printf( % s %c %d, name, gender, age); }
172
173
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
174
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.
175
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.
176
177
r+ w+ a+
178
179
180
181
182
183
184
185
186
187
188
189
The statement scanf( %6s%d, string, &i) can be rewritten using the function fscanf( ) as:
fscanf(stdin, %6s%d, string, &i);
190
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.
191
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.
192
current offset
194
current offset
195
current offset
196
current offset
197
After invoking rewind( ), the current position in the file is always the first byte position, i.e., at the beginning of the file.
198
199
200
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.
203