6

Estoy tratando de almacenar un archivo .txt en variables tipo char en C, el problema es que el resultado al compilar me imprime dos veces la última línea y no entiendo la razón.

  • En el archivo .txt tengo lo siguiente:
123.22.0.212 255.255.0.0
2.169.73.5 255.255.0.0
2.50.10.36 255.255.192.0
  • Resultado al Compilar es el siguiente:
123.22.0.212 255.255.0.0
2.169.73.5 255.255.0.0
2.50.10.36 255.255.192.0
2.50.10.36 255.255.192.0
  • Código en C:
#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE * archivo = fopen("direcciones.txt", "rb");    

    if(archivo == NULL)
    {
        perror("Error en la apertura del archivo");
        return 1;
    }

    /*leyendo caracter por caracter*/
    char ip[12];
    char mask[12];

    while( feof(archivo) == 0)
    {
        fscanf(archivo, "%s%s", &ip, &mask);
        printf("%s %s\n", ip, mask);
    }

    fclose(archivo);
    printf("\n\nSe ha leido el archivo correctamente...");

    return 0;   
}   
Trauma
  • 25,297
  • 4
  • 37
  • 60
Víctor Álvarez
  • 2,593
  • 4
  • 18
  • 41

1 Answers1

9

Primero, lo que no preguntas pero está igualmente mal:

Tus datos de prueba son:

123.22.0.212 255.255.0.0
2.169.73.5 255.255.0.0
2.50.10.36 255.255.192.0

Y tus variables para almacenarlos

char ip[12];
char mask[12];

Sin embargo, según mis cuentas, 255.255.192.0 tiene 13 caracteres. Tus variables están mal dimensionadas. Y ya puestos, 255.255.255.255 necesitaría 16 bytes. 15 para los caracteres en sí, y 1 mas para el 0 final.

Seguimos:

char ip[16];
char mask[16];
...
fscanf(archivo, "%s%s", &ip, &mask);

En C, no existe el concepto de buffer o zona-de-memoria-continua. Una formación o arreglo no existe como tal. A grandes rasgos, es un favor que te hace el compilador de reservarte un trozo de memoria ... y te entrega un puntero a esa zona.

En otras palabras: ip y mask ya son punteros. De hecho, si usas &ip o &mask, el compilador te mostrará un bonito aviso:

warning: format %s expects argument of type char *, but argument has type char (*)[12]

Vale, ahora tu problema: Muy sencillo, feof( ) comprueba el indicador eof del archivo, pero dicho indicador solo se establece al realizar una operación, nunca antes:

  1. El feof( ) comprueba que todo está bien.
  2. Lees del archivo.
  3. El feof( ) comprueba que todo está bien.
  4. Al estar ya al final del archivo, fscanf( ) no lee nada (con lo que se mantiene lo último que hubieras leido. Ahora se establece el indicador eof.
  5. El feof( ) detecta el problema.

Tu código, corregido, quedaría así:

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

int main( ) {
  FILE * archivo = fopen( "direcciones.txt", "rb" );    

  if( archivo == NULL ) {
    perror( "Error en la apertura del archivo" );
    return 1;
  }

  char ip[16];
  char mask[16];

  while( 1 ) {
    fscanf( archivo, "%s%s", ip, mask );

    if( feof( archivo ) != 0 ) {
      break;
    }

    printf( "%s %s\n", ip, mask );
  }

  fclose( archivo );
  printf( "\nSe ha leido el archivo correctamente...\n" );

  return 0;   
}
Trauma
  • 25,297
  • 4
  • 37
  • 60
  • 1
    Excelente respuesta. [Aquí](https://es.stackoverflow.com/a/320974/2742) el mismo problema versión [tag:c++]. – PaperBirdMaster Jan 29 '20 at 07:56
  • @PaperBirdMaster Estoy `99.99%` seguro de que ya hay varias sobre esto ... pero no las encontraba, y tenía un ratito muerto que aprovechar. El buscador interno del sitio deja bastante que desear :-( – Trauma Jan 29 '20 at 07:59
  • No he puesto el comentario para criticar tu respuesta si no para complementarla, aunque si quieres fustigarte: siéntete libre de hacerlo. – PaperBirdMaster Jan 29 '20 at 08:00
  • 1
    No me he explicado. Lo que quiero decir es que la pregunta ya se ha echo varias veces y habría que marcarla como duplicada ... pero que tardaba mas en buscar una anterior que en responderla. Gracias por el *piropo* en todo caso :-) – Trauma Jan 29 '20 at 08:03
  • @Trauma que tal? Volví a ejecutar tu código y ahora el problema es que no me lee la ultima linea, no se porque – Víctor Álvarez Feb 09 '20 at 17:59
  • Hola @Alvarez. He vuelto a probarlo, y se ejecuta correctamente para tus datos de prueba. ¿ Puede ser que tengas algún caracter *extraño* en tu archivo a leer ? – Trauma Feb 11 '20 at 04:33