FOSS
FOSS @foss

C  Command Line Arguments

It is possible to pass some values from the command line to your C programs when they are executed. These values are called command line arguments and many times they are important for your program especially when you want to control your program from outside instead of hard coding those values inside the code.

The command line arguments are handled using main() function arguments where argc refers to the number of arguments passed, and argv[] is a pointer array which points to each argument passed to the program. Following is a simple example which checks if there is any argument supplied from the command line and take action accordingly

Code Snippet (C)
#include <stdio.h>

int main( int argc, char *argv[] )  {

   if( argc == 2 ) {
      printf("The argument supplied is %s\n", argv[1]);
   }
   else if( argc > 2 ) {
      printf("Too many arguments supplied.\n");
   }
   else {
      printf("One argument expected.\n");
   }
}

Output

FOSS
FOSS @foss

Resizing and Releasing Memory

When your program comes out, operating system automatically release all the memory allocated by your program but as a good practice when you are not in need of memory anymore then you should release that memory by calling the function free().

Alternatively, you can increase or decrease the size of an allocated memory block by calling the function realloc(). Let us check the above program once again and make use of realloc() and free() functions

Code Snippet (C)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {

   char name[100];
   char *description;

   strcpy(name, "Zara Ali");

   /* allocate memory dynamically */
   description = malloc( 30 * sizeof(char) );
	
   if( description == NULL ) {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   } else {
      strcpy( description, "Zara ali a DPS student.");
   }
	
   /* suppose you want to store bigger description */
   description = realloc( description, 100 * sizeof(char) );
	
   if( description == NULL ) {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   } else {
      strcat( description, "She is in class 10th");
   }
   
   printf("Name = %s\n", name );
   printf("Description: %s\n", description );

   /* release memory using free() function */
   free(description);
}

Output

FOSS
FOSS @foss

Allocating Memory Dynamically

While programming, if you are aware of the size of an array, then it is easy and you can define it as an array. For example, to store a name of any person, it can go up to a maximum of 100 characters, so you can define something as follows −

char name[100];

But now let us consider a situation where you have no idea about the length of the text you need to store, for example, you want to store a detailed description about a topic. Here we need to define a pointer to character without defining how much memory is required and later, based on requirement, we can allocate memory as shown in the below example

Code Snippet (C)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {

   char name[100];
   char *description;

   strcpy(name, "Zara Ali");

   /* allocate memory dynamically */
   description = malloc( 200 * sizeof(char) );
	
   if( description == NULL ) {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   } else {
      strcpy( description, "Zara ali a DPS student in class 10th");
   }
   
   printf("Name = %s\n", name );
   printf("Description: %s\n", description );
}

Output

FOSS
FOSS @foss

C  Memory Management

The C programming language provides several functions for memory allocation and management. These functions can be found in the <stdlib.h> header file.

Sr.No.Function & Description
1

void *calloc(int num, int size);

This function allocates an array of num elements each of which size in bytes will be size.

2

void free(void *address);

This function releases a block of memory block specified by address.

3

void *malloc(size_t size);

This function allocates an array of num bytes and leave them uninitialized.

4

void *realloc(void *address, int newsize);

This function re-allocates memory extending it upto newsize.

FOSS
FOSS @foss

