Uncategorized

Programando en C: Estructuras

Capítulo 11: Estructuras

Que son las estructuras?

Las estructuras en C, que no tienen nada que ver con las estructuras de datos tal y como las hemos presentado en los capítulos anteriores, constituyen un nivel superior de ordenación de los datos, que estaría por encima de las matrices, y por debajo de Los objetos, tal y como se entienden en el paradigma de programación orientada a objetos.

El lenguaje C, de base, no tiene soporte para el paradigma de programación orientada a objetos, al menos de forma nativa, aunque se puede conseguir mediante el uso de librerías, o, más frecuentemente, mediante el uso del lenguaje C++, que frecuentemente recibe el nombre de » C con clases «

así pues, si bien el lenguaje se no tiene soporte para programación orientada a objetos de forma nativa, en esta publicación vamos a presentar una serie de conceptos acerca de este paradigma de programación, ya que nos ayudan a entender la utilidad de las estructuras

¿Qué es la programación orientada a objetos?

Si nos fijamos en lo que hemos aprendido hasta el momento, podremos observar como, en un momento dado, empezamos trabajando con variables, pero más adelante, extendimos el concepto de variables mediante el uso de estructuras de datos más avanzadas, como por ejemplo, las matrices.

de esta forma, las variables nos ayudan a solucionar una serie de problemas concretos, ya que nos permiten almacenar datos de uno a uno en cada una de estas variables.

Sin embargo, en multitud de ocasiones, necesitamos guardar varios datos, varias piezas de información, dentro de la misma estructura.

así pues, las estructuras de datos avanzadas, no son más que una solución a ese problema que frequentemente se nos puede presentar.

de la misma forma, en cuanto a la funcionalidad, empezamos la publicación presentando cómo ejecutar instrucciones, pero en un momento dado, observamos como la programación en base a funciones suponía un avance en cuanto a nuestra metodología con como programadores, y por tanto, el uso de funciones, y el encapsulado que ello representa, nos permite realizar desarrollos más complejos, pero a la vez de una forma más mantenerle.

hasta el momento, digamos que por una parte hemos ido evolucionando en cuanto al almacenaje de información, y por otra parte, hemos ido al más avanzando en la ejecución de instrucciones.

la programación orientada a objetos, o lo que es lo mismo, la programación mediante clases, supone un avance un paso más allá todavía en el mismo camino y en la misma dirección en la que nosotros ya hemos empezado a avanzar.

Supone la aparición de una estructura superior llamada clase,que alguna, en una misma burbuja, en una misma cápsula, variables, que pasan a llamarse propiedades, y funciones, que pasan a llamarse métodos.

Así que, desde el plano más básico, las clases no añaden nuevas estructuras de datos ni nuevas funciones que no conozcamos, simplemente, las agregan Y las engloban dentro de una misma burbuja, por supuesto únicamente cuando esto tiene algún tipo de sentido, es decir, cuando ese conjunto de propiedades y ese conjunto de métodos tiene, con textualmente, una función y un sentido en común.

Como he comentado anteriormente, Fede no tiene soporte nativo para trabajar con clases, pero tiene un elemento parecido llamado estructura.

La estructura tiene un comportamiento muy parecido con respecto a las clases, ya que nos permite introducir una serie de variables, que pasan a llamarse propiedades, y que se aglutinan teniendo un sentido

Que son las estructuras?

Las estructuras, por tanto, no son más que grupos de datos, que comparten un significado entre sí, y que además, tienen una enumeración finita.

El clásico ejemplo de estructuras en C, lo encontramos en la declaración de un punto en el espacio tridimensional.

En el momento en el que pensamos en declarar un punto en el espacio tridimensional, sabemos que ese punto, si nos ceñimos a las tres dimensiones del espacio, tiene invariablemente tres propiedades: Su valor en LG X, su valor en el FY, su valor en el FZ.

