Write a private version of
scanf
analogous tominprintf
from the previous section
Found this exercise more challenging than the previous one.
I think partly that's because I have no experience with scanf
, so needed to play around with it for a while before I understood how it behaves.
I implemented a similar method to the previous answer in the C Answers book by collecting a format string and passing it to scanf
.
minscanf
supports %d
, %i
, %o
, %u
, %x
, %c
, %s
, %f
and some specifications like spaces and words but didn't include support for things like the *
(suppression character).
Definitely not a full solution and could be improved, but I think I got the gist of it.
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
void minscanf(char *fmt, ...)
{
va_list ap;
char *p;
int *dval;
int *ival;
int *oval;
unsigned int *uval;
unsigned int *xval;
char *cval;
char *sval;
float *fval;
char fmtstr[100], *pfmtstr = fmtstr;
va_start(ap, fmt);
for (p = fmt; *p; p++) {
*pfmtstr++ = *p;
if (*p != '%')
continue;
else
p++;
while (!isalpha(*p)) {
*pfmtstr++ = *p++;
}
*pfmtstr++ = *p;
*pfmtstr = '\0';
switch(*p) {
case 'd':
dval = va_arg(ap, int *);
scanf(fmtstr, dval);
break;
case 'i':
/* according to spec %i can take octal */
ival = va_arg(ap, int *);
scanf(fmtstr, ival);
break;
case 'o':
oval = va_arg(ap, int *);
scanf(fmtstr, oval);
break;
case 'u':
uval = va_arg(ap, unsigned int *);
scanf(fmtstr, uval);
break;
case 'x':
xval = va_arg(ap, unsigned int *);
scanf(fmtstr, xval);
break;
case 'c':
cval = va_arg(ap, char *);
scanf(fmtstr, cval);
break;
case 's':
sval = va_arg(ap, char *);
scanf(fmtstr, sval);
break;
case 'e':
case 'f':
case 'g':
fval = va_arg(ap, float *);
scanf(fmtstr, fval);
break;
}
pfmtstr = fmtstr; /* reset format string */
}
va_end(ap);
}
int main()
{
int d;
int i;
int o;
unsigned int u;
unsigned int x;
char c;
char s[100];
float f;
minscanf("randomword %d", &d);
minscanf("%i", &i);
minscanf("%o", &o);
minscanf("%u", &u);
minscanf("%x", &x);
minscanf("%c %c", &c, &c); /* newline, space and char */
minscanf("%s", s);
minscanf("%f", &f);
printf("d: %d\n", d);
printf("i: %u\n", i);
printf("o: %u\n", o);
printf("u: %u\n", u);
printf("x: %u\n", x);
printf("c: %c\n", c);
printf("s: %s\n", s);
printf("f: %f\n", f);
}