Necesito una mano con programación en C!

Hola,

Llevo como 8 horas intentando hacer un pequeño programa y he probado DE TODO Y MÁS y no lo logro.

El programa consiste en abrir un fichero .txt, el cuál está lleno de direcciones de correo y textos

"hola me llamo paco ejemplo@ejemplo.com mis amigos me pegan ejemplo2@ejemplo.com y me gusta la gelatina de limon ejemplo3@ejemplo.com"

Vale, lo que necesito es que el programa, después de abrir ese fichero, busque automáticamente todas las direcciones de correo del texto y me las separe y me las presente... el resultado sería algo así:

"ejemplo@ejemplo.com
ejemplo2@ejemplo.com
ejemplo3@ejemplo.com"

Sonaba sencillo, pero me está amargando la vida. La única forma que he logrado hacer algo parecido es esta:

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

int main(argc, argv)
int argc;
char *argv[];
{
FILE * archivo;
char lletres[100];
char *a;
   
   fflush (stdin);
   archivo = fopen(argv[1], "r");

   
   while(feof(archivo)==0){   
      fgets(lletres, 100, archivo);
      a=strchr(lletres,'.');
      if (a!=NULL){   
         if(*a=='.'){
            a++;   
            if(*a=='c'){
               a++;   
               if(*a=='o'){
                  printf("%s",lletres);   
               }
            }
         }
      }
            
      while(*a==' '){
         a--;
         if (a==' '){
            printf("%s",a);         
         
         }
      }
   }
                  
   fclose (archivo);

   return 0;
}


Como veis, lo que hace el programa es buscar ".co" a lo largo del texto y así consigo que me imprima las direcciones de correo, pero... tienen que estar todas en la misma línea... si hay un intro de por medio, ahí es dónde el programa se peta.

Y luego, si tengo direcciones ".net" o ".es" ya la hemos jodido...

He probado de todo, he intentado con distintos bucles a poner un puntero señalando a la "@" y de ahí incrementar y decrementar hasta encontrar el espacio en blanco, pero NO lo he logrado de ninguna forma.

A ver si alguien me puede echar una mano porque estoy al borde del suicidio ya...

Gracias.
Imagen

Busca expresiones regulares en C en Google. ¡Ah!, y programa en inglés.