De esta forma, cuando declaramos una estructura, realmente lo que estamos declarando es 1 U de datos llamada., Y dentro de ella, declaramos tres propiedades, que son X, Y, Z

Declaración de estructuras

En el siguiente ejemplo vamos a materializar el caso que previsualización amos en el párrafo anterior.

Si trabajamos con el ejemplo de un punto en el espacio tridimensional, veremos como una estructura se declararía de la siguiente forma:

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    struct Punto{        int x;        int y;        int z;    };}

Por una parte, como hemos podido observar, declaramos el nombre de la estructura, para, a continuación, dentro de las llaves, introducir cada uno de los parámetros, es decir, cada una de las propiedades que va a tener esa estructura, cada una de ellas, con su propio tipo de datos.

de esta forma, declaramos, de forma abstracta, y todavía no usándola, la plantilla de lo que será esa estructura de datos, al igual que declaramos de forma abstracta una función antes de usarla.

adicionalmente, podemos inicializar el valor de la estructura, con un concepto que está a caballo entre la inicialización de una variable, y un método constructor en el caso de la programación orientada a objetos.

La sintaxis quedaría de la siguiente manera:

main.c


lo que haríamos en ese caso es preparar la estructura para que, cada vez que se cree un punto nuevo, se le asignen una serie de valores iniciales a las propiedades, antes de que nosotros podamos escribir los nuestros propios.

Si nosotros escribimos los nuestros propios, por supuesto sobrescribirán a los valores por defecto, pero si no queremos introducir valores por defecto, sabremos que al crear una estructura, por defecto ya tiene un juego de valores pre implementados.

Creación de estructuras

Una vez que ya tenemos una estructura declarada en memoria, es decir, tenemos la plantilla Del comportamiento y los elementos que va a tener esa estructura, es cuando tenemos que crear nuevos objetos a partir de ella.

Una vez más, es en este punto donde la creación de estructuras a partir de la plantilla, tiene evidentemente similitudes con la programación y la creación de objetos a partir de clases.

así que podremos crear nuevas estructuras simplemente invocando al código de la siguiente forma.

main.c

#include <stdio.h>
int main(int argc, char *argv[]) {    struct Punto{        int x;        int y;        int z;    };    struct Punto punto1;    punto1.x = 100;    punto1.y = 200;    punto1.z = 300;    printf(«La propiedad x es: %d \n»,punto1.x);}

la creación de propiedades de tipo cadena tiene una particularidad con respecto a la escritura de las propiedades de tipo numérico.

Para el trabajo con propiedad de ese tipo numérico, simplemente tenemos que aplicar un operador de igualdad para asignar valor a la propiedad de la estructura.

Sin embargo, si lo que queremos es asignar propiedades en formato de cadena alfa número Alfa numérica, tendremos que usar la siguiente función para conseguir el pase correcto de los parámetros:

main.c

#include <stdio.h>
int main(int argc, char *argv[]) {    struct RegistroAgenda{        char nombre[50];        char telefono[50];        char email[50];    };    }

Como podremos comprobar, simplemente utilizando una de las funciones de la librería de tratamiento de cadenas, podremos no aplicar una igualdad, pero si realizar una copia de la cadena dentro de el valor de la propiedad.

Si seguimos el siguiente ejemplo conjunto:

main.c
#include <stdio.h>#include <string.h>int main(int argc, char *argv[]) {    struct RegistroAgenda{        char nombre[50];        char telefono[50];        char email[50];    };    // Primer registro    struct RegistroAgenda registro1;    strcpy(registro1.nombre,»Jose Vicente»);    strcpy(registro1.telefono,»12345678″);    strcpy(registro1.email,»info@josevicentecarratala.com»);    // Segundo registro    struct RegistroAgenda registro2;    strcpy(registro2.nombre,»Juan»);    strcpy(registro2.telefono,»87654321″);    strcpy(registro2.email,»juan@josevicentecarratala.com»);    // Devolvemos:    printf(«El nombre del primer registro es: %s \n»,registro1.nombre);    printf(«El telefono del segundo registro es: %s \n»,registro2.telefono);}

