5

Estaba aprendiendo sobre pilas y haciendo un ejercicio se me ocurrió que envés de pedirle datos númericos al usuario le pidiera cadenas de texto. El ejercicio pide que esto se haga en un menú. La cosa es que hice el correspondiente código pero cuando el usuario pide que le muestren los datos (nombres) registrados, se muestran todos menos el primero.

Ej: Si digita Daniel,Jose,Marta , al imprimir muestra Marta,Jose pero no muestra a Daniel

Aunque esto no sea practico en un entorno real solo por curiososidad me gustaría que alguien aclarara mi duda.

#include<iostream>
#include<stdlib.h>

using namespace std;

struct Nodo
{
    string nombreCompleto;
    struct Nodo *sgte;
};

void agregar(Nodo *&, string);
void sacar(Nodo *&, string&);
void menu();

int main() {

    menu();

    system("pause");
    return 0;
}

void agregar(Nodo *&pila, string n)
{
    Nodo *nuevo = new Nodo();
    nuevo->nombreCompleto = n;
    nuevo->sgte = pila;
    pila = nuevo;
    cout << "Se agrega " << nuevo->nombreCompleto;
}

void sacar(Nodo *&pila, string& n)
{
    Nodo *aux = pila;
    n = aux->nombreCompleto; 
    pila = aux->sgte; 
    delete aux;

}



void menu()
{
    Nodo *pila = NULL;
    string flag = "0", data;
    int *opcion, n = 0;

    do{


        while (n <= 0 || n > 3)
        {
            cout << "Digite 1 para almacenar, 2 para mostrar los elementos de la pila y 3 para salir: "; cin >> n;
        }opcion = &n; 

        switch (*opcion)
        {
        case 1:cout << "\nInserte un nombre  "; cin >> data; agregar(pila, data); cout << "\n\n";
            break;
        case 2:cout<<"Los elementos de la pila son: \n\n"; 

            while (pila != NULL)
            {

                sacar(pila, data);
                if (pila != NULL) {
                    cout << data << " , ";
                }
                else
                {
                    cout << "\n*FIN datos*\n\n";
                }
            }flag = "3";
            break;
        case 3:system("cls"); cout << "El proceso ha terminado.\n\n"; flag = "3";
            break;
        } n = 0; 

    } while (flag!="3");

}
jean
  • 149
  • 2
  • 6
  • 2
    Esto te pasa porque cuando llamas a la función sacar la última vez, al salir, pila vale NULL y como tienes un if que solo imprime la cadena cuando pila sea distinto de NULL, la última no la imprime. Tal cual lo tienes hecho, puedes hacer una cosa así rápida. Si eliminas el contenido de data antes de llamar a la función sacar (borrando cualquier contenido de una iteracion anterior), si data tiene contenido al salir de la función, lo imprimes y sino no, en vez de comprobar si pila es NULL o no, cosa que ya compruebas en el while para terminar de dar vueltas. – SuperG280 Jun 25 '19 at 07:36

1 Answers1

3

No se te muestra el primer dato, porque después de la llamada a sacar, el puntero pila apunta a NULL por lo que no supera el if1. No necesitas esa comprobación:

while (pila != NULL)
{
    sacar(pila, data);
    cout << data << " , ";
}
flag = "3";
cout << "\n*FIN datos*\n\n";

Otras cosas a tener en cuenta.

  1. Estás programando en C++, pero incluyes cabeceras de C (<stdlib.h>) que además ni usas. Lee este hilo para saber más detalles.
  2. Confundes nodos con pilas: creas un objeto Nodo pero lo pasas a las funciones como si fuese la pila, eso es tan erróneo como decir que un escalón es una escalera, sinceramente ¿Te parecen lo mismo?:

  1. Aunque C++ es un lenguaje multiparadigma, es conocido por su orientación a objetos; no estás usando esa característica.
  2. En C++ el literal de puntero nulo es nullptr.
  3. La indentación ayuda a leer y entender el código, no queda más molón poner varias instrucciones en una línea, al contrario.
  4. La nomenclatura es importante, no tiene sentido mezclar abreviaciones (sgte) e identificadores multipalabra completos (nombreCompleto) en el mismo código, ¡menos aún en el mismo objeto!.

Aplicando correcciones para seguir las pautas anteriores, tu código podría parecerse a:

struct Pila
{
    void agregar(std::string);
    std::string sacar();

private:

    struct Nodo
    {
        std::string nombreCompleto;
        Nodo *siguiente = nullptr;
    };

    Nodo *raiz = nullptr;
};

void Pila::agregar(std::string n)
{
    raiz = new Nodo{n, raiz};
}

std::string Pila::sacar()
{
    auto *aux = raiz;
    auto resultado = aux->nombreCompleto; 
    raiz = aux->siguiente; 
    delete aux;

    return resultado;
}

Puedes ver el código funcionando en Wandbox.


  1. El crédito va para SuperG280 en los comentarios.
PaperBirdMaster
  • 44,474
  • 6
  • 44
  • 82
  • Gracias por tu explicación :) , perdon por mi ignorancia estoy aprendiendo a programar por simple curiosidad y aun no llego al concepto de orientación a objetos – jean Jun 25 '19 at 18:26
  • No te disculpes por ignorancia, al contrario: saber de tu ignorancia te permite abrir la mente a conocimientos nuevos. Sigue así. – PaperBirdMaster Jun 26 '19 at 07:08