Categories
Computer Science / Information Technology Language: C

Functions and Recursion

Introduction to Functions

A function is a self-contained block of statements that perform a coherent task of some kind. Every C program can be thought of as a collection of these functions. In other words, a function is a block of code with a name and statements in it and is supposed to execute a particular task. A task could be anything which the programmer
desires. Consider the following example:

#include <stdio.h>
foo ( ) 
{
   printf("In foo function!\n") ;
}
int main ( ) 
{
    foo ( );
    printf ( "In the main function" ) ;
    return 0;
}

output:

In foo function!
In the main function

Note: The programs defined here might throw warnings when run. Just assume that the programs are correct for the time being. The warnings will be dealt with once we reach the function declaration and prototype topic.


The main( ) itself is a function and through it, we are calling the function foo( ). The word ‘call’ means that the control passes to the function foo( ). When the foo( ) function runs out of statements to execute, the control returns to main( ) and resumes executing its code at the exact point where it left off. Thus, main( ) becomes the ‘calling’ function, whereas foo( ) becomes the ‘called’ function.

Consider the following example:

#include <stdio.h>
hyderabad( )
{
printf( "\nAt Hyderabad" ) ;
printf( "\nGoing back home\n" ) ;
}
chennai( )
{
printf( "\nAt Chennai" ) ;
printf( "\nGoing back home\n" ) ;
}
bengaluru( )
{
printf( "\nAt Bengaluru" ) ;
printf( "\nGoing back home\n" ) ;
}
int main( )
{
printf( "At home\n" ) ;
printf( "\nGoing to Bengaluru" ) ;
bengaluru( ) ;
printf( "\nGoing to Chennai" ) ;
chennai( ) ;
printf( "\nGoing to Hyderabad" ) ;
hyderabad( ) ;
}

The output of the above program is as follows:

At home

Going to Bengaluru
At Bengaluru

Going back home

Going to Chennai
At Chennai
Going back home

Going to Hyderabad
At Hyderabad
Going back home

From this program several conclusions can be drawn:

  • Any C program contains at least one function.
  • If a program contains only one function, it must be the main( ).
  • If a C program contains more than one function, then one (and only one) of these functions must be main( ) because program execution always begins with main().
  • There is no limit on the number of functions that might be present in a C program.
  • Each function in a program is called in the sequence specified by the function calls in main( ).
  • After each function has done its thing, control returns to main( ). When main( )runs out of function calls, the program ends.

As we have noted earlier the program execution always begins with main( ). Except for this fact, all C functions enjoy a state of perfect equality. No precedence and no priorities. A function can call another function and the second function can, in turn, call the third function and so on. To better illustrate this, consider the following example.

#include <stdio.h>
hyderabad( ) 
{
    printf ( "\nI am in Hyderabad" ) ;
}
chennai( ) 
{
    printf ( "\nI am in Chennai" ) ;
    hyderabad( ) ;
    printf ( "\nI am back in Chennai" ) ;
}
bengaluru( )
{
    printf ( "\nI am in Bengaluru" ) ;
    chennai( ) ;
    printf ( "\nI am back in Bengaluru" ) ;
}
int main( ) {
printf ( "I am in main" ) ;
bengaluru( ) ;
printf ( "\nI am finally back in main" ) ;
}

The output:

I am in main
I am in Bengaluru
I am in Chennai
I am in Hyderabad
I am back in Chennai
I am back in Bengaluru
I am finally back in main

Here, main( ) calls other functions, which in turn call still other functions. Trace carefully the way control passes from one function to another. Since the compiler always begins the program execution with main( ), every function in a program must be called directly or indirectly by main( ). In other words, the main( ) function drives other functions

Points to remember so far

a. C program is a collection of one or more functions.
b. A function gets called when the function name is followed by a semicolon. For example,

bengaluru( ) 
{
 chennai( ) ;
}

c. A function is defined when the function name is followed by a pair of braces in which one or more statements may be present. For example,

void bengaluru( )
{
   Statement 1 ;
   Statement 2 ;
   Statement 3 ;
}

d. Any function can be called from any other function. Even main( ) can be called from other functions. For example,

#include <stdio.h>
message( )
{
   printf ( "\nMessage" ) ;
   main( ) ;
}
int main( )
{
   message( ) ;
}

Note: This executes without an error but goes into an infinite loop by both the functions calling each other.
e. A function can be called any number of times. For example,

#include <stdio.h>
foo( ) 
{
    printf ( "\nIn foo" ) ;
}
int main( ) {
foo( ) ;
foo( ) ;
}

f. The order in which the functions get called is the same as the order in which the function calls occur and not in the order how the function is defined.

#include <stdio.h>
foo2( )
{
    printf ( "\nIn foo2" ) ;
}
foo1( ) {
printf ( "\nIn foo1" ) ;
}
int main( ) {
foo1( ) ;
foo2( ) ;
}

Here, even though the function foo2 is defined before function foo1, foo1 is called first as the calling statement in the main( ) function occurs in that order. However, it is advisable to define the functions in the same order in which they are called. This makes the program easier to understand.
g. A function can call itself. Such a process is called ‘recursion’. More on that later.
h. A function cannot be defined in another function. Thus, the following program code throws a compilation error.

#include <stdio.h>
int main( ) 
{
     printf ( "\nI am in main" ) ;
     foo( ) 
   {
       printf ( "\nI am in foo" ) ;
   }
}

There are basically two types of functions:
i. Library functions Ex. printf( ), scanf( ) etc.
ii. User-defined functions Ex. bengaluru( ), chennai( ) etc.
As the name suggests, library functions are commonly required functions grouped and stored in what is called a Library. This library of functions is present on the disk and is written by compiler authors. Almost always a compiler comes with a library of standard functions. The procedure of calling both types of functions is the same.

Advantages of using functions:

  • The use of functions enhances the readability of a program. A big code is always difficult to read. Breaking the code into smaller Functions keeps the program organized, easy to understand and makes it reusable.
  • The C compiler follows top-to-down execution, so the control flow can be easily managed in the case of functions. The control will always come back to the main() function.
  • It reduces the complexity of a program and gives it a modular structure.
  • In case we need to test only a particular part of the program we will have to run the whole program and figure out the errors which can be quite a complex process. Another advantage here is that functions can be individually tested which is more convenient than the above-mentioned process.
  • A function can be used to create our header file or a function can be called n number of times in the same file which can be used in any number of programs i.e. the reusability. This also helps in error isolation during the debug process.
  • Functions help in dividing a complex problem into simpler ones.

