174 lines
2.7 KiB
C
174 lines
2.7 KiB
C
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <ctype.h>
|
|
|
|
|
|
int match_space(FILE *f)
|
|
{
|
|
int ch;
|
|
|
|
while ((ch = fgetc(f)) != EOF && isspace(ch))
|
|
{}
|
|
|
|
if (ch != EOF)
|
|
ungetc(ch, f);
|
|
|
|
if (ferror(f))
|
|
return -1;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int match_char(FILE *f, char c)
|
|
{
|
|
int ch = fgetc(f);
|
|
if (ch == c)
|
|
return 1;
|
|
|
|
if (ch != EOF)
|
|
ungetc(ch, f);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int scan_char(FILE *f, va_list ap)
|
|
{
|
|
int ch = fgetc(f);
|
|
char *cp = va_arg(ap, char *);
|
|
|
|
if (ch == EOF)
|
|
return -1;
|
|
|
|
*cp = (char)ch;
|
|
return 1;
|
|
}
|
|
|
|
int scan_int(FILE *f, va_list ap)
|
|
{
|
|
int *ip = va_arg(ap, int *);
|
|
int value = 0;
|
|
int sign = 1;
|
|
int ch;
|
|
|
|
ch = fgetc(f);
|
|
|
|
if (ch == '-')
|
|
{
|
|
sign = -1;
|
|
ch = fgetc(f);
|
|
}
|
|
else if (ch == '+')
|
|
{
|
|
ch = fgetc(f);
|
|
}
|
|
|
|
if (!isdigit(ch))
|
|
{
|
|
if (ch != EOF)
|
|
ungetc(ch, f);
|
|
return -1;
|
|
}
|
|
|
|
while (isdigit(ch))
|
|
{
|
|
value = value * 10 + (ch - '0');
|
|
ch = fgetc(f);
|
|
}
|
|
|
|
if (ch != EOF)
|
|
ungetc(ch, f);
|
|
|
|
*ip = value * sign;
|
|
return 1;
|
|
}
|
|
|
|
int scan_string(FILE *f, va_list ap)
|
|
{
|
|
char *sp = va_arg(ap, char *);
|
|
int i = 0;
|
|
int ch;
|
|
|
|
ch = fgetc(f);
|
|
if (ch == EOF)
|
|
return -1;
|
|
|
|
while (ch != EOF && !isspace(ch))
|
|
{
|
|
sp[i++] = (char)ch;
|
|
ch = fgetc(f);
|
|
}
|
|
sp[i] = '\0';
|
|
|
|
if (ch != EOF)
|
|
ungetc(ch, f);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int match_conv(FILE *f, const char **format, va_list ap)
|
|
{
|
|
switch (**format)
|
|
{
|
|
case 'c':
|
|
return scan_char(f, ap);
|
|
case 'd':
|
|
match_space(f);
|
|
return scan_int(f, ap);
|
|
case 's':
|
|
match_space(f);
|
|
return scan_string(f, ap);
|
|
case '\0':
|
|
return -1;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int ft_vfscanf(FILE *f, const char *format, va_list ap)
|
|
{
|
|
int nconv = 0;
|
|
|
|
int c = fgetc(f);
|
|
if (c == EOF)
|
|
return EOF;
|
|
ungetc(c, f);
|
|
|
|
while (*format)
|
|
{
|
|
if (*format == '%')
|
|
{
|
|
format++;
|
|
if (match_conv(f, &format, ap) != 1)
|
|
break;
|
|
else
|
|
nconv++;
|
|
}
|
|
else if (isspace(*format))
|
|
{
|
|
if (match_space(f) == -1)
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (match_char(f, *format) != 1)
|
|
break;
|
|
}
|
|
format++;
|
|
}
|
|
|
|
if (ferror(f))
|
|
return EOF;
|
|
|
|
return nconv;
|
|
}
|
|
|
|
int ft_scanf(const char *format, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, format);
|
|
int ret = ft_vfscanf(stdin, format, ap);
|
|
va_end(ap);
|
|
|
|
return ret;
|
|
} |