#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; }