Ayuda ordenar y eliminar palabras texto

Iniciado por Fire_Hugo12, 15 Diciembre 2012, 18:18 PM

0 Miembros y 1 Visitante están viendo este tema.

Fire_Hugo12

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:

/*
   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]);
}

x64core

Tu podrías estar buscando esto:

Ordenamiento burbuja en C++

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.

naderST

#2
Cita de: x64Core en 16 Diciembre 2012, 06:42 AM
Tu podrías estar buscando esto:

Ordenamiento burbuja en C++

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.

x64core

Cita de: naderST en 16 Diciembre 2012, 07:26 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.

Fire_Hugo12

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)

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);
   }
}

naderST

Cita de: 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)

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?

Cita de: x64Core en 16 Diciembre 2012, 08:52 AM
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.

Fire_Hugo12

#6
la llamo dentro de un switch en el main:


//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);
}

naderST

Cita de: Fire_Hugo12 en 16 Diciembre 2012, 23:33 PM
la llamo dentro de un switch en el main:


//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.

Fire_Hugo12

aaah oks gracias naderST y x64Core ya solucione el problema y termine el programa
:D

rir3760

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 (cpp) [Seleccionar]
#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <vector>
#include <algorithm>
using namespace::std;

typedef vector<map<string, int>::iterator>::size_type vec_iter_sz;

bool cmp(map<string, int>::iterator a, map<string, int>::iterator b);

int main()
{
   cout << "Introduce la linea: ";
   string linea;
   getline(cin, linea);
   
   stringstream in(linea);
   string palabra;
   map<string, int> frec;
   vector<map<string, int>::iterator> ndx;
   while (in >> palabra) {
      map<string, int>::iterator it = frec.find(palabra);
     
      if (it == frec.end()) {
         frec[palabra] = 1;
         ndx.push_back(frec.find(palabra) );
      } else
         frec[palabra]++;
   }
   
   sort(ndx.begin(), ndx.end(), cmp);
   for (vec_iter_sz i = 0; i != ndx.size(); i++)
      cout << ndx[i]->first << " (" << ndx[i]->second << ")" << endl;
     
   return 0;
}

bool cmp(map<string, int>::iterator a, map<string, int>::iterator b)
{
   return a->second < b->second || a->second == b->second && a->first <= b->first;
}


Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language