Ok, guardas un archivo de texto en la 'cadena[1280]' y lo que quieres es separar ese texto palabra por palabra, dicho de otra forma quieres tokenizar por espacios, comas, puntos, saltos de linea y todos los signos de puntuacion que se te ocurran. Primero te redefino la estructura que guardaras en la lista:
Código C:
Ver originalstruct PALABRA {
char *texto;
struct tagPALABRA *siguiente;
};
typedef struct PALABRA PALABRA;
typedef struct PALABRA *LISTA;
Ahora una vez leido el archivo tienes algo asi:
Código C:
Ver originalLISTA lista;
char cadena [] = "Esto es una prueba de texto, para ver como funciona esto de las listas. Otra linea de texto.";
Lo siguiente es eso de tokenizar; creas una funcion que se encargue de ello a la que le envias el texto y te retorna una LISTA con las palabras encontradas. Primero defines los caracteres por los que quieres cortar:
Y ahora tokenizas:
Código C:
Ver originalLISTA crea_lista(char *texto) {
LISTA lista = 0;
char *pch;
pch
= strtok(texto
, TOKENCHARS
); while(pch) {
//en pch tienes la palabra de este bucle
//aqui la guardaras en la lista
//buscas la siguiente
}
return lista;
}
Para cada while obtienes una palabra del texto 'cadena', y para cada palabra (es decir para cada pch) tienes que insertarla en la lista. Pues haces otra funcion que se encargue de ello, esta nueva funcion recibe el texto y un puntero a la lista, de forma que crea una nueva estructura PALABRA, la rellena con el texto proporcionado (que será cada pch encontrado en 'crea_lista') e inenta añadirla al final de la lista; si la lista está vacía se asigna como primer y unico elemento, si tiene elementos se busca el ultimo y se añade como siguiente de ese ultimo:
Código C:
Ver originalchar inserta_palabra(char *texto, LISTA *lista) {
PALABRA *palabra, *ptr;
if(!(palabra
= malloc(sizeof(PALABRA
)))) { return 0;
}
palabra->texto = texto;//ojo con esto: solo lectura
palabra->siguiente = 0;
if(!(ptr = *lista)) {
*lista = palabra;
}
else {
while(ptr->siguiente) {
ptr = ptr->siguiente;
}
ptr->siguiente = palabra;
}
return 1;
}
Ojo una nota: cuando asignas el texto proporcionado al texto de la palabra lo hago como solo lectura, es decir no deberas escribir encima del texto que hay en las estructuras; obviamente puedes cambiarlo y usar un char[100] y copiar el texto, o bloquear con malloc la longitud de texto necesaria, solo te propongo una idea facil.
Ahora implementas dentro de la funcion 'crea_lista' la llamada a esta funcion para cada pch que encuentras en el ciclo while:
O ya que te propongo una funcion de insercion con control de error para memoria no disponible puedes aprovechar e implementar esta llamada:
Código C:
Ver originalif(!inserta_palabra(pch, &lista)) {
elimina_lista(&lista);
break;
}
Junto con la funcion de implementar la lista necesitas la que te libere la memoria bloqueada para esa lista, lo que hace es recorrer la lista, liberar la memoria bloquedad para cada nodo y finalmente asignar nulo a la lista:
Código C:
Ver originalvoid elimina_lista(LISTA *lista) {
PALABRA *ptr, *sig;
ptr = *lista;
while(ptr) {
sig = ptr->siguiente;
ptr = sig;
}
*lista = 0;
}
Ya tienes la lista. Antes de seguir te intereserá comprobar si ha funcionado, debes implementar una funcion que recorra esa lista:
Código C:
Ver originalvoid muestra_lista(LISTA lista) {
LISTA ptr;
if(!(ptr = lista)) {
}
else {
while(ptr) {
ptr = ptr->siguiente;
}
}
}
Ahora vuelves al main y haces la prueba:
Código C:
Ver originalLISTA lista;
char cadena [] = "Esto es una prueba de texto, para ver como funciona esto de las listas. Otra linea de texto.";
if((lista = crea_lista(cadena))) {
muestra_lista(lista);
elimina_lista(&lista);
}
Lo siguiente es la funcion que busca palabras en la lista; hace lo mismo que la de mostrar las palabras pero en vez de printarlas las compara con la palabra proporcionada, en caso de colision incrementa un contador y lo retorna al final:
Código C:
Ver originalint encuentra_palabra(char *texto, LISTA lista) {
LISTA ptr = lista;
int ctd = 0;
while(ptr) {
if(!strcmp(texto
, ptr
->texto
)) { ctd++;
}
ptr = ptr->siguiente;
}
return ctd;
}
Para la llamada solo tienes que proporcionarle un texto y una lista sobre la que trabajar, te retornará el numero de colisiones:
Código C:
Ver originalint q;
q = encuentra_palabra("de", lista);
Seguramente te habras fijado en que strcmp es 'case sensitive', es decir que 'hola' es diferente de 'Hola'; algunas librerias proporcionan una strcmp insensitiva (pero que no es estandar), aqui te dejo una implementacion que encontré por ahi (perdon no recuerdo de donde la saqué, tendria que citar el autor)
Código C:
Ver originalint stricmp (const char *p1, const char *p2) {
register unsigned char *s1 = (unsigned char *) p1;
register unsigned char *s2 = (unsigned char *) p2;
unsigned char c1, c2;
do
{
c1
= (unsigned char) toupper((int)*s1
++); c2
= (unsigned char) toupper((int)*s2
++); if (c1 == '\0')
{
return c1 - c2;
}
}
while (c1 == c2);
return c1 - c2;
}
Ahora puedes implementar el buscador con ambas funciones y añadir un argumento que permita la busqueda sensitiva/insensitiva:
Código C:
Ver originalint encuentra_palabra(char *texto, LISTA lista, char ci) {
LISTA ptr = lista;
int ctd = 0;
while(ptr) {
if(ci) {
if(!stricmp(texto, ptr->texto)) {
ctd++;
}
}
else {
if(!strcmp(texto
, ptr
->texto
)) { ctd++;
}
}
ptr = ptr->siguiente;
}
return ctd;
}
En la llamada solo le indicas 0 para sensitive, o 1 para insensitive
Código C:
Ver originalLISTA lista;
char cadena [] = "Hola que tal hola qué TAL";
int q;
if((lista = crea_lista(cadena))) {
q = encuentra_palabra("hola", lista, 0);
q = encuentra_palabra("hola", lista, 1);
elimina_lista(&lista);
}
Saludos
vosk