1

Queridos amigos de stack overflow.

El presente es para solicitar colaboración en proyecto de ultimo corte, debo realizar un arbol binario que guarde personas con su edad, tengo ya un código adelantado, pero tengo un error al asignar al nuevo_nodo->campo nombre que tome el valor de la variable nom que es de tipo char, les mostraré el código y de ante mano les agradezco la colaboración

#include <iostream>
#include <string.h>

struct Nodo{
    char nombre[30];
    int edad;
    Nodo *der;
    Nodo *izq;
};

using namespace std;
//prototipos de funcion

Nodo *crearNodo(int,char[]);
void insertarNodo(Nodo *&, int, char[]);
void mostrarArbol(Nodo *, int);
void menu();

Nodo *arbol = NULL;


int main(int argc, char** argv) {

    menu();

    return 0;
}

//menu

void menu(){
    int ed, opcion, contador=0;
    char nom[30];
    do{
        cout<<"MENU"<<endl;
        cout<<"1. insertar un nuevo nodo"<<endl;
        cout<<"2.mostrar arbol"<<endl;
        cout<<"3.salir"<<endl;
        cout<<"opcion"<<endl;
        cin>>opcion;

        switch(opcion){
            case 1: cout<<"digite su edad"<<endl;
            cin>>ed;
            cout<<"digite su nombre"<<endl;
            cin.getline(nom,30);
            insertarNodo(arbol,ed, nom);
            cout<<"\n";
            system("pause");
            break;

            case 2: cout<<"mostrar el arbol\n\n";
            mostrarArbol(arbol,contador);
            cout<<"\n";
            system("pause");
        }
        system("cls");
    }while(opcion!=3);
}

Nodo *crearNodo(int ed, char nom){


    Nodo *nuevo_nodo = new Nodo();
          nuevo_nodo->edad = ed;
          nuevo_nodo->nombre=nom;
          nuevo_nodo->der = NULL;
          nuevo_nodo->izq = NULL;

          return nuevo_nodo;
}

void insertarNodo(Nodo *&arbol, int ed, char nom){

    if(arbol == NULL){
        Nodo *nuevo_nodo = crearNodo(ed,nom);
        arbol = nuevo_nodo;
    }
    else{
        int valorRaiz = arbol->edad;
        if(ed<valorRaiz){
            insertarNodo(arbol->izq,ed,nom);

        }
        else{
            insertarNodo(arbol->der,ed,nom);
        }
    }


}


void mostrarArbol(Nodo *arbol, int cont){

    if(arbol==NULL){

        return;
    }
    else{

        mostrarArbol(arbol->der,cont+1);
        for(int i=0;i<cont;i++){
            cout<<" ";
        }
        cout<<arbol->edad<<endl;
        cout<<arbol->nombre<<endl;
        mostrarArbol(arbol->izq,cont+1);
    }
}

2 Answers2

1

El código falla en la función crearNodo(), concretamente en la siguiente línea:

strcpy(nuevo_nodo->nombre,nom);

El problema es que tus funciones insertarNodo() y crearNodo() deberían recibir apuntadores a char y reciben simplemente char.

Cambia esto:

Nodo *crearNodo(int ed, char nom);
void insertarNodo(Nodo *&arbol, char nom);

A esto:

Nodo *crearNodo(int ed, char *nom);
void insertarNodo(Nodo *&arbol, char *nom);
  • Si que pena contigo lo que sucede es que me dijeron que con esa funcion hacia la asignacion de una cadena de caracteres pero no me funciono o no se como utilizarla. – Edwin Garcia May 17 '18 at 21:48
  • la variable nom no es puntero, es solo variable normal, en ella se guarda el nombre en el caso 1 del switch y se envia como para metro para que el nuevo_nodo->nombre tome el nombre ingresado en la estructura – Edwin Garcia May 17 '18 at 23:30
1

Tu código dos problemas importantes:

  • Los prototipos de función no coinciden con las definiciones:
    • crearNodo se declara como Nodo *(int,char[]) y se define como Nodo *(int, char).
    • insertarNodo se declara como void(Nodo *&, int, char[]) y se define como void(Nodo *&, int, char).
  • Estás programando C++ usando cabeceras de C: la cabecera <string.h> es del lenguaje C, dispone de una versión para C++ que es <cstring>. Lee este hilo para más información al respecto.

Aparte de los problemas anteriores, tienes otros problemas menores:

  • Programas en C++ con paradigmas de C: No es que esté prohibido hacerlo, pero dado que C++ ofrece utilidades para hacer que tu código sea más seguro y compacto ¿por qué usar alternativas más verbosas que requieren más control (y por ello tienen más probabilidad de error)?
  • ¿Por qué no usas objetos?: Esta es una variación de la anterior, C++ es un lenguaje multiparadigma, pero en sus fundamentos está la orientación a objetos ¿por qué no sacas provecho de ello?

Conociendo estos problemas de tu código, veámos el fallo:

Nodo *crearNodo(int ed, char nom){


    Nodo *nuevo_nodo = new Nodo();
          nuevo_nodo->edad = ed;
          nuevo_nodo->nombre=nom; // Asignación incorrecta.
          nuevo_nodo->der = NULL;
          nuevo_nodo->izq = NULL;

          return nuevo_nodo;
}

Tu problema está al asignar el nombre, y es normal. El argumento nom es de tipo char mientras que Nodo::nombre es de tipo char[30]. Son tipos distintos y por lo tanto no asignables, podrías solucionarlo así:

nuevo_nodo->nombre[0] = nom; // Asignación correcta.

Pero aunque sea correcto, seguramente no es lo que quieres hacer; asumo que esperas que nom sea más de una letra y suponiendo que la función crearNodo tuviese la misma firma que en su definición el código correcto sería éste:

Nodo *crearNodo(int ed, char nom[]){
//  char[], no char --> ~~~~~~~~~~


    Nodo *nuevo_nodo = new Nodo();
          nuevo_nodo->edad = ed;
          std::copy(nom, nom + 30, nuevo_nodo->nombre);
//        ~~~~~~~~~ <-- función de copia.
          nuevo_nodo->der = NULL;
          nuevo_nodo->izq = NULL;

          return nuevo_nodo;
}

Sin embargo, yo propongo algo diferente:

Propuesta.

Empieza por cambiar tu Nodo así:

struct Nodo{
    std::string nombre;
    int edad = 0;
    Nodo *der = nullptr;
    Nodo *izq = nullptr;
};

Al ser el miembro Nodo::nombre un objeto de tipo std::string podrás asignar nombres arbitrariamente largos (no limitados a 30 caracteres). En el resto de miembros, al añadir valores por defeco en su definición, podrás tener control sobre tus datos de manera más segura.

El Nodo debería ser un objeto interno de una clase Arbol, siendo esta última clase la propietaria de las funciones de creación e inserción de nodos (en lugar de funciones sueltas):

struct Arbol{

    void insertar(int edad, std::string nombre);
    void mostrar();

private:

    Nodo *crear(int edad, std::string nombre);
    void insertar(Nodo *&posicion, int edad, std::string nombre);

    struct Nodo{
//  ~~~~~~~~~~~ <--- El Nodo pertenece al Abol y es inaccesible desde fuera
        std::string nombre;
        int edad = 0;
        Nodo *der = nullptr;
        Nodo *izq = nullptr;
    };

    Nodo *raiz = nullptr;
};

El código anterior sigue los principios de encapsulamiento al ocultar al usuario del objeto Arbol todo aquello con lo que no debería interactuar. Las funciones privadas pueden ser mucho más sencillas incluso siguiendo tu mismo código:

Nodo *Arbol::crear(int edad, std::string nombre){
    return new Nodo{nombre, edad};
}

void Arbol::insertar(Nodo *&posicion, int edad, char nombre){

    if (posicion == nullptr){
        posicion = crearNodo(edad, nombre);
    }
    else{
        insertarNodo(edad < posicion->edad ? posicion->izq : posicion->der, edad, nombre);
    }
}
PaperBirdMaster
  • 44,474
  • 6
  • 44
  • 82
  • Ya realice la asignacion correcta y ya me sale un error diferente Nodo *crearNodo(int ed, char nom){ Nodo *nuevo_nodo = new Nodo(); nuevo_nodo->edad = ed; nuevo_nodo->nombre[30]=nom; nuevo_nodo->der = NULL; nuevo_nodo->izq = NULL; return nuevo_nodo; } Me dice que en esta linea hay un problema dice undefined reference to 'insertarNodo(Nodo*&, int, char)' – Edwin Garcia May 22 '18 at 17:27
  • `undefined reference to 'insertarNodo(Nodo*&, int, char)'` significa que estás usando la función `insertarNodo(Nodo*&, int, char)` pero no está definida. – PaperBirdMaster May 23 '18 at 05:34