Rojos saludos.
Ya probé a buscar expresiones regulares, pero por desgracia tengo que programar en C y no en C++ :(

Gracias de todas formas.
Buenas,

Mírate la función strtok...

Saludos
A ver, antes de ver el código con tiempo (y por la hora que es casi que no me da para más) yo preferiría tu primera opción, la de la @ que te vale para cualquier extensión de correo, y te quitas de distinciones con .com, .net, etc.
xSlipKoRnx escribió:Ya probé a buscar expresiones regulares, pero por desgracia tengo que programar en C y no en C++ :(

Gracias de todas formas.


http://www.pcre.org/

Rojos saludos.
Rugal_kof94 escribió:A ver, antes de ver el código con tiempo (y por la hora que es casi que no me da para más) yo preferiría tu primera opción, la de la @ que te vale para cualquier extensión de correo, y te quitas de distinciones con .com, .net, etc.

He intentado de todo, y no he logrado nada de esa forma...

paliyoes escribió:
xSlipKoRnx escribió:Ya probé a buscar expresiones regulares, pero por desgracia tengo que programar en C y no en C++ :(

Gracias de todas formas.


http://www.pcre.org/

Rojos saludos.

Es triste pero si le envío un "main.c" a mi profesor y no tiene las librerías necesarias, directamente me pondrá un 0. Necesito que sea con las librerias GNU.

el Dr Katz escribió:Buenas,

Mírate la función strtok...

Saludos

He probado a hacer mil cosas con strtok, pero como digo, no logro hacer un bucle que me incremente el puntero automáticamente hasta llegar al espacio en blanco que habrá al acabar la direccion de email, donde debería pararse. No lo he logrado (soy novatísimo en programación, pero de eso ya os habréis dado cuenta).
1.- Albergas todas las palabras en un array usando si quieres strchr para saber por dónde cortar la cadena original (Fichero).
2.- Recorres el array verificando que, exista una y sólo un @ por cada elemento.
3.- Que después de la arroba exista al menos un . y un caracter alfanumérico tras él.

Acuérdate de verificar que los caracteres alfanuméricos son los permitidos para ser usados en un email.

Rojos saludos.
- Recorres el texto buscando todas las palabras. Define como caracter de separación el espacio.
- Programate una función (busca en google las specs exactas para la validación) que le metas una palabra y te devuelva si es un correo o no. Ni preguntes por la @ antes, que lo haga todo esta función.
- Recorre todas las palabras pasandolas a esa función.
- Guardate las palabras para las que el resultado de la función sea true.
- Sácalas a un fichero de texto, consola, o lo que quieras.
- Finish
Buenas,

Para aumentar el puntero podrías hacer algo tal que así;

   char temp[] = "hola que un@email.com tal, como dos@email.com te tres@mail.com va?";
   char temp2[100];
   char *ptr;

   ptr = strtok(temp, " ");

   while(ptr!= NULL) {
      memcpy(temp2, ptr, strlen(ptr));
      //aquí comprobar en temp2 si es un email
      ptr = strtok(ptr + strlen(ptr) + 1, " ");
   }

De esta forma puedes trabajar sobre temp2 sin joderle la marrana al strtok.

Saludos
Nada, no sé hacer nada de lo que me decís.

La situación es que el profesor que tenemos apenas nos ha explicado, y como evaluación final nos mandó un ejercicio diferente a cada uno de nosotros, a mí me tocó este y es sin duda muchísimo más avanzado que lo que nosotros hemos llegado a dar, porque hasta ahora he aprobado y es que esto no sé ni por dónde voy, no tengo ni la más remota idea.

Qué puto asco, de verdad, tengo dolor de cabeza y la puñetera vista cansada y aun no he logrado ni la mitad de lo que quería... el caso es que ya he recurrido hoy a la ayuda en internet como última via (llevo desde el viernes con el programa) ya que mañana es el día de entrega.

En fin, mierda para mí.

Gracias a todos.
Yo haría lo siguiente:

1) Si el fichero no es "enormico" lo cargaría en memoria para rastrear más rápida y cómodamente (necesitas averiguar la longitud del fichero, cosas que puedes hacer posicionando con fseek al final (SEEK_END y 0 de desplazamiento) y obteniendo la posición con ftell(). Asignas memoria con malloc() en un puntero tipo char (por ejemplo, char *text =malloc(filesize) ), pones el puntero del fichero al principio (SEEK_SET y 0 de desplazamiento) y lees el fichero sobre esa memoria. Acuérdate de liberar con free() más tarde, cuando acabes con el fichero)

2) Asignamos unas variables (tipo int) como pstart = 0 y pend = lo que nos dio ftell() - 1 como espació de fichero a recorrer

3) Iniciamos un bucle (por ejemplo, controlado por un int pos1)que recorra toda la memoria entre pstart y pend hasta que encuentre un '@' (preguntando text[pos1]=='@'). Eso si, asegúrate que los txt no tienen codificación especial que pueda dar problemas y sean texto plano

4) Ahora puedes utilizar una variable que aplicada al puntero recorra la memoria hacia atrás (si pos1 contiene '@', creamos un pos2= pos1 y vamos decrementando), teniendo en cuenta el inicio de ésta (pstart) buscando ese límite o un carácter que suponga ruptura (en cuyo caso habrá que sumar uno a la posición para situarnos al principio de la palabra) . Para simplificar cualquier carácter que tenga un valor numérico text[pos2]>=0 y text[pos2]<=32 de forma simultánea lo tomamos como de ruptura (lo cual abarca valores para espacio (32) tab (9) avance y retroceso de línea (10 y 13), entre otros). Supongamos que esa posición de inicio encontrada la asignamos a lim1;

