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:
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 originalif (calabaza == true)
{
int resultado; // variable estática
//...
} // 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 originalarbol * dePostaArbol(string cadena){
string buf; // Have a buffer string
pilaArbol stack_tree= pilaArbol();
pilaArbol * pPila;
arbol * salida = NULL; //La formula en postfija
arbol* pab;
stringstream ss (cadena); // Inserta la cadena en un stream que separa tokens por " "
while (ss >> buf){
if (buf.compare("DIA")==0){//OPERADOR DIAMANTE
insertarOperadorEnPila(stack_tree,-1);//DIA == -1
}else if (buf.compare("BOX")==0){//OPEEADOR CAJA
insertarOperadorEnPila(stack_tree,-2);//BOX == -2
}else if (buf.compare("NOT")==0){//NEGACION
insertarOperadorEnPila(stack_tree,-3);//DIA == -3
}else if (buf.compare("AND")==0){//OPERADOR AND1
insertarOperadorEnPila(stack_tree,-4);//DIA == -4
}else if (buf.compare("OR")==0){//OPERADOR OR
insertarOperadorEnPila(stack_tree,-5);//DIA == -5
}else if (buf.compare("IMPLIES")==0){//IMPLICACION
insertarOperadorEnPila(stack_tree,-6);//DIA == -6
}else{//OPERANDO...
int valorOperador;
pab= new arbol();
valorOperador=codifica(buf);
pab->setValor(valorOperador);
stack_tree.Push(pab);
}
pPila=&stack_tree;
}
if (stack_tree.isEmpty()){
cout<<"Error: El algoritmo de conversion de postfija a arbol ha fallado..."<<endl;
stack_tree.destruir();
}else{
salida=stack_tree.Pop();
if(stack_tree.isEmpty()){
stack_tree.destruir();
return salida;
}else{
cout<<"Error: El algoritmo de conversion de postfija a arbol ha fallado..."<<endl;
stack_tree.destruir();
}
}
}
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:
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 originalif (calabaza == true)
{
int resultado; // variable estática
//...
} // 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 originalarbol * dePostaArbol(string cadena){
string buf; // Have a buffer string
pilaArbol* stack_tree= new arbol;
*stack_tree = pilaArbol();
pilaArbol * pPila;
arbol * salida = NULL; //La formula en postfija
arbol* pab;
stringstream ss (cadena); // Inserta la cadena en un stream que separa tokens por " "
while (ss >> buf){
if (buf.compare("DIA")==0){//OPERADOR DIAMANTE
insertarOperadorEnPila(*stack_tree,-1);//DIA == -1
}else if (buf.compare("BOX")==0){//OPEEADOR CAJA
insertarOperadorEnPila(*stack_tree,-2);//BOX == -2
}else if (buf.compare("NOT")==0){//NEGACION
insertarOperadorEnPila(*stack_tree,-3);//DIA == -3
}else if (buf.compare("AND")==0){//OPERADOR AND1
insertarOperadorEnPila(*stack_tree,-4);//DIA == -4
}else if (buf.compare("OR")==0){//OPERADOR OR
insertarOperadorEnPila(*stack_tree,-5);//DIA == -5
}else if (buf.compare("IMPLIES")==0){//IMPLICACION
insertarOperadorEnPila(*stack_tree,-6);//DIA == -6
}else{//OPERANDO...
int valorOperador;
pab= new arbol();
valorOperador=codifica(buf);
pab->setValor(valorOperador);
stack_tree->Push(pab);
}
pPila=stack_tree;
}
if (stack_tree->isEmpty()){
cout<<"Error: El algoritmo de conversion de postfija a arbol ha fallado..."<<endl;
stack_tree->destruir();
}else{
salida=stack_tree->Pop();
if(stack_tree->isEmpty()){
stack_tree->destruir();
return salida;
}else{
cout<<"Error: El algoritmo de conversion de postfija a arbol ha fallado..."<<endl;
stack_tree->destruir();
}
}
}
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).