guía de práctica 2

23
GUÍA DE PRÁCTICA I.Datos Generales Elaboró: Raúl Peralta Meza Práctica Nro: 2 Curso: Programación Electrónica Título: Estructuras y uniones Programa: P. P. de Ingeniería Electrónica, Universidad Católica de Santa María de Arequipa II.Pre-requisitos Conocimientos básicos de WINDOWS. Uso del IDE BorlandC 3.1. Diagramas de flujo. Instrucciones de control de flujo, funciones , apuntadores y estructuras. Nociones de variables, memoria y apuntadores. III.Objetivos :Estudiar las estructuras y uniones para almacenar datos. :Analizar la forma como se guardan y extraen valores de las estructuras y uniones. IV.Procedimiento a) Definiciones previas. Estructura.- Colección de una o más variables, donde cada una pertenezca a un tipo de dato diferente agrupadas bajo un solo nombre para manejo conveniente. El objetivo de las estructuras es organizar los datos dentro de un programa debido a que permite que un grupo de estructuras relacionadas se les trate como una unidad en lugar de como entidades separadas. Union.- Es una variable que puede contener (en momentos diferentes) objetos de diferentes tipos y tamaños ; el compilador hace el seguimiento del tamaño y requisitos de alineación. Las uniones proporcionan una forma de manipular diferentes clases de datos dentro de una sola zona de almacenamiento. Tydef.- Facilidad que brinda el C para crear nuevos tipos de datos. Normalmente se crean en base a los tipos ya existentes o estructuras. b) Pasos a ejecutar en BORLANDC 3.1 Elaboro: MSc. Raúl Peralta Meza

Upload: louis

Post on 13-Jun-2015

797 views

Category:

Travel


0 download

TRANSCRIPT

GUÍA DE PRÁCTICA

I.Datos Generales

Elaboró: Raúl Peralta Meza Práctica Nro: 2Curso: Programación Electrónica Título: Estructuras y unionesPrograma: P. P. de Ingeniería Electrónica, Universidad Católica de Santa María de Arequipa II.Pre-requisitos

•Conocimientos básicos de WINDOWS.•Uso del IDE BorlandC 3.1.•Diagramas de flujo. Instrucciones de control de flujo, funciones , apuntadores y estructuras.•Nociones de variables, memoria y apuntadores.

III.Objetivos

:Estudiar las estructuras y uniones para almacenar datos.:Analizar la forma como se guardan y extraen valores de las estructuras y uniones.

IV.Procedimiento

a) Definiciones previas.

Estructura.- Colección de una o más variables, donde cada una pertenezca a un tipo de dato diferente agrupadas bajo un solo nombre para manejo conveniente. El objetivo de las estructuras es organizar los datos dentro de un programa debido a que permite que un grupo de estructuras relacionadas se les trate como una unidad en lugar de como entidades separadas.

Union.- Es una variable que puede contener (en momentos diferentes) objetos de diferentes tipos y tamaños ; el compilador hace el seguimiento del tamaño y requisitos de alineación. Las uniones proporcionan una forma de manipular diferentes clases de datos dentro de una sola zona de almacenamiento.

Tydef.- Facilidad que brinda el C para crear nuevos tipos de datos. Normalmente se crean en base a los tipos ya existentes o estructuras.

b) Pasos a ejecutar en BORLANDC 3.1

1. Estructuras

Supongamos 1 punto en el plano cartesiano (x,y). Necesitamos de 2 valores para definirlo, ambos del tipo entero. Si usamos dos enteros podriamos definirlo asi: int p1x, p2y; Para definir una estructura usamos el siguiente formato:

struct nombre_de_la_estructura { campos de estructura;};

NOTA: Es importante no olvidar el ';' al final de la definición.

Para nuestro ejemplo podemos crear una estructura en la que almacenaremos las coordenadas de un punto:

struct punto{ int x; int y;};

Elaboro: MSc. Raúl Peralta Meza

A cada elemento de esta estructura (x, y) se le llama campo o miembro. Ahora ya tenemos definida la estructura, pero aun no la hemos usado. Necesitamos declarar una variable perteneciente a este tipo de estructura.

struct punto a;

Podemos inicializar una estructura:

struct punto a={100,75};

Para acceder a cada uno de los datos que componen la estructura es necesario usar el operador miembro de una estructura “.” que conecta al nombre de la estructura con el nombre del miembro. Ej: a.x; // Accedemos a la variable x de la estructuta a (a es de tipo punto)

Ejemplo: Diseñar un programa que reciba un punto (x,y) y calcule la distancia del punto al origen (0,0).

#include <stdio.h>#include <conio.h>#include <math.h>

struct punto{int x;int y;

};

struct punto a;

int main(void){int distancia;

clrscr();printf("Ingrese valores:");scanf("%d %d", &a.x, &a.y);distancia=sqrt( a.x*a.x + a.y*a.y);printf("Distancia: %d",distancia);return 0;

}

2. Estructuras anidadas

Las estructuras pueden defiirse unas dentro de otras (anidadas) Por ejemplo considere la estructura rectángulo:

struct punto{int x;int y;

};struct rectangulo{ struct punto pa; struct punto pb. };struct rectangulo rect;

Para acceder al dato x del punto a bastará con escribir: rect.pa.x

En el siguiente ejemplo vamos a considerar un programa que pida las coordenadas de un rectángulo:

#include <stdio.h>#include <conio.h>#include <math.h>

struct punto{int x;int y;

};struct rectangulo{

struct punto pa;struct punto pb;

};

struct rectangulo rect;

Elaboro: MSc. Raúl Peralta Meza

int main(void){int distancia;

clrscr();printf("Ingrese punto a:");scanf("%d %d", &rect.pa.x, &rect.pa.y);printf("Ingrese punto b:");scanf("%d %d", &rect.pb.x, &rect.pb.y);printf("Los lados miden: %d %d", rect.pb.x-rect.pa.x,rect.pb.y-rect.pa.y);return 0;

}

3. Arrays de estructuras

Supongamos ahora que queremos guardar la información de varios alumnos. Con una variable tipo estructura sólo podemos guardar los datos de un alumno. Para manejar los datos de los demás necesitamos declarar arrays de estructuras:

struct estructura_alumno alumno[ELEMENTOS];

#include <stdio.h>

#define ELEMENTOS 3

struct estructura_alumno { char nombre[30]; int codigo; int nota; };

struct estructura_alumno alumno[ELEMENTOS]; //array de estructuras

int main(){int i;

for(i=0;i<ELEMENTOS;i++ ){ printf( "\nDatos del alumno %i:\n", i+1 ); printf( "Nombre: " ); scanf("%s",&alumno[i].nombre[0]); printf( "Codigo: " ); scanf("%d",&alumno[i].codigo); printf( "Nota: " ); scanf("%d",&alumno[i].nota);

} for(i=0;i<ELEMENTOS;i++ ){

printf( "Alumno: %s ", alumno[i].nombre); printf( "Codigo: %d ", alumno[i].codigo); printf( "Nota: %d \n", alumno[i].nota); }

return 0;}

Observaciones.-

La línea:

scanf("%s",&alumno[i].nombre[0]);

Permite el ingreso de una cadena que es almacenada en la estructura alumno[i] en el campo nombre. Note como es que se a colocado &alumno[i].nombre[0] haciendo referencia a la direción del primer elemento del arreglo nombre.

También pudo colocarse la expresión:

scanf("%s",alumno[i].nombre);

Esto debido a que la dirección del primer elemento de un arreglo unidimensional es igual a al nombre del arreglo.

Elaboro: MSc. Raúl Peralta Meza

3. Inicializar una estructura

A las estructuras podemos darles valores iniciales. Primero tenemos que definir la estructura y luego asignar un valor inicial. Por ejemplo:

struct estructura_amigo amigo = { "Juanjo", "Lopez", "592-0483", 30 };

NOTA: Algunos compiladores exigen poner antes de struct la palabra static.

Por supuesto hemos de meter en cada campo el tipo de datos correcto. La definición de la estructura es:

struct estructura_amigo { char nombre[30]; char apellido[40]; char telefono[10]; int edad; };

por lo tanto el nombre ("Juanjo") debe ser una cadena de no más de 29 letras (recordemos que hay que reservar un espacio para el símbolo '\0'), el apellido ("Lopez") una cadena de menos de 39, el teléfono una de 9 y la edad debe ser de tipo char.

Vamos a ver la inicialización de estructuras en acción:

#include <stdio.h>

struct estructura_amigo { char nombre[30]; char apellido[40]; char telefono[10]; int edad; };

struct estructura_amigo amigo = { "Juanjo", "Lopez", "592-0483", 30 };

int main() { printf( "%s tiene ", amigo.apellido ); printf( "%i años ", amigo.edad ); printf( "y su teléfono es el %s.\n" , amigo.telefono ); }

También podemos inicializar un array de la siguiente forma:

struct estructura_amigo amigo[] = { "Juanjo", "Lopez", "504-4342", 30, "Marcos", "Gamindez", "405-4823", 42, "Ana", "Martinez", "533-5694", 20 };

En este ejemplo cada línea es un registro. Como sucedía en los arrays si damos valores iniciales al array de estructuras no hace falta indicar cuántos elementos va a tener. En este caso la matriz tiene 3 elementos, que son los que le hemos pasado.

Elaboro: MSc. Raúl Peralta Meza

4. Uniones

Hemos visto que las estructuras toman una parte de la memoria y se la reparten entre sus miembros. Cada miembro tiene reservado un espacio para él solo. El tamaño total que ocupa una estructura en memoria es la suma del tamaño que ocupa cada uno de sus miembros.

Las uniones tienen un aspecto similar en cuanto a cómo se definen, pero tienen una diferencia fundamental con respecto a las estructuras: los miembros comparten el mismo trozo de memoria.

El espacio que ocupa en memoria una unión es el espacio que ocupa el campo más grande. Para entenderlo mejor vamos a ver un ejemplo:

Una unión la definimos:

union nombre_de_la_unión { campos de la unión };

NOTA: No se debe olvidar el ';' después de cerrar llaves '}'.

Ejemplo:

union _persona { char nombre[10]; char inicial; };

Creamos una unión y sus elementos son un nombre de 10 bytes (nombre[10]) y la inicial (1 byte). Como hemos dicho la unión ocupa el espacio de su elemento más grande, en este caso nombre. Por lo tanto la unión ocupa 10 bytes. Las variables nombre e inicial comparten el mismo sitio de la memoria. Si accedemos a nombre estaremos accediendo a los primeros 10 bytes de la unión (es decir, a toda la unión), si accedemos a inicial lo que tendremos es el primer byte de la unión.

Ejemplo: Vamos a desarrollar un programa que lea una cadena (nombre) e indique cual es la inicial de dicho nombre.

#include <stdio.h>

union persona { char nombre[10]; char inicial; };

union persona pers;

int main() { printf("Escribe tu nombre: "); gets(pers.nombre); printf("\nTu nombre es: %s\n", pers.nombre); printf("Tu inicial es: %c\n", pers.inicial); return 0; }

Para comprender mejor eso de que comparten el mismo espacio en memoria vamos a ampliar el ejemplo. Si añadimos unas líneas al final que modifiquen sólo la inicial e imprima el nuevo nombre:

Elaboro: MSc. Raúl Peralta Meza

#include <stdio.h>

union persona { char nombre[10]; char inicial; };

union persona pers;

int main() { printf("Escribe tu nombre: "); gets(pers.nombre); printf("\nTu nombre es: %s\n", pers.nombre); printf("Tu inicial es: %c\n", pers.inicial); /* Cambiamos la inicial */ pers.inicial='Z'; printf("\nAhora tu nombre es: %s\n", pers.nombre); printf("y tu inicial es: %c\n", pers.inicial); return 0; }

Elaboro: MSc. Raúl Peralta Meza

5. Punteros y estructuras

Como sabemos, podemos declarar un bloque de los datos que contienen diversos tipos de datos por medio de la declaración de una estructura. Por ejemplo, los datos de una persona pueden ser contenidos en una estructura como:

struct tag { char lname[20]; /* apellido */ char fname[20]; /* nombre */ int age; /* edad */ float rate; /* promedio */ };

Recordemos que podemos tener acceso a miembros de la estructura con el operador '.' como en:

#include <stdio.h>#include <string.h>

struct tag { char lname[20]; char fname[20]; int age; float rate; };

struct tag my_struct;

int main(void){ strcpy(my_struct.lname,"Jensen"); strcpy(my_struct.fname,"Ted"); printf("\n%s ",my_struct.fname); printf("%s\n",my_struct.lname); return 0;}

Esta estructura particular es algo pequeña comparada a con otros programas usados en C. Para hacerla más interesante vamos a agregar:

date_of_hire;

date_of_last_raise; last_percent_increase; emergency_phone; medical_plan; Social_S_Nbr; etc.....

Elaboro: MSc. Raúl Peralta Meza

Asumimos que tenemos una gran cantidad de empleados y que deseamos manipular los datos en estas estructuras por medio de funciones. Por ejemplo puede ser que deseemos una funcion que imprima el nombre del empleado pasando una estructura a una función. Sin embargo, en el C original (Kernighan & Ritchie, 1ra edición) no era posible pasar una estructura, sólo un puntero a una estructura podía pasarse. En ANSI C, ahora es permitido pasar la estructura completa. Pero, puesto que nuestra meta aquí es aprender más sobre punteros, no asumiremos eso.

De todas formas, si pasamos la estructura entera significa que debemos hacer una copia de todo el contenido de la estructura en la función que llamamos. Con estructuras grandes éste podía ser un problema. Sin embargo, pasar un puntero mínimiza el espacio utilizado.

En cualquier caso, debido que ésta es una discusión sobre punteros, discutiremos cómo vamos a pasar un puntero a una estructura y después como usarlo dentro de la función.

Considere el caso descrito, es decir deseamos una función que acepte como parámetro un puntero a una estructura y dentro de esa función deseamos tener acceso a los miembros de la estructura. Por ejemplo deseamos imprimir el nombre del empleado que esta en nuestra estructura.

Entonces sabemos que nuestro puntero indicador va a señalar a una estructura declarada usando la estructura tipo 'tag'. Declaramos tal puntero con la declaración:

struct tag *st_ptr;

y lo indicamos en nuestra estructura ejemplo con:

st_ptr = & my_struct;

Ahora, podemos tener acceso a un miembro dado a través de la “indirección” del puntero. ¿Pero, cómo “indirecionamos” el puntero a una estructura? Bien, considere el hecho de que deseemos utilizar el puntero para fijar la edad de un empleado. Escribiríamos:

(* st_ptr).age = 63;

Mire esto cuidadosamente. Dice, reemplace con lo que hay dentro de paréntesis por lo que el st_ptr señale, que es el my_struct . Así, se asemeja a my_struct.age .

Sin embargo, la siguiente es una expresión bastante usada por los programadores en C, que han creado una sintaxis alterna con el mismo significado y es:

st_ptr->age = 63;

Con éso en mente, mire el programa siguiente:

#include <stdio.h>#include <string.h>

struct tag{ /* tipo de estructura */ char lname[20]; /* apellido */ char fname[20]; /* nombre */ int age; /* edad */ float rate; /* promedio */};

struct tag my_struct; /* define la estructura */void show_name1(struct tag *p); /* funcion prototipo */void show_name2(struct tag *p); /* funcion prototipo */int main(void){struct tag *st_ptr; /* apuntador a la estructura */st_ptr = &my_struct; /* el apuntador str_ptr tiene la

Elaboro: MSc. Raúl Peralta Meza

direccion*/strcpy(my_struct.lname,"Jensen"); /* Inicializamos la estructura */strcpy(my_struct.fname,"Ted");printf("\n%s ",my_struct.fname); /* Imprimimos, verificamos */printf("%s\n",my_struct.lname);my_struct.age = 63;show_name1(st_ptr); /* pasamos el puntero*/show_name2(st_ptr); /* pasamos el puntero*/return 0;

}

void show_name1(struct tag *p){printf("\n%s ", (*p).fname); /* p apuntador a la estructura*/printf("%s ", (*p).lname);printf("%d\n", (*p).age);

}

void show_name2(struct tag *p){printf("\n%s ", p->fname); /* p apuntador a la estructura*/printf("%s ", p->lname);printf("%s ", p->age);

}

El lector debe compilar y poner a funcionar el programa, con ayuda del debuger entenderá como es que funciona. Debe trabajarlo de la siguiente manera:

Vamos a dar una paso adelante. Podríamos usar un puntero para recorrer un arreglo de estructuras?. La respuesta es SI todo lo que debemos hacer es iniciar el puntero con la dirección del primer elemento del arreglo de estructuras y luego incrementar el puntero para movernos de una a otra ubicación. La aritmética de apuntadores nos permitirá calcular las direcciones apropiadas.

Ejemplo: Desarrollar un programa que declare un arreglo de estructuras de tipo punto (para almacenar un punto en el plano cartesiano) a continuación imprima los puntos.

Elaboro: MSc. Raúl Peralta Meza

#include <stdio.h>#include <conio.h>#include <math.h>

struct punto{int x;int y;

};

struct punto a[5]={ 0,0, 1,1, 2,2, 3,3, 4,4};

void imprime1(struct punto *p){int i;

for(i=0;i<5;i++){printf("\np[%d]= %d %d", i , (*p).x , (*p).y );p++;

}}

void imprime2(struct punto *p){int i;

for(i=0;i<5;i++){printf("\np[%d]= %d %d", i , p->x , p->y );p++;

}}

int main(void){int i; struct punto *ptr;

clrscr();ptr=&a[0];imprime1(ptr); // o pudo ser imprime1(&a[0]);imprime2(ptr); // o pudo ser imprime2(&a[0]);return 0;

}

Cuestionario Final

En base a punteros desarrollar dos funciones:

/Escriba un programa que utilice un arreglo datos[0],.... datos[9], para almacenar el nombre y el salario de n personas según la siguiente especificación:

struct sregistro{ char nombre[30];

float salario;

};

struct sregistro datos[10];

/Escriba la función total(p):

float total(struct sregistro *p)

que calcule la suma de todos los salarios del arreglo datos del ejercicio anterior.

Elaboro: MSc. Raúl Peralta Meza