From 4b8a2c7481116b15d28bebf61e34cb807a762635 Mon Sep 17 00:00:00 2001 From: Rui Ribeiro <42305006+ruiribeiro04@users.noreply.github.com> Date: Wed, 1 Oct 2025 13:50:54 +0100 Subject: [PATCH] Added simpler ft_scanf --- level-1/scanf/ft_scanf_clean.c | 194 +++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 level-1/scanf/ft_scanf_clean.c diff --git a/level-1/scanf/ft_scanf_clean.c b/level-1/scanf/ft_scanf_clean.c new file mode 100644 index 0000000..2fba64a --- /dev/null +++ b/level-1/scanf/ft_scanf_clean.c @@ -0,0 +1,194 @@ +#include +#include +#include + +/* + * 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; +} \ No newline at end of file