Header Ads

Functions

 



Function are the subprograms which are used to compare a value or perform a task. They cannot independently and always called by the main() program or by some other function. There are two kinds of functions

 i) Library or Built-in-Function

ii) User-defined Function.


The Library functions are pre-defined set of functions. Their task is limited. User could not understand internal working of these functions. User can only use the functions but cannot change or modify them. Library or built in function-in-functions are used to perform standard operation, e.g. square root of a number sqrt(x), absolute value fabs(x), scanf(), printf() and so on. These functions are available with the compiler are used along with the required header files such as math.h, stdio.h, string.h hand so on at the beginning of the program.


The User defined functions are very different. The functions defined by the user according to his/her requirement are called as User-defined functionsUser defined functions are self-contained block statements which are written by the user to compute a value or to perform a task. They can be called by main program repeatedly as per the requirement. User can modify the function according to the requirement. User certainly understands the internal working of the function. User has full scope to implement his/her own ideas in the function.


It performs some well-defined task, which will be useful to other parts of the program.


Uses of functions

  1. Functions are very much useful when a block of statements has to be written/ executed again
  2. Function are useful when the program size is too large or complex. Functions are called to perform each task sequentially from the main program. It is like a top down modular programming technique to solve a problem. (Remember that modular programming; statements are executed from top to bottom in sequence to produce a result)
  3. Functions are also used to reduce difficulties during the debugging a program. 

Functions are probably the most important weapon in our battle against software complexity. You'll want to learn when it's appropriate to break processing out into functions (and also when it's not), and how to set up function interfaces to best achieve the qualities mentioned above: reusability, information hiding, clarity, and maintainability. 


USER DEFINED FUNCTIONS-


In a C language, functions are declared to compute and return the value of specific datatype to the calling program. Function can also be written to perform the task. It may return many values indirectly to the calling program and these are referred to as void function.


Advantages of function

  1. Problems can be factored into understandable and manageable steps.
  2. Functions provide the way to reuse code that is required more than one place in the program.
  3. The length of program can be reduced.
  4. It is easy to locate a faulty function.
  5. A function can be used in other programs.
  6. A function can be called more than once.
  7. A function can be placed in any order.

Q. 1) Distinguish between function prototype and function definition.

The function prototype is only declaration that indicates return type and number of arguments the function will use. The function definition itself is a function. The operation of function is defined in the function definition.


Q.2) How function works? Explain how arguments are passed and results are returned? 

1) Once a function is defined and called, it takes some data from the calling function and returns a value to the called function.

2) The detail of inner working of a function is unknown to the rest of the program.    Whenever a function is called, control passes to the called function and working of calling function is paused. When the execution of called function is completed, control returns to the calling function and executes the next statement.

3) The values of actual arguments passed by the calling function are received by the formal arguments of called function. The number of actual and formal arguments should be same. Extra arguments are discarded if they are defined. If the formal arguments are more than the actual arguments then the extra arguments appear as garbage. Any mismatch in the data type will produce the unexpected result.

4) The function operates on formal arguments and sends back the result to calling functionThe return () statement performs this task.


Q.3) Explain the different formats of return () statements. How many values return statement returns at each call? 

The return statement can return only one value at each call. Different formats of return statement are as follows


a) return (expression);


Example:

       return (a+b+c);

If such a statement is executed, the expression within the parenthesis is first solved and the result obtained is returned.


b) A function may use one or more return statements. It is used when we want to return a value depending upon certain conditions. 


return statements


c) return (&p);

If above syntax is used it returns address of the variable. 


d) return(*p);

The above statement returns value of variable through the pointer.


e) return(sqrt(r));

If such format is used, when control reaches to the return statement, control again passes to function sqrt(). The return statement collects the result obtained from sqrt() function and returns it to the calling function. Here the return statement calls the function sqrt()


f) return(float (square(2.8))

All functions return by default integer value. To force the function return other type of value, we have to specify the data type to be used. When a value is returned it automatically converts to function data type. In the above example, the return value will be converted to float type.


4) Why the return statement is not necessary when function is called by reference?

In call by reference method, address of actual argument is obtained and values are placed in memory address of the variables. Hence, it is not necessary to use return statement.


5) Does the function prototype should match with the function definition

It is necessary that the function prototype and function definition should match in terms of return value an number of argument. 


6) Can we define a user-defined function with the same library function name?

Yes, we can define user-defined function with same library function name. Before that, confirm the respective library function file should not be included. 


7) Is it possible to call library function recursively

Yes, it is possible to call library function recursively.


8) How function helps to reduce the program size?

If we want to perform a task repetitively then it is not necessary to re-write the particular block of the program repeatedly. Shift the particular block of statements in user-defined function. The function defined can be called any number of times to perform the task. Using functions large programs can be reduced to smaller ones. It is easy to debug and find out the errors in it. It also increases readability.


Overloaded functions 


Two or more functions are having the same name then such functions are said to be overloaded. When two o more functions are having same no of parameters then they must be different in their data types. Function Overloading is an example of Compile time Polymorphism.


For example, 

Code

#include <stdio.h> 
int divide (int a, int b) // // overloaded function 
{
  return (a/b); 
} 

float divide (float a, float b)// // overloaded function 
{ 
  return (a/b); 
}

void main() 
{ 
  int x=5,y=2,r1; 
  float n=5.0,m=2.0,r2; 
  rl=divide(x,y);
  r2=divide(n,m); 
  printf("\nResult1=%d",rl); 	// output 2 
  printf("\nResult2=%f",r2); 	// output 2.5 
} 

In this case we have defined two functions with the same name, but one of them accepts two arguments of  type int and the other accepts them of type float. The compiler knows which one to call in each case by examining the types when the function is called. If it is called with two ints as arguments it calls to the function that has two int arguments in the prototype and if it is called with two floats it will call to the one which has two floats in its prototype. 


Recursion

A Recursive is defined as a function that calls itself to solve a smaller version of its task until a final call is made which does not require a call to itself Since a recursive function repeatedly calls itself, it makes use of the system stack to temporarily store the return address and local variables of the calling function. Every recursive solution has two major cases: They are


Base condition, in which the problem is simple enough to be solved directly without making any further calls to the same function. 


Recursive case, in which first the problem at hand is divided into the simpler sub-parts. Second the function calls itself but with sub-parts of the problem obtained in the first step. Third. the result is obtained by combining the solutions of simpler subparts.


Therefore, recursion is defining large and complex problem in terms of smaller and more easily solvable problems. In recursive functions, a complex problem is defined in terms of simpler problems and the simples problem is given explicitly.


Condition for Recursion: Recursion can be applied to those problems where successive terms are getting generated and terminating (base condition) must be known.


Tip: Every recursive function must have at least one base case. Otherwise, the recursive function will generate an infinite sequences of calls, thereby resulting in an error condition known as an infinite stack.


Steps of a Recursive program

Step1: Specify the base condition which will stop the function from making a call to itself

Step2: Check to see whether the current value being processed matches with the value of base case. If yes, process and return the value.

Step3: Divide the problem into smaller or simpler sub-problems.

Step4: Call the function from each sub-problem.

Step5: Combine the results of the sub-problems.

Step6: Return the result of the entire problem. 


Example 1: n! = n * (n-1)!


5 ! = 5 * 4 * 3 * 2 * 1

      = 120

This can be done as 

5!=5 * 4! , where 4! = 4 * 3! 

Therefore, 5! = 5 *  4  *  3!

Similarly, we can also write, 

5 !=5 * 4 * 3 * 2!

Expanding further

5 != 5 * 4 * 3 * 2 * 1!

5 ! = 5 * 4 * 3 * 2 * 1.  We know, 1!=1


Above problem can realized as


Fact(5)  =  5 * Fact(4)

               =  5 * 4 *  Fact(3)

               = 5 * 4 * 3 *  Fact(2)

               = 5 * 4 * 3 * 2 * Fact(1)

               = 5 * 4 * 3 * 2 * 1 


Recursive Condition of the factorial will call itself but with a smaller value of n, this case can be given as

Fact(n) = n * Fact(n-1)


Types of Recursion 


Direction Recursion: A function is said to be directly recursive if it explicitly calls itself.


int Test(int n)

{

     if(n == 0)

     {

         return n;

      }

      else

      {

          return (Test(n-1));

       }

}


Indirect Recursion: A function is said to be indirectly recursive if it contains a call to another function which ultimately calls it. Following two functions are indirectly recursive as they both call each other.


int  Test1 (int n)

{

    if(n==0)

    {

        return n;

     }

     else

    {

        return Test2(n) 

    }

}


int Test2 (int n)

{

    return Test1(n-1);

}


Tail Recursion: A Recursive function is said to be tail recursive if no operations are pending to be performed when the recursive function returns to its caller. When the called function returns. Tail recursive functions highly desirable because they are much more efficient to use as the amount of information that has to be stored on the system, stack is independent of the number of recursive calls. Whenever there is a pending operatic be performed, the function becomes non-tail recursive. In such a non-tail recursive function, information each pending operation must be stored, so the amount of information directly depends on the number of calls. 


Non-Tail Recursion:


int Test (int n)

{

   if(n==1)

   {

       return 1;

    }

    else

    {

        return (n * Test(n-1));

     }

}


However, the same factorial function can be written in tail recursive manner.


int Test (n)

{

     return Test1(n, 1);

}


int Test1 (int n, int res)

{

    if(n==1)

    {

       return res;

     }

     else

     {

        return Test1 (n-1, n * res );

      }

}


Recursion Versus Iteration: Recursion is more of a top-down approach to the problem solving in which the original problem is divided into the smaller subproblems. on the contrary, Iteration follows a bottom-up approach that begins with what is known and then constructing the solution step by step.


Recursion is an excellent way of solving complex problems especially when the problem can be defined in recursive terms. For such problems, a recursive code can be written and modified in a much simpler and clearer manner.


However, Recursive solutions are not always the best solutions. In some cases, recursive programs may require substantial amount of run-time overhead. therefore, when implementing a recursive solution, there is a trade- off involved between the time spent in constructing and maintaining program and the cost incurred in running time and memory space required for the execution of the program.


Whenever a recursive function is called, some amount of overhead in the form of a runtime stack is always involved. Before jumping to the function with a smaller parameter, the original parameters, the local variables and the return address of the calling function are all stored on the system stack. Therefore, while using recursion a lot of time is needed to first push all the information on the stack when the function is called then again in retrieving the information stored on the stack once the control passes back to calling function.


Advantage of Recursion:

  1. Recursive solutions often tend to be shorter and simpler than non-recursive ones.
  2. Code is clearer and easier to use.
  3. Recursion works similar to the original formula to solve a problem
  4. Recursion follows a divide and conquer technique to solve problems.
  5. In some (limited) instances, recursion may be more efficient.

Drawback of Recursion:

  1. For some programmers and readers, recursion is a difficult concept.
  2. Recursion is implemented using system stack. If the stack space on the system is limitedrecursion to a deeper level will be difficult to implement.
  3. Aborting a recursive program in midstream can be a very slow process
  4. Using a recursive function takes more memory and time to execute as compared to its non-recursive counterpart.
  5. It is difficult to find bugs, particularly while using global variables.
  6. It takes more memory and execution time. 

No comments

Powered by Blogger.