In this article, we will learn how to implement your own custom printf() function in C language.
The printf() function is present in <stdio.h> header and uses a const char* and variable length arguments as its parameters. Hence we would be using <stdarg.h> header file which provides operations available on variable arguments passed to a function.
Prerequisites: Variadic Functions in C, Strings in C
Problem Statement: Write your own printf() function in C
Example Outputs:
Code 1: myprintf("Hello world %i",404);
Output: Hello world 404.
Code 2: char s[]="Multiverse is real";
myprintf("%s Hello %.3f",s,2.3);
Output: Multiverse is real Hello 2.30
Algorithm:
- Create a function int myprintf() with const char* and '...' as its parameters. ('. . .' enables the function to receive any number of arguments).
- Initialize a pointer of type va_list to work with variable arguments. Pass the pointer to va_start.
- Process the passed string with a delimiter as '%' or '\0', and store it in a token string.
- For every token starting with '%' check if its next characters are a format specifier defined in C. It can be 'i','s','lf'.
- Pass the token string and value retrieved from va_arg() to fprintf() in order to print the required value to the console.
- Once the whole string is processed, end the va_arg pointer.
- Return 0.
Code:
// C program to implement your own printf() function
#include <stdarg.h>
#include <stdio.h>
// your own printf
int myprintf(const char* str, ...)
{
// initializing list pointer
va_list ptr;
va_start(ptr, str);
// char array to store token
char token[1000];
// index of where to store the characters of str in
// token
int k = 0;
// parsing the formatted string
for (int i = 0; str[i] != '\0'; i++) {
token[k++] = str[i];
if (str[i + 1] == '%' || str[i + 1] == '\0') {
token[k] = '\0';
k = 0;
if (token[0] != '%') {
fprintf(
stdout, "%s",
token); // printing the whole token if
// it is not a format specifier
}
else {
int j = 1;
char ch1 = 0;
// this loop is required when printing
// formatted value like 0.2f, when ch1='f'
// loop ends
while ((ch1 = token[j++]) < 58) {
}
// for integers
if (ch1 == 'i' || ch1 == 'd' || ch1 == 'u'
|| ch1 == 'h') {
fprintf(stdout, token,
va_arg(ptr, int));
}
// for characters
else if (ch1 == 'c') {
fprintf(stdout, token,
va_arg(ptr, int));
}
// for float values
else if (ch1 == 'f') {
fprintf(stdout, token,
va_arg(ptr, double));
}
else if (ch1 == 'l') {
char ch2 = token[2];
// for long int
if (ch2 == 'u' || ch2 == 'd'
|| ch2 == 'i') {
fprintf(stdout, token,
va_arg(ptr, long));
}
// for double
else if (ch2 == 'f') {
fprintf(stdout, token,
va_arg(ptr, double));
}
}
else if (ch1 == 'L') {
char ch2 = token[2];
// for long long int
if (ch2 == 'u' || ch2 == 'd'
|| ch2 == 'i') {
fprintf(stdout, token,
va_arg(ptr, long long));
}
// for long double
else if (ch2 == 'f') {
fprintf(stdout, token,
va_arg(ptr, long double));
}
}
// for strings
else if (ch1 == 's') {
fprintf(stdout, token,
va_arg(ptr, char*));
}
// print the whole token
// if no case is matched
else {
fprintf(stdout, "%s", token);
}
}
}
}
// ending traversal
va_end(ptr);
return 0;
}
// driver code
int main()
{
myprintf("Integer: %d\nString: %s\nFloat: %0.2f\n", 10,
"GeeksforGeeks", 12.2548);
return 0;
}
Output
Integer: 10 String: GeeksforGeeks Float: 12.25
Time Complexity:
The time complexity of the above code is: O(n * L), where,
- n: length of format specifier. For example, If %0.5f then n=3.
- L: Length of the output.
In most practical cases, the time complexity is O(1).
Must Read - printf() in C