Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: sMARIO en 18 Abril 2014, 03:25 am



Título: Manejar ficheros
Publicado por: sMARIO en 18 Abril 2014, 03:25 am
Hola, estoy haciendo un programa en C que trabaja con ficheros de entrada y salida pero no se acceder a lo que necesito. Dentro del fichero de entrada hay varias líneas con 3 campos: nombre, tipo y dirección.
Por ejemplo:
Código:
www.google.es A 130.206.193.53
www.youtube.com A 211.132.198.42

Bien, yo para manejarlo mejor, cojo la primera linea y la paso a una cadena de caracteres con fgets. Una vez tengo la cadena compruebo que el tipo es correcto (sólo puede haber dos tipos, o A o B) con strchr.

El problema viene con la dirección, pues tengo que comprobar que no se salga del rango 0-255, que no aparezca un 5º número (130.210.222.32.1), etc... Resumiendo, que tenga el formato de una dirección IP.
No se muy bien como mirar eso, lo que se me va ocurriendo acaba en un código enorme y dudo que sea así.

A ver si alguien puede echarme una mano. Todo esto es para comprobar que no hay errores y después crear una lista con nodos de tres cadenas de caracteres una para cada campo.

EDITO:
Acabo de ver que con fscanf puedo separar los campos, por ejemplo:
Código:
char cadena[100];
char cadena2[100];
int valor;
...
fscanf (f, "%[a-z0-9]:%d:%[a-z0-9]\n", cadena, &valor, cadena2);

Pero claro, mi fichero de entrada va separado con espacios y si pongo más espacios o tabulaciones también tendría que funcionar:
Código:
www.google.es                   A  130.206.193.53
www.youtube.com    A         211.132.198.42

Además de que seguiría desconociendo el tema de saber si el formato de la IP es correcto.



Perdón por el doble post, es por no borrar todo lo anterior ni llenarlo de EDITO.

Creo que si alguien me explica como meter cada campo en una cadena de caracteres sabría seguir, vamos, que si tengo "www.google.es A 130.206.193.53" como meto www.google.es en una cadena, A en otra y 130.206.193.53 en otra.


Título: Re: Manejar ficheros
Publicado por: rir3760 en 18 Abril 2014, 19:38 pm
estoy haciendo un programa en C que trabaja con ficheros de entrada y salida pero no se acceder a lo que necesito. Dentro del fichero de entrada hay varias líneas con 3 campos: nombre, tipo y dirección.
Por ejemplo:
Código:
www.google.es A 130.206.193.53
www.youtube.com A 211.132.198.42
Bien, yo para manejarlo mejor, cojo la primera linea y la paso a una cadena de caracteres con fgets. Una vez tengo la cadena compruebo que el tipo es correcto (sólo puede haber dos tipos, o A o B) con strchr.
Un problema si utilizas esa función es donde se localiza el carácter, por ejemplo si la linea inicia con "www.Amazon.com Z ..." podrías deducir que es valida cuando no es así.

Una forma de procesar el contenido del archivo es leyendo este linea por linea mediante fgets y a continuación validar, esto ultimo lo puedes realizar "in situ" (mediante strtok) o bien extrayendo primero los componentes (mediante sscanf) para solo entonces validarlos.

Cual aproximación tomar depende del programa y el manejo que tengas de C. La primera tiene la ventaja de no necesitar almacenamiento adicional mientras que la segunda permite realizar parte de la validación de forma automática.

Creo que si alguien me explica como meter cada campo en una cadena de caracteres sabría seguir, vamos, que si tengo "www.google.es A 130.206.193.53" como meto www.google.es en una cadena, A en otra y 130.206.193.53 en otra.
Utilizando sscanf, por ejemplo:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int main(void)
  5. {
  6.   char linea[] = "www.google.es A 130.206.193.53";
  7.   char nombre[sizeof linea]; /* Solo por indicar un valor */
  8.   char cat;
  9.   char ip[sizeof linea]; /* Solo por indicar un valor */
  10.  
  11.   if (sscanf(linea, "%s %c %s", nombre, &cat, ip) == 3)
  12.      printf("Nombre: %s\nCategoria: %c\nIP: %s\n", nombre, cat, ip);
  13.  
  14.   return EXIT_SUCCESS;
  15. }

El problema viene con la dirección, pues tengo que comprobar que no se salga del rango 0-255, que no aparezca un 5º número (130.210.222.32.1), etc... Resumiendo, que tenga el formato de una dirección IP. No se muy bien como mirar eso, lo que se me va ocurriendo acaba en un código enorme y dudo que sea así.
La validación ya sea automática o manual es relativamente corta. Se debe verificar que los caracteres solo sean dígitos formando cuatro enteros separados por puntos con el ultimo terminado con '\n' (ya que fgets lee la linea incluyendo ese carácter).

Un ejemplo de validacion manual de IPs:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <ctype.h>
  4.  
  5. int check_ip(char const *ip, unsigned char byte[]);
  6.  
  7. int main(void)
  8. {
  9.   char *linea[] = {
  10.      "130.206.193.53\n",
  11.      "211.132.198.42\n",
  12.      "130.206.193\n",
  13.      "256.132.198.42\n",
  14.      "130 . 206 . 193 . 53\n",
  15.      "211.198.42.\n",
  16.      "130..193.53\n",
  17.      ".132.198.42\n",
  18.      "130.206.193.192.191\n",
  19.      "255.132.198.42 xxx\n",
  20.      "4294967297.4294967297.4294967297.4294967297\n"
  21.   };
  22.   size_t num_lineas = sizeof linea / sizeof linea[0];
  23.   size_t i;
  24.  
  25.   for (i = 0; i < num_lineas; i++){
  26.      unsigned char byte[4];
  27.  
  28.      if (check_ip(linea[i], byte))
  29.         printf("IP: %u.%u.%u.%u\n", byte[0], byte[1], byte[2], byte[3]);
  30.      else
  31.         printf("Error: %s", linea[i]);
  32.   }
  33.  
  34.   return EXIT_SUCCESS;
  35. }
  36.  
  37. int check_ip(char const *ip, unsigned char byte[])
  38. {
  39.   char sep[] = "...\n";
  40.   int nb = 0;
  41.   unsigned num = 0;
  42.   int in = 0;
  43.  
  44.   while (nb < 4){
  45.      if (isdigit(*ip)){
  46.         num = num * 10 + *ip - '0';
  47.         in = 1;
  48.      }else if (in && num < 256 && *ip == sep[nb]){
  49.         byte[nb] = num;
  50.         nb++;
  51.         num = 0;
  52.         in = 0;
  53.      }else
  54.         break;
  55.  
  56.      ip++;
  57.   }
  58.  
  59.   return nb == 4 && *ip == '\0';
  60. }

Su salida (en mi caso) es:
Código:
IP: 130.206.193.53
IP: 211.132.198.42
Error: 130.206.193
Error: 256.132.198.42
Error: 130 . 206 . 193 . 53
Error: 211.198.42.
Error: 130..193.53
Error: .132.198.42
Error: 130.206.193.192.191
Error: 255.132.198.42 xxx
IP: 1.1.1.1

Como se muestra en la salida un detalle evidente pero que se debe enfatizar es: la función no esta completa y puede producir un resultado incorrecto si el numero sobrepasa la capacidad del tipo "unsigned int" (ejemplo en la ultima linea de la salida). Añadir la validación faltante es cuestión de minutos (y un poco de esfuerzo).

Un saludo


Título: Re: Manejar ficheros
Publicado por: sMARIO en 19 Abril 2014, 03:52 am
Muchas gracias, ya conseguí arreglarlo  ;-)