Podremos comprobar cómo, a partir de una estructura, asignaremos tanto valores numéricos como valores alfa numéricos sin ningún problema dentro del mismo proyecto.

Estructuras dentro de matrices

agenda.c
#include <stdio.h>#include <string.h>int main(int argc, char *argv[]) {    struct RegistroAgenda{        char nombre[50];        char telefono[50];        char email[50];    };        // Primer registro    struct RegistroAgenda registros[1];    strcpy(registros[1].nombre,»Jose Vicente»);    strcpy(registros[1].telefono,»12345678″);    strcpy(registros[1].email,»info@josevicentecarratala.com»);            printf(«El registro es: %s»,registros[1].nombre);}

Ejercicio del curso

A continuación, aplicamos el contenido didáctico de esta unidad, al ejercicio práctico que estamos desarrollando en el curso

 queda patente como el uso de estructuras tiene claras ventajas con respecto, por ejemplo, si nos fijamos en la unidad anterior, al uso de matrices de múltiples dimensiones

 por ejemplo, en el caso de las matrices de múltiples dimensiones, es perfectamente entendible que cada uno de los registros tenga una entidad numérica, el registro número 1, el registro número 2, el registro número 3 de la agenda telefónica

 pero si nos fijamos en el ejercicio anterior, en la segunda dimensión, teníamos un carácter uno para el nombre, dos para el teléfono, y tres para el correo electrónico punto esto es perfectamente usable y funcional, pero sin embargo, finalmente somos nosotros quién le damos sentido a la segunda dimensión

 con las estructuras, en cambio, para con el ejemplo del curso, tenemos exactamente el mismo almacenaje de datos, pero lo hacemos de un modo mucho más entendible, tanto desde el almacenaje de los datos, como también desde la recuperación de los mismos, ya que no estamos llamando a un índice anónimo de una matriz, sino que estamos llamando a una propiedad de una forma mucho más clara y transparente

 dicho esto, la consecuencia no es necesariamente que las estructuras siempre sean mejores con respecto al uso de matrices multidimensionales, simplemente es una herramienta más que el lenguaje de programación pone a nuestra disposición 

