Added simpler ft_scanf
This commit is contained in:
parent
96b4d2e9eb
commit
4b8a2c7481
194
level-1/scanf/ft_scanf_clean.c
Normal file
194
level-1/scanf/ft_scanf_clean.c
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Consome todos os caracteres de espaço em branco consecutivos do stream.
|
||||||
|
* Retorna 1 em sucesso, -1 em caso de erro de leitura.
|
||||||
|
*/
|
||||||
|
int match_space(FILE *f)
|
||||||
|
{
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
// Lê caracteres enquanto não for o fim do ficheiro e forem espaços
|
||||||
|
while ((ch = fgetc(f)) != EOF && isspace(ch))
|
||||||
|
{
|
||||||
|
// O corpo do loop está vazio de propósito, apenas consome os caracteres
|
||||||
|
}
|
||||||
|
|
||||||
|
// Se o loop parou por um caractere que não é espaço, coloca-o de volta
|
||||||
|
if (ch != EOF)
|
||||||
|
ungetc(ch, f);
|
||||||
|
|
||||||
|
// Verifica se ocorreu um erro de leitura durante as operações
|
||||||
|
if (ferror(f))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tenta corresponder a um caractere específico 'c'.
|
||||||
|
* Já era simples e eficiente, não necessitou de alterações.
|
||||||
|
*/
|
||||||
|
int match_char(FILE *f, char c)
|
||||||
|
{
|
||||||
|
int ch = fgetc(f);
|
||||||
|
if (ch == c)
|
||||||
|
return 1; // Sucesso, caractere corresponde
|
||||||
|
|
||||||
|
// Se não correspondeu, e não é o fim do ficheiro, devolve o caractere
|
||||||
|
if (ch != EOF)
|
||||||
|
ungetc(ch, f);
|
||||||
|
|
||||||
|
return -1; // Falha na correspondência
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lê um único caractere do stream e armazena-o.
|
||||||
|
* Já era simples e direto, não necessitou de alterações.
|
||||||
|
*/
|
||||||
|
int scan_char(FILE *f, va_list ap)
|
||||||
|
{
|
||||||
|
int ch = fgetc(f);
|
||||||
|
char *cp = va_arg(ap, char *);
|
||||||
|
|
||||||
|
if (ch == EOF)
|
||||||
|
return -1; // Falha se chegar ao fim do ficheiro
|
||||||
|
|
||||||
|
*cp = (char)ch;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lê um inteiro do stream, ignorando espaços iniciais e tratando o sinal.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user