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