Exercise 7-3 (minprintf)

Chapter_7     Exercise_7-2 Exercise_7-4







Exercise 7-3     K&R, p. 156


Exercise 7-3. Revise minprintf() to handle more of the other facilities of printf().




minprintf.c     K&R, p. 153-156         download


#include <stdio.h> // for printf(), putchar()
#include <string.h> // for strcat()
#include <ctype.h> // for isdigit()
#include <stdarg.h> // for va_arg, va_list, va_start, va_end

#define MAXLEN 100 // max length of print format

// minimal printf() with variable argument list
void minprintf(char *fmt, ...);

int main()
{
char msg[] = "hello";
short sh = 0;
unsigned u = 1;
float f = -.2f;
double d = 1234567890;
double dd = d*d;
long double ld = dd*dd;

minprintf("msg: \"%s\"\n", msg);
minprintf("msg: \"%8s\"\n", msg);
minprintf("msg: \"%-8s\"\n", msg);
minprintf("msg: \"%8.4s\"\n", msg);
minprintf("msg: \"%8.*s\"\n", 4, msg);
minprintf("msg: \"%-8.4s\"\n", msg);
minprintf("msg: \"%-8.*s\"\n", 4, msg);
minprintf("pointer address: %p\n", msg);
minprintf("msg[0]: \'%c\'\n", msg[0]);
minprintf("%hd, %u, %f\n", sh, u, f);
minprintf("%4hd, %-4u, %8.2f\n", sh, u, f);
minprintf("%4hd, %-4u, %8.*f\n", sh, u, 2, f);
minprintf("%e, %f, %g\n", d, d, d);
minprintf("%12.4e, %-14.2f, %10.2g\n", d, d, d);
minprintf("%12.*e, %-14.*f, %10.*g\n", 4, d, 2, d, 2, d);
minprintf("%lE, %lf, %lG\n", dd, dd, dd);
minprintf("%Lg, %LG\n", ld, ld);
minprintf("%LE, %Lf\n", ld, ld);

return 0;
}

// minimal printf() with variable argument list
void minprintf(char *fmt, ...)
{ // argument pointer: will point to each
va_list ap; // unnamed argument in turn
char format[MAXLEN]; // print format
char cval; // char value
char *p, *sval; // string value
void *vp; // pointer to void
short shval; // short value
short unsigned shuval; // short unsigned value
int i, ival; // integer value
int max; // maximum field width
unsigned uval;
long lval;
long unsigned luval;
long long llval;
long long unsigned lluval;
double dval; // double value
long double ldval;

max = 0;
format[0] = '%'; // initialize
format[1] = '\0'; // end string
va_start(ap, fmt); // make ap point to first unnamed arg
for (p = fmt; *p; p++)
{
if (*p != '%' && format[1] == '\0')
{ // haven't got to the formatting part yet
putchar(*p); // write the string as it is
continue; // go to next for() iteration
} // here *p == '%' or format[1] != '\0'
switch(*++p) // after ++p, p points to print format
{
case '-': case '.': case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7': case '8': case '9':
i = 1;
format[i++] = *p;
p++;
while (isdigit(*p) || *p == '.')
{
format[i++] = *p;
p++;
}
if (*p == '*')
{
format[i++] = *p; // '*'
max = va_arg(ap, int); // next unnamed arg (max field width)
p++;
}
format[i] = '\0';
p--; // p is incremented at the end of for()
p--; // and at the beginning of switch()
break;
case 'c':
cval = va_arg(ap, int); // next unnamed arg (char as int)
printf("%c", cval);
max = 0, format[1] = '\0'; // reset
break;
case 'h':
strcat(format, "h");
p++;
i = strlen(format);
format[i++] = *p; // char after 'h'
format[i] = '\0';
if (*p == 'd'||*p == 'i'||*p == 'o'||*p == 'x'||*p == 'X')
{ // take next unnamed argument as int
shval = va_arg(ap, int); // next unnamed arg (short as int)
if (max) // max > 0
{printf(format, max, shval);}
else {printf(format, shval);} // short integer
max = 0, format[1] = '\0'; // reset
break;
}
else if (*p == 'u')
{ // take next unnamed argument as unsigned int
shuval = va_arg(ap, unsigned); // unsigned int
if (max) // max > 0
{printf(format, max, shuval);}
else {printf(format, shuval);} // short unsigned int
max = 0, format[1] = '\0'; // reset
break;
}
else // unknown
{
printf("Unknown format: \"%s\"\n", format);
return;
}
case 'd': case 'i': case 'o': case 'x': case 'X':
ival = va_arg(ap, int); // next unnamed arg (int)
i = strlen(format);
format[i++] = *p;
format[i] = '\0';
if (max) // max > 0
{printf(format, max, ival);}
else {printf(format, ival);}
max = 0, format[1] = '\0'; // reset
break;
case 'u':
uval = va_arg(ap, unsigned);
strcat(format, "u");
if (max) // max > 0
{printf(format, max, uval);}
else {printf(format, uval);}
max = 0, format[1] = '\0'; // reset
break;
case 'l':
strcat(format, "l");
p++;
i = strlen(format);
format[i++] = *p;
format[i] = '\0';
if (*p == 'd'||*p == 'i'||*p == 'o'||*p == 'x'||*p == 'X')
{
lval = va_arg(ap, long);
if (max) // max > 0
{printf(format, max, lval);}
else {printf(format, lval);}
max = 0, format[1] = '\0'; // reset
break;
}
else if (*p == 'u')
{
luval = va_arg(ap, long unsigned);
if (max) // max > 0
{printf(format, max, luval);}
else {printf(format, luval);}
max = 0, format[1] = '\0'; // reset
break;
}
else if(*p == 'l')
{
p++;
i = strlen(format);
format[i++] = *p;
format[i] = '\0';
if (*p == 'd'||*p == 'i'||*p == 'o'||*p == 'x'||*p == 'X')
{
llval = va_arg(ap, long long);
if (max) // max > 0
{printf(format, max, llval);}
else {printf(format, llval);}
max = 0, format[1] = '\0'; // reset
break;
}
else if (*p == 'u')
{
lluval = va_arg(ap, long long unsigned);
if (max) // max > 0
{printf(format, max, lluval);}
else {printf(format, lluval);}
max = 0, format[1] = '\0'; // reset
break;
}
else // unknown
{
printf("Unknown format: \"%s\"\n", format);
return;
}
}
else if (*p == 'e' || *p == 'f' || *p == 'g' ||
*p == 'E' || *p == 'F' || *p == 'G')
{
dval = va_arg(ap, double);
if (max) // max > 0
{printf(format, max, dval);}
else {printf(format, dval);}
max = 0, format[1] = '\0'; // reset
break;
}
else // unknown
{
printf("Unknown format: \"%s\"\n", format);
return;
}
case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
i = strlen(format);
format[i++] = *p;
format[i] = '\0';
dval = va_arg(ap, double);
if (max) // max > 0
{printf(format, max, dval);}
else {printf(format, dval);}
max = 0, format[1] = '\0'; // reset
break;
case 'L':
strcat(format, "L");
p++;
i = strlen(format);
format[i++] = *p;
format[i] = '\0';

if (*p == 'd'||*p == 'i'||*p == 'o'||*p == 'x'||*p == 'X')
{
llval = va_arg(ap, long long);
if (max) // max > 0
{printf(format, max, llval);}
else {printf(format, llval);}
max = 0, format[1] = '\0'; // reset
break;
}
else if (*p == 'u')
{
lluval = va_arg(ap, long long unsigned);
if (max) // max > 0
{printf(format, max, lluval);}
else {printf(format, lluval);}
max = 0, format[1] = '\0'; // reset
break;
}
else if (*p == 'e' || *p == 'f' || *p == 'g' ||
*p == 'E' || *p == 'F' || *p == 'G')
{
ldval = va_arg(ap, long double);
if (max) // max > 0
{printf(format, max, ldval);}
else {printf(format, ldval);}
max = 0, format[1] = '\0'; // reset
break;
}
else // unknown
{
printf("Unknown format: \"%s\"\n", format);
return;
}
case 's':
strcat(format, "s");
sval = va_arg(ap, char *);
if (max) // max > 0
{printf(format, max, sval);}
else {printf(format, sval);}
max = 0, format[1] = '\0'; // reset
break;
case 'p':
vp = va_arg(ap, void *);
printf("%p", vp);
max = 0, format[1] = '\0'; // reset
break;
default:
putchar(*p);
max = 0, format[1] = '\0'; // reset
break;
} // end of switch()
} // end of for()
va_end(ap); // clean up when done
}
/*
gcc minprintf.c -o minprintf
./minprintf
msg: "hello"
msg: " hello"
msg: "hello "
msg: " hell"
msg: " hell"
msg: "hell "
msg: "hell "
pointer address: 0x7fffa0ab56f2
msg[0]: 'h'
0, 1, -0.200000
0, 1 , -0.20
0, 1 , -0.20
1.234568e+09, 1234567890.000000, 1.23457e+09
1.2346e+09, 1234567890.00 , 1.2e+09
1.2346e+09, 1234567890.00 , 1.2e+09
1.524158E+18, 1524157875019052032.000000, 1.52416E+18
2.32306e+36, 2.32306E+36
2.323057E+36, 2323057227982592286636176640212729856.000000
*/









Chapter_7     Exercise_7-2 BACK_TO_TOP Exercise_7-4



Comments

Popular posts from this blog

Contents

Blogger Page Margins in Contempo