Ayuda imprimir solo una vez la repeticiones de un arreglo

Iniciado por prosebas, 16 Marzo 2020, 18:37 PM

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

prosebas

Buenas tardes, tengo que hacer un codigo para determinar las ocurrencias,sin embargo, ya tengo el arreglo de ocurrencias y palabras pero no se como hacer para que cuando vaya imprimir me imprima solo una vez la palabra que este repetida. Cree una estructura para solucionar eso pero no he podido hacer la impresion de forma correcta (el codigo que anexo esta sin la impresión, puesto que no supe hacerla para solo imprimirla una vez). Agradeceria si me ayudan.



#include <iostream>
#include <string.h>
#include<ctype.h>
using namespace std;
struct ocu
{
   string word;
   int ocurrencias=0;
};
void ocurrencia(char Parrafo[],string *Palabras,int *ocurrencias,int &arra_y,struct ocu *ocurren);
int main()
{
   struct ocu *ocurren=new ocu[50];
   int *ocurrencias=new int[50],tamano,arra_y=0,cant=0;
   char Parrafo[500];
   string *Palabras = new string[50];
   cin.getline(Parrafo, sizeof(Parrafo));
   tamano=strlen(Parrafo);
   for(int i=0; i<tamano; i++)
       Parrafo=tolower(Parrafo);
   ocurrencia(Parrafo,Palabras,ocurrencias,arra_y,ocurren);
}

void ocurrencia(char Parrafo[],string *Palabras,int *ocurrencias,int &arra_y,struct ocu *ocurren)
{
   char *ptro,cant=0;
   ptro = strtok(Parrafo, " .,;");
   while (ptro != NULL)
   {
       *(Palabras+arra_y)=ptro;
       ptro = strtok(NULL, " .,;");
       arra_y++;
   }
   for(int i=0; i<arra_y; i++)
       *(ocurrencias+i)=1;

   for(int i=0; i<arra_y; i++)
   {
       for(int j=0; j<arra_y; j++)
       {
           if(*(Palabras+i)==*(Palabras+j))
           {
               if(i==j)
               {}
               else
                   *(ocurrencias+i)= *(ocurrencias+i)+1;
           }
       }
   }
}


K-YreX

Cuando pongas código utiliza etiquetas de Código GeSHi. Las puedes seleccionar encima del cuadro de texto, en el desplegable que dice exactamente eso: Código GeSHi. Usa las del lenguaje apropiado.

No he revisado si tu código encuentra las ocurrencias correctamente, confiaré en tus dotes de programador.  :xD
Pero vamos que si tienes un array de una struct que almacena (palabra, repeticiones) es muy sencillo mostrarlas:
Código (cpp) [Seleccionar]

for(size_t i = 0; i < longitudArray; i++)
    cout << "La palabra: " << estructura.palabra << " aparece: " << estructura.repeticiones << " veces" << endl;

Tendrás que cambiar el nombre de las variables que he utilizado por las que estás utilizando tú.

Un problema puede ser saber cuántas posiciones del array de struct estás utilizando realmente. Tendrás que llevar un contador que se incremente con cada nueva inserción.
Si estás haciendo esto por mérito propio o es algún ejercicio en el que nadie te limita a lo que puedes o no puedes usar, siempre puedes utilizar algún contenedor de la STL para no tener que manejar directamente la memoria (será más fácil pero por tanto menos gratificante).
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

prosebas


for(size_t i = 0; i < longitudArray; i++)
    cout << "La palabra: " << estructura.palabra << " aparece: " << estructura.repeticiones << " veces" << endl;

Tendrás que cambiar el nombre de las variables que he utilizado por las que estás utilizando tú.

Hola creo que no me entendiste, yo tengo un arreglo de palabras, sin embargo , puedan haber palabras repetidas y solo quiero imprimirla una vez. El codigo que mandaste imprime todas las posiciones del arreglo .Yo lo pense de la siguiente manera.Sí la palabra tiene ocurrencia mayor a 1 recorro el arreglo y borre las palabras q sean iguales(Null) y luego imprimo el arreglo modificado se me acaba de ocurrir voy a intentarlo asi.

K-YreX

La idea más sencilla como te he respondido en el mensaje es la siguiente:

palabras := array de struct (palabra, repeticiones)
palabrasGuardadas := 0

MIENTRAS !finArchivo HACER
  palabra = leerSiguientePalabra()

  // Recorres las palabras que ya has guardado a ver si coincide alguna:
  i := 0
  MIENTRAS i < palabrasGuardadas AND palabra != palabras[i].palabra HACER
    i := i + 1
  FIN MIENTRAS

  // Sales cuando llegas al final (y entonces es nueva) o cuando encuentras la palabra guardada en i:
  SI i == palabrasGuardadas ENTONCES
    palabras[palabrasGuardadas].palabra = palabra
    palabras[palabrasGuardadas].repeticiones = 1
    palabrasGuardadas := palabrasGuardadas + 1
  SINO ENTONCES
    palabras[i].repeticiones := palabras[i].repeticiones + 1
  FIN SI
FIN MIENTRAS


Es mejorable teniendo las palabras ordenadas para hacer las búsquedas más eficientes o usando otras estructuras de datos pero para empezar basta con que consigas implementar este pseudocódigo.
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

prosebas

Gracias por sus respuestas. Lo termine haciendo asi

for(int i=0; i<arra_y; i++)
    {
        if(*(ocurrencias+i)>1)
        {
            for(int j=arra_y-1; j>0; j--)
            {
                if(i==j) {}
                else
                {
                    if(*(Palabras+i)==*(Palabras+j))
                    {
                        *(Palabras+j)="0";
                        *(ocurrencias+j)=0;
                    }
                }

            }
        }
    }
    for(int i=0; i<arra_y; i++)
    {
        if(*(Palabras+i)!="0")
        {
            ocurren[cant].word=*(Palabras+i);
            ocurren[cant].ocurrencias=*(ocurrencias+i);
            cant++;
        }

    }
       cout<<endl<<"Palabras && ocurrencias"<<endl;
    for(int i=0; i<cant; i++)
  cout<<ocurren.word<<"  -->"<<ocurren.ocurrencias<<endl;

@XSStringManolo

Cuando no quieras repetir las ocurrencias utiliza un set (plantilla de la STL) en lugar de un array. En muchos casos puedes hacer la cuenta de los elementos mientras los intrlduces en el set para contar las ocurrencias si ni te interesa conservarlas.

También puedes usar un array y recorrer todo el array por cada vez que introduzcas un elemento. Una forma sencilla es usando el método find con los métodos end y append/push. Es más eficiente meter todos los elementos en el array y removerlos usando regex, tienes varias alternativas válidas para hacer lo mismo.

Serapis

Operando con arrays (si es obligatorio), hay opciones más eficientes; por ejemplo:

1 - Si el array de origen estuviere ordenado, no seria preciso más que imprimir el ítem y luego ir saltando los siguientes ítems mientras sean iguales al actual.

2 - Por tanto algo muy eficiente es ordenar primero el array si no lo está, y luego proceder con el paso 1.

3 - Recurrir a un array temporal... Se empieza imprimiento la primera palabra y añadiéndola al array B. Luego cuando se quiere imprimir otra palabra se comprueba si se existe en el array B, si no existe se añade al array B. fiamlemente el array B se imprime que solo contiene palabras únicas (también se puede ir imprimiendo sobre la marcha). Este método es más efectivo cuando el array no está ordenado (y no se permite ordenarlo). Resulta tanto más eficiente, cuando más elevado sea el número de repetidos (ese suceso implica pocos ítems en el array B, entre los que buscar cada vez). Debe descartarse si el array de origen fuera gigante, o si el número de repetidos es muy escaso, pués Descartar este método y forzado a usar arrays, implica usar el propio array en sendos bucles, el externo para el ítem actual, el interno para buscar su existencia en los previos. Tiene la desventaja de precisar un array temporal, ocupando más memoria.

4 - Si al caso, para 3, en vez de usar como estructura (temporal) un array, se permite otro tipo de estructura, que permita añadir los ítems ordenados, mejor, pués la búsqueda en esa estructura 'B', podría hacerse mediante una búsqueda binaria (caso de por ejemplo un árbol binario), o mejor una búsqueda atómica (si la estructura elegida fuera una tabla hash).

Por lo mismo si en origen se permite otras estructuras, siempre será más eficiente una tabla hash que cualquier otro método.

Como entiendo que es un ejercicio de algún centro de enseñanza y se trata de un principiante, queda descartado el uso de estructuras complejas (e imagino que posiblemente incluso quede descartado ordenar el array). Así que en tales circunstancias el caso 3 sería el más eficiente... ya que pone a prueba al estudiante en el uso de arrays y algorítmica, que es lo que en definitiva se persigue con el ejercicio.