CodeSteps

Python, C, C++, C#, PowerShell, Android, Visual C++, Java ...

C Programming – Developing “printf” like function

“printf” is a very famous function in “C” Programming. This is the primary function we use in “C” to display something on the screen. If you are a serious developer, definitely you will get a thought on developing the “printf” function or you will get a question “How it was developed?”.

“printf” is a special function. Why I am using special here is, unlike other functions where a fixed number of arguments are required to pass; “printf” can allow passing any number of arguments. This really leads to a question; how did “printf” get this flexibility to accept any number of arguments?

In this article, I am going to explain how we can write “printf” like functions. My intention is not to implement every option “printf” supports, but to open the doors to show you how to implement those options.

Before continuing reading this article, I am strongly recommending reading this article first:

How to pass variable number of arguments to C/C++ functions?

I am assuming you are aware of using the variable arguments list in “C”. If not, read the above article.

Now let’s look at our “printf” function first, before developing a function like “printf”.

The syntax of the function looks like below:

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

The syntax of the “printf” function is so simple, right? Yes. It is.

The first argument tells, we need to pass a constant string and the second argument (an ellipse) tells, we can pass any number of arguments.

The functionality of “printf” is purely based on its first argument. That means, “printf” changes the way it prints purely depending on its first argument.

We can “printf” the first argument as “Format Specifier”. Each element in the format specifier string has some meaning. For eg: format specifier “%d” to print numbers, “%s” to print strings, etc. This article is not meant for explaining the functionality of “printf”, I am not covering all the format specifiers here.

On success “printf” function returns the number of characters written.

For simplicity, I am going to implement the functionality for “%d” and “%s” format specifiers in our “printf” like function. Let’s start our implementation.

Step 1. Declare a function with the same syntax of “printf”. Give the function name you like. I am giving “myprintf” as the function name.

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

Step 2. Our function logic is purely depending on the first argument “cost char *format”. And for simplicity I am going to implement “%d” and “%s” format specifiers only.

To get a list of format specifiers from the first argument, we need to parse them from the “format” string.

The code for this one would be like this:

   while ( format[i] != '' )
   {
       if ( ( format[i] == '%' ) && ( ( i + 1 ) < len ) )
       {
          switch ( format[i+1] )
          {
             case 'd':
                     {
                        // deal with integer value
                     }
                     break;
 
             case 's':
                     {
                        // deal with string value
                     }
                     break;
          }
       }
       i++;
   }

From the above code, we are considering only “%d” and “%s” format specifiers and when they found printing the respective value.

As I mentioned at the beginning of the article, my intention of writing this article is not to implement the exact implementation of the “printf” function; but my intention is to share with you how to implement a “printf” like function. That is the reason, I kept the code simple and just implemented partial implementation for “%d” and “%s” format specifiers.

Step 3. We need to write a code to print integer values for “%d” and for “%s” we need to print associated string values. Usually, we use the “printf” function to print the values.

But here we are implemented the “printf” like function. So, I don’t want to use the “printf” function in our “printf” like function. That is the reason, we have to find out another way of displaying integer values and string values without using the standard “printf” function.

We use “putchar” function to print a character on the console. What about integer values? Convert each digit to an ASCII character and print the character using “putchar” function. We can use “itoa” function also.

In the same way, we will print each character of a string using “putchar” function.

Now we have an idea of how to implement the logic. This is the time to implement the code.

Step 4. Let’s put it all together. The complete code looks like below:

#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>

int myprintf(const char *format, ...)
{
   if ( format == NULL )
      return 0;

   va_list valist;
   va_start(valist, format);

   int num = 0;
   char *token = NULL;
   int i = 0;
   int len = strlen(format);
   int nprinted = 0;
   int found = 0;
   
   while ( format[i] != '' )
   {
       num = 0;
       found = 0;
       token = NULL;

       if ( ( format[i] == '%' ) && ( ( i + 1 ) < len ) )
       {
          switch ( format[i+1] )
          {
             case 'd':
                     {
                        found = 1;

                        int str[40];
                        int j = 0;

                        num = va_arg(valist, int);

                        int temp = num;

			  if ( num < 0 )
                           num = -num;

                        while ( num != 0 )
                        {
                           str[j++] = (num % 10);
                           num /= 10;
                        }

                        if ( temp < 0 )
                            str[j++] = '-';
                        
                        nprinted += j;
                        j--;
                        
                        while ( j >= 0 )
                        {
                           if ( str[j] != '-' )
                              putchar(str[j--] + '0');
                           else
                              putchar(str[j--]);
                        }
                     }
                     break;
 
             case 's':
                     {
                        found = 1;

                        token = va_arg(valist, char *);
                        if ( token != NULL )
                        {
                           int j = 0;

                           while ( token[j] != '' )
                           {
                              nprinted++;
                              putchar(token[j]);
                              j++;
                           }
                        }
                     }
                     break;
          }

          if ( found != 0 )
          {
             i += 2;
             continue;
          }
       }
   
       putchar(format[i]);
       nprinted++;

       i++;
   }

   va_end(valist);

   return nprinted;
}

// 
void main()
{
   myprintf("%s : %d\n", "Hello!", 123);
}

Observe that my function name is “myprintf”. It will work well with “%d” and “%s” format specifiers. Once we compile and run the application, it will display the following message.

Hello! : 123

Finally, we have successfully created a “printf” like function.

// Malin

C Programming – Developing “printf” like function

One thought on “C Programming – Developing “printf” like function

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top