It should be noted that the function func() has its last argument as ellipses, i.e. three dotes (...) and the one just before the ellipses is always an int which will represent the total number variable arguments passed. To use such functionality, you need to make use of stdarg.h header file which provides the functions and macros to implement the functionality of variable arguments and follow the given steps −

    • Define a function with its last parameter as ellipses and the one just before the ellipses is always an int which will represent the number of arguments.
      • Create a va_list type variable in the function definition. This type is defined in stdarg.h header file.
        • Use int parameter and va_start macro to initialize the va_list variable to an argument list. The macro va_start is defined in stdarg.h header file.

          • Use va_arg macro and va_list variable to access each item in argument list.
          • Use a macro va_end to clean up the memory assigned to va_list variable.

          Code Snippet (C)
          #include <stdio.h>
          #include <stdarg.h>
          
          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));
          }

          Output

          FOSS
          FOSS @foss

          C  Variable Arguments

          Sometimes, you may come across a situation, when you want to have a function, which can take variable number of arguments, i.e., parameters, instead of predefined number of parameters. The C programming language provides a solution for this situation and you are allowed to define a function which can accept variable number of parameters based on your requirement. The following example shows the definition of such a function.

          int func(int, ... ) {
          .
          .
          .
          }

          int main() {
          func
          (1, 2, 3);
          func
          (1, 2, 3, 4);
          }


          FOSS
          FOSS @foss

          Fibonacci Series

          The following example generates the Fibonacci series for a given number using a recursive function

          Code Snippet (C)
          #include <stdio.h>
          
          int fibonacci(int i) {
          
             if(i == 0) {
                return 0;
             }
          	
             if(i == 1) {
                return 1;
             }
             return fibonacci(i-1) + fibonacci(i-2);
          }
          
          int  main() {
          
             int i;
          	
             for (i = 0; i < 10; i++) {
                printf("%d\t\n", fibonacci(i));
             }
          	
             return 0;
          }

          Output

          FOSS
          FOSS @foss

          C - Recursion

          Recursion is the process of repeating items in a self-similar way. In programming languages, if a program allows you to call a function inside the same function, then it is called a recursive call of the function.

          void recursion() {
          recursion
          (); /* function calls itself */
          }

          int main() {
          recursion
          ();
          }

          The C programming language supports recursion, i.e., a function to call itself. But while using recursion, programmers need to be careful to define an exit condition from the function, otherwise it will go into an infinite loop.

          Recursive functions are very useful to solve many mathematical problems, such as calculating the factorial of a number, generating Fibonacci series, etc.

          Number Factorial

          The following example calculates the factorial of a given number using a recursive function

          Code Snippet (C)
          #include <stdio.h>
          
          unsigned long long int factorial(unsigned int i) {
          
             if(i <= 1) {
                return 1;
             }
             return i * factorial(i - 1);
          }
          
          int  main() {
             int i = 12;
             printf("Factorial of %d is %d\n", i, factorial(i));
             return 0;
          }

          Output

          FOSS
          FOSS @foss

          Program Exit Status

          It is a common practice to exit with a value of EXIT_SUCCESS in case of program coming out after a successful operation. Here, EXIT_SUCCESS is a macro and it is defined as 0.

          If you have an error condition in your program and you are coming out then you should exit with a status EXIT_FAILURE which is defined as -1. So let's write above program as follows

          Code Snippet (C)
          #include <stdio.h>
          #include <stdlib.h>
          
          main() {
          
             int dividend = 20;
             int divisor = 5;
             int quotient;
           
             if( divisor == 0) {
                fprintf(stderr, "Division by zero! Exiting...\n");
                exit(EXIT_FAILURE);
             }
          	
             quotient = dividend / divisor;
             fprintf(stderr, "Value of quotient : %d\n", quotient );
          
             exit(EXIT_SUCCESS);
          }
          FOSS
          FOSS @foss

          Divide by Zero Errors

          It is a common problem that at the time of dividing any number, programmers do not check if a divisor is zero and finally it creates a runtime error.

          The code below fixes this by checking if the divisor is zero before dividing:

          Code Snippet (C)
          #include <stdio.h>
          #include <stdlib.h>
          
          main() {
          
             int dividend = 20;
             int divisor = 0;
             int quotient;
           
             if( divisor == 0){
                fprintf(stderr, "Division by zero! Exiting...\n");
                exit(-1);
             }
             
             quotient = dividend / divisor;
             fprintf(stderr, "Value of quotient : %d\n", quotient );
          
             exit(0);
          }