riva said:
This is an interview question from:
http://www.freshersworld.com/interview/technical_interview_C.htm
Can You write a function similar to printf() ?
I can only think using putchar() and casting for such a thing.
/* BEGIN min_printf.c */
/*
** min_printf uses the following 6 features from stdio.h:
** 1 EOF
** 2 FILE
** 3 stdout
** 4 putc
** 5 feof
** 6 ferror
**
** min_printf uses the following 4 features from stdarg.h:
** 1 va_list
** 2 va_start
** 3 va_end
** 4 va_arg
*/
#include <stdio.h>
#include <stdarg.h>
#define put_c(c, stream) putc((c), (stream))
#define put_char(c) put_c((c), stdout)
#define sput_c(c, stream) \
(put_c((c), (stream)) == EOF \
&& (feof(stream) || ferror(stream)) ? EOF : 1)
#define sfput_char(c) (sput_c((c), stdout))
int (put_c)(int c, FILE *stream);
int (put_char)(int c);
/*
** 5 different conversion specifiers
** are supported by min_printf: %% %c %d %s %u
** and no fancy stuff.
*/
int min_printf(const char *format, ...);
static int sfput_d(int d);
static int sfput_s(const char *s);
static int sfput_u(unsigned u);
static int sfput_u_plus_1(unsigned u);
int (put_c)(int c, FILE *stream)
{
return put_c(c, stream);
}
int (put_char)(int c)
{
return put_char(c);
}
int min_printf(const char *format, ...)
{
int count, increment;
va_list ap;
va_start(ap, format);
for (count = 0; *format != '\0'; ++format) {
if (*format == '%') {
switch (*++format) {
case '%':
increment = sfput_char('%');
break;
case 'c':
increment = sfput_char(va_arg(ap, int));
break;
case 'd':
increment = sfput_d(va_arg(ap, int));
break;
case 's':
increment = sfput_s(va_arg(ap, char *));
break;
case 'u':
increment = sfput_u(va_arg(ap, unsigned));
break;
default:
increment = sfput_char(*format);
break;
}
} else {
increment = sfput_char(*format);
}
if (increment != EOF) {
count += increment;
} else {
count = -42;
break;
}
}
va_end(ap);
return count;
}
static int sfput_s(const char *s)
{
int count;
for (count = 0; *s != '\0'; ++s) {
if (sfput_char(*s) == EOF) {
count = EOF;
break;
}
++count;
}
return count;
}
static int sfput_d(int d)
{
int count;
if (0 > d) {
count = put_char('-');
if (count != EOF) {
count = sfput_u_plus_1(-(d + 1));
if (count != EOF) {
++count;
}
}
} else {
count = sfput_u(d);
}
return count;
}
static int sfput_u(unsigned u)
{
int count;
unsigned digit, tenth;
tenth = u / 10;
digit = u - 10 * tenth + '0';
count = tenth != 0 ? sfput_u(tenth) : 0;
return count != EOF && put_char(digit) != EOF ? count + 1 : EOF;
}
static int sfput_u_plus_1(unsigned u)
{
int count;
unsigned digit, tenth;
tenth = u / 10;
digit = u - 10 * tenth + '0';
if (digit == '9') {
if (tenth != 0) {
count = sfput_u_plus_1(tenth);
} else {
count = put_char('1') == EOF ? EOF : 1;
}
digit = '0';
} else {
count = tenth != 0 ? sfput_u(tenth) : 0;
++digit;
}
return count != EOF && put_char(digit) != EOF ? count + 1 : EOF;
}
/* END min_printf.c */