5) Una vez sabemos el inicio procedemos a buscar desde '@' hacia adelante (de nuevo pos2= pos1, e incrementando pos2) teniendo el límite en 'pend' en éste caso (inclusive). Si encontramos el carácter de ruptura, el final del correo estará en esa posición -1, si no, pend es la posición final. Supongamos que esa posición la asignamos a lim2, mientras que pstart y pos1 habría que actualizarlos a la posición+1 para buscar el siguiente correo (o sea, saltando el carácter de ruptura a la siguiente posición y sin rebasar la posición de pend que es el último caracter del fichero)

6) Ahora solo queda escribir los caracteres entre los dos límites encontrados (entre text[lim1] y text[lim2] inclusive) en un fichero.

7) volvemos al punto 3)
Gracias.

No entiendo casi nada de lo que me explicas. Cuando digo que soy novato es incluso peor que eso, estoy a un nivel muy básico.

Gracias de todas formas, de verdad.
ya intentaste haciendo un ciclo infinito que pare cuando el archivo que estás revisando termina?, algo así como:

for(;;){//ciclo infinito
while(!archivo.eof()){ //el '!' es para indicar que no se ha llegado al final del archivo
//tu código
}
}


aunque creo que necesita la librería fstream.h, creo que si es librería GNU
Gracias, he probado eso pero no he conseguido que funcione.

De todas formas..... ¡¡¡¡¡¡lo he conseguido!!!! (al 98%).

Código:

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

int main(argc, argv)
int argc;
char *argv[];
{

FILE * archivo;
char contenidoarchivo[100];
char *pch;
unsigned int i;
char *dominio[4] = {".net", ".com", ".es"};

   fflush (stdin);
   archivo = fopen(argv[1], "r");

   while(feof(archivo)==0){
    fgets(contenidoarchivo, 100, archivo);

      pch = strtok (contenidoarchivo," ");
      while (pch != NULL)
        {
            for(i = 0; i < 3; i++)
            if(strstr(pch, dominio[i]) != NULL)
            printf ("%s\n",pch);
            pch = strtok (NULL, " ");
        }
    }
      return(0);
}



Ya hace lo que quiero, pero por alguna razón a veces se me come algunas letras, por ejemplo, me presenta la lista:

"hola@ejemplo.com
hola1@ejemplo.net
hola2@ejemplo.es
la3@ejemplo.net
jemplo.com"

Pasa poco, pero pasa. Qué podría ser?
Yo haría algo sencillito sin complicarme demasiado, así en pseudocódigo...

string largo, string aux_palabra, string aux subpalabra;
while(aux_palabra= strsep(&largo, " \t")) != NULL){
if(subpalabra=strsep(&aux_palabra,"."!= NULL))
if(strsep(&subpalabra,"@"!= NULL)
{
printf("%S",aux_palabra);
}
}


Básicamente separa las palabras, luego mira si tienen un punto y luego si hay una arroba antes del punto. No es muy fino porque no mira si hay varias arrobas y tal, pero con direcciones bien formadas debería ir... y sinceramente, paso de mirar como van los punteros porque es un coñazo, C es una pesadilla para trabajar con strings, eso te lo dejo para ti, no te voy a hacer los deberes XD


xSlipKoRnx escribió:Ya hace lo que quiero, pero por alguna razón a veces se me come algunas letras, por ejemplo, me presenta la lista:

"hola@ejemplo.com
hola1@ejemplo.net
hola2@ejemplo.es
la3@ejemplo.net
jemplo.com"

Pasa poco, pero pasa. Qué podría ser?


Diría que estás tuncando strings cuando lees del archivo. Lees 100 caracteres y corta donde toca, si corta a mitad de la palabra, pues la próxima vez que lea empezará desde donde se quedó y la palabra aparecerá cortada.
15 respuestas