Passing values between functions:

  • Communication between the ‘calling’ and the ‘called’ functions is necessary during various scenarios.
  • The mechanism used to convey information to the function is the ‘argument’.
  • You have unknowingly used the arguments in the printf( ) and scanf( ) functions; the format string and the list of variables used inside the parentheses in these functions are arguments.
  • In the following program, in main( ) we receive the values of a, b and c through the keyboard and then output the sum of a, b and c. The calculation of sum is done in function calculate_sum( ). So, we must pass on the values of a, b, c to calculate_sum( ), and once calculate_sum( ) calculates the sum we must return it from calculate_sum( ) back to main( ).
#include <stdio.h>
int calculate_sum ( x, y, z )
int x, y, z ;
{
    int d ;
    d = x + y + z ;
    return ( d ) ;
}
int main( )
{
    int a, b, c, sum ;
    printf ( "\nEnter any three numbers " ) ;
    scanf ( "%d %d %d", &a, &b, &c ) ;
    sum = calculate_sum ( a, b, c ) ;
    printf ( "\nSum = %d", sum ) ;
}

output

Enter any three numbers 1 2 3
Sum = 6

Points to note:

  • The values a, b, c are passed from main( ) to caculate_sum( ) by making a call to the function calculate_sum( ) and mentioning a, b and c in the parentheses:
sum = calculate_sum ( a, b, c ) ;
  • In the calculate_sum( ) function these values get collected in three variables x, y and z:
calculate_sum ( x, y, z )
int x, y, z ;
  • The variables a, b and c are called ‘actual arguments’, whereas the variables x, y and z are called ‘formal arguments’ or ‘parameters’.
  • Any number of arguments can be passed to a function being called. The order, type and the number of the actual and formal arguments must always be the same.
  • Instead of using different variable names x, y and z, we could have used the same variable names a, b and c. But the compiler would still treat them as different variables since they are in different functions.
  • There are two methods of declaring formal arguments. The one that we have used in our program is known as the Kernighan and Ritchie (or just K & R) method.
calculate_sum ( x, y, z )
int x, y, z ;
  • Another method is the ANSI method which is more commonly used:
calculate_sum ( int x, int y, int z )
  • In the above program, we want to return the sum of x, y and z. Therefore, it is necessary to use the return statement. The return statement serves two purposes:
    • On executing the return statement it immediately transfers the control back to the calling function.
    • It returns the value next to return, to the calling program. In the above program, the value of the sum of three numbers is returned.
  • There is no restriction on the number of return statements in a function. Also, the return statement need not always be present at the end of the called function. The following program illustrates these facts.
foo( ) 
{
char ch ;
printf ( "\nEnter any alphabet " ) ;
scanf ( "%c", &ch ) ;
if ( ch >= 65 && ch <= 90 )
    return ( ch ) ;
else
    return ( ch + 32 ) ;
}
  • In this function, different return statements will be executed depending on the evaluation of if-else.
  • Whenever the control returns from a function some value is returned. If a meaningful value is returned then it should be accepted in the calling program by equating the called function to some variable. For example,
sum = calculate_sum ( a, b, c ) ;
  • All the following are valid return statements given that the return type of the functions they are in, justify the data-type of values being returned by return statements.
return ( a ) ; // If the return type of the function is the
same as that of the data type of ‘a’
return ( 23 ) ; // If the return type of the function is int
return ( 12.34 ) ; // If the return type of the function is
float or double
return 89 ; // If the return type of the function is int
return ; // If the return type of the function is void
  • In the last statement, a garbage value is returned to the calling function since we are not returning any specific value. Note that in this case the parentheses after return are dropped.
  • If we want that a called function should not return any value, in that case, we must mention so by using the keyword void as shown below.
void display( ) 
{
printf ( "\nHeads I win..." ) ;
printf ( "\nTails you lose" ) ;
}
  • A function can return only one value at a time. Thus, the following statements are invalid.
return ( a, b ) ;
return ( x, 12 ) ;
  • But the following examples are valid:
return ( a ) ;
return ( x ) ;
  • If the value of a formal argument is changed in the called function, the corresponding change does not take place in the calling function. For example,
#include <stdio.h>
fun ( int b ) {
    b = 60 ;
    printf ( "\n%d", b ) ;
}
int main( )
 {
    int a = 30 ;
    fun ( a ) ;
    printf ( "\n%d", a ) ;
}

Output:

60
30
  • Even if the value of b is changed in fun( ), the value of ‘a’ in main( ) remains unchanged. This means that when values are passed to a called function the values present in actual arguments are not physically moved to the formal arguments; just a photocopy of values of the actual argument is made into formal arguments.

Scope Rule of Functions

Consider the following program

display ( int j ) 
{
   int k = 35 ;
   printf ( "\n%d", j ) ;
   printf ( "\n%d", k ) ;
}
int main( )
{
   int i = 20 ;
   display ( i ) ;
}
  • Note that the main function is sending the value 20 in variable ‘i’ to the function display( ).
  • This program begs a vital question. Is it necessary to send the value of ‘i’ to display( )? Is it not possible for the display( ) function to directly access it without main( ) having to pass the value?
  • The answer to the above questions is No. Because by default the scope of a variable is local to the function in which it is defined. The presence of i is known only to the function main( ) and not to any other function.
  • Similarly, the variable k is local to the function display( ) and hence it is not available to main( ). That is why to make the value of ‘i’ available to display( ) we have to explicitly pass it to display( ). This is done by calling functions. A function can be called in 2 ways.
    ○ Call by value (Which we are seeing in this section)
    ○ Call by reference (Which we will see in a short while)
  • Likewise, if we want k to be available to main( ) we will have to return it to main( ) using the return statement. In general, we can say that the scope of a variable is local to the function, more specifically, the block in which it is defined.

Calling convention

  • Calling convention indicates the order in which arguments are passed to a function when a function call is encountered. There are two possibilities here:
    • Arguments might be passed from left to right.
    • Arguments might be passed from right to left.

C language follows the second order. Consider the following function call:

fun (a, b, c, d ) ;

In this call, it doesn’t matter whether the arguments are passed from left to right or from right to left. However, in some function calls, the order of passing arguments becomes an important consideration. For example:

int a = 1 ;
printf ( "%d %d %d", a, ++a, a++ ) ;

It appears that this printf( ) would output 1 2 3. This however is not the
case. Surprisingly, it outputs 3 3 1. This is because C’s calling convention is from right to left.

Call by Value and Call by Reference

Whenever we have called a function with arguments, we have always passed the ‘values’ of variables to the called function. Such function calls are called ‘call by value’. All the examples we saw till now that pass values to functions were called by value. For example:

f = factr ( a ) ;

Here, one can see that the ‘value’ of ‘a’ is being passed to function factr().
Hence, call by value. One can pass the address of the variable to the function. This is called ‘call by reference’. Note that this feature of C functions needs at least an elementary knowledge of a concept called ‘pointers’.
In call by reference, the addresses of actual arguments in the calling function are copied into formal arguments of the called function. This means that by using these addresses we would have access to the actual arguments and hence we would be able to manipulate them. The following program illustrates this fact.

#include <stdio.h>
void swap( int *x, int *y )
{
     int t ;
     t = *x ;
    *x = *y ;
    *y = t ;
}
int main( )
{
int a = 10, b = 20 ;
swap ( &a, &b ) ;
printf ( "\na = %d b = %d", a, b ) ;
}

Output:

a = 20 b = 10

Note that this program swaps the values of a and b using their addresses stored in x and y. Using a call by reference intelligently we can make a function return more than one value at a time, which is not possible ordinarily. This is shown in the program given below.

#include <stdio.h>
void area_perimeter ( float r, float *a, float *p )
{
*a = 3.14 * r * r ;
*p = 2 * 3.14 * r ;
}
int main( ) 
{
     float area, perimeter, radius ;
     printf ( "\nEnter radius of a circle " ) ;
     scanf ( "%f", &radius ) ;
     area_perimeter ( radius, &area, &perimeter ) ;
     printf ( "Area = %f", area ) ;
     printf ( "\nPerimeter = %f", perimeter ) ;
}

Output

Enter radius of a circle 5
Area = 78.500000
Perimeter = 31.400000

Here, we are passing the value of radius but addresses of area and perimeter. And since we are passing the addresses, any change that we make in values stored at addresses contained in the variables a and p would make the change effective in main( ). That is why when the control returns from the function area_perimeter( ) we can output the values of area and perimeter.
Thus, we have been able to indirectly return two values from a called function, and hence, have overcome the limitation of the return statement, which can return only one value from a function at a time.

Library functions

  • Note that pow(), printf(), scanf(), sqrt() etc are all library functions that are already defined by compiler authors and are ready to use as they come shipped with the compiler.
  • But one cannot use these functions without “including the header file” associated with the functions.
  • Header files are a special type of file that only contain the function prototypes, i.e., the function name, return type and the order and data type of the parameters of the functions.
  • Once the header file is included, it helps the compiler to evaluate the function calls you do in your program to find if there is any mismatch in the way you are calling and the way it has to be called. If there is a mismatch, the compiler throws a compile-time error namely ‘undefined reference’ which means that the function call you are making is referring to no function definition.
  • So it is not just essential to include the header files corresponding to the functions you are going to use in the program but it is equally important to call the functions with the proper name, arguments, the data type, and order of the arguments.

Exercises

  1. Write a function to calculate the factorial value of any integer entered through the keyboard. The function is to take the integer as the parameter and return the factorial of the received number back. Read the user input and print the factorial in the main function.
  2. Write a function power ( a, b ), to calculate the value of a raised to b. Read a and b using scanf( ) in main( ) and print the power value returned from power( ) function in main( ) function.
  3. Write a function to take a year as an input parameter and return 1 if the year is a leap year and 0 otherwise.
  4. Write a function to take a positive integer as an input parameter and return 1 if the integer is palindrome and 0 otherwise.
  5. Write a function to take a positive integer as an input parameter and print the prime factors of the input integer. Let the return type of the function be void. a. Prime factors of the 24 are 2, 2, 2 and 3, whereas prime factors of 35 are
    5 and 7
  6. Write a function that receives a float and an int from main( ), finds the product of these two and returns the product which is printed through main( ).
  7. Write a function that receives 5 integers and returns the sum, average and standard deviation of these numbers. Call this function from main( ) and print the results in main( ).
  8. Write a function that receives marks received by a student in 3 subjects and returns the average and percentage of these marks. Call this function from main() and print the results in main( ).
  9. A 5-digit positive integer is entered through the keyboard, write a function to calculate the sum of digits of the 5-digit number. Call this function from main( ) and print the results in main( ).
  10. Write a function to find the binary equivalent of a given decimal integer as an argument and display it.

Function Declaration and Prototypes

Any C function by default returns an int value. By default (when you do not mention a return type), the return type of a function is assumed to be an integer. If we desire that a function should return a value other than an int, then it is necessary to explicitly mention it. Suppose we want to find out the square of a number using a function. This is what this simple program would look like:

#include <stdio.h>
#include <math.h>
square ( float x ) 
{
    float y ;
    y = x * x ;
    return ( y ) ;
}
int main( ) 
{
    float a, b ;
    printf ( "Enter any number " ) ;
    scanf ( "%f", &a ) ;
    b = square ( a ) ;
    printf ( "Square of %f is %f", a, b ) ;
}

And here are three sample runs of this program…

Enter any number 3
Square of 3 is 9.000000
Enter any number 1.5
Square of 1.5 is 2.000000
Enter any number 2.5
Square of 2.5 is 6.000000

The first of these answers is correct. But a square of 1.5 is not 2. Neither is 6 a square of 2.5. This happened because any C function, by default, always returns an integer value. Therefore, even though the function square( ) calculates the square of 1.5 as 2.25, the problem crops up when this 2.25 is to be returned to main( ). square( ) is not capable of returning a float value. So it typecasts 2.25 to integer i.e.2 and then it
returns 2. The value 2 is stored in b which is a floating-point variable. This will cause the compiler to typecast an integer value to a floating-point value i.e. 2.000000. The following program segment illustrates how to make square( ) capable of returning a float value.

#include <stdio.h>
#include <math.h>
int main( )
{
    float square ( float ) ;
    float a, b ;
    printf ( "Enter any number " ) ;
    scanf ( "%f", &a ) ;
    b = square ( a ) ;
    printf ( "Square of %f is %f", a, b ) ;
}
float square ( float x ) 
{
    float y ;
    y = x * x ;
    return ( y ) ;
}

output

Enter any number 1.5

Square of 1.5 is 2.250000
Enter any number 2.5
Square of 2.5 is 6.250000

Now the expected answers i.e. 2.25 and 6.25 are obtained. Note that the function square( ) must be declared in main( ) as

float square ( float ) 

This statement is often called the prototype declaration of the square( ) function. This means that square( ) is a function that receives a float and returns ‘a’ float. We have done the prototype declaration in main( ) because we have called it from main( ). There is a possibility that we may call square( ) from several other functions other than main( ). In such a case we would make only one declaration outside all the functions at the beginning of the program.
In some programming situations, we want that a called function that should not return any value. This is made possible by using the keyword void. This is illustrated in the following program.

#include <stdio.h>
#include <math.h>
int main( ) 
{
   void foo( ) ;
   foo( ) ;
}
void foo( )
{
   printf ( "\nIn foo" ) ;
}

Here, the foo( ) function has been defined to return void; which means it would return nothing. Therefore, it would just flash the message and return the control back to the main( ) function.
One can avoid writing function prototypes altogether. Just place the function definition anywhere before the function is called for the first time and the compiler should not throw any warning or errors. The same program as above can be rewritten as follows:

#include <stdio.h>
#include <math.h>

void foo( ) 
{
  printf ( "\nIn foo" ) ;
}
int main( ) 
{
  foo( ) ;
}

This produces the same output as the previous one. It is always advised to declare the function prototypes soon after the header files in the order they are called and then define the main( ) after which the functions can be defined in the order they have been declared.

Variadic functions

Variadic functions are functions (e.g. printf) that take a variable number of arguments. The declaration of a variadic function uses an ellipsis as the last parameter, e.g.

int printf(const char* format, ...);

Accessing the variadic arguments from the function body uses the following library facilities from stdarg.h:

  1. va_list: A data type that holds the information needed by va_start, va_arg, va_end, and va_copy.
  2. va_start: Enables access to variadic function arguments. Should be called first. This takes two parameters: identifier of type va_list and number of arguments.
  3. va_arg: Accesses the next variadic function arguments. Takes two parameters: identifier of type va_list and data type of the value currently being traversed. This returns the value being traversed.
  4. va_copy: Makes a copy of the variadic function arguments.
  5. va_end: Ends traversal of the variadic function arguments. Takes one parameter: identifier of type va_list which was used in va_start.

The following example illustrates a variadic function:

#include <stdio.h>
#include <stdarg.h>
// The first argument is the total number of arguments being passed.
// This is done for the ease to know when to stop traversing a list
of arguments.
double average(int num,...)
{
    va_list valist;
    double sum = 0.0;
    int i;
    /* initialize valist for num number of arguments */
    va_start(valist, num);
    /* access all the arguments assigned to valist */
    for (i = 0; i < num; i++) {
    sum += va_arg(valist, int);
}
    /* clean memory reserved for valist */
    va_end(valist);
    return sum/num;
}
int main() 
{
    printf("Average of 2, 3, 4, 5 = %f\n", average(4, 2,3,4,5));
    printf("Average of 5, 10, 15 = %f\n", average(3, 5,10,15));
    return 0;
}

Recursion

  • In its simplest sense, recursion in a programming language is a function calling itself. That is, the caller function and the called function are the same.
  • A typical recursive function consists of an exit condition that, upon being true, breaks the process of the function calling itself. And an optional logic of operation and then a statement to call itself.
  • To understand recursion better, consider the following program to calculate the factorial of a given number. Note that this approach doesn’t make use of recursion.
#include <stdio.h>
int factorial ( int x )
{
    int f = 1, i ;
    for ( i = x ; i >= 1 ; i-- )
    f = f * i ;
    return ( f ) ;
}
int main( )
{
    int a, fact ;
    printf ( "\nEnter any number " ) ;
    scanf ( "%d", &a ) ;
    fact = factorial ( a ) ;
    printf ( "Factorial value = %d", fact ) ;
}

Output

Enter any number 3
Factorial value = 6
  • Now, the following is the recursive version of the function to calculate the factorial value.
#include <stdio.h>
int rec ( int x )
{
    int f ;
    if ( x == 1 )
       return ( 1 ) ; // Exit condition
    else
       f = x * rec ( x - 1 ) ;
    return ( f ) ;
}
int main( )
{
     int a, fact ;
     printf ( "\nEnter any number " ) ;
     scanf ( "%d", &a ) ;
     fact = rec ( a ) ;
     printf ( "Factorial value = %d", fact ) ;
}

And here is the output for four runs of the program

Enter any number 1
Factorial value = 1
Enter any number 2
Factorial value = 2
Enter any number 3
Factorial value = 6
Enter any number 5
Factorial value = 120
  • In the first run number is 1, the condition if ( x == 1 ) is satisfied and hence 1 (which indeed is the value of 1 factorial) is returned through the return statement.
  • When the number is 2, the ( x == 1 ) test fails, so we reach the statement
f = x * rec ( x - 1 ) ;
  • And here is where we meet recursion. Since the current value of x is 2, it is the same as saying that we must calculate the value (2 * rec ( 1 )). Now the control goes into the rec( ) function again with 1 as an argument. The function returns 1 and hence value (2 * rec( 1 )) reduces to (2 * 1) and the value 2 is returned to main ( ).
  • Now perhaps you can see what would happen if the value of a is 3, 4, 5 and so on.
    ● For the value of a = 5, we might say what happens is,
    ○ rec ( 5 ) returns ( 5 times rec ( 4 ),
    ■ which returns ( 4 times rec ( 3 ),
    ● which returns ( 3 times rec ( 2 ),
    ○ which returns ( 2 times rec ( 1 ),
    ■ which returns ( 1 )
    ○ )
    ● )
    ■ )
    ○ )

Exercises

  1. A 5-digit positive integer is entered through the keyboard, write a function to calculate the sum of digits of the 5-digit number using recursion
  2. A positive integer is entered through the keyboard and write a program that prints the prime factors of the number recursively.
  3. Write a recursive function to obtain the first 25 numbers of a Fibonacci sequence.
  4. A positive integer is entered through the keyboard, write a function to find the binary equivalent of this number using recursion.
  5. Write a recursive function to obtain the running sum of the first 25 natural numbers.
  6. Given three variables x, y, z write a function to circularly shift their values to right. In other words if x = 5, y = 8, z = 10 after circular shift y = 5, z = 8, x =10 after
    circular shift y = 5, z = 8 and x = 10. Call the function with variables a, b, c to circularly shift values. Hint: Use call by reference function calls.
Categories
Computer Science / Information Technology Language: C

Decision Control Statements

Many times, we want a set of instructions to be executed in one situation, and an entirely different set of instructions to be executed in another situation. This kind of situation is dealt with in C programs using decision control instruction. A decision control instruction can be implemented in C using:

  • The if statement
  • The if-else statement
  • The conditional operators

The if statement

C uses the keyword ‘if’ to implement the decision control instruction. The general form of if statement looks like this:

if ( this condition is true )
    execute this statement;

The keyword ‘if’ tells the compiler that what follows is a decision control instruction. The condition following the keyword if is always enclosed within a pair of parentheses. If the condition, whatever it is, is true, then the statement is executed. If the condition is not true then the statement is not executed; instead, the program skips past it. A condition can be expressed using C’s ‘relational’ operators which are listed in the following table:

ExpressionExplanation
x == yx is equal to y
x != yx is not equal to y
x < yx is less than y
x > yx is greater than y
x <= yx is less than or equal to y
x >= yx is greater than or equal to y
Relational operator expressions example

The following example program illustrates the if statement. It reads the age of the user and determines if the user can vote.

#include <stdio.h>
int main() 
{
    int age;
    scanf("%d", &age);
    if (age > 18)
        printf("Eligible");
    return 0;
}

Expression as condition

An expression can be any valid expression including a relational expression which can be used as a condition inside of if. We can even use arithmetic expressions in the if statement. For example, all the following if statements are valid

if ( 3 + 2 % 5 )
    printf ( "This works" ) ;
if ( a = 10 )
    printf ( "Even this works" ) ;
if ( -5 )
    printf ( "Surprisingly even this works" ) ;

Points to note:

  • Note that in C a non-zero value (integer or float) is considered to be true, whereas a 0 is considered to be false. Hence all three printf() statements get executed in the above example.
  • In the second if, 10 gets assigned to a so the if is now reduced to if ( a ) or if ( 10). Since 10 is non-zero, it is true hence again printf( ) gets executed.

Multiple Statements within if

It may so happen that in a program we want more than one statement to be executed if the expression following if is satisfied. If such multiple statements are to be executed then they must be placed within a pair of braces as illustrated in the following example.

#include <stdio.h>
int main()
{
    int age;
    scanf("%d", &age);
    if (age > 18)
    {
        printf("Eligible");
        printf("Please get the voter id ready");
    }
    return 0;
}

If the pair of brackets enclosing the printf() statements under if is removed, the compiler considers only the first statement as the if block. Hence the default scope of the if statement is the immediately next statement after it.

The if-else statement

if statement executes a set of statements when the condition placed in it evaluates to true. It does nothing when the expression evaluates to false. An else block coupled with an if block helps in executing a totally different set of instructions when the condition fails. Consider the same voter example which we saw earlier. The program should check if the age is greater than 18. And if it is not, the program should print “Not eligible”.

#include <stdio.h>
int main() 
{
    int age;
    scanf("%d", &age);
    if (age > 18)
    {
        printf("Eligible");
        printf("Please get the voter id ready");
    }
    else 
    {
        printf("Not eligible");
        printf("Wait for appropriate age");
    }
    return 0;
}

Points to note:

  • The group of statements after the if up to and not including the else is called an ‘if block’. Similarly, the statements after the else form the ‘else block’.
  • Notice that the else is written exactly below the if. There should not be any statement between the if block and else block. This will raise a compilation error.
  • Had there been only one statement to be executed in the if block and only one statement in the else block we could have dropped the pair of braces.
  • As with the if statement, the default scope of else is also the statement immediately after the else. To override this default scope a pair of braces as shown in the above example must be used.

Nested if-else

It is perfectly all right if we write an entire if-else construct within either the body of the if statement or the body of an else statement. This is called nesting of ifs. This is shown in the following program:

#include <stdio.h>
int main() 
{
    int n;
    scanf("%d", &n);
    if (n % 3 == 0)
        printf("Divisible by 3");
    else 
    {
        if (n % 5 == 0)
            printf("Divisible by 5");
        else
            printf("Neither divisible by 3 nor 5");
    }
    return 0;
}

Use of logical operators

Logical operators (‘AND’, ‘OR’, ‘NOT’) are extensively used in conditional statements. These operators can be used to reduce the nesting and complexity of the conditional statements. Consider the following example where the percentage of a student is read and the class is printed based on the following criteria:

  • Percentage above or equal to 60 – First division
  • Percentage between 50 and 59 – Second division
  • Percentage between 40 and 49 – Third division
  • Percentage less than 40 – Fail
#include <stdio.h>
int main() 
{
    float per;
    scanf("%f", &per);
    if ( per >= 60 )
            printf ( "First division ") ;
    else 
    {
            if ( per >= 50 )
                printf ( "Second division" ) ;
            else 
            {
                if ( per >= 40 )
                    printf ( "Third division" ) ;
                else
                    printf ( "Fail" ) ;
            }
    }
    return 0;
}

Points to note:

  • As the number of conditions goes on increasing the level of indentation also goes on increasing. As a result, the whole program creeps to the right.
  • Care needs to be exercised to match the corresponding ifs and elses.
  • Care needs to be exercised to match the corresponding pair of braces.
  • The readability of the program takes a serious hit.

The same program can be rewritten using logical operators as follows and all the above disadvantages can be eliminated:

#include <stdio.h>
int main()
{
    float per;
    scanf("%f", &per);
    if ( per >= 60 )
        printf ( "First division ") ;
    if ( ( per >= 50 ) && ( per < 60 ) )
        printf ( "Second division" ) ;
    if ( ( per >= 40 ) && ( per < 50 ) )
        printf ( "Third division" ) ;
    if ( per < 40 )
        printf ( "Fail" ) ;
    return 0;
}

Points to note:

  • The mismatching of the ifs with their corresponding elses gets avoided.
  • In spite of using several conditions, the program doesn’t creep to the right

The else-if clause

The else-if clause (also called as if-else-if ladder) gives a powerful way of handling multiple cases and possibilities. The syntax is as follows:

if (condition)
    statement 1;
else if (condition)
    statement 2;
.
.
else
    Statement;

Here, the last else statement is optional. The if statements are executed from the top down. As soon as one of the conditions controlling the if is true, the statement associated with that if is executed, and the rest of the C else-if ladder is bypassed. If none of the conditions is true, then the final else statement will be executed.


Consider the same example of the printing class of the student based on the percentage. It can be written in a different way using else-if as follows:

#include <stdio.h>
int main() 
{
    float per;
    scanf("%f", &per);
    if ( per >= 60 )
        printf ( "First division ") ;
    else if ( ( per >= 50 ) && ( per < 60 ) )
        printf ( "Second division" ) ;
    else if ( ( per >= 40 ) && ( per < 50 ) )
        printf ( "Third division" ) ;
    else
        printf ( "Fail" ) ;
    return 0;
}

Points to be noted

  • This program reduces the indentation of the statements. In this case, every else is associated with its previous if.
  • The last else goes to work only if all the conditions fail.
  • No other statements should be placed between the ladder. If there are multiple statements in an else-if case, they have to be enclosed in brackets.

Advantages of the else-if clause:

  • In case if-else had to replicate the output logic of the else-if ladder, it would be more complex. The following example illustrates the contrast between the two:
