keypoints
very best explanation for each call present here:
https://www.hackerearth.com/practice/notes/know-our-printf-variable-number-of-arguments-to-a-function/
Easy printf implementaion:
or
Full printf implementation:
http://www.firmcodes.com/write-printf-function-c/
https://www.eskimo.com/~scs/cclass/int/sx11b.html
Used area:
- initialization of variable
- (va_list <variable>)
- like malloc or memset
- va_start(<variable>,<number>)
- like foreach
- va_arg(<variable>,<datatype>) inside loop
- like memory free
- va_end(<variable>)
#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)); }
very best explanation for each call present here:
The standard header
<stdarg.h>
contains a set of macro definitions that define how to step through an argument list. The implementation of this header will vary from machine to machine, but the interface it presents is uniform.- The type
va_list
is used to declare a variable that will refer to each argument in turn; in minimal_printf , this variable is calledap
, for "argument pointer". - The macro
va_start
initializesap
to point to the first unnamed argument. It must be called once beforeap
is used. - There must be at least one named argument; the final named argument is used by
va_start
to get started. - Each call of
va_arg
returns one argument and stepsap
to the next;va_arg
uses a type name to determine what type to return and how big a step to take. - Finally,
va_end
does whatever cleanup is necessary. It must be called before the program returns.
Here is the implemetation of our minimal_printf() which gives us idea about both the original printf() and variable number of argument function.
Easy printf implementaion:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
void errmsg( const char* format, ... )
{
va_list arglist;
printf( "Error: " );
va_start( arglist, format );
vprintf( format, arglist );
va_end( arglist );
}
int main( void )
{
errmsg( "%s %d %s", "Failed", 100, "times" );
return EXIT_SUCCESS;
}
Ref: https://stackoverflow.com/questions/5977326/call-printf-using-va-listor
#include<stdio.h>
#include<stdarg.h>
char ErrStr[128];
char Status[128];
int flag=1;
void Feeder( char *buff,...)
{
va_list arglist;
va_start(arglist,buff);
//customized operations...
if (flag<0)
vsprintf(ErrStr,buff,arglist);
else if (flag>=0)
vsprintf(Status,buff,arglist);
va_end(arglist);
}
int main()
{
Feeder("Hello World %d %f %s\n",5,5.55,"55.55");
if(Status[0])
printf("Result: %s\n",Status);
return 0;
}
Ref: http://cc.byexamples.com/2007/01/18/va-list-create-function-like-printf-2/Full printf implementation:
#include<stdio.h>
#include<stdarg.h>
void Myprintf(char *,...); //Our printf function
char* convert(unsigned int, int); //Convert integer number into octal, hex, etc.
int main()
{
Myprintf(" WWW.FIRMCODES.COM \n %d", 9);
return 0;
}
void Myprintf(char* format,...)
{
char *traverse;
unsigned int i;
char *s;
//Module 1: Initializing Myprintf's arguments
va_list arg;
va_start(arg, format);
for(traverse = format; *traverse != '\0'; traverse++)
{
while( *traverse != '%' )
{
putchar(*traverse);
traverse++;
}
traverse++;
//Module 2: Fetching and executing arguments
switch(*traverse)
{
case 'c' : i = va_arg(arg,int); //Fetch char argument
putchar(i);
break;
case 'd' : i = va_arg(arg,int); //Fetch Decimal/Integer argument
if(i<0)
{
i = -i;
putchar('-');
}
puts(convert(i,10));
break;
case 'o': i = va_arg(arg,unsigned int); //Fetch Octal representation
puts(convert(i,8));
break;
case 's': s = va_arg(arg,char *); //Fetch string
puts(s);
break;
case 'x': i = va_arg(arg,unsigned int); //Fetch Hexadecimal representation
puts(convert(i,16));
break;
}
}
//Module 3: Closing argument list to necessary clean-up
va_end(arg);
}
char *convert(unsigned int num, int base)
{
static char Representation[]= "0123456789ABCDEF";
static char buffer[50];
char *ptr;
ptr = &buffer[49];
*ptr = '\0';
do
{
*--ptr = Representation[num%base];
num /= base;
}while(num != 0);
return(ptr);
}
#include <stdio.h>
#include <stdarg.h>
extern char *itoa(int, char *, int);
void myprintf(const char *fmt, ...)
{
const char *p;
va_list argp;
int i;
char *s;
char fmtbuf[256];
va_start(argp, fmt);
for(p = fmt; *p != '\0'; p++)
{
if(*p != '%')
{
putchar(*p);
continue;
}
switch(*++p)
{
case 'c':
i = va_arg(argp, int);
putchar(i);
break;
case 'd':
i = va_arg(argp, int);
s = itoa(i, fmtbuf, 10);
fputs(s, stdout);
break;
case 's':
s = va_arg(argp, char *);
fputs(s, stdout);
break;
case 'x':
i = va_arg(argp, int);
s = itoa(i, fmtbuf, 16);
fputs(s, stdout);
break;
case '%':
putchar('%');
break;
}
}
va_end(argp);
}
REf:
http://www.firmcodes.com/write-printf-function-c/
https://www.eskimo.com/~scs/cclass/int/sx11b.html
Used area:
- To calculate average
- in cli framework
Reference:
No comments:
Post a Comment