Code:
#include <stdio.h>
#include <stdarg.h>
static int indices[511];
static char *formats[] = {
"",
"%hd","%hi","%ho","%hu","%hx","%hn", /* Short int */
"%d", "%i", "%o", "%u", "%x", "%n", /* int */
"%ld","%li","%lo","%lu","%lx","%ln", /* long int */
"%c", "%s", /* char */
"%e", "%f", "%g", /* float */
"%le","%lf","%lg", /* double */
"%Le","%Lf","%Lg", /* long double */
NULL,
};
static void initIndices ( void )
{
char **p;
int mark = 1;
for ( p = formats + 1; *p != NULL; p++ ) {
if ( (*p)[2] != '\0' )
indices[(*p)[1] + (*p)[2]] = mark++;
else
indices[(*p)[1]] = mark++;
}
}
int readConsoleInput ( char *buf, size_t size, char *fmt, ... )
{
char *p, *fstr;
int n = 0, nitems = 0;
va_list args;
if ( fgets ( buf, size, stdin ) == NULL )
return EOF;
initIndices();
va_start ( args, fmt );
for ( p = fmt; *p != '\0'; p++ ) {
if ( *p != '%' )
continue;
switch ( *++p ) {
case 'h':
fstr = formats[indices[p[0] + p[1]]];
n += sscanf ( buf, fstr, va_arg ( args, short int * ) );
break;
case 'l':
fstr = formats[indices[p[0] + p[1]]];
if ( p[1] == 'e' || p[1] == 'f' || p[1] == 'g' )
n += sscanf ( buf, fstr, va_arg ( args, double * ) );
else
n += sscanf ( buf, fstr, va_arg ( args, long int * ) );
break;
case 'L':
fstr = formats[indices[p[0] + p[1]]];
n += sscanf ( buf, fstr, va_arg ( args, long double * ) );
break;
case 'd': case 'i': case 'o': case 'u': case 'x': case 'n':
fstr = formats[indices[p[0]]];
n += sscanf ( buf, fstr, va_arg ( args, int * ) );
break;
case 'c': case 's':
fstr = formats[indices[p[0]]];
n += sscanf ( buf, fstr, va_arg ( args, char * ) );
break;
case 'e': case 'f': case 'g':
fstr = formats[indices[p[0]]];
n += sscanf ( buf, fstr, va_arg ( args, float * ) );
break;
default:
/* Ignore */
break;
}
if ( n == EOF )
return EOF;
nitems += n;
}
va_end ( args );
return nitems;
}
-Prelude