Tengo un archivo de texto que quiero leer. El archivo tiene el siguiente contenido:

Asdsf adsfsd
54
asdfa adwfasd
12
asdf adf 
545
asdf asdfasfd
3243
adfasf asdfasdf
324324
asfda asdfasdf
3124
adfa asdfas
432
asdf ad

Y mi código:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>


struct Element {
    int edad;
    char name[50];
};

int main() {
    struct Element aux;
    FILE* fitxer;
    fopen_s(&fitxer, "Text.txt", "r");
    if (fitxer != NULL) {
        while (!feof(fitxer)) {
            fgets(aux.name, 50, fitxer);
            aux.name[strlen(aux.name) - 1] = '\0';
            int ret = fscanf_s(fitxer, "%i", &aux.edad);
            char endl;
            fscanf_s(fitxer, "%c", &endl);
            printf("%d %s \n", aux.edad, aux.name);
        }
        fclose(fitxer);
    }
    else {
        printf("Error: File not found.");
    }    
}

Tuve problemas antes porque no sabía que f_scanf no toma el carácter final. Ahora el problema es que hay algunas cadenas en el archivo que se están cortando. Salida:

54 Asdsf adsfsd
12 asdfa adwfasd
545 asdf adf
3243 asdf asdfasfd
324324 adfasf asdfasdf
3124 asfda asdfasdf
432 adfa asdfas
432 asdf a

Por ejemplo, en este ejemplo, se corta la última letra. Sospecho que tiene algo que ver con la conversión a cadena, agregando el carácter '\0', pero no puedo encontrar el error.

También me gustaría preguntar si hay una manera de hacerlo más elegante.

0
Norhther 9 may. 2020 a las 19:06

3 respuestas

La mejor respuesta

Al menos 3 problemas:

Prueba incorrecta para el final del archivo, evite los números mágicos

árbitra

//while (!feof(fitxer)) {
//    fgets(aux.name, 50, fitxer);
while (fgets(aux.name, sizeof aux.name, fitxer)) {

A fscanf_s(fitxer, "%c", &endl); le falta un aumento.

Investigue fscanf_s() si está interesado, o mejor aún, simplemente use fgets() como entrada.

Código incorrecto para eliminar posibles pruebas '\n'

Alternativas: 1 2

// aux.name[strlen(aux.name) - 1] = '\0';
aux.name[strcspn(aux.name, "\n")] = '\0';
1
chux - Reinstate Monica 9 may. 2020 a las 16:42
aux.name[strlen(aux.name) - 1] = '\0';

Esta línea corta el último carácter de la cadena que leyó con fgets. Para la mayoría de las líneas, ese carácter es el \n al final de la línea. Pero supongo que su última línea no tiene un salto de línea al final. Entonces cortas el último personaje real.

Para solucionar esto, solo debe cortar el último carácter si es igual a '\n'.

PD: Su última llamada a fscanf_s a falla y termina imprimiendo el mismo número que la línea anterior. No estoy seguro de si eso es intencional o no.

PPS: Si su última llamada a fscanf_s no falló, su ciclo while se repetirá una vez más de lo debido porque feof solo devuelve verdadero si una lectura anterior falló debido al final del archivo. Por lo tanto, en lugar de utilizar feof, es probable que desee verificar directamente si sus operaciones de lectura fallaron.

0
sepp2k 9 may. 2020 a las 16:18

Con

aux.name[strlen(aux.name) - 1] = '\0';

Se deshace de un comportamiento bien conocido de fgets: almacena toda la línea en el búfer de salida incluido el carácter '\n'.

¿Pero qué pasa si ese personaje no está presente? Cortarías el último personaje.

Es exactamente lo que sucede cuando lees la última línea del archivo. Como no hay caracteres '\n' finales, fgets se detiene en cuanto se alcanza el final del archivo.

Para solucionarlo, solo verifique si el carácter que se va a sustituir es el esperado.

Algo como esto:

size_t len = strlen(aux.name);

if(len > 0 && aux.name[len - 1] == '\n')
    aux.name[len - 1] = '\0';

La comprobación len > 0 evita un comportamiento indefinido en el caso de una cadena de longitud 0 (ocurre si el primer carácter de la línea es '\0').

1
Roberto Caboni 9 may. 2020 a las 16:48