Tema Tema6: 6: Estructuras Estructurasyytipos tiposde dedatos datos definidos definidospor porel elusuario usuario Fundamentos de Informática 1º Ingeniería Industrial Escuela Superior de Ingenieros Universidad de Sevilla Ismael Alcalá Torrego José Ángel Acosta Rodríguez Fernando Dorado Navas Fabio Gómez Estern-Aguilar Manuel López Martínez Amparo Núñez Reyes Carlos Vivas Venegas TEMA TEMA6: 6: Estructuras Estructurasyytipos tiposde dedatos datos definidos por el usuario definidos por el usuario ESTRUCTURAS: ESTRUCTURAS: Colección Colecciónde devariables variablesque quese se referencian bajo el mismo nombre. referencian bajo el mismo nombre. Uso Usode deestructuras estructuras DEFINICIÓN DECLARACIÓN ASIGNACIÓN DEFINICIÓN: DEFINICIÓN: Establece la plantilla de la estructura, especificando las variables que forman parte de ella (Miembros) y sus tipos. struct fecha { int dia; int mes; int anio; }; Nombre IMPORTANTE ASIGNACIÓN: ASIGNACIÓN: DECLARACIÓN: DECLARACIÓN: struct fecha f_nac; Tipo dato Miembros Nombre f_nac.dia = 20; f_nac.mes = 10; f_nac.anio = 2005; Agrupando Agrupandooperaciones operaciones Definición + Declaración struct complejo { float real; float imag; } a, b, c; Declaración + Asignación struct complejo a = {2 ,5}; Estructuras Estructuras Referencia Referenciaaasus suselementos: elementos: struct fecha fnac={22,7,1985}; El tipo de dato es el del miembro (int). printf(“La fecha es %d/%d/%d\n”, fnac.dia, fnac.mes, fnac.anio); ¿Cómo ¿Cómose sealmacenan almacenanen enmemoria? memoria? struct fecha { int dia; int mes; int anio; }; Ej: struct fecha f; dia mes f anio Los miembros se almacenan contiguos en la memoria bajo el nombre de la estructura. Estructuras Estructurasanidadas: anidadas: Un miembro de una estructura puede ser a su vez otra estructura struct fecha { int dia; int mes; int anio; }; struct ficha { char nombre[20]; struct fecha fnac; } ficha1; ASIGNACIÓN ASIGNACIÓN/ /USO: USO: El tipo de dato es el del último miembro ficha1.fnac.dia= 22; “Miembro dia de la estructura fnac, que es a su vez una estructura tipo fecha y miembro de ficha1” Estructuras Estructuras struct biblio{ char titulo[40]; char autor[40]; float precio; }; Tablas Tablasde deestructuras: estructuras: Ej: struct biblio t[10]; Acceso a los elementos: Precio del libro t[3] igual a 15 Ej: t[3].precio=15; Tercera letra del titulo del libro t[5] igual a ‘c’. t[5].titulo[2]=‘c’; t.precio [6] = 20; MAL !! Nuevo operador Punteros Punterosaaestructuras estructuras Ej: struct biblio libro={“El Quijote”,”Cervantes”,20); struct biblio *p = &libro; libro.precio (*p).precio p -> precio ¿Cómo ¿Cómose sepasan pasanestructuras estructurasaafunciones? funciones? Por valor a) Estructuras completas b) Miembros Individuales Por referencia struct biblio t[10]; struct fecha f; … func1( f ); func2( t[3] ); struct biblio t[10]; struct fecha f; … func1( t ); func2( &f ); struct biblio t[10]; struct fecha f; … func1( t[2].titulo[2] ); func2( f.mes ); struct biblio t[10]; struct fecha f; … func1(&(t[2].titulo[2]) ); func2( &(f.dia) ); Estructuras Estructuras Ejemplos: Ejemplos: Paso Pasode deestructuras estructurasaafunciones: funciones:Por Porvalor valor Programemos la suma de dos números complejos de dos modos distintos Estructuras completas struct complejo { float real; float imag; }; struct complejo sumacomp (struct complejo, struct complejo); void main(void) { struct complejo c1={1,2}; /*1+2i*/ struct complejo c2={3,4}; /*3+4i*/ struct complejo r; r=sumacomp(c1, c2); printf(“Resultado = %d+%di\n” , r.real, r.imag); } struct complejo sumacomp (struct complejo x, struct complejo y) { struct complejo s; s.real=x.real+y.real; s.imag=x. imag+y. imag; return s; } Miembros individuales struct complejo { float real; float imag; }; float suma(float , float ); void main(void) { struct complejo c1={1,2}; /*1+2i*/ struct complejo c2={3,4}; /*3+4i*/ struct complejo r; r.real=suma(c1.real, c2.real); r.imag=suma(c1.imag, c2. imag); printf(“Resultado = %d+%di\n”,r.real,r.imag); } float suma (float x, float y) { return x+y; } Estructuras Estructuras Ejemplos: Ejemplos: Paso Pasode deestructuras estructurasaafunciones: funciones:Por Porreferencia referencia Resolvemos ahora el problema de intercambiar dos números complejos llamando a funciones apropiadas de dos modos distintos: Estructuras completas struct complejo { float real; float imag; }; void intercomp (struct complejo *, struct complejo *); void main(void) { struct complejo c1={1,2}; /*1+2i*/ struct complejo c2={3,4}; /*3+4i*/ intercomp(&c1, &c2); printf(“c1 = %d+%di\n c2 = %d+%di\n” ,c1.real, c1.imag ,c2.real, c2.imag); } void intercomp (struct complejo *x, struct complejo *y) { struct complejo aux; aux.real = x ->real; aux.imag = x -> imag; x ->real = y -> real; x-> imag = y -> imag; y -> real = aux. real; y -> imag = aux.imag; } Miembros individuales struct complejo { float real; float imag; }; void intercambia(float *, float *); void main(void) { struct complejo c1={1,2}; /*1+2i*/ struct complejo c2={3,4}; /*3+4i*/ intercambia(&(c1.real), &(c2.real)); intercambia(&(c1.imag), &(c2.imag)); printf(“c1 = %d+%di\n c2 = %d+%di\n” ,c1.real, c1.imag ,c2.real, c2.imag); } void intercambia (float *x, float *y) { float aux; aux=*x; *x=*y; *y=aux; } Estructuras Estructuras Ejemplos: Ejemplos: Paso Pasode deestructuras estructurasaafunciones: funciones:Por Porreferencia referencia Resolvemos ahora el problema de intercambiar dos números complejos llamando a funciones apropiadas de dos modos distintos: Estructuras completas struct complejo { float real; float imag; }; void intercomp (struct complejo *, struct complejo *); void main(void) { struct complejo c1={1,2}; /*1+2i*/ struct complejo c2={3,4}; /*3+4i*/ intercomp(&c1, &c2); printf(“c1 = %d+%di\n c2 = %d+%di\n” ,c1.real, c1.imag ,c2.real, c2.imag); } Miembros individuales struct complejo { float real; float imag; }; void intercambia(float *, float *); void main(void) { struct complejo c1={1,2}; /*1+2i*/ struct complejo c2={3,4}; /*3+4i*/ intercambia(&(c1.real), &(c2.real)); intercambia(&(c1.imag), &(c2.imag)); printf(“c1 = %d+%di\n c2 = %d+%di\n” ,c1.real, c1.imag ,c2.real, c2.imag); } void intercomp (struct complejo *x, struct complejo *y) { void intercambia (float *x, float *y) struct complejo aux; { aux.real = x ->real; float aux; aux.imag = x -> imag; aux=*x; x ->real = y -> real; *x=*y; También se puede x-> imag = y -> imag; *y=aux; y -> real = aux. real; } y -> imag = aux.imag; Ahora son estructuras } *x=*y Estructuras Estructuras Sentencia Sentencia typedef typedef typedef tipo nombre Permite definir nuevos nombres de datos Ej: typedef struct biblio libros; struct biblio t[10]; libros t[10]; Otros OtrosComentarios Comentarios ¿ . A la izquierda del operador flecha SIEMPRE punteros a estructura -> o -> ? A la izquierda del operador punto SIEMPRE estructuras . El tipo de dato de una secuencia de referencias de estructuras es SIEMPRE el del último elemento aaa . bbb -> ccc -> ddd Ejemplo: struct S1 { int a; struct S1 *p; }; struct S2 { char n[10]; struct S1 m; }; struct S3 { float *b; struct S2 q[5]; } s; a) s q[3] m b) s q c) s *(q+2) p n d) *( s b) e) &(s q+1 m n[3]) a Estructuras Estructuras Sentencia Sentencia typedef typedef typedef tipo nombre Permite definir nuevos nombres de datos Ej: typedef struct biblio libros; struct biblio t[10]; libros t[10]; Otros OtrosComentarios Comentarios ¿ . A la izquierda del operador flecha SIEMPRE punteros a estructura -> o -> ? A la izquierda del operador punto SIEMPRE estructuras . El tipo de dato de una secuencia de referencias de estructuras es SIEMPRE el del último elemento aaa . bbb -> ccc -> ddd Ejemplo: struct S1 { int a; struct S1 *p; }; struct S2 { char n[10]; struct S1 m; }; struct S3 { float *b; struct S2 q[5]; } s; a) s . q[3] . b) s q c) s *(q+2) m .p Puntero a struct S1 n d) *( s b) e) &(s q+1 m n[3]) a Estructuras Estructuras Sentencia Sentencia typedef typedef typedef tipo nombre Permite definir nuevos nombres de datos Ej: typedef struct biblio libros; struct biblio t[10]; libros t[10]; Otros OtrosComentarios Comentarios ¿ . A la izquierda del operador flecha SIEMPRE punteros a estructura -> o -> ? A la izquierda del operador punto SIEMPRE estructuras . El tipo de dato de una secuencia de referencias de estructuras es SIEMPRE el del último elemento aaa . bbb -> ccc -> ddd Ejemplo: struct S1 { int a; struct S1 *p; }; struct S2 { char n[10]; struct S1 m; }; struct S3 { float *b; struct S2 q[5]; } s; . q[3] . m . p b) s . q -> n a) s c) s *(q+2) d) *( s b) e) &(s q+1 m n[3]) Puntero a struct S1 Vector de caracteres a Estructuras Estructuras Sentencia Sentencia typedef typedef typedef tipo nombre Permite definir nuevos nombres de datos Ej: typedef struct biblio libros; struct biblio t[10]; libros t[10]; Otros OtrosComentarios Comentarios ¿ . -> o -> ? . El tipo de dato de una secuencia de referencias de estructuras es SIEMPRE el del último elemento A la izquierda del operador flecha SIEMPRE punteros a estructura A la izquierda del operador punto SIEMPRE estructuras aaa . bbb -> ccc -> ddd Ejemplo: struct S1 { int a; struct S1 *p; }; struct S2 { char n[10]; struct S1 m; }; struct S3 { float *b; struct S2 q[5]; } s; . q[3] . m . p b) s . q -> n c) s . *(q+2) . m . a) s d) *( s b) e) &(s q+1 n[3]) Puntero a struct S1 Vector de caracteres a Entero Estructuras Estructuras Sentencia Sentencia typedef typedef typedef tipo nombre Permite definir nuevos nombres de datos Ej: typedef struct biblio libros; struct biblio t[10]; libros t[10]; Otros OtrosComentarios Comentarios ¿ . -> o -> ? . El tipo de dato de una secuencia de referencias de estructuras es SIEMPRE el del último elemento A la izquierda del operador flecha SIEMPRE punteros a estructura A la izquierda del operador punto SIEMPRE estructuras aaa . bbb -> ccc -> ddd Ejemplo: struct S1 { int a; struct S1 *p; }; struct S2 { char n[10]; struct S1 m; }; struct S3 { float *b; struct S2 q[5]; } s; . q[3] . m . p b) s . q -> n c) s . *(q+2) . m . d) *( s . b) a) s e) &(s q+1 n[3]) Puntero a struct S1 Vector de caracteres a Entero Flotante Estructuras Estructuras Sentencia Sentencia typedef typedef typedef tipo nombre Permite definir nuevos nombres de datos Ej: typedef struct biblio libros; struct biblio t[10]; libros t[10]; Otros OtrosComentarios Comentarios ¿ . -> o -> ? . El tipo de dato de una secuencia de referencias de estructuras es SIEMPRE el del último elemento A la izquierda del operador flecha SIEMPRE punteros a estructura A la izquierda del operador punto SIEMPRE estructuras aaa . bbb -> ccc -> ddd Ejemplo: struct S1 { int a; struct S1 *p; }; struct S2 { char n[10]; struct S1 m; }; struct S3 { float *b; struct S2 q[5]; } s; . q[3] . m . p b) s . q -> n c) s . *(q+2) . m . d) *( s . b) e) &(s . q+1 -> n[3]) a) s Puntero a struct S1 Vector de caracteres a Entero Flotante Apuntador a carácter Estructuras Estructuras Otros OtrosComentarios Comentarios(II) (II) Precaución con los punteros como miembros de estructuras struct polinomio { int grado; float *coef; }; No es igual que coef es un puntero a flotante. Hay que inicializarlo antes de usarlo struct polinomio { int grado; float coef[101]; }; coef es un vector de flotantes . Se reserva espacio para 101 flotantes Ejemplo: struct polinomio { int grado; float *coef; }; void main(void) { int i; struct polinomio p; printf(“Introduce grado del polinomio\n); scanf(“%d”,&(p.grado)); if((p.coef=(float *)malloc((p.grado+1)* sizeof(float)))==NULL) {printf(“Error memoria\n”); exit(0);} for(i=0;i<grado+1;i++) {printf(“\n Coeficiente x^%d”); scanf(“%d”,p.coef+i); } deriva_pol(&p); imprime_pol(p); free(p.coef); } struct polinomio { int grado; float coef[101]; }; void main(void) { int i; struct polinomio p; printf(“Introduce grado del polinomio (Menor o igual que 100)\n); scanf(“%d”,&(p.grado)); for(i=0;i<grado+1;i++) {printf(“\n Coeficiente x^%d”); scanf(“%d”,p.coef[i]); } deriva_pol(&p); imprime_pol(p); } Estructuras Estructuras Otros OtrosComentarios Comentarios(II) (II) Precaución con los punteros como miembros de estructuras struct polinomio { int grado; float *coef; }; No es igual que coef es un puntero a flotante. Hay que inicializarlo antes de usarlo struct polinomio { int grado; float coef[101]; }; coef es un vector de flotantes . Se reserva espacio para 101 flotantes Ejemplo: struct polinomio { int grado; float *coef; }; void main(void) { int i; struct polinomio p; printf(“Introduce grado del polinomio\n); scanf(“%d”,&(p.grado)); if((p.coef=(float *)malloc((p.grado+1)* sizeof(float)))==NULL) {printf(“Error memoria\n”); exit(0);} for(i=0;i<grado+1;i++) {printf(“\n Coeficiente x^%d”); scanf(“%d”,p.coef+i); } Hay que usar deriva_pol(&p); imprime_pol(p); reserva dinámica free(p.coef); de memoria } struct polinomio { int grado; float coef[101]; }; void main(void) { int i; struct polinomio p; printf(“Introduce grado del polinomio (Menor o igual que 100)\n); scanf(“%d”,&(p.grado)); for(i=0;i<grado+1;i++) {printf(“\n Coeficiente x^%d”); scanf(“%d”,p.coef[i]); } deriva_pol(&p); imprime_pol(p); Reserva estática } para el vector de coeficientes