Estructuras en C
Contents
Estructuras en C#
Objetivos
Objetivo 1…
Objetivo 2…
1. Conceptualizacion#
Anteriormente vimos que los arrays esta una coleccion de datos de un mismo tipo agrupados bajo un mismo nombre. C, pese a no ser un lenguaje de programacion orientado a objetos maneja un tipo de dato compuesto conocido como estructura. En si, una estructura es lo mas cercano a la definición que conocemos de clase en los lenguajes de programación, la unica diferencia respecto a las clases (sin hablar en el sentido estricto de la palabra), es que una estructura es como una clase con miembros pero sin metodos.
La mayor ventaja de estas, es que permiten la creacion de nuevos tipos de datos, liberando al programador de tener que restringirse al uso de los tipos de datos tipicos ofrecidos por el lenguaje como tal (int
, double
, float
, etc.) lo cual hace posible organizar datos complicados, particularmente en largos programas.
Una estructura, es una coleccion de variables agrupadas bajo un mismo nombre. Las variables dentro de una estructura se denominan como miembros y pueden ser accedidas de manera individual en caso de ser necesario.
En resumen:
Una estructura puede contener cualquier número de miembros.
Los miembros de la estructura pueden ser de cualquier tipo.
Mediante estructuras es posible tratar como grupo cualquier conjunto de variables relacionadas.
Las estructuras facilitan la organización de datos complicados.
2. Trabajando con estructuras#
2.1. Declaración de una estructura#
La declaración de una estructura tiene la siguiente sintaxis:
struct nombre-estructura {
tipo_1 miembro_1;
tipo_2 miembro_2;
tipo_3 miembro_3;
...
tipo_N miembro_N;
};
Ejemplos#
Definir una estructura asociada a un punto en el plano cartesiano.
Fig. 47 Punto.#
La definición de la estructura se muestra a continuación:
struct Punto2D { float x; float y; };
Definir una estructura asociada a una fecha.
Fig. 48 Fecha.#
La definición de la estructura se muestra a continuación:
struct Date { unsigned year; unsigned month; unsigned day; };
Definir una estructura asociada a una hora.
Fig. 49 Tiempo.#
La definición de la estructura se muestra a continuación:
struct Tiempo { unsigned int hr; unsigned int min; unsigned int sec; };
Definir una estructura asociada a un album musical.
Fig. 50 Album.#
La definición de la estructura se muestra a continuación:
struct Album { char titulo[64]; char artista[32]; char genero[32]; char *canciones; };
Definir una estructura asociada a una canción.
Fig. 51 Cancion.#
La definición de la estructura se muestra a continuación:
struct Cancion { char titulo[64]; char artista[32]; char compositor[32]; short duracion; struct fecha f_publicacion; };
Definir una estructura asociada a un libro
Fig. 52 Libro.#
La definición de la estructura se muestra a continuación:
struct Book { int book_id; char title[50]; char author[40]; int pages; float price; };
2.2. Definición de variables tipo struct#
Las variables de estructuras se pueden definir de dos formas:
Listándolas inmediatamente después de la llave de cierre de la llave de cierre de la declaración de la estructura, algo como esto tal y como se muestra en el siguiente codigo en el cual se declaran dos variables (
book1
ybook2
) tipostruct Book
(simulación):struct Book { int book_id; char title[30]; char author[20]; int pages; float price; } book1, book2; int main() { return 0; }
Listando el tipo de la estructura seguida por las variables correspondientes en cualquier lugar del programa antes de utilizarlas, así, asumiendo que la estructura está declarada. El siguiente codigo muestra esto, notese que la declaración de las variables (
book1
ybook2
) es similar a la declaración para datos no estructurados (int
,double
, etc), aquí, la unica difetencia es que estas serán para el caso datos tipostruct Book
(simulación):struct Book { int book_id; char title[30]; char author[20]; int pages; float price; }; struct Book book1, book2; int main() { return 0; }
La salida sea para uno u otro caso se muestra a continuación:

Fig. 53 Estructuras tipo libro.#
Note
Los conceptos aplicados para los tipos de datos simples aplican para estructuras tambien; de modo que, es posible crear variables normales, arrays, matrices y apuntadores de estructuras entre otros.
Ejemplos#
Empleando la estructura tipo
Punto2D
crear las siguientes variables:Dos variables llamadas
p1
yp2
(local).Un array de
3
elementos llamadovP
(local).Un apuntador llamado
*ptrP
que apunte ap[1]
(global).Una matrix de
2x2
llamadamP
(global).
La solución se muestra a continuación (simulación):
#include <stdio.h> struct Punto2D { float x; float y; }; // Datos tipo Punto2D globales struct Punto2D vP[3]; struct Punto2D mP[2][2]; int main() { // Datos tipo Punto2D locales struct Punto2D p1, p2; struct Punto2D *ptrP = &vP[1]; return 0; }
A continuación, se muestra el resultado en memoria de la ejecución del código anterior:

Fig. 54 Estructuras tipo punto.#
2.3. Inicializacion de variables tipo struct#
Al igual que para el caso de las variables simples, las estructuras pueden tener valores iniciales una vez se declaran. Como estas con estructuras compuestas, lo que se hace para inicializarlas, es inicializar miembro por miembro. A continuacion se describen las dos formas de llevar a cabo esto.
2.3.1. Usando una lista de inicialización#
Esta es similar a la empleada para los arrays, y lo que se hace es inicializar cada miembro de la estructura con el correspondiente valor inicial asociado. Cada valor inicial es separado por coma (,
). Veamos.
Ejemplo: Iniciar la estructura Cancion con la siguiente informacion asociada a una cancion de Billie Holiday. A continuacion se muestra el codigo:
#include <stdio.h>
// Declaracion de la estructura
struct Cancion {
char titulo[20];
char artista[32];
char compositor[32];
short duracion;
char URL[32];
};
// Funcion main
int main() {
// Inicializacion de la variable (sadSong) tipo struct Cancion
struct Cancion sadSong = {
"Strange fruit",
"Billie Holiday",
"Abel Meeropol",
164,
"http://bit.ly/1mU1gBT"
};
return 0;
}
La simulación del código anterior, se muestra a continuación:
A continuacion se muestra como quedan las estructura tipo Cancion (sadSong
) al ejecutarse el codigo:

Fig. 55 Estructuras tipo cancion (variable sadSong
).#
2.3.2. Inicialización específica de cada uno de los miembros#
Básicamente, consiste en la designación de cada uno de los miembros siguiendo la siguiente forma.
.miembro = valor; // designador
Ejemplo: Realizar la misma inicilizacion del caso anterior, pero en este caso emplear la inicializacion especifica de miembros:
#include <stdio.h>
// Declaracion de la estructura
struct Cancion {
char titulo[20];
char artista[32];
char compositor[32];
short duracion;
char URL[32];
};
// Funcion main
int main() {
// Inicializacion de la variable (sadSong) tipo struct Cancion
struct Cancion sadSong = {
.titulo = "Strange fruit",
.artista = "Billie Holiday",
.compositor = "Abel Meeropol",
.duracion = 164,
.URL = "http://bit.ly/1mU1gBT"
};
return 0;
}
La simulación del código anterior, se puede realizar a continuación:
Note, que el resultado es el mismo que el mostrado para el ejemplo de inicializacón anteriormente realizado.
2.3.3. Caso en el que no se inicializan todos lo miembros#
Ya sea que se emplee una u otra de las formas anteriormente mencionadas, es posible inicializar parcialmente una variable tipo estructura, para ello, basta con no pasar todos los elementos que puede contener la lista de inicialización. A continuación se muestra un ejemplo:
Ejemplo: Crear dos variables tipo struct Cancion
, estas variables no tendran todos los parametros inicialidos:
#include <stdio.h>
// Declaracion de la estructura
struct Cancion {
char titulo[20];
char artista[32];
char compositor[32];
short duracion;
char URL[32];
};
// Variables globales tipo struct Cancion
struct Cancion song1 = {"Mi cerebro esta boca abajo"};
struct Cancion song2 = {
.titulo = "Noches de Hungria",
.compositor = "Julio Jaramillo",
.duracion = 127
};
// Funcion main
int main() {
return 0;
}
La simulación del código se muestra a continuación:
En la siguiente figura se muestra el resultado del codigo anterior, notese lo que sucede como quedan los miembros que no fueron inicializados.

Fig. 56 Variables tipo cancion sin inicializar todos sus miembros.#
2.4. Empleo de la palabra clave typedef
para crear alias#
La palabra reservada typedef
permite a un programador crear un sinónimo de un tipo de dato definido por el usuario o de un tipo ya existente. La sintaxis para usar esta palabra clave es la siguiente:
tipo_dato typedef nombre_alias;
Ejemplos#
Dada la siguiente declaracion de variables:
double alto, ancho;
Teniendo en cuenta que
alto
yancho
son medidas de longitud, podemos crear un alias para una variable tipodouble
llamadolongitud
y el efecto será el mismo que el del caso anterior, el código para el caso sera el siguiente (simulación):typedef double longitud; longitud alto, ancho;
El resultado se muestra a continuacion:
Fig. 57 Uso de
typedef
para la creacion de alias.#La mayor ventaja del uso del
typedef
se ve con las estructuras. A continuación se muestra el resultado:Sin usar
typedef
: Cree dos variables tipoPunto2D
llamadasP1
yP2
con valores(2,3)
y(-1,6)
. No empleetypedef
:#include <stdio.h> // Declaracion de las estructura struct Punto2D { float x; float y; }; // Funcion main int main() { // Declaracion de variables struct Punto2D P1 = { 2, 3 }; struct Punto2D P2 = { .x = -1, .y = 6 }; return 0; }
La simulación se muestra a continuación:
La salida del programa anterior se muestra a continuación:
Fig. 58 Uso variables tipo
struct Punto2D
sin usartypedef
.#Usando
typedef
: Realice lo mismo que en el punto anterior, pero esta vez haga uso de la palabra clavetypedef
para crear un alias parastruct Punto2d
llamadoPunto2D
:#include <stdio.h> // Declaracion de las estructura struct Punto2D { float x; float y; }; // Creacion del alias typedef struct Punto2D Punto2D; // Funcion main int main() { // Declaracion de variables Punto2D P1 = { 2, 3 }; Punto2D P2 = { .x = -1, .y = 6 }; return 0; }
La simulación para este codigo se muestra a continuación:
La salida del programa anterior es:
Fig. 59 Uso variables tipo
struct Punto2D
usandotypedef
.#
2.5. Manipulando estructuras#
Por manipulacion de la estructuras (dentro de este contexto) nos queremos referir al acceso a los miembros de esta, tal y como sucede cuando se accede a los miembros de un objeto en el caso de la POO. Para el caso de las estructuras en particulas, existen dos formas de acceder:
Empleando el operador punto (
.
)Emplenando el operador flecha (
->
)
2.5.1. Usando el operador punto (.
)#
Usado cuando se definen variables del tipo de la estructura. Básicamente tiene la siguiente sintaxis:
<nombre_variable_estructura>.<nombre_miembro> = datos;
Ejemplos
Crear dos puntos
P1
yP2
. Luego de su declaracion inicialicelos con los siguientes valores:(1,1)
y(10,3)
.// Declaracion de las estructura struct Punto2D { float x; float y; }; // Creacion del alias typedef struct Punto2D Punto2D; // Funcion main int main() { // Declaracion de los puntos Punto2D P1, P2; // Manipulacion (acceso a los miembros) P1.x = 1; P1.y = 1; P2.x = 10, P2.y = 3; return 0; }
La simulación del programa se puede realizar a continuación:
Observe como quedan los campos de las variables
P1
yP2
despues de la ejecucion del codigo anterior.Fig. 60 Manipulando variables tipo
Punto2D
.#Crear una estructura asociada a un
libro
y posteriormente declarar dos libros (como un array) con la siguiente informacion.Fig. 61 Libros.#
La información sobre los libros se resume en la siguiente tabla:
#
BookID
Title
Author
Pages
Price
1
1211
C Primer Plus
Stephen Prata
984
585.00
2
1212
The ANSI C Programming
Dennis Ritchie
214
125.00
El código solucion se muestra a continuación, note que la forma como se accede a la variable tipo
Book
en el correspondiente arreglo esbook[i]v
para el caso, por ende la forma de acceder a cada uno de los miembros del array en cuestion serábook[i].miembro
:#include <stdio.h> #include <string.h> // Declaracion de las estructura struct Book { int book_id; char title[24]; char author[20]; int pages; float price; }; // Creacion del alias typedef struct Book Book; // Declaracion del array de libros Book books[2]; int main() { // Manipulacion (acceso a los miembros) // Libro # 1 books[0].book_id = 1211; //OJO: books[0].title = "C Primer Plus" es un ERROR strcpy(books[0].title,"C Primer Plus"); strcpy(books[0].author,"Stephen Prata"); books[0].pages = 984; books[0].price = 585.00; // Libro #2 books[1].book_id = 1212; strcpy(books[1].title,"The ANSI C Programming"); strcpy(books[1].author,"Dennis Ritchie"); books[1].pages = 214; books[1].price = 125.00; return 0; }
El código anterior puede ser simulado a continuación:
A continuacion se muestra el resultado en memoria:
Fig. 62 Resultado en memoria para variables asociadas a los libros.#
2.5.2. Usando el operador flecha (->
)#
El operador flecha (->
) es empleado cuando se hace uso de punteros a estructuras, su sintaxis es de la siguiente forma:
<puntero_estructura>-><nombre_miembro> = datos;
Ejemplos
Suponga que se tiene una estructura asociada a las fechas. Tambien, suponga que tiene una variable llamada
diaDestino
cuyo valor asociado es el 5 de noviembre de 1955 (primer viaje en el tiempo de Marty MacFly). Luego cree una variable tipo apuntador a esta este tipo de estructura y modifique a traves de este el valor dediaDestino
al 21 de octubre de 2015 (fecha a la cual viaja Marty MacFly al futuro). Imprima los valores en cada caso.El código solucion se muestra a continuacion:
#include <stdio.h> struct Date { unsigned year; unsigned month; unsigned day; }; typedef struct Date Fecha; int main() { /* Declaracion de variables */ Fecha diaDestino; // Varible tipo fecha Fecha *diaPtr; // Variable tipo apuntador a fecha diaPtr = &diaDestino; // Inicializacion del apuntador /* Viaje al pasado */ // Fijando por medio del operador punto (.) los valores // de dia destino al 5 de noviembre de 1955 diaDestino.year = 1955; diaDestino.month = 11; diaDestino.day = 5; printf("Destination time: %d/%d/%d\n", diaDestino.day, diaDestino.month, diaDestino.year); /*Viaje al futuro */ // Fijando por medio del operador flecha (->) los valores // de dia destino al 21 de octubre de 2015 diaPtr->year = 2015; diaPtr->month = 10; diaPtr->day = 21; printf("Destination time: %d/%d/%d\n", diaPtr->year, diaPtr->month, diaPtr->year); return 0; }
La simulación del código anterior se muestra a continuación:
Hay que aclarar que el uso del operador punto (
.
) tambien puede ser empleado con variables tipo apuntador, para ello se sigue la siguiente forma:Implemente el mismo ejemplo anterior, pero esta vez use el operador punto (
.
) para modificar los miembros de la variable tipo Date a traves del apuntador.El codigo solución se muestra a continuacion:
#include <stdio.h> struct Date { unsigned year; unsigned month; unsigned day; }; typedef struct Date Fecha; int main() { /* Declaracion de variables */ Fecha diaDestino; // Varible tipo fecha Fecha *diaPtr; // Variable tipo apuntador a fecha diaPtr = &diaDestino; // Inicializacion del apuntador /* Viaje al pasado */ // Fijando por medio del operador punto (.) los valores // de dia destino al 5 de noviembre de 1955 diaDestino.year = 1955; diaDestino.month = 11; diaDestino.day = 5; printf("Destination time: %d/%d/%d\n", diaDestino.day, diaDestino.month, diaDestino.year); /*Viaje al futuro */ // Fijando por medio del operador flecha (->) los valores // de dia destino al 21 de octubre de 2015 (*diaPtr).year = 2015; (*diaPtr).month = 10; (*diaPtr).day = 21; printf("Destination time: %d/%d/%d\n", diaPtr->year, diaPtr->month, diaPtr->year); return 0; }
La simulación se muestra a continuación:
Si realiza la simulación, podrá notar que la salida es exactamente la misma que la del ejemplo anterior.
2.5.3. Estructuras anidadas#
Una estructura puede tener a su vez otra estructura como miembro. A continuacion se muestra un ejemplo para ello.
Ejemplos
Suponga que se tiene la siguiente tabla asociada a personajes historicos.
Fig. 63 Personajes.#
La siguiente tabla muestra información relacionada con los personajes mostrados anteriormente:
Nombre
Nacimiento
Muerte
Profesion
Ernest Hemingway
21/07/1899
02/07/1961
Escritor
Albert Einstein
14/03/1879
18/04/1955
Fisico
Note que para el problema podemos crear dos estructuras, una asociada al personaje y otra asociada a las fechas. Asi mismo, podemos ver que las fechas pueden ser tratadas como estructuras del personaje. A continuacion vamos a mostrar el código que define ambas estructuras:
struct date { unsigned year; unsigned month; unsigned day; }; typedef struct date fecha; struct personajeHistorico { char nombre[21]; fecha nacimiento; fecha muerte; char profesion[21]; }; typedef struct personajeHistorico personaje; int main() { personaje per1 = { .nombre = "Ernest Hemingway", .nacimiento = { .year = 21, .month = 07, .day = 1899, }, .muerte = { 02, 07, 1961 }, .profesion = "Escritor" }; personaje per2, *ptr; fecha d = {14, 03, 1879}; ptr = &per2; strcpy(per2.nombre,"Albert Einstein"); strcpy(ptr->profesion,"Fisico"); (*ptr).nacimiento = d; per2.muerte.year = 1955; per2.muerte.month = 4; per2.muerte.day = 18; return 0; }
La simulación del código anterior se muestra a continuación:
Notese que en el ejemplo anterior, se combinan varias de las cosas que hemos discutido previamente. El resultado en memoria se muestra a continuacion:
Fig. 64 Resultado en memoria cuando existen estructuras anidadas.#
2.6. Estructuras y funciones#
Los conceptos vistos hasta el momento sobre funciones tambien aplican a las estructuras ya que las estructuras pueden ser usadas como parametros y valores de retorno por citar unos cuantos casos. La unica cosa adicional, respecto a las funciones que trabajan con variables normales, es que las funciones con estructuras hacen uso de los operadores de acceso para la manipulacion y el procesamiento de los datos de acuerdo a lo que se desea que haga la funcion. Como en el caso tradicional, las funciones en las que se emplean estructuras pueden ser pasadas por valor y por referencia. A continuacion se describe cada caso:
2.6.1. Paso de estructuras por valor#
En este caso la estructura pasada como argumento a la funcion es copiada al parametro de la funcion, de modo que el procesamiento se hace sobre la copia y no sobre la estructura pasada como argumento.
Ejemplos
Definir una estructura que este asociada a un numero completo. Luego haga una funcion que imprima el numero complejo en cuestion en la forma \(parteReal + parteImaginaria*i\). Luego probar el programa para imprimir los numeros: \(2\), \(-3i\), \(-2.3 + 10.5i\), \(1.23 - 3.67i\)
El codigo solucion se muestra a continuación:
#include <stdio.h> /** Declaracion de estructuras */ typedef struct complejo { float re; float im; } complejo; /** Declaracion de funciones */ void imprimirComplejo(complejo); // void imprimirComplejo(complejo num) /** Funcion main */ int main() { /* Creando los numeros */ complejo n1 = {2, 0}; // 2 complejo n2 = {.re = 0, .im = -3}; // -3*i complejo n3, n4; n3.re = -2.3; // -2.3 + 10.5*i n3.im = 10.5; n4.re = 1.23; // 1.23 - 3.67*i n4.im = -3.67; /* Llamando las funciones para imprimir */ imprimirComplejo(n1); printf("\n"); imprimirComplejo(n2); printf("\n"); imprimirComplejo(n3); printf("\n"); imprimirComplejo(n4); printf("\n"); return 0; } /** Definicion de funciones */ void imprimirComplejo(complejo num) { if (num.im == 0) { // Real puro printf("%.2f",num.re); } else if (num.re == 0) { // Imaginario puro printf("%.2f*i",num.im); } else if (num.im < 0) { // Complejo con parte imaginaria negativa printf("%.2f - %.2f*i",num.re,(-1)*num.im); } else { // Complejo con parte imaginaria positiva printf("%.2f + %.2f*i",num.re,num.im); } }
A continuación puede realizar la simulación del código anterior:
Notese que en el anterior codigo se empleo
typedef
al declarar la estructura para definir de una vez el alias.En la anterior funcion se un numero complejo como parametro, sin embargo tambien es posible retornar otras estructuras variables de retorno. Para ello en el siguiente ejemplo:
Hacer una funcion que sume dos numeros complejos y retorne el resultado de realizar la suma como otro complejo.
Hacer un test sumando los numeros: \(2 - 11i\) y \(8 + 9i\)
A continuación se muestra el código solución:
#include <stdio.h> /** Declaracion de estructuras */ typedef struct complejo { float re; float im; } complejo; /** Declaracion de las funciones */ void imprimirComplejo(complejo); complejo sumarComplejos(complejo, complejo); void test(void); // Funcion para testing /** Funcion main */ int main() { /* Probando todo mediante la funcion test */ test(); return 0; } /** Definicion de funciones */ void imprimirComplejo(complejo num) { if (num.im == 0) { // Real puro printf("%.2f",num.re); } else if (num.re == 0) { // Imaginario puro printf("%.2f*i",num.im); } else if (num.im < 0) { // Complejo con parte imaginaria negativa printf("%.2f - %.2f*i",num.re,(-1)*num.im); } else { // Complejo con parte imaginaria positiva printf("%.2f + %.2f*i",num.re,num.im); } } complejo sumarComplejos(complejo c1, complejo c2) { complejo solucion; solucion.re = c1.re + c2.re; solucion.im = c1.im + c2.im; return solucion; } void test(void) { complejo c1 = {2, -11}, c2 = {8, 9}; complejo c3 = sumarComplejos(c1,c2); imprimirComplejo(c1); printf("\n"); imprimirComplejo(c2); printf(" + \n---------\n"); imprimirComplejo(c3); }
La simulación del código anterior se muestra a continuación:
Mejorar el codigo anterior agregando dos funciones que hagan lo siguiente:
Calcule la magnitud de un numero complejo.
Calcule el angulo de un numero complejo.
El codigo anterior se mejoro quedando de la siguiente manera:
#include <stdio.h> #include <math.h> /** Macros */ #define PI 3.14 // Converts degrees to radians. #define degreesToRadians(angleDegrees) (angleDegrees * PI / 180.0) // Converts radians to degrees. #define radiansToDegrees(angleRadians) (angleRadians * 180.0 / PI) /** Declaracion de estructuras */ typedef struct complejo { float re; float im; } complejo; /** Declaracion de funciones */ void imprimirComplejo(complejo); // void imprimirComplejo(complejo num) double calcularMagnitud(complejo); complejo sumarComplejos(complejo c1, complejo c2); void test1(void); void test2(void); /** Funcion main */ int main() { /* Creando los numeros */ // test1(); ---> Comentado por que ya se probo que dio bien test2(); return 0; } /** Definicion de funciones */ void imprimirComplejo(complejo num) { if (num.im == 0) { // Real puro printf("%.2f",num.re); } else if (num.re == 0) { // Imaginario puro printf("%.2f*i",num.im); } else if (num.im < 0) { // Complejo con parte imaginaria negativa printf("%.2f - %.2f*i",num.re,(-1)*num.im); } else { // Complejo con parte imaginaria positiva printf("%.2f + %.2f*i",num.re,num.im); } } double calcularMagnitud(complejo num) { return sqrt(pow(num.re,2) + pow(num.im,2)); } double obtenerAngulo(complejo num) { if (num.re >= 0 & num.im >= 0) { // Cuadrante I return radiansToDegrees(atan2(num.im,num.re)); } else if(num.re < 0 & num.im >= 0) { // Cuadrante II return 180 - radiansToDegrees(atan2(-num.im,num.re)); } else if(num.re < 0 & num.im < 0) { // Cuadrante III return 180 + radiansToDegrees(atan2(-num.im,-num.re)); } else { // Cuadrante IV return 360 - radiansToDegrees(atan2(-num.im,num.re)); } } complejo sumarComplejos(complejo c1, complejo c2) { complejo solucion; solucion.re = c1.re + c2.re; solucion.im = c1.im + c2.im; return solucion; } void test1(void) { complejo c1 = {2, -11}, c2 = {8, 9}; complejo c3 = sumarComplejos(c1,c2); imprimirComplejo(c1); printf("\n"); imprimirComplejo(c2); printf(" + \n-------------------\n"); imprimirComplejo(c3); } void test2(void) { complejo c1 = {sqrt(3),1}; complejo c2 = {-1,1}; complejo c3 = {-sqrt(3),-1}; complejo c4 = {1,-1}; printf("mag(c1) = %.1lf, ang(c1) = %.1lf\n",calcularMagnitud(c1),obtenerAngulo(c1)); printf("mag(c2) = %.1lf, ang(c2) = %.1lf\n",calcularMagnitud(c2),obtenerAngulo(c2)); printf("mag(c3) = %.1lf, ang(c3) = %.1lf\n",calcularMagnitud(c3),obtenerAngulo(c3)); printf("mag(c4) = %.1lf, ang(c4) = %.1lf\n",calcularMagnitud(c4),obtenerAngulo(c4)); }
La salida en pantalla del programa anterior es:
mag(c1) = 2.0, ang(c1) = 30.0 mag(c2) = 1.4, ang(c2) = 315.1 mag(c3) = 2.0, ang(c3) = 210.0 mag(c4) = 1.4, ang(c4) = 315.0
2.6.2. Paso de estructuras por referencia#
En este caso, los parametros pasados a la funcion seran apuntadores a la estructura a pasar. El comportamiento es como el que se da en el caso de las funciones con datos tradicionales.
Ejemplos
Tome la estructura asociada a los libros y realice una funcion que permita imprimir en pantalla la informacion asociada a un libro. El llamado para la funcion sera por referencia. A continuación se muestra el código solución:
#include <stdio.h> // Declaracion de las estructura struct Book { int book_id; char title[24]; char author[20]; int pages; float price; }; /** Declaracion de funciones */ void printBookInfo(struct Book *lptr); // Declaracion del array de libros // Notese que no se usaron alias struct Book books[2]; /** Funcion principal */ int main() { // Manipulacion (acceso a los miembros) // Libro # 1 books[0].book_id = 1211; //OJO: books[0].title = "C Primer Plus" es un ERROR strcpy(books[0].title,"C Primer Plus"); strcpy(books[0].author,"Stephen Prata"); books[0].pages = 984; books[0].price = 585.00; // Libro #2 books[1].book_id = 1212; strcpy(books[1].title,"The ANSI C Programming"); strcpy(books[1].author,"Dennis Ritchie"); books[1].pages = 214; books[1].price = 125.00; // Imprimiendo la informacion de los libros for(int i = 0; i < 2; i++) { printBookInfo(&books[i]); printf("\n"); } return 0; } /** Definicion de funciones */ void printBookInfo(struct Book *lptr) { printf("Book name: %s\n", lptr->title); printf("Author: %s\n", lptr->author); printf("Pages: %d\n", lptr->pages); }
El código anterior puede ser simulado a continuación:
Finalmente, la salida en pantalla se muestra a continuacion:
Book name: C Primer Plus Author: Stephen Prata Pages: 984 Book name: The ANSI C Programming Author: Dennis Ritchie Pages: 214
Hacer un programa que defina un vector tridimensional como una estructura. El programa tambien debera implementar las siguientes funciones para la manipulacion de vectores:
Imprimir vector.
Calcular suma.
Calcular resta.
Calcular producto escalar.
Una vez hecho lo anterior probar el programa con los vectores
[1,3,0]
y[2,5,-4]
.El codigo solución se muestra a continuacion:
#include <stdio.h> /** Declaracion de estructuras */ typedef struct vector3D { float x; float y; float z; } vector3D; /** Declaracion de las funciones */ void imprimirVector3D(vector3D *vPrt); vector3D sumarVector3D(vector3D *v1P, vector3D *v2P); vector3D restarVector3D(vector3D *v1P, vector3D *v2P); double pEscalar(vector3D *v1P, vector3D *v2P); void test(void); // Funcion para testing /** Funcion main */ int main() { /* Probando todo mediante la funcion test */ test(); return 0; } /** Definicion de funciones */ void imprimirVector3D(vector3D *vPtr) { printf("[%.1f,%.1f,%.1f]",(*vPtr).x, (*vPtr).y, (*vPtr).z); } vector3D sumarVector3D(vector3D *v1P, vector3D *v2P) { vector3D r; r.x = v1P->x + v2P->x; r.y = v1P->y + v2P->y; r.z = v1P->z + v2P->z; return r; } vector3D restarVector3D(vector3D *v1P, vector3D *v2P) { vector3D r; r.x = v1P->x - v2P->x; r.y = v1P->y - v2P->y; r.z = v1P->z - v2P->z; return r; } double pEscalar(vector3D *v1P, vector3D *v2P) { return(v1P->x*v2P->x + v1P->y*v2P->y + v1P->z*v2P->z); } void test(void) { vector3D v1 = {1,3,0}, v2 = {2,5,-4}, vSum, vRes; double p_esc; vSum = sumarVector3D(&v1,&v2); vRes = restarVector3D(&v1,&v2); p_esc = pEscalar(&v1,&v2); printf("Suma -> \n"); imprimirVector3D(&v1); printf(" + "); imprimirVector3D(&v2); printf(" = "); imprimirVector3D(&vSum); printf("\n\n"); printf("Resta -> \n"); imprimirVector3D(&v1); printf(" - "); imprimirVector3D(&v2); printf(" = "); imprimirVector3D(&vRes); printf("\n\n"); printf("Producto escalar -> \n"); imprimirVector3D(&v1); printf(" * "); imprimirVector3D(&v2); printf(" = %.1f\n",p_esc); }
La simulación del programa se muestra a continuación:
La salida del programa anterior se muestra a continuacion:
Suma -> [1.0,3.0,0.0] + [2.0,5.0,-4.0] = [3.0,8.0,-4.0] Resta -> [1.0,3.0,0.0] - [2.0,5.0,-4.0] = [-1.0,-2.0,4.0] Producto escalar -> [1.0,3.0,0.0] * [2.0,5.0,-4.0] = 17.0
Emplando llamados por referencia es posible pasar a funciones arreglos y matrices tal como se analizo en algun momento. Por ejemplo supongase que un caminante esta registrando las coordenadas (x,y) de diferentes puntos en los cuales realiza su caminata. Supongase, que el sistema de registro de datos registra 5 coordenadas. Teniendo en cuenta la siguiente estructura para las coordenadas:
typedef struct coordenadas2D { float x; float y; } coord2D;
Implementar las siguientes funciones:
Una funcion para desplegar una coordenada, esta seguira el siguiente prototipo:
void printCoord2D(coord2D *c);
Una funcion para desplegar el contenido de un vector de coordenadas:
void printCoord2DVector(coord2D *v, int tam);
Una funcion que calcule la distancia entre dos coordenadas:
double calcularDistancia(coord2D *pStart, coord2D *pEnd);
Obtener la distancia total recorrida (suma de la distancia de todos lo puntos):
double calcularDistanciaTotal(coord2D *vecPuntos, int N);
Obtener la distancia del tramo mayor y la del tramo menor.
void obtenerDistanciasExtremas(coord2D *vecPuntos, int N, double *disMin, double *disMax);
Probar las funciones anteriores con una funcion llamada
caso_de_uso
para la cual se definen las siguientes coordenadas:P1(0,0)
,P2(3,2)
,P3(-4,5)
,P4(-6,-2)
yP5(-6,-3)
.
Solucion: En el codigo mostrado abajo se definen los puntos anteriormente mostrados y se verifican que los resultados del programa sean los arrojados anteriormente de manera manual. Si todo esta bien se tendrán resultados simulares a los siguiente:
Distancia entre los puntos sera:
d(P1,P2) = 3.61
d(P2,P3) = 7.62
d(P3,P4) = 7.28
d(P4,P5) = 1
Salidas a desplegar:
d_total = 19.5
d_min = 1
d_max = 7.62
A continuación se muestra el código:
#include <stdio.h> #include <math.h> /** Declaracion de estructuras */ typedef struct coordenadas2D { float x; float y; } coord2D; /** Declaracion de las funciones */ void printCoord2D(coord2D *c); void printCoord2DVector(coord2D *v, int tam); double calcularDistancia(coord2D *pStart, coord2D *pEnd); double calcularDistanciaTotal(coord2D *vecPuntos, int N); void obtenerDistanciasExtremas(coord2D *vecPuntos, int N, double *disMin, double *disMax); void caso_de_uso(void); /** Funcion main */ int main() { caso_de_uso(); return 0; } /** Definicion de las funciones */ void printCoord2D(coord2D *c) { printf("(%.2f,%.2f)",(*c).x,(*c).y); } void printCoord2DVector(coord2D *v, int tam) { for(int i = 0; i < tam; i++) { printCoord2D(v++); printf("\n"); } } double calcularDistancia(coord2D *pStart, coord2D *pEnd) { double dist; double dx = pEnd->x - pStart->x; double dy = pEnd->y - pStart->y; dist = sqrt(pow(dx,2) + pow(dy,2)); return dist; } double calcularDistanciaTotal(coord2D *vecPuntos, int N) { // Code coord2D pIni, pFin; double d_total = 0; pIni = *vecPuntos; // *vecPuntos = vecPuntos[0]; for(int i = 1; i < N; i++) { pFin = *(vecPuntos + i); // *(vecPuntos + i) = vecPuntos[i]; // printf("%.2lf\n",calcularDistancia(&pIni, &pFin)); d_total += calcularDistancia(&pIni, &pFin); pIni = pFin; } return d_total; } void obtenerDistanciasExtremas(coord2D *vecPuntos, int N, double *disMin, double *disMax) { // Code coord2D *pIni, *pFin; pIni = &vecPuntos[0]; pFin = &vecPuntos[1]; double d = calcularDistancia(pIni, pFin); double d_min = d, d_max = d; calcularDistancia(pIni,pFin); pIni = vecPuntos; for(int i = 2; i < N; i++) { pIni = pFin; pFin = vecPuntos + i; // vecPuntos + i = &vecPuntos[i]; d = calcularDistancia(pIni, pFin); if(d <= d_min) { d_min = d; } else if(d >= d_max) { d_max = d; } } *disMin = d_min; *disMax = d_max; } void caso_de_uso(void) { printf("Puntos registrados\n"); double m, M; coord2D coords[5] = { {0,0}, {3,2}, {-4,5}, {-6,-2}, {-6,-3} }; printCoord2DVector(coords, 5); printf("\n"); printf("-> Distancia total: %.2lf\n",calcularDistanciaTotal(coords,5)); obtenerDistanciasExtremas(coords, 5, &m, &M); printf("-> Distancia minima: %.2lf\n",m); printf("-> Distancia maxima: %.2lf\n",M); }
Para el cual la salida en pantalla del programa anterior es la siguiente:
Puntos registrados
(0.00,0.00)
(3.00,2.00)
(-4.00,5.00)
(-6.00,-2.00)
(-6.00,-3.00)
-> Distancia total: 19.50
-> Distancia minima: 1.00
-> Distancia maxima: 7.62
3. Enlaces#
https://computer.howstuffworks.com
https://www.studytonight.com/c/structures-in-c.php
https://www.tutorialspoint.com/cprogramming/c_structures.htm
https://www.programiz.com/c-programming/c-structures
https://www.geeksforgeeks.org/structures-c/
https://github.com/fordea/c-programming-a-modern-approach