if (i == 10)
printf("i is 10");
else if (i == 15)
printf("i is 15");
else
printf("i is not
present");

if (i == 10)
printf("i is 10");
else {
if (i == 15)
printf("i is 15");
else
printf("i is not present");
}

Common mistakes

Using assignment operator instead of ‘==’ comparison operator as shown:

#include <stdio.h>
int main() 
{
    float per = 8.9;
    if ( per = 7.9 );
    printf ( "Same");
    return 0;
}

The program will print “Same” irrespective of the value of ‘per’.

  • Putting semicolon at the end of if() such as follows:
#include <stdio.h>
int main() 
{
      float per = 8.9;
      if ( per == 7.9 );
      printf ( "Same");
      return 0;
}

The above program prints “Same”.

  • Comparing floating-point variables with double. Consider the following example.
#include <stdio.h>
int main() 
{
    float per = 8.9;
    if ( per == 8.9 )
    printf ( "Same");
    else
    printf("Different");
    return 0;
}

The output of the above program will surprisingly be “Different” as ‘8.9’ is double and ‘per’ is float and they are not the same.

The conditional operators / Ternary operators

The conditional operators ‘?’ and ‘:’ are sometimes called ternary operators since they take three arguments. They form a foreshortened if-then-else. The general form is:

expression 1 ? expression 2 : expression 3 

This decodes to:

if expression 1 is true, then the value returned will be expression 2, otherwise, the value returned will be expression 3.

Example: y = ( x > 5 ? 3 : 4 ); The above statement assigns y to 3 if the value of x is greater than 5 and 4 otherwise.

Points to note:

  • Conditional operators could be used for statements other than arithmetic statements. This is illustrated as follows:
    • ( i == 8 ? printf (“QM”) : printf (“C Programming”)) ;
    • printf ( “%c” , ( a <= ‘z’ ? a : ‘!’ ));
  • The conditional operators can be nested as shown below.
    • big = ( a > b ? ( a > c ? 3: 4 ) : ( b > c ? 6: 8 ));
  • Consider the following conditional expression:
    • a > b ? g = a : g = b ;
    • This will make the compiler throw an error ‘Lvalue Required’. The error can be overcome by enclosing the statement in the : part within a pair of parenthesis. This is shown below:
    • a > b ? g = a : ( g = b ) ;
  • In absence of parentheses, the compiler believes that b is being assigned to the result of the expression to the left of second =. Hence it reports an error.
  • The limitation of the conditional operators is that after the ? or after the : only one C statement can occur. In practice rarely is this the requirement.

Excercise

  1. If cost price and selling price of items is given, write a program to determine whether the seller has made profit or incurred loss and print how much profit he made or loss he incurred.
  2. Write a program to find out whether a given number is odd or even.
  3. Given an year, write a program to determine whether it is a leap year or not.
  4. According to the Gregorian calendar, it was Monday on the date 01/01/1900. If any year is input through the keyboard write a program to find out what is the day on 1st January of this year.
  5. Given a five-digit number, write a program to obtain the reversed number and to determine whether the original and reversed numbers are equal or not.
  6. Given 3 numbers, print the minimum, maximum and average of them.
  7. Given the three angles of triangle, check if the triangle is valid or not.
  8. Find the absolute value of a number entered through the keyboard.
  9. Given the length and breadth of a rectangle, write a program to find whether the area of the rectangle is greater than its perimeter.
  10. Given three points (x1, y1), (x2, y2) and (x3, y3), write a program to check if all the three points fall on one straight line.
  11. Given the coordinates (x, y) of a center of a circle and it’s radius, write a program which will determine whether a point lies inside the circle, on the circle or outside the circle. (Hint: Use sqrt( ) and pow( ) functions)
  12. Given a point (x, y), write a program to find out if it lies on the x-axis, y-axis or at the origin, viz. (0, 0).
  13. Given the three sides of a triangle, write a program to check whether the triangle is isosceles, equilateral, scalene or right angled triangle.
  14. If the three sides of a triangle are entered through the keyboard, write a program to check whether the triangle is valid or not. The triangle is valid if the sum of two sides is greater than the largest of the three sides.
Categories
Computer Science / Information Technology Language: C

Introduction to C

The inception of C

  • Designed and developed in AT&T’s Bell Labs in 1972 by Dennis Ritchie.
  • It is a reliable, fast, simple, and easy to use language.
  • It is a middle-level language which just close enough to the machine as well as to the programmer. This gives the programmer fine control over machine properties such as memory and processer.
  • UNIX, Linux, Android, PHP, Python, C++ and so many other products and languages are written in C making it the most influential and powerful language for a professional to learn.
  • C is everywhere. Smartphones, computers, enterprise machines, dish TV set-up boxes, cameras, microwaves, washing machines and 99% of smart devices run C or a morphed version of C. So, C is a basic skill to have if ones want to become a professional in computers.

Let’s get started

  • C is a language just like English and Kannada which is used to communicate.
  • English and other natural languages are used to communicate with other humans and we use C to communicate with computers.
  • Just the way we learn natural languages by starting with the alphabet followed by words that form sentences finally constituting a paragraph, we learn C from alphabets, digits, and special symbols followed by constants, variables, and keywords which form instructions finally constituting a program.

The C Character Set

  • A character denotes any alphabet, digit or special symbol used to represent information.
  • In C,
    • Alphabets are: from A to Z and from a to z. (Obviously)
    • Digits are from 0 to 9 (Duh!)
    • Special symbols are anything printable on your keyboard other than the above two groups.

C Tokens

Tokens are the result of a combination of C character set and form the fundamental building blocks of the C programming language. There are 5 types of C tokens. They are:

Keywords:

  • These are reserved words that have a specific meaning in the language.
  • Each keyword has its dedicated functionality.
  • English has over 4,70,000 words and we have learnt it. Guess how many keywords does C have? Just 32. Do you still think C is difficult?
  • Here are the keywords of C:
autodoubleintstruct
breakelselongswitch
caseenumregistertypedef
charexternreturnunion
constfloatshortunsigned
continueforsignedvoid
defaultgotosizeofvolatile
doifstaticwhile
Keywords in C

Identifiers

  • The computer consists of millions of cells in which data is stored. To make the retrieval, storage and usage of the values easy, these memory cells are given names. Since the value in a particular cell might change or vary, these locations are called variables/identifiers.
  • Here are rules for naming identifiers:
    • The first character of an identifier should either be an alphabet or an underscore and nothing else. And then it could be followed by characters or digits or underscores.
    • Identifiers in C are case sensitive. I.e., abc is a different identifier than Abc.
    • Keywords should not be used as identifiers.
    • The length of the identifiers should not be more than 31 characters.
    • Tip: Identifiers should be written in such a way that it is meaningful, short and easy to read.
  • Examples of valid and invalid identifiers:
ValidInvalid
num
sum_of_array
sumOfArray
_len
first
side1
side_2
Side2
X’mas
switch
main()
sum of array
2nd
$dollars
period.
percent%
Examples of valid and invalid identifiers

Constants:

  • Contrary to variables, constants are the entities that remain unchanged throughout the execution of the program.
  • Essentially the values which variables hold are constants.
  • Consider ‘num’ variable holding the value 3 as shown in the following figure:
  • Here, 3 is the constant. The value ‘3’ never changes. ‘num’ is the variable that holds the constant 3. The constant in ‘num’ may change over the course of the execution; hence, it is a variable.

Types of constants:

  • Primary constants:
    • Integer constant
    • Real constant
    • Character constant
    • Void
  • Secondary / Derived constants:
    • Array: Collection of similar primary constants under a single name.
    • Pointer: Constant which is the location of another constant
    • Structure: Collection of similar or dissimilar primary constants.
    • Union: Memory overlapping collection of similar or dissimilar primary / secondary constants.
  • User-defined:
    • Enum: It is mainly used to assign names to integral constants, the names make a program easy to read and maintain.
    • Typedef: can be used to give a type a new name.

We shall currently focus on primary constants for now and pick up the 2ndand 3rd types in upcoming modules.

Primary constants:

Integer constant;

  • An integer constant is a positive or negative non-decimal integer value.
  • Must not have decimal point.
  • If no sign is present, it is assumed positive.
  • No commas or blanks are to be present within an integer constant.
  • There are classifications of integer constants based on their base value. They are listed as follows:
    • Decimal Integer Constants
      • Integer constants consist of a set of digits, through 9, preceded by an optional – or + sign.
      • Example of valid decimal integer constants 341, -341, 0, 8972
    • Octal Integer Constants
      • Integer constants consisting of a sequence of digits from the set 0 through 7 starting with 0 are said to be octal integer constants.
      • Example of valid octal integer constants 010, 0424, 0, 0540
    • Hexadecimal Integer Constants
      • Hexadecimal integer constants are integer constants having a sequence of digits preceded by 0x or 0X. They may also include alphabets from A to F representing numbers 10 to 15.
      • Example of valid hexadecimal integer constants 0xD, 0X8d, 0X, 0xbD

Real constant

  • Real constants also called Floating Point constants, are numbers with the addition of decimal values to integers.
  • The real constants could be written in two forms—Fractional form and Exponential form.
  • Following rules must be observed while constructing real constants expressed in the fractional form:
    • A real constant must have at least a one-digit, decimal point. (Yes! ‘5.’ is a valid floating-point number!)
    • It could be either positive or negative.
    • If no sign is mentioned, by default, it is positive.
    • No commas or blanks are allowed within a real constant.
  • In the exponential form, the real constant is represented in two parts. The part appearing before ‘e’ is called mantissa, whereas the part following ‘e’ is called the exponent. Thus 0.000342 can be written in exponential form as 3.42e-4 (which in normal arithmetic means 3.42 x 10 -4).
  • Following rules must be observed while constructing real constants expressed in exponential form:
    • The mantissa part and the exponential part should be separated by the letter e or E.
    • The mantissa part may have a positive or negative sign.
    • The default sign of the mantissa part is positive.
    • The exponent must have at least one digit, which must be a positive or negative integer. The default sign is positive.

Character constant:

  • A character constant is a single alphabet, a single digit or a single special symbol enclosed within single inverted commas.
  • Both the inverted commas should point to the left. For example, ’A’ is a valid character constant whereas ‘A’ is not.
  • Ex.: ‘A’, ‘I’, ‘5’, ‘=’

Void

  • A void is an empty data type that has no value. We use void data type in functions when we don’t want to return any value to the calling function and we also use it in pointers to create a generic pointer. We shall see functions and pointers in upcoming modules.

Operators:

  • Operators in C are special symbols used to perform the functions. The data items on which the operators are applied are known as operands. Operators are applied between the operands. Depending on the number of operands, operators are classified as follows:

Unary Operator

  • A unary operator is an operator applied to a single operand. For example: increment operator (++), decrement operator (–), sizeof, (type)*, address-of operator (&).

Binary Operator

  • The binary operator is an operator applied between two operands. The following is the list of the binary operators:
  • Arithmetic Operators (+, -, *, /, %)
    • Surprisingly, there are no operator for exponentiation, but there is a function named pow() which we shall see later.
  • Relational Operators (<, >, <=, >=, ==, !=)
  • Shift Operators (<<, >>)
  • Logical Operators (!, &&, ||)  Logical ‘!’ operator is unary
  • Bitwise Operators (~, &, |, ^)  Bitwise ‘!’ is unary
  • Conditional Operators / Ternary operator
  • Assignment Operator (=)

Special symbols:

  • The following are the special symbols in C: ~ ‘ ! @ # % ^ & * ( ) _ – + = | \ { } [ ] : ; ” ‘ < > , . ? / $
  • They have special meaning and are used to achieve concepts through length and breadth of C. (They will reveal themselves along with their purpose as and when the topics are rolled out)

Qualifiers:

There are several qualifiers such as short, long, signed, unsigned that can be applied to the primary data types. The possible qualifiers for the basic type are shown in the table:

Data typeQualifier
Charsigned, unsigned
intshort, long, signed, unsigned
floatNo qualifier
doublelong
voidNo qualifier
Data types and their corresponding qualifiers

Each compiler is free to choose the appropriate size for its hardware with restrictions that short and int are at least 16 bits and long is at least 32 bits and the size of short < int < long.

Char is the same as an integer. If a char is stored in a variable, it stores its corresponding ASCII value which ranges from (0, 255). Hence, qualifier signed or unsigned may be applied to char or any integer.

Unsigned numbers are always positive or zero and obey the laws of arithmetic modulo 2n, where n is the number of bits in the type. E.g., char is 8 bits so unsigned char variables have values between 0 and 28 i.e., values between 0 and 255

Ranges of various data types in C
  • If we do not specify either signed or unsigned, most compilers will assume the type to be signed.
  • So, signed int x;
    can be written as: int x;
  • short and long can be used alone as type specifiers.
    short = short int
    long = long int
  • short int x;
    can be written as short x;

First C program!

It’s a tradition that the first program should be “Hello world!”. Following the same tradition, let’s step into our first program.

#include <stdio.h>
int main()
{
    printf("Hello World");
    return 0;
}

Let us now understand this program in detail.

Structure of a C Program

  • Each instruction in a C program is written as a separate statement.
  • The statements in a program must appear in the same order in which we wish them to be executed.
  • Blank spaces may be inserted between two words to improve the readability of the statement.
  • All statements should be in lower case letters.
  • C has no specific rules for the position at which a statement is to be written in a given line. That’s why it is often called a free-form language. But it is advisable to indent with a tab for every progressive nested block.
  • Every C statement must end with a semicolon (;). Thus; acts as a statement terminator.

Comments in a C Program

  • Comments are used in a C program to clarify either the purpose of the program or the purpose of some statements in the program.
  • It is not considered by the compiler while creating an executable file. It is solely for the reader of the program.
  • It is a good practice to begin a program with a comment indicating the purpose of the program, its author and the date on which the program was written.
  • Here are a few things that you must remember while writing comments in a C program:
    • Comment about the program should be enclosed within /* */
    • When the purpose of a statement(s) isn’t obvious, it is worthwhile mentioning the purpose using a comment. For example:
/* formula for simple interest */
si = p * n * r / 100 ;
  • Any number of comments can be written at any place in the program. For example, a comment can be written before the statement, after the statement or within the statement as shown below.
/* formula */
si = p * n * r / 100;
si = p * n * r / 100 ;
/* formula */
si = p * n * r / /* formula */ 100 ;
  • The normal language rules do not apply to text written within /* .. */. Thus, we can type this text in a small case, capital or a combination. This is because the comments are solely given for the understanding of the programmer or the fellow programmers and are completely ignored by the compiler.
  • Comments cannot be nested. This means one comment cannot be written inside another comment. The following example is invalid.
/*Cal of SI /* Author: QM date: 25/06/2016 */ */
  • A comment can be split over more than one line, as in,
/* This comment
has three lines
in it */

Such a comment is often called a multi-line comment.

  • ANSI C permits single-line comments to be written as follows:
// Calculation of simple interest
// Formula

But note that ‘//’ comments a single line starting from where it was written.

Si = p * t * r / 100 // simple interest
// Formula

So, in this example, the comments are considered from ‘//’ and everything before it till the margin is considered for compilation.

What is main()?

  • main() is a function. A function is nothing but a container for a set of statements.
  • In a C program, there can be multiple functions.
  • The execution of statements starts with the main() function
  • All statements that belong to main() are enclosed within a pair of braces {} as shown below.
int main()
{
    statement 1;
    statement 2;
    statement 3;
}
  • A function may or may not return a value. The main() function always returns an integer value, hence there is an int before main().
  • The integer value that we are returning is 0. 0 indicates success. If for any reason the statements in main() fail to do their intended work we can return a non-zero number from main(). This would indicate failure.
  • As there could be many reasons for failure, we could place a return code standard concerning the program. One of such codes could be returning -1 for entering a floating-point value instead of an integer value.
  • Some compilers like Turbo C/C++ even permit us to return nothing from main(). In such a case we should precede it with the keyword void. But this is a non-standard way of writing the main() function.

Variables and their Usage

Consider the following C program:

/* Calculation of simple interest */
/* Author: QM Date: 25/06/2016 */
# include <stdio.h>
int main()
{
    int p, n ;
    float r, si ;
    p = 1000 ;
    n = 3 ;
    r = 8.5 ;
    /* formula for simple interest */
    si = p * n * r / 100 ;
    printf ( "%f\n" , si ) ;
    return 0 ;
}

Any variable used in the program must be declared before using it. For example,

int p, n ; /* declaration */
float r, si ; /* declaration */
si = p * n * r / 100 ; /* usage */

In the statement,

si = p * n * r / 100 ;

* and / are the arithmetic operators.

printf() and its Purpose

printf()is used to display contents onto the user screen. Concerning the above program, we can note the following points:

  • Once the value of si is calculated it needs to be displayed on the screen. We have used printf() to do so.
  • For us to be able to use the printf() function, it is necessary to use #include at the beginning of the program. #include is a pre-processor directive. It has to be used every time we use printf(). The purpose and definition of pre-processor directives will be covered in later modules.
  • Syntax of printf( ) function is as follows:
printf ( "<format specifier>",<list of variable> ) ; 
  • The following table is a reference for data type and their corresponding format specifiers:
Format SpecifierType
%cCharacter
%dSigned integer
%e or %EScientific notation of floats
%fFloat values
%g or %GSimilar to %e or %E
%hiSigned integer (short)
%huUnsigned Integer (short)
%iUnsigned Integer
%l or %ld or %liLong
%lfDouble
%LfLong Double
%luUnsigned int or unsigned long
%lli or %lldLong long
%lluUnsigned long long
%oOctal representation
%pPointer
%sString
%uUnsigned int
%x or %XHexadecimal representation
%nPrints nothing
%%Prints % character
Format Specifiers

In addition to format specifiers like %f, %d and %c, the format string may also contain any other characters. These characters are printed as they are when printf() is executed.

  • Given below are some more examples of usage of printf() function:
printf ( "%f", si ) ;
printf ( "%d %d %f %f", p, n, r, si ) ;
printf ( "Simple interest = Rs. %f", si ) ;
printf ( "Principal = %d \nRate = %f", p, r ) ;

The output of the last statement would look like this…

Principal = 1000
Rate = 8.500000

‘\n’ is called the newline character and it takes the cursor to the next line. Therefore, you get the output split over two lines. ‘\n’ is one of the several Escape Sequences available in C.
Here are some more escape sequences and we shall see them in detail in upcoming modules.

  • An expression is nothing but a valid combination of constants, variables and operators. printf() can also print the result of an expression. Examples of valid expressions are as follows:
3
3 + 2
c
a + b * c – d

The results of these expressions can be printed as shown below.

printf( "%d %d %d %d", 3, 3 + 2, c, a + b * c – d );

Note that using expressions in printf() is optional. We can print a statement without any expression just as well.

Receiving Input

  • In the program we saw earlier, the values of p, n and r were hard-coded.
  • Often C programs are required to read input from the user to make the program more resourceful and portable.
  • To achieve this motive, scanf() is one of the programs we use. It reads constants from the user and stores them into the address of a mentioned variable.
  • It can be considered as a complementary to printf() function. • The syntax of scanf() is as follows:
scanf("<format -specifier>", &<variable_name>); 

This is illustrated in the program given below.

/* Calculation of simple interest */
/* Author gekay Date 25/06/2016 */
# include <stdio.h>
int main( )
{
    int p, n ;
    float r, si ;
    printf ( "Enter values of p, n, r" ) ;
    scanf ( "%d %d %f", &p, &n, &r ) ;
    si = p * n * r / 100 ;
    printf ( "%f\n" , si ) ;
    return 0 ;
}
  • Note the use of the ampersand (&) before the variables in the scanf() function is a must.
  • ‘&’ is an ‘Address of’ operator. It gives the location number (address) used by the variable in memory.
  • When we say &a, we are telling scanf() at which memory location should it store the value supplied by the user from the keyboard.
  • Note that a blank, a tab or a new line must separate the values supplied to scanf().
  • A blank is created using a spacebar, a tab using the Tab key and a new line using the Enter key. This is shown below. Ex.: The three values are separated by blank:
    1000 5 15.5

Ex.: The three values separated by tab:
1000 5 15.5
Ex.: The three values separated by a newline:
1000
5
15.5
The following is another example stitching all the theories discussed:

/* Just for fun. Author: QM */
# include <stdio.h>
int main( )
{
    int num ;
    printf ( "Enter a number" ) ;
    scanf ( "%d", &num ) ;
    printf ( "Now I’m letting you on a secret...\n" ) ;
    printf ( "You have just entered the number %d\n", 
    num ) ;
    return 0 ;
}

Programming challenges

  • Shradha has a basic salary of n rupees. 10% of the basic salary is her house rent allowance and 40% of the basic salary is her dearness allowance. Print the gross salary she gets.
    • INPUT:
      • First line: An integer n
    • Output:
      • Her gross salary

You cannot copy content of this page