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:
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:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char linea[] = "www.google.es A 130.206.193.53";
char nombre[sizeof linea]; /* Solo por indicar un valor */
char cat;
char ip[sizeof linea]; /* Solo por indicar un valor */
if (sscanf(linea
, "%s %c %s", nombre
, &cat
, ip
) == 3) printf("Nombre: %s\nCategoria: %c\nIP: %s\n", nombre
, cat
, ip
);
return EXIT_SUCCESS;
}
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:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int check_ip(char const *ip, unsigned char byte[]);
int main(void)
{
char *linea[] = {
"130.206.193.53\n",
"211.132.198.42\n",
"130.206.193\n",
"256.132.198.42\n",
"130 . 206 . 193 . 53\n",
"211.198.42.\n",
"130..193.53\n",
".132.198.42\n",
"130.206.193.192.191\n",
"255.132.198.42 xxx\n",
"4294967297.4294967297.4294967297.4294967297\n"
};
size_t num_lineas = sizeof linea / sizeof linea[0];
size_t i;
for (i = 0; i < num_lineas; i++){
unsigned char byte[4];
if (check_ip(linea[i], byte))
printf("IP: %u.%u.%u.%u\n", byte
[0], byte
[1], byte
[2], byte
[3]); else
printf("Error: %s", linea
[i
]); }
return EXIT_SUCCESS;
}
int check_ip(char const *ip, unsigned char byte[])
{
char sep[] = "...\n";
int nb = 0;
unsigned num = 0;
int in = 0;
while (nb < 4){
num = num * 10 + *ip - '0';
in = 1;
}else if (in && num < 256 && *ip == sep[nb]){
byte[nb] = num;
nb++;
num = 0;
in = 0;
}else
break;
ip++;
}
return nb == 4 && *ip == '\0';
}
Su salida (en mi caso) es:
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