Asesoria Memoria Dinamica

Iniciado por Omar_2013, 11 Marzo 2014, 21:59 PM

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

Omar_2013

Hola, estoy haciendo un programa para contar el numero de palabras que tenga una frase, el problema es que por supuesto siempre el numero de palabras varia, por lo que segun pienso yo, hay que usar memoria dinamica

Código (cpp) [Seleccionar]

int main(int argc, char *argv[])
{
    char Lectura[200], *PTok, **Palabras=NULL;
    int i=0, j=0, ContPal=1;
   
    cin.getline(Lectura, sizeof(Lectura));
   
    PTok=strtok(Lectura," ");
   
    while ( PTok!= NULL )
    {
          AgrEspacio(Palabras, ContPal);//AgrEspacio Agrega Una Fila De Mas A Palabras
          strcpy( Palabras[i], PTok );
          PTok=strtok(NULL," ");
          i+=1;
          ContPal+=1;
    }
   
    for ( j=0; j<i; j++ )
        cout<<Palabras[j]<<endl;
   
    system("PAUSE");
    return EXIT_SUCCESS;
}



El problema como tal es esa funcion para agregar una fila a la matriz, ya que si compila, pero estoy violando el acceso a la memoria en una parte del codigo de esa funcion

Código (cpp) [Seleccionar]

void AgrEspacio ( char **Palabras, int NumPal)
{
     char **TemFilas=new char*[NumPal];
     
     for ( int i=0; i<NumPal; i++ )
     {
         TemFilas[i]=new char[200]; 
         TemFilas[i]=Palabras[i];
     }
         
     Palabras=TemFilas;   
}

La verdad este tema de memoria dinamica se me hace un poco dificil de entender, ya que no se bien cuando es correcto usarla, por ejemplo en este ejercicio podria haber creado una matriz estatica como
Código (cpp) [Seleccionar]
char Palabras[100][200]; en vez de pensar en memoria dinamica, pero la ventaja es que con esta voy agregando filas a mi matriz cuando lo voy necesitando en vez de declarar una estatica y ocupar memoria que tal vez no usare

Gracias por su tiempo.

engel lex

no es mas facil un
(usando string.h)

char lectura[200];
int i = 0;
int j = 0;
cin >> lectura;
for(i=0;i<strlen(lectura);i++){
  if(lectura[i]==' ')
    j++;
}
cout >> "hay " >> j >> " palabras";


creo que necesita un par de retoques, pero deberia funcionar
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

Omar_2013

Esque la salida del programa deve de ser asi:

Entrada: "Anita Lava La Tina"
Salida: Anita --> 1 vez
           Lava -->  1 vez
           La    -->   1 Vez
           Tina -->  1 Vez

amchacon

Código (cpp) [Seleccionar]
void AgrEspacio ( char **Palabras, int NumPal)
{
        char **TemFilas=new char*[NumPal];
     
        for ( int i=0; i<NumPal; i++ )
        {
            TemFilas[i]=new char[200]; 
            TemFilas[i]=Palabras[i];
        }
     
        Palabras=TemFilas; 
}


1º Palabras debe pasarse por referencia (&).
2º La igualación TermFilas = Palabras no tiene ningún sentido. Te estas cargando lo que acababas de reservar con new.

Saludos.
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar

Omar_2013

Lo que queria hacer al igualar TemFilas[i]=Palabras[i]; era copiar el contenido ya que TemFilas[i] tiene un espacio de mas y esa es la que quiero usar[/size]

amchacon

No, no haces eso. La función te irá perfectamente así:

Código (cpp) [Seleccionar]
void AgrEspacio ( char **&Palabras, int NumPal)
{
   char **TemFilas=new char*[NumPal];
   
   for ( int i=0; i<NumPal; i++ )
   {
       TemFilas[i]=new char[200];  
   }
   
   Palabras=TemFilas;  
}


Aunque yo eliminaria la variable auxiliar:

Código (cpp) [Seleccionar]
void AgrEspacio ( char **&Palabras, int NumPal)
{
   Palabras =new char*[NumPal];
   
   for ( int i=0; i<NumPal; i++ )
   {
       TemFilas[i]=new char[200];  
   }
}
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar

eferion

#6
No es necesario usar memoria dinámica... al menos no es necesario que tú te encargues de ello.

Sería más sencillo usando un vector:

Código (cpp) [Seleccionar]

int main(int argc, char *argv[])
{
 char Lectura[200], *PTok;
 vector< string > Palabras;
 int i=0, j=0, ContPal=1;

 cin.getline( Lectura, sizeof( Lectura ) );

 PTok = strtok(Lectura," " );

 while ( PTok != NULL )
 {
    Palabras.push_back( PTok );
    PTok = strtok( NULL, " " );  
 }

 for ( int i=0; i < Palabras.size( ); i++ )
   cout<<Palabras[ i ] << endl;

 system("PAUSE");
 return EXIT_SUCCESS;
}


Está muy bien que aprendas a usar memoria dinámica es un recurso muy potente... pero si la usas acuérdate de liberarla después.

Cita de: Omar_2013 en 11 Marzo 2014, 22:38 PM
Lo que queria hacer al igualar TemFilas[i]=Palabras[i]; era copiar el contenido ya que TemFilas[i] tiene un espacio de mas y esa es la que quiero usar[/size]

Si tu haces TemFilas = Palabras... teniendo en cuenta que ambas variables son punteros... estás haciendo que el puntero TemFilas apunte a Palabras, en otras palabras:

* situación inicial:
   TemFilas = 0xF093 <-- Basura
   Palabras = 0x1234 <-- Dirección apuntada por el puntero
* Con TemFilas = new char[200]; tenemos
   TemFilas = 0x8000 <-- Posición de inicio del array recién reservado
   Palabras = 0x1234 <-- Dirección apuntada por el puntero
* Con TemFilas=Palabras
   TemFilas = 0x1234 <-- Perdiste toda referencia a la posicion 8000 que es donde está el array recién creado
   Palabras = 0x1234 <-- Dirección apuntada por el puntero

¿Qué quiere decir esto? Lo siguiente. Una vez haces TemFilas = Palabras sucede lo siguiente:


strcpy( Palabras[i], "prueba" );
cout << Palabras[i] << "-" << TemFilas[i] << endl; // Imprime: prueba-prueba
TemFilas[i][2] = '#';
cout << Palabras[i] << "-" << TemFilas[i] << endl; // Imprime: pr#eba-pr#eba


Esto es así porque los dos punteros apuntan a la misma cadena y cualquier cambio en la cadena se ve reflejado en los dos punteros.


rir3760

Como ya te comento eferion deberías utilizar la biblioteca estándar de C++. Puedes utilizar las clases vector y string para que ellas se encarguen del manejo de memoria y la clase istringstream para obtener las palabras de la linea. Por ejemplo:
Código (cpp) [Seleccionar]
#include <iostream>
using std::cin;
using std::cout;
using std::endl;

#include <string>
using std::string;
using std::getline;

#include <vector>
using std::vector;

#include <sstream>
using std::istringstream;

int main()
{
   cout << "Introduce la linea: ";
   string linea;
   getline(cin, linea);
   
   istringstream is(linea);
   vector<string> palabra;
   string aux;
   while (is >> aux)
      palabra.push_back(aux);
   
   // En C++11 se puede utilizar "auto" para abreviar la declaracion
   for (vector<string>::size_type i = 0; i != palabra.size(); ++i)
      cout << i << ": " << palabra[i] << endl;
   
   return 0;
}


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