Declarar un array de structs de tamaño dinamico

publicado por: Anonymous

buenas, lo que quiero conseguir es declarar un struct con array que tenga su tamaño dinamico, pero cuando lo hago el programa se me cierra mostrando un error.

aqui esta lo que he logrado

#include<iostream>
using namespace std;

struct datos{
    double porc, peso,porc_peso;
    string nombre;
};

int main(){
    int a,b,c, i = 0;
    datos *d;   //<<esto es lo  que quiero declarar de tamanyo dinamico

    while(true){
        cout<<"nombre bebe : ";
        cin>>d[i].nombre;
        if(d[i].nombre == "stop")break;

        cout<<"peso de "<<d[i].nombre<<" (Gr): " ;
        cin>>d[i].peso;
        i++;
    }
    i--;
}

al principio se ejecuta bien, pero al ingresar el peso por 2da vez ( cin>>d[1].peso ) se me cierra el programa.

O mas bien dicho,windowns me dice que el programa ha dejo de funcionar.

solución

Problema

al principio se ejecuta bien, pero al ingresar el peso por 2da vez ( cin>>d[1].peso ) se me cierra el programa.

Lo sorprendente es que te funcione siquiera la primera vez, ya que en los usos que le das a d, dicho puntero jamás contuvo una instancia de datos así que incurres en comportamiento indefinido y podría pasar cualquier cosa… que funcione, que no funcione o que salgan demonios disparados de tus fosas nasales.


Sugerencia

Dado que estás tratando datos dinámicos, debes solicitar memoria para dichos datos en tiempo de ejecución (dinámicamente). Usando un puntero la operación se complica mucho a no ser que pidas de antemano la cantidad de datos a tratar:

int cantidad = 0;
cout << "cantidad: ";
cin >> cantidad;
datos *dato = new datos[cantidad]; //<<aqui se solicita el tamanyo dinamico

for (int indice = 0; indice < cantidad; ++indice){
    cout << "nombre bebe : ";
    cin >> dato[indice].nombre;
    if (dato[indice].nombre == "stop") break;

    cout<< "peso de " <<dato [indice].nombre << " (Gr): " ;
    cin >> dato[indice].peso;
}

//...
delete[] dato; //<<aqui se LIBERAN los datos dinamicos

De no pedir de antemano los datos a tratar, a cada vuelta del bucle deberías:

  1. Crear un buffer con un elemento más.
  2. Copiar los datos antiguos en el buffer nuevo.
  3. Añadir los datos nuevos al buffer nuevo.
  4. Volver al punto nº1.

Lo cuál es complicado en exceso.

Solución

Por suerte C++ dispone de herramientas que hacen los pasos anteriores automáticamente, usando la plantilla std::vector de la stl:

std::vector<datos> coleccion; //<<aqui tiene tamanyo 0 (esta vacio)

while(true){
    cout<<"nombre bebe : ";
    datos dato; //<<aqui creamos un nuevo elemento
    cin>>dato.nombre;
    if(dato.nombre == "stop")break;

    cout<<"peso de "<<dato.nombre<<" (Gr): " ;
    cin>>dato.peso;
    coleccion.push_back(dato); //<<aqui anyadimos el nuevo elemento a la coleccion
}

La coleccion de datos crece dinamicamente, sin necesidad de preocuparse por solicitar o liberar memoria (ya se encarga std::vector).

Otras cosas a tener en cuenta

  1. Te falta incluir la cabecera <string>; deberías publicar código funcional si quieres que te ayuden a resolver tu problema.
  2. Las variables a, b y c no se usan.
  3. Evita usar nombres de variable de una sola letra a no ser que sean auto-explicativas (como por ejemplo las coordenadas x, y, z) ya que hace confuso leer, entender y depurar el código.
  4. Aunque no es estrictamente necesario, da un valor inicial a todas tus variables, en muchas ocasiones seguir esta recomendación te ayuda a evitar otros errores.
  5. No se para que decrementas i al finalizar el bucle.
  6. La función main SIEMPRE debe devolver un valor es aconsejable que devuelva un valor, añade return 0;.
Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *