Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Fire_Hugo12 en 15 Diciembre 2012, 18:18 pm



Título: Ayuda ordenar y eliminar palabras texto
Publicado por: Fire_Hugo12 en 15 Diciembre 2012, 18:18 pm
Hola soy nuevo en el foro y quisiera ver si me pueden ayudar con este programa... lo que hace es dado un texto ingresado muestra la cantidad de ocurrencias que tiene cada palabra, pero las muestra desordenadas, por ejemplo "hola amigo que que" ... la salida seria:
hola->1
amigo->1
que->2
como puedo hacer para que me los muestre ordenados de mayor a menor en numero de ocurrencias?
y otra duda.. como puedo hacer para eliminar la mas baja o las mas bajas?

Gracias de antemano, aqui esta mi codigo:

Código:
/*
   Recibe una cadena y devuelve las palabras de dicha cadena.
   Los espacios y saltos de linea son los separadores entre palabras.
*/
void separador(char renglon[80], char palabras[100][80], int *total)
{
   int i, j=0;

   for(i=0; i<strlen(renglon); i++)
   {
       /* Si es un caracter distinto de espacio y salto de linea */
       if(renglon[i]!=' ' && renglon[i]!='\n')
       {
  palabras[*total][j] = renglon[i];
  j++;

          /* Si el caracter siguiente es fin de cadena */
          if(renglon[i+1]=='\0')
  {
     palabras[*total][j] = '\0'; /* Indica fin de palabra */
     *total = *total+1; /* Aumenta el numero de palabras */
     j=0;
  }
       }
       /* Si es espacio o salto de linea */
       else if(renglon[i]==' ' || renglon[i]=='\n')
       {
  /* Si el caracter anterior no es espacio ni salto de linea */
  if(i>0 && renglon[i-1]!=' ' && renglon[i-1]!='\n')
  {
     palabras[*total][j] = '\0'; /* Indica fin de palabra */
     *total = *total+1; /* Aumenta el numero de palabras */
     j=0;
  }
       }
   }
}


void ocurrencias(char nombre_archivo[100])
{
   char renglon[80];
   char palabras[100][80]; /* Todas las palabras */
   char palabras_diferentes[100][80]; /* Solo palabras diferentes */
   int i, j, k, total=0 /* Numero total de palabras*/,
   diferentes=0 /* Numero de palabras diferentes */;
   int Rep[100]; /* Repeticiones de cada palabra diferente */

   FILE *archivo;

   archivo=fopen(nombre_archivo,"r");

   if(archivo==NULL)
   {
      printf("No se encuentra archivo: %s\n", nombre_archivo);
      return ;
   }

   /* Lee el archivo linea a linea y obtiene las palabras de esa linea */
   while(fgets(renglon,80,archivo))
   {
       separador(renglon,palabras, &total);
   }

   fclose(archivo);

   /* Saca copia del arreglo original */
   for(i=0; i<total; i++)
       strcpy(palabras_diferentes[i], palabras[i]);

   /* Saca palabras diferentes */
   diferentes = total;
   for(i=0;i<diferentes;i++)
   {
      for(j=i+1;j<diferentes;j++)
      {
  /* Si encuentra palabra repetida */
  if(!strcmp(palabras_diferentes[i], palabras_diferentes[j]))
  {
     /* Recorre una posicion elementos posteriores */
     for(k=j+1;k<diferentes;k++)
strcpy(palabras_diferentes[k-1], palabras_diferentes[k]);

     diferentes--;
     j--;
  }
       }
   }

   /* haya repeticiones de cada palabra distinta */
   for(i=0; i<diferentes; i++)
       Rep[i] = 0;
   for(i=0; i<diferentes; i++)
       for(j=0;j<total;j++)
  if(!strcmp(palabras_diferentes[i], palabras[j]))
     Rep[i]++;

   /* Muestra informacion */
   printf("Palabras y numero de ocurrencias del archivo: %s\n\n", nombre_archivo);
   printf("Total de palabras: %d\n", total);
   printf("Palabras distintas: %d\n\n", diferentes);

   for(i=0; i<diferentes; i++)
       printf("%s -> %d\n", palabras_diferentes[i], Rep[i]);
}


Título: Re: Ayuda ordenar y eliminar palabras texto
Publicado por: x64core en 16 Diciembre 2012, 06:42 am
Tu podrías estar buscando esto:

Ordenamiento burbuja en C++ (http://codigomaldito.blogspot.com/2005/11/ordenamiento-burbuja.html)

ordena una lista de enteros podrias hacer un array con las veces que se repiten las palabras, o mejor aún hacer una estructura de este tipo:

typedef struct WordInfo
{
   PCHAR   lpWord;
   ULONG   nRep;
}

lpWord, puntero a la palabra.
nRep, las veces que se repite la palabra.

de esta forma lo tienes mejor ordenado.


Título: Re: Ayuda ordenar y eliminar palabras texto
Publicado por: naderST en 16 Diciembre 2012, 07:26 am
Tu podrías estar buscando esto:

Ordenamiento burbuja en C++ (http://codigomaldito.blogspot.com/2005/11/ordenamiento-burbuja.html)

ordena una lista de enteros podrias hacer un array con las veces que se repiten las palabras, o mejor aún hacer una estructura de este tipo:

typedef struct WordInfo
{
   PCHAR   lpWord;
   ULONG   nRep;
}

lpWord, puntero a la palabra.
nRep, las veces que se repite la palabra.

de esta forma lo tienes mejor ordenado.

Sin ánimos de ofender amigo, considero que lo más correcto es que el código que coloques para este tipo de casos sea código estándar, ya que no sabemos que compilador está utilizando Fire_Hugo12. Por las dudas tenemos que PCHAR es equivalente a un apuntador a caracter (char *) y ULONG es equivalente a un entero largo sin signo (unsigned long int). Con respecto al problema puedes utilizar una lista enlazada e ir insertando de manera ordenada en tu caso de mayor a menor. Para eliminar la más baja o las más bajas vas recorriendo palabra a palabra y comprobando si no es la más baja la concatenas en otra nueva cadena y reduces el contador de dicha palabra, esto lo haces hasta que dicho contador llegue a cero.


Título: Re: Ayuda ordenar y eliminar palabras texto
Publicado por: x64core en 16 Diciembre 2012, 08:52 am
Sin ánimos de ofender amigo, considero que lo más correcto es que el código que coloques para este tipo de casos sea código estándar, ya que no sabemos que compilador está utilizando Fire_Hugo12. Por las dudas tenemos que PCHAR es equivalente a un apuntador a caracter (char *) y ULONG es equivalente a un entero largo sin signo (unsigned long int). Con respecto al problema puedes utilizar una lista enlazada e ir insertando de manera ordenada en tu caso de mayor a menor. Para eliminar la más baja o las más bajas vas recorriendo palabra a palabra y comprobando si no es la más baja la concatenas en otra nueva cadena y reduces el contador de dicha palabra, esto lo haces hasta que dicho contador llegue a cero.

Claro todo el mundo sabe eso, ni siquiera tengo la idea de porque lo mencionas. respecto al tema se tendría que mirar tu código
y de que forma lo implementas para saber si es tan veloz y eficiente.


Título: Re: Ayuda ordenar y eliminar palabras texto
Publicado por: Fire_Hugo12 en 16 Diciembre 2012, 19:03 pm
Gracias a las 2 por las respuestas, ya logre ordenarlo por cantidad de repeticiones... lo unico que me falta y tengo una duda es en la parte de borrar los menores, tengo que "v" es el menor numero de repeticiones pero me da un error en la funcion, me dice "error: too few arguments to function 'void borrar(tipoNodo**, int) " que puede ser?
(el compilador que uso es el codeblock)

Código:
void borrar(Lista *lista, int v)
 {
   pNodo anterior, nodo;

   nodo = *lista;
   anterior = NULL;
   while(nodo && nodo->valor < v)
   {
      anterior = nodo;
      nodo = nodo->siguiente;
   }
   if(!nodo || nodo->valor != v) ;
   else { /* Borrar el nodo */
      if(!anterior) /* Primer elemento */
         *lista = nodo->siguiente;
      else  /* un elemento cualquiera */
         anterior->siguiente = nodo->siguiente;
      free(nodo);
   }
}


Título: Re: Ayuda ordenar y eliminar palabras texto
Publicado por: naderST en 16 Diciembre 2012, 21:00 pm
Gracias a las 2 por las respuestas, ya logre ordenarlo por cantidad de repeticiones... lo unico que me falta y tengo una duda es en la parte de borrar los menores, tengo que "v" es el menor numero de repeticiones pero me da un error en la funcion, me dice "error: too few arguments to function 'void borrar(tipoNodo**, int) " que puede ser?
(el compilador que uso es el codeblock)

Código:
void borrar(Lista *lista, int v)
 {
   pNodo anterior, nodo;

   nodo = *lista;
   anterior = NULL;
   while(nodo && nodo->valor < v)
   {
      anterior = nodo;
      nodo = nodo->siguiente;
   }
   if(!nodo || nodo->valor != v) ;
   else { /* Borrar el nodo */
      if(!anterior) /* Primer elemento */
         *lista = nodo->siguiente;
      else  /* un elemento cualquiera */
         anterior->siguiente = nodo->siguiente;
      free(nodo);
   }
}

Ojo CodeBlocks es el IDE lo más seguro es que tu compilador sea GCC. Podrías colocar el fragmento de código donde haces el llamado a la función borrar?

Claro todo el mundo sabe eso, ni siquiera tengo la idea de porque lo mencionas. respecto al tema se tendría que mirar tu código
y de que forma lo implementas para saber si es tan veloz y eficiente.

No todo el mundo lo sabe, por eso lo menciono y como he visto varios posts que respondes y colocas código NO estándar quise hacer la acotación, pero OJO esto no es nada personal, simplemente te lo digo porque a MI parecer es lo más correcto, no quiero caer en discusiones acerca del tema. No tengo ninguna implementación, pero en esencia es lo mejor ir insertando de manera ordenada en una lista enlazada o un arreglo para que al momento de eliminar la palabra o las palabras con el número menor de ocurrencias se sabe de ante mano que es la última en la lista o en el arreglo.


Título: Re: Ayuda ordenar y eliminar palabras texto
Publicado por: Fire_Hugo12 en 16 Diciembre 2012, 23:33 pm
la llamo dentro de un switch en el main:

Código:
//dependiendo la opc del menu
switch(opc)
   {
      case 1:
              ingresar();
              system("cls");
              break;
      case 2:
              busqueda();
              getch();
              break;
      case 3: cout<<"El Numero de Repeticion que desea eliminar es: ";
              cin>> v;
              borrar();
              break;
   }
 }while(opc!=4);
}


Título: Re: Ayuda ordenar y eliminar palabras texto
Publicado por: naderST en 17 Diciembre 2012, 05:50 am
la llamo dentro de un switch en el main:

Código:
//dependiendo la opc del menu
switch(opc)
   {
      case 1:
              ingresar();
              system("cls");
              break;
      case 2:
              busqueda();
              getch();
              break;
      case 3: cout<<"El Numero de Repeticion que desea eliminar es: ";
              cin>> v;
              borrar();
              break;
   }
 }while(opc!=4);
}

La función borrar recibe dos parámetros y no le estás pasando ninguno, debes pasarle la lista y el valor.


Título: Re: Ayuda ordenar y eliminar palabras texto
Publicado por: Fire_Hugo12 en 17 Diciembre 2012, 22:20 pm
aaah oks gracias naderST y x64Core ya solucione el problema y termine el programa
 :D


Título: Re: Ayuda ordenar y eliminar palabras texto
Publicado por: rir3760 en 18 Diciembre 2012, 03:01 am
Algo que preocupa, en base a los fragmentos de código fuente, es no utilizar la biblioteca estándar de C++. Por ejemplo puedes leer la linea con getline, obtener las palabras de ella con un objeto de tipo stringstream, evitar los duplicados con un mapa, etc.

Un ejemplo de ello (sin validaciones) es:
Código
  1. #include <iostream>
  2. #include <string>
  3. #include <sstream>
  4. #include <map>
  5. #include <vector>
  6. #include <algorithm>
  7. using namespace::std;
  8.  
  9. typedef vector<map<string, int>::iterator>::size_type vec_iter_sz;
  10.  
  11. bool cmp(map<string, int>::iterator a, map<string, int>::iterator b);
  12.  
  13. int main()
  14. {
  15.   cout << "Introduce la linea: ";
  16.   string linea;
  17.   getline(cin, linea);
  18.  
  19.   stringstream in(linea);
  20.   string palabra;
  21.   map<string, int> frec;
  22.   vector<map<string, int>::iterator> ndx;
  23.   while (in >> palabra) {
  24.      map<string, int>::iterator it = frec.find(palabra);
  25.  
  26.      if (it == frec.end()) {
  27.         frec[palabra] = 1;
  28.         ndx.push_back(frec.find(palabra) );
  29.      } else
  30.         frec[palabra]++;
  31.   }
  32.  
  33.   sort(ndx.begin(), ndx.end(), cmp);
  34.   for (vec_iter_sz i = 0; i != ndx.size(); i++)
  35.      cout << ndx[i]->first << " (" << ndx[i]->second << ")" << endl;
  36.  
  37.   return 0;
  38. }
  39.  
  40. bool cmp(map<string, int>::iterator a, map<string, int>::iterator b)
  41. {
  42.   return a->second < b->second || a->second == b->second && a->first <= b->first;
  43. }

Un saludo