Estructuras

Sitio: Facultad de Ingeniería U.Na.M.
Curso: Computación ET-344
Libro: Estructuras
Imprimido por: Invitado
Día: miércoles, 3 de julio de 2024, 06:30

1. Introducción

Las estructuras son el segundo tipo de datos estructurados que veremos.

Las estructuras nos permiten agrupar varios datos, aunque sean de distinto tipo, algo parecido a listas de  Python.

En las estructuras hay un tipo de relación al igual que lo hay en un arreglo, permitiendo manipularlos todos juntos, con un mismo identifcador o nombre  o por separado accediendo a cada miembro de la estructura como cada componente de un arreglo

Las estructuras son llamadas también muy a menudo registros, o en inglés"records" y se puede pensan a modo de analogía como una fila de una hoja de cálculo.

Son estructuras análogas en muchos aspectos a los registros debases de datos. Y siguiendo la misma analogía, cada variable de unaestructura se denomina a menudo campo, o "field"

Una estructura es un vestigio histórico de C. Desde la perspectiva del programador, una estructura puede considerarse como una clase que tiene todas las variables de instancia pública y no tiene métodos miembros, esto último tendrá mas claridad cuando veamos el tema que sigue que es clases.

2. Sintaxis

struct [<identificador>]

                                       { [<tipo> <nombre_variable>[,<nombre_variable>,...]]; .} //miembros

                                         [<variable_estructura>[,<variable_estructura>,...]; //Instancias

Al momento de declarar una instancia el nombre de la estructura es un nombre opcional para referirse a la estructura, pero suele  se conveniente incorporarlo para que si algún otra persona intenta comprender el código.

Las variables de estructura son variables declaradas del tipo de la estructura, como los sería float, bool o int, pero notemos que este tipo es PROPIO DEL PROGRAMADOR!!, sería una "plantilla de datos de distinto tipo".

Algunos de los elementos de la sintaxis son opcionales.

IMPORTANTE:

Si las definiciones de la Estructuras sean GLOBALES ( fuera de main ), cada función puede usar esa estructura (plantilla de datos ) y puede crear  instancias LOCALES ( variables de Concexto LOCAL),.

Esto permitiría en un programa use las estructuras dentro de las  funciones.

Figura 1

3. Ejemplo de uso

#include <iostream>
#define N 3
using namespace std;
int main(){
    struct datos {bool valido;float temperaturas[N];} enero;//declaro estructura (plantilla) y defino instancia
    datos febrero; // defino una instancia, esto SI usa espacio en memoria.
    cout<<" Carguemos la Instancia enero: ";
    enero.valido=true; //asigno valor.
    cout<<endl;
    for(int i=0;i<N;i++){cout<<"temperatura["<<i<<"] :";cin>>enero.temperaturas[i];}
    cout<<"Miembro valido :";
    cout<<enero.valido<<endl;
    cout<<"Miembro temperaturas :";
    for(int i=0;i<N;i++){cout<<"temperatura["<<i<<"] :"<<enero.temperaturas[i]<<"\t";}
    cout<<endl;
    return 0;
}
Si ejecutamos este código fuente para ingresos 25.1, 26.2, 27.3 la salida sería:
Figura 2


¿Cómo accedo al miembro utilizando el nombre de la instancia?
¿Uso el nombre de la plantilla para acceder al contenido de cada miembro?
¿Una esctructura no instanciada usa espacio de memoria?
¿Qué tamaño tiene una estructura?
¿Qué operador me permite acceder al miembro invocando el nombre de la instancia?
¿Qué son los miembros de una estructura?
¿Dónde se declaran y definen los miembros de una estructura?

4. Inicialización y Acceso

Inicialización

#include<iostream>  
using namespace std;  
int main(){
   struct St_datos {float temperatura; int fecha[3];} dato; 
   dato={25.0,23,6,2021}; 
   cout<<dato.temperatura<<endl;  
   cout<<dato.fecha[0]<<endl;
   cout<<dato.fecha[1]<<endl;    
   cout<<dato.fecha[2]<<endl;
   return 0; 
}


Alternativa 2

#include<iostream>
using namespace std;
int main(){
   struct St_datos {float temperatura; int fecha[3];};
   St_datos dato;
   dato={25.0,23,6,2021};
   cout<<dato.temperatura<<endl;
   cout<<dato.fecha[0]<<endl;
   cout<<dato.fecha[1]<<endl;
   cout<<dato.fecha[2]<<endl;
   return 0;
}

Acceso con operador . (punto)

Para acceder a un elemento o miembro de la estructura:

nombre_de_la_instancia.nombre_del_miembro
Ejemplo:
cout<<dato.fecha[0]<<endl; //Nombre de instancia (dato)  punto Nombre del miembro punto fecha
cout<<dato.temperatura<<endl; //Nombre de instancia (dato)  punto Nombre del miembro temperatura.
Que es un anuncio - Gestion.Org
  • NO confundir el nombre de la estructura ( plantilla de datos ) con la variable (instancia) .
  • St_datos es el nombre de la plantilla de datos o estructura dato es el nombre de la instancia.
  • Para acceder a CADA miembro de la plantilla, si uso el NOMBRE DE LA INSTANCIA, debo usar el operador punto para acceder al miembro.
  • Notar la similitud de acceso que tiene una Estructura con las propiedades de un objeto en Python.

Igualando Estructuras.

Una propiedad interesante de las estructuras, es que si igualo dos estructuras del mismo tipo B=A, cada uno de los miembros de la estructura A son copiados a cada uno de los miembros de la estructura B.
Veamos un ejemplo:

La salida de este script sería:


Estructura como argumento de función.


Al igual que cualquier variable, una instancia se puede pasar como argumento de una función.


Nota que:
  • El argumento del prototipo y de la llamada es un tipo de dato persona.
  • Ver que la estructura es GLOBAL!! , está fuera de main, por eso mostrar puede usarla.




5. Arreglos de Estructuras.

Una estructura es una plantilla de datos o tipo de dato y como cualquier dato puede ser un arreglo,.

Una arreglo de estructura es un conjunto de instancias que están ubicados  contíguos en memoria.

Vemos un ejemplo:

#include <iostream>
#define semana 2
#define dia 3
using namespace std;
int main(){
    struct datos {bool valido;float temperaturas[dia];} enero[semana];//declaro estructura (plantilla)
        // y defino instancia
    struct datos febrero; // defino una instancia, esto SI usa espacio en memoria.
    cout<<" Carguemos la Instancias enero: ";cout<<endl;
    for(int x=0;x<semana;x++){    
        for(int z=0;z<dia; z++){
            cout<<"Semana "<<x<<" , día :"<<z<<" : ";       
            enero[x].valido=true;        
            cin>>enero[x].temperaturas[z]; // ver que utilizo los indices para accedar
            // a cada elemento del arreglo de un miembro
        }    
    }
    cout<<"Temperturas Enero:"<<endl;
    for(int x=0;x<semana;x++){
        for(int z=0;z<dia; z++){
            if (enero[x].valido)           
            cout<<"Semana "<<x<<" , día :"<<z<<" : "<<enero[x].temperaturas[z]<<"\t";
        }    
        cout<<endl;    
    }
    return 0;
}
¿Como accedo a cada instancia  del arreglo enero?
¿Como accedo a cada miembro del arreglo temperatura?


6. Estructuras Anidadas

Como una estructura en un tipo de datos o plantilla creada por el programador, nada impide que no se pueda declarar una o mas estructuras  dentro de una estructura.

Que es un anuncio - Gestion.OrgLas estructuras definidas dentro de otra estructura DEBEN estar instanciadas, si no, NO HAY FORMA DE ACCEDER  ellas.

#include <iostream>
>#define instancias 2
using namespace std;
//Declaro Estructuras Globales.
struct St_Personas 
{
char nombre[10],apellido[20];
long dni;
};//declaro estructura (plantilla) NO hay instancias!!
struct St_otros_datos 
{
int dia,mes,anio; 
};//declaro estructura (plantilla) NO hay instancias!!  
int main()
{
//declaro estructuras anidadas..pero DOY NOMBRE A LAS INSTANCIAS! struct St_Registro{St_Personas persona; St_otros_datos otros;} alta_datos[instancias]; for(int s=0;s<instancias;s++) { cout<<endl<<"Nombre :";cin>>alta_datos[s].persona.nombre; cout<<endl<<"Apellido :";cin>>alta_datos[s].persona.apellido; cout<<endl<<"DNI :";cin>>alta_datos[s].persona.dni; cout<<endl<<"Dia Nacimiento :";cin>>alta_datos[s].otros.dia; cout<<endl<<"Mes Nacimiento :";cin>>alta_datos[s].otros.mes; cout<<endl<<"Año Nacimiento :";cin>>alta_datos[s].otros.anio; } for(int s=0;s<instancias;s++) { cout<<endl; cout<<alta_datos[s].persona.nombre<<"\t"; cout<<alta_datos[s].persona.apellido<<"\t"; cout<<alta_datos[s].persona.dni<<"\t"; cout<<alta_datos[s].otros.dia<<"\t"; cout<<alta_datos[s].otros.mes<<"\t"; cout<<alta_datos[s].otros.anio<<"\t"; cout<<endl; } return 0; }
  pensar
¿Como accedo al miembro de una estructura anidada? , trate de identificar las partes y descríbalas con los nombres apropiados.
¿alta_datos que tipo de datos es? ¿Es local o global?
¿personas que tipo de datos es?¿Es local o global?
¿otros que tipo de datos es?¿Es local o global?
¿St_Personas que es? ¿Es local o global?
¿St_otros_datos  que es? ¿Es local o global?

7. Ejercicio Estucturas.

Un docente debe cargar las notas de alumnos que están entre [0;10]. Tiene 3 evaluaciones y cada evaluación tiene su recuperatorio y la nota del recuperatorio reemplaza a la nota del parcial. Se regulariza cuando el promedio es 7 o mas y no tiene aplazos ( nota menor a 4)

Se pide al alumno que realice  un programa que permita

  • Cargar las notas de los parciales
  • Cargar las notas de los recuperatorios
  • Listar los alumnos regulares.
Condicionamientos:
NO usar funciones.
Usar estructuras anidadas, una para los nombres y otra para las notas de las evaluaciones.
Usar una constante simbólica para indicar la candidad de alumnos.


8. Solución Ejercicio.



#include<iostream>
#define cantidad 2
#define sin_nota -1
using namespace std;
int main()
{
bool nota_valida= true;
struct St_alumnos{char nombre[20];char apellido[20];};//para Nombre y apellido.
struct St_evaluaciones{float nota[2];};//indice 0:Parcial, Indice 1: Recuperatorio
>struct St_registros {St_alumnos alumno;St_evaluaciones calificaciones;} registro[cantidad];
// Carga de Nombres .
for(int a=0;a<cantidad;a++)
{cout<<endl<<"Ingrese Nombre: ";cin>>registro[a].alumno.nombre;
cout<<endl<<"Ingrese Apellido: ";cin>>registro[a].alumno.apellido;
registro[a].calificaciones.nota[0]= sin_nota;//para saber si se cargaron valores
registro[a].calificaciones.nota[1]= sin_nota;//para saber si se cargaron valores
}
// Carga de Notas

or(int a=0;a<cantidad;a++)
{
cout<<registro[a].alumno.nombre<<" "<<registro[a].alumno.apellido<<endl;
for(int h=0;h<2;h++)
{nota_valida=true;
cout<<"Ingrese nota Parcial "<<h+1<<": ";
 while (nota_valida)
   {cin>>registro[a].calificaciones.nota[h];//ingreso nota.
   //Controlo que esté en [0;10] o que sea -1
   if(((registro[a].calificaciones.nota[h]<0) or (registro[a].calificaciones.nota[h]>10))and !(registro[a].calificaciones.nota[h]==sin_nota))
   {cout<<"Nota no valida, reingrese :"; 
   nota_valida=true;}
   else nota_valida=false;
   }
}
}
//Muestro notas de parcial
for(int a=0;a<cantidad;a++)
{
cout<<registro[a].alumno.nombre<<" "<<registro[a].alumno.apellido<<endl;
 for(int h=0;h<2;h++)
  {
  cout<<" Parcial "<<h+1<<": "<<registro[a].calificaciones.nota[h]<<endl;
  }
  cout<<endl;
}   
//Carga de Recuperatorios Falta.
//Mostrar Regulares  Falta.
}

Esta es una propuesta de resolución, faltaría la parte de carga de recuperatorio y luego generar las condiciones para cada alumno.