Ver Mensaje Individual
  #5 (permalink)  
Antiguo 14/03/2013, 12:12
amchacon
 
Fecha de Ingreso: julio-2012
Mensajes: 375
Antigüedad: 12 años, 4 meses
Puntos: 28
Respuesta: Duda sobre c++. Se pierden datos al salir de un while.

Vamos a ver, hay que diferencia entre memoria estática y memoria dinámica.

La memoría estática es la que se coje internamente de la pila, cada vez que declaramos una variable/objeto estamos cogiendola de la pila:

Código C++:
Ver original
  1. int cosa;
  2. arbol font;
  3.  
  4. //...

Estas variables, son variables de ambito. Nacen con un ambito de llaves y mueren cuando finaliza este.

Por ejemplo, si se crea durante un if:

Código C++:
Ver original
  1. if (calabaza == true)
  2. {
  3.     int resultado; // variable estática
  4.    //...
  5. } // muerte de la variable resultado

La memoria dinámica es la que se crea con new y dura hasta que se llama a delete.

Volviendo al ejemplo actual:

Código C++:
Ver original
  1. arbol * dePostaArbol(string cadena){
  2.         string buf; // Have a buffer string
  3.         pilaArbol stack_tree= pilaArbol();
  4.         pilaArbol * pPila;
  5.         arbol * salida = NULL; //La formula en postfija
  6.         arbol* pab;
  7.         stringstream ss (cadena); // Inserta la cadena en un stream que separa tokens por " "
  8.         while (ss >> buf){
  9.             if (buf.compare("DIA")==0){//OPERADOR DIAMANTE
  10.                 insertarOperadorEnPila(stack_tree,-1);//DIA == -1
  11.             }else if (buf.compare("BOX")==0){//OPEEADOR CAJA
  12.                 insertarOperadorEnPila(stack_tree,-2);//BOX == -2
  13.             }else if (buf.compare("NOT")==0){//NEGACION
  14.                 insertarOperadorEnPila(stack_tree,-3);//DIA == -3
  15.             }else if (buf.compare("AND")==0){//OPERADOR AND1
  16.                 insertarOperadorEnPila(stack_tree,-4);//DIA == -4
  17.             }else if (buf.compare("OR")==0){//OPERADOR OR
  18.                 insertarOperadorEnPila(stack_tree,-5);//DIA == -5
  19.             }else if (buf.compare("IMPLIES")==0){//IMPLICACION
  20.                 insertarOperadorEnPila(stack_tree,-6);//DIA == -6
  21.             }else{//OPERANDO...
  22.                
  23.                 int valorOperador;
  24.                 pab= new arbol();
  25.                 valorOperador=codifica(buf);
  26.                 pab->setValor(valorOperador);
  27.                 stack_tree.Push(pab);
  28.             }
  29.             pPila=&stack_tree;
  30.         }
  31.         if (stack_tree.isEmpty()){
  32.             cout<<"Error: El algoritmo de conversion de postfija a arbol ha fallado..."<<endl;
  33.             exit (-1);
  34.             stack_tree.destruir();
  35.         }else{
  36.             salida=stack_tree.Pop();
  37.             if(stack_tree.isEmpty()){
  38.                 stack_tree.destruir();
  39.                 return salida;
  40.             }else{
  41.                 cout<<"Error: El algoritmo de conversion de postfija a arbol ha fallado..."<<endl;
  42.                 exit (-1);
  43.                 stack_tree.destruir();
  44.             }
  45.         }
  46.     }

El error está cuando asignamos el puntero pPila a la variable estática stack_tree. No es que los punteros pierdan la referencia, esque cuando salimos de la función se borra stack_tree y el puntero pPila apunta ahora, a una memoria vacía.

La solución consiste en poner stack_tree como memoria dinámica:

Código C++:
Ver original
  1. int cosa;
  2. arbol font;
  3.  
  4. //...

Estas variables, son variables de ambito. Nacen con un ambito de llaves y mueren cuando finaliza este.

Por ejemplo, si se crea durante un if:

Código C++:
Ver original
  1. if (calabaza == true)
  2. {
  3.     int resultado; // variable estática
  4.    //...
  5. } // muerte de la variable resultado

La memoria dinámica es la que se crea con new y dura hasta que se llama a delete.

Volviendo al ejemplo actual:

Código C++:
Ver original
  1. arbol * dePostaArbol(string cadena){
  2.         string buf; // Have a buffer string
  3.         pilaArbol* stack_tree= new arbol;
  4.         *stack_tree = pilaArbol();
  5.         pilaArbol * pPila;
  6.         arbol * salida = NULL; //La formula en postfija
  7.         arbol* pab;
  8.         stringstream ss (cadena); // Inserta la cadena en un stream que separa tokens por " "
  9.         while (ss >> buf){
  10.             if (buf.compare("DIA")==0){//OPERADOR DIAMANTE
  11.                 insertarOperadorEnPila(*stack_tree,-1);//DIA == -1
  12.             }else if (buf.compare("BOX")==0){//OPEEADOR CAJA
  13.                 insertarOperadorEnPila(*stack_tree,-2);//BOX == -2
  14.             }else if (buf.compare("NOT")==0){//NEGACION
  15.                 insertarOperadorEnPila(*stack_tree,-3);//DIA == -3
  16.             }else if (buf.compare("AND")==0){//OPERADOR AND1
  17.                 insertarOperadorEnPila(*stack_tree,-4);//DIA == -4
  18.             }else if (buf.compare("OR")==0){//OPERADOR OR
  19.                 insertarOperadorEnPila(*stack_tree,-5);//DIA == -5
  20.             }else if (buf.compare("IMPLIES")==0){//IMPLICACION
  21.                 insertarOperadorEnPila(*stack_tree,-6);//DIA == -6
  22.             }else{//OPERANDO...
  23.                
  24.                 int valorOperador;
  25.                 pab= new arbol();
  26.                 valorOperador=codifica(buf);
  27.                 pab->setValor(valorOperador);
  28.                 stack_tree->Push(pab);
  29.             }
  30.             pPila=stack_tree;
  31.         }
  32.         if (stack_tree->isEmpty()){
  33.             cout<<"Error: El algoritmo de conversion de postfija a arbol ha fallado..."<<endl;
  34.          
  35.             stack_tree->destruir();
  36.                 exit (-1);
  37.         }else{
  38.             salida=stack_tree->Pop();
  39.             if(stack_tree->isEmpty()){
  40.                 stack_tree->destruir();
  41.                 return salida;
  42.             }else{
  43.                 cout<<"Error: El algoritmo de conversion de postfija a arbol ha fallado..."<<endl;
  44.              
  45.                 stack_tree->destruir();
  46.    exit (-1);
  47.             }
  48.         }
  49.     }

Notesé:

- Que para acceder al contenido de stack_tree usamos * (porque es un puntero).
- Que para llamar a los método de stack_tree usamos el operador -> (porque estamos usando puntero).