mirror of
https://github.com/gbdk-2020/gbdk-2020.git
synced 2026-03-05 23:14:44 +01:00
154 lines
2.5 KiB
C
154 lines
2.5 KiB
C
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <ctype.h>
|
|
|
|
static unsigned char scan_skip(char *s, unsigned char i)
|
|
{
|
|
oncemore:
|
|
while(isspace(s[i]))
|
|
i++;
|
|
if(s[i] == 0) {
|
|
gets(s);
|
|
i = 0;
|
|
goto oncemore;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
static unsigned char scan_int(char *s, unsigned char i, unsigned char base, char *nb)
|
|
{
|
|
char n = 0;
|
|
unsigned char j, sign = 0;
|
|
|
|
switch(s[i])
|
|
{
|
|
case '-':
|
|
sign++;
|
|
/* and fall through */
|
|
case '+':
|
|
++i;
|
|
break;
|
|
}
|
|
while(1) {
|
|
if(isdigit(s[i]))
|
|
j = s[i] - '0';
|
|
else if(isalpha(s[i]))
|
|
j = toupper(s[i]) - 'A' + 10;
|
|
else
|
|
break;
|
|
if(j >= base)
|
|
break;
|
|
n = base * n + j;
|
|
i++;
|
|
}
|
|
*nb = (sign == 0 ? n : -n);
|
|
return i;
|
|
}
|
|
|
|
static unsigned char scan_long(char *s, unsigned char i, unsigned char base, int *nb)
|
|
{
|
|
int n = 0;
|
|
unsigned char j, sign = 0;
|
|
|
|
switch(s[i])
|
|
{
|
|
case '-':
|
|
sign++;
|
|
/* and fall through */
|
|
case '+':
|
|
++i;
|
|
break;
|
|
}
|
|
while(1) {
|
|
if(isdigit(s[i]))
|
|
j = s[i] - '0';
|
|
else if(isalpha(s[i]))
|
|
j = toupper(s[i]) - 'A' + 10;
|
|
else
|
|
break;
|
|
if(j >= base)
|
|
break;
|
|
n = base * n + j;
|
|
i++;
|
|
}
|
|
*nb = (sign == 0 ? n : -n);
|
|
return i;
|
|
}
|
|
|
|
char scanf(char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
char s[64];
|
|
unsigned char i = 0;
|
|
char nb = 0;
|
|
|
|
gets(s);
|
|
va_start(ap, fmt);
|
|
for(; *fmt; fmt++) {
|
|
if(isspace(*fmt))
|
|
continue;
|
|
i = scan_skip(s, i);
|
|
if(*fmt == '%') {
|
|
switch(*++fmt) {
|
|
case 'c':
|
|
/* char */
|
|
*va_arg(ap, char *) = s[i++];
|
|
break;
|
|
case 'd':
|
|
/* decimal int */
|
|
case 'u':
|
|
/* unsigned int */
|
|
i = scan_int(s, i, 10, va_arg(ap, char *));
|
|
break;
|
|
case 'o':
|
|
/* octal int */
|
|
i = scan_int(s, i, 8, va_arg(ap, char *));
|
|
break;
|
|
case 'x':
|
|
/* hexadecimal int */
|
|
i = scan_int(s, i, 16, va_arg(ap, char *));
|
|
break;
|
|
case 's':
|
|
/* string */
|
|
{
|
|
char j = 0;
|
|
char *d = va_arg(ap, char *);
|
|
while((d[j++] = s[i++]) != 0)
|
|
;
|
|
}
|
|
break;
|
|
case 'l':
|
|
/* long */
|
|
switch(*++fmt) {
|
|
case 'd':
|
|
/* decimal long */
|
|
case 'u':
|
|
/* unsigned long */
|
|
i = scan_long(s, i, 10, va_arg(ap, int *));
|
|
break;
|
|
case 'o':
|
|
/* octal long */
|
|
i = scan_long(s, i, 8, va_arg(ap, int *));
|
|
break;
|
|
case 'x':
|
|
/* hexadecimal long */
|
|
i = scan_long(s, i, 16, va_arg(ap, int *));
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
if(s[i] != *fmt)
|
|
return -1;
|
|
break;
|
|
}
|
|
nb++;
|
|
} else
|
|
if(s[i] != *fmt)
|
|
return -1;
|
|
}
|
|
va_end(ap);
|
|
|
|
return nb;
|
|
}
|