agenda.c
/* Programa agendapor Jose Vicente Carratala */#include <stdio.h>#include <string.h>#define NOMBREPROGRAMA «Programa agenda»#define VERSION «1.0»#define AUTOR «Jose Vicente Carratala»
int main(int argc, char *argv[]) {        struct RegistroAgenda{        char nombre[50];        char telefono[50];        char email[50];    };    // Primer registro    struct RegistroAgenda agenda[100];    strcpy(agenda[1].nombre,»Jose Vicente»);    strcpy(agenda[1].telefono,»12345678″);    strcpy(agenda[1].email,»info@josevicentecarratala.com»);        // Segundo registro    strcpy(agenda[2].nombre,»Juan»);    strcpy(agenda[2].telefono,»53254″);    strcpy(agenda[2].email,»juan@josevicentecarratala.com»);    // Tercer registro    strcpy(agenda[3].nombre,»Jaime»);    strcpy(agenda[3].telefono,»64566″);    strcpy(agenda[3].email,»jaime@josevicentecarratala.com»);        // Mensaje de bienvenida printf(«%s v%s \n»,NOMBREPROGRAMA,VERSION); printf(«%s \n»,AUTOR); printf(«\t 1 – Listado de registros \n»); printf(«\t 2 – Introducir un registro \n»); printf(«\t 3 – Eliminar un registro \n»); printf(«\t 4 – Buscar un registro \n»); printf(«\t 5 – Actualizar un registro \n»); printf(«Tu opcion: «); char opcion = getchar(); printf(«La opción que has seleccionado es: %c \n»,opcion); switch(opcion){     case ‘1’:         printf(«Vamos a listar los registros \n»);         printf(«Registro: %s %s %s \n»,agenda[1].nombre,agenda[1].telefono,agenda[1].email);         printf(«Registro: %s %s %s \n»,agenda[2].nombre,agenda[2].telefono,agenda[2].email);         printf(«Registro: %s %s %s \n»,agenda[3].nombre,agenda[3].telefono,agenda[3].email);         break;        case ‘2’:         printf(«Vamos a introducir un registro»);         break;        case ‘3’:         printf(«Vamos a eliminar un registro»);         break;        case ‘4’:         printf(«Vamos a buscar un registro»);         break;     case ‘5’:         printf(«Vamos a actualizar un registro»);         break;        default:            printf(«La opción que has introducido no es válida»);            break; } return 0;}

Estructuras de bucle

Las estructuras de control del bucle nos permiten repetir la ejecución de una serie de instrucciones.

En ocasiones, es necesario una cierta parte del programa número determinado, o incluso indeterminado de veces.

De esta forma, cuando en un programa repetimos varias veces una pieza del código, debemos saber que existen varios tipos de estructuras que nos permiten automatizar este proceso.

Un ejemplo bastante típico y característico serían los días de un calendario mensual.

Supongamos que queremos representar los 30 días estándar de un mes, por lo que el código necesario tendría un aspecto aproximadamente como el siguiente.

Cuando en un programa vemos que se repite una porción del código, nuestra mente del programador debe advertirnos de que debería haber una forma a más sencilla de representar esa parte del código.

A continuación, vamos a ver de qué herramientas de control de bucle disponemos.

La estructura de control for.

La estructura de control sur, tiene la sintaxis que vemos en el ejemplo anterior, de la cual podemos destacar, que primero introducimos la palabra reservada favor, a continuación, dentro de los paréntesis, introducimos las tres condiciones, de inicio, de finalización, y de incremento, y por último, dentro de las llaves, introducimos el código que se va a repetir.

De esta forma, el ejemplo del calendario quedaría representado de la siguiente manera.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int diasDelMes = 30;    for(int i = 1;i<diasDelMes;i++){        printf(«Hoy es un día \n»);    }}

Como podemos comprobar, constituye una forma muy conveniente de repetir la ejecución.

Además, nos podremos fijar de que a lo largo de la utilización del buque favor, se define una variable, que recibe el nombre de variable y te Ladora.

Es por esta razón que la letra elegida para ocupar esta función suele ser la letra vocal y, aunque, como podemos comprobar, que esta función puede ser desarrollada por cualquier variable.

en el ejemplo amor mostrado, podremos comprobar como la variable empieza en el día número uno del mes, llega hasta el día 30 del mes, y cada vez que ejecutamos el bucle, es decir, cada vez que se repite el bucle, encontramos un nuevo día más añadido al bucle de información.

Además, la variable utilizada como integradora, se puede usar dentro de las llaves, dentro de el código que se utiliza en el programa.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int diasDelMes = 30;    for(int i = 1;i<=diasDelMes;i++){        printf(«Hoy es el dia %i del mes \n»,i);    }}

Podemos variar el código tanto como necesitemos, para realizar, por ejemplo, las siguientes variaciones.

El siguiente ejemplo, muestra los días únicamente impares del mes.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int diasDelMes = 30;    for(int i = 1;i<=diasDelMes;i+=2){        printf(«Hoy es el dia %i del mes \n»,i);    }}

El siguiente ejemplo, muestra los días únicamente Padres del mes.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int diasDelMes = 30;    for(int i = 2;i<=diasDelMes;i+=2){        printf(«Hoy es el dia %i del mes \n»,i);    }}

El siguiente ejemplo muestra los días pares empezando en el 10, y acabando en el 20.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int diasDelMes = 30;    for(int i = 10;i<=20;i+=2){        printf(«Hoy es el dia %i del mes \n»,i);    }}

Además, el Peter Ador no tiene porque ir desde un número inferior hasta un número superior.

En el siguiente ejemplo se muestra la enumeración de días del mes, desde el día 30, hasta el día uno.

la estructura de control Wilde

Si bien la estructura de control llamada favor resulta muy conveniente porque contiene, dentro de los paréntesis, tanto la condición de inicio, como la condición de finalización, como la condición de incremento o decremento, la estructura de control de Google de tipo while, tiene un formato parecido, en cuanto a que se invoca a la estructura, se pone entre paréntesis las condiciones, y se ejecuta el código a repetir entre las llaves, pero tiene la característica de que, dentro de los paréntesis, únicamente es posible poner la condición de finalización.

De esta forma, si por ejemplo escribimos el siguiente código, encontraremos que estaremos ejecutando un bucle infinito.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int dia = 1;    while(dia < 30){        printf(«Hoy es el dia %i del mes \n»,dia);    }}

Es decir, podremos comprobar que no existe una condición de finalización, y por tanto, el programa entrará en una situación de ejecución constante sin fin.

Esto no es en se negativo, sino que existen diversos casos en los que puede interesarnos ejecutar un programa sin una finalización concreta . nueve

De todas formas, en el caso más típico y característico, es decir, en el caso de un bucle del cual esperamos poder controlar tanto el inicio, como al final, como en el incremento, formularemos el bucle while como podemos ver en el ejemplo a continuación.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int dia = 1;    while(dia < 30){        printf(«Hoy es el dia %i del mes \n»,dia);        dia++;    }}

Cómo podremos ver, finalmente, al igual que en el bucle favor, existen la condición de inicio, deparada, y de incremento, con la diferencia de que en este ejemplo que se presenta, la condición de inicio está fuera del bucle, la condición de finalización está dentro de los paréntesis, y la condición de incremento se encuentra dentro del código del propio Google.

El bucle Do While

El bucle Duguay constituye una variación con respecto al bucle repetitivo guay que hemos visto con anterioridad.

El bucle Güell contiene una condición de finalización, en definitiva, una condición de ejecución, que hará que el bucle se ejecute mientras que esa condición sea cierta.

Si la condición no es cierta, el bucle no se ejecutará.

Si vemos por ejemplo el siguiente caso, podremos comprobar que, si la condición no es cierta, el bucle, de hecho, no se llega a ejecutar ni una sola vez.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int dia = 1;    while(dia < 30){        printf(«Hoy es el dia %i del mes \n»,dia);        dia++;    }}

Precisamente para estos casos existe el bucle de Uruguay.

Existen casos y situaciones, aunque honestamente no se dan todos los días, en los que es necesario que el contenido del bucle se ejecute al menos una vez, aunque su condición de validación no sea cierta.

Es por eso que este bucle, en ocasiones, recibe el nombre de » bucle de primero dispara y luego pregunta «.

En el ejemplo que presento a continuación, puede fácilmente visualizarse como, aunque el código no se debería ejecutar, ya que la condición de ejecución no es cierta, pero sin embargo, sí que se llega a ejecutar una vez.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int dia = 34;    do{        printf(«Hoy es el dia %i \n»,dia);    }while(dia <= 30);}

Como podemos comprobar, primero se ejecuta el código, y luego se valida la veracidad de la expresión evaluada.

El problema estriba en que si la condición es falsa, para cuando es evaluada, el código ya se ha ejecutado una vez.

Por supuesto, al validar, falsa, el código no se volverá a ejecutar, a menos que en un momento la condición sea cierta de nuevo.

Por último, es importante notar que el bucle Dubái es el único que es obligatorio finalizar con un punto y,, Arrizar a diferencia del resto de estructuras de control.

la estructura de control for each

cuando hemos guardado la información en una matriz, es muy común, en un momento dado, más adelante con respecto al momento del guardado, necesita recuperar la información contenida en esa matriz.

main.c

De esta forma, es perfectamente posible recordar el contenido de la matriz usando una estructura de control de tipo foro.

Esto puede hacerse, introduciendo manualmente la longitud de la matriz, o bien, usando la propiedad de longitud de la matriz.

Sin embargo, es mucho más conveniente usar una estructura de control de Google que sirve específicamente para poner recorrer matrices.

Esta estructura de control tiene la forma que se describe en ejemplo a continuación.

Antes de empezar a desarrollar el contenido

La estructura de control goto:

Ejercicio del curso:

En la versión anterior del ejercicio en la opción de listado de registros, teníamos una forma completamente ineficiente de obtener de vuelta los registros de la estructura que guarda la agenda

 si nos fijamos, en el desarrollo anterior del ejercicio, cada vez que realizábamos un listado, lo que conseguíamos era listar uno a uno, de forma repetitiva, los elementos de la agenda. esto, evidentemente, es terriblemente ineficiente. en el desarrollo de programas informáticos, siempre que vemos que una estructura se repite varias veces, nos vemos repetirla a mano, sino que deberíamos encontrar una forma automatizada de realizar esa repetición

 esto es exactamente lo que nos proporcionan las estructuras de control de bucle, la posibilidad de que el programa repita automáticamente por nosotros una tarea que, hasta el momento, habíamos tenido que repetir de manera completamente manual

 así que en esta aplicación de la unidad didáctica al ejercicios del curso, como podemos comprobar, se ha utilizado una estructura de control for para automatizar la devolución de registros en el listado en pantalla

 de esta forma, ahora no importaría en la teoría que el listado de registros tuviera uno, dos, tres, o 3000 componentes, porque simplemente tendríamos que indicar una nueva finalización a la estructura de control for 

agenda.c
/* Programa agendapor Jose Vicente Carratala */#include <stdio.h>#define NOMBREPROGRAMA «Programa agenda»#define VERSION «1.0»#define AUTOR «Jose Vicente Carratala»
int main(int argc, char *argv[]) { struct RegistroAgenda{        char nombre[50];        char telefono[50];        char email[50];    };    // Primer registro    struct RegistroAgenda agenda[100];    strcpy(agenda[1].nombre,»Jose Vicente»);    strcpy(agenda[1].telefono,»12345678″);    strcpy(agenda[1].email,»info@josevicentecarratala.com»);        // Segundo registro    strcpy(agenda[2].nombre,»Juan»);    strcpy(agenda[2].telefono,»53254″);    strcpy(agenda[2].email,»juan@josevicentecarratala.com»);    // Tercer registro    strcpy(agenda[3].nombre,»Jaime»);    strcpy(agenda[3].telefono,»64566″);    strcpy(agenda[3].email,»jaime@josevicentecarratala.com»);     // Mensaje de bienvenida printf(«%s v%s \n»,NOMBREPROGRAMA,VERSION); printf(«%s \n»,AUTOR); printf(«\t 1 – Listado de registros \n»); printf(«\t 2 – Introducir un registro \n»); printf(«\t 3 – Eliminar un registro \n»); printf(«\t 4 – Buscar un registro \n»); printf(«\t 5 – Actualizar un registro \n»); printf(«Tu opcion: «); char opcion = getchar(); printf(«La opción que has seleccionado es: %c \n»,opcion); switch(opcion){     case ‘1’:         for(int i = 1; i<=3;i++){             printf(«Registro: %s %s %s \n»,agenda[i].nombre,agenda[i].telefono,agenda[i].email);         }         break;        case ‘2’:         printf(«Vamos a introducir un registro»);         break;        case ‘3’:         printf(«Vamos a eliminar un registro»);         break;        case ‘4’:         printf(«Vamos a buscar un registro»);         break;     case ‘5’:         printf(«Vamos a actualizar un registro»);         break;        default:            printf(«La opción que has introducido no es válida»);            break; } return 0;}

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *