4. Estructuras (registros)Definir una estructura en el lenguaje C Para usar una estructura, primero...
Transcript of 4. Estructuras (registros)Definir una estructura en el lenguaje C Para usar una estructura, primero...
4. Estructuras (registros)Programación II, FCFM, BUAP
Son colecciones de variables relacionadas bajo un nombre.
Permiten agrupar variables del mismo o diferente tipo, bajo un mismo nombre. Inclusive puede contener otra(s) estructuras.
A las estructuras se les conoce también como registros.
A cada elemento de una estructura se le llama miembro o campo.
Alumno
Matrícula:Nombre:
Sexo:Carrera:
Semestre:Promedio:
Definir una estructura en el lenguaje C
Para usar una estructura, primero hay que definir un nuevo tipo de dato y luego declarar una variable de ese tipo, es decir, hay que definir a la estructura antes de usarla en la declaración de variables.
El tipo de dato puede ser: básico o primitivo, arreglo, puntero o estructura.
El tipo de dato no puede ser extern, static, auto o register.
Las variables no pueden ser inicializadas dentro de la estructura.
El nombre de un miembro es local a la estructura.
struct alumno
{
char matricula[10];
char nombre[TAM], sexo, carrera[3];
unsigned short int semestre;
float promedio;
};
int main( )
{
struct alumno a1, a2,
a3 = {"201611111", "José García", 'M', "AC", 4, 9.64};
char matri[ ] ="201599999“;
char nom[TAM] = “Lucero Luna Salas";
float p = 8.76;
a1.sexo = 'M';
Los registros pueden ser globales o locales
Si en la lista entre corchetes existen menos inicializadores que miembros de una estructura, los miembros restantes se inicializan automáticamente en 0, caracter nulo o NULL dependiendo del tipo de dato de cada miembro restante
Para acceder al campo de una estructura se usa el operador punto
struct alumno
{
char matricula[10];
char nombre[TAM], sexo, carrera[3];
unsigned short int semestre;
float promedio;
};
int main( )
{
struct alumno a1, a2,
a3 = {"201611111", "José García", 'M', "AC", 4, 9.64};
char matri[ ] ="201599999“;
char nom[TAM] = “Lucero Luna Salas";
float p = 8.76;
a1.sexo = 'M';
a1.semestre = 6;
a1.promedio = p;
strcpy(a1.carrera,"MA");
strcpy(a1.matricula,matri);
strcpy(a1.nombre,nom);
printf("Ingresa tu nombre:");
fgets(a2.nombre, TAM, stdin);
printf(“¿Carrera?"); scanf("%s",a2.carrera);
printf("Ingresa tu promedio:");
scanf("%f", &a2.promedio);
printf("%s,%s,%c,%s,%hu,%.2f \n", a1.matricula, a1.nombre, a1.sexo, a1.carrera, a1.semestre, a1.promedio);
printf("%s,%s,%.2f \n", a2.nombre, a2.carrera, a2.promedio);
…
struct alumno
{
char matricula[10];
char nombre[TAM], sexo, carrera[3];
unsigned short int semestre;
float promedio;
};
typedef struct alumno Ralumno;
int main( )
{
Ralumno a1, a2,
a3 = {"201611111", "José García", 'M', "AC", 4, 9.64};
char matri[ ] ="201599999“;
char nom[TAM] = “Lucero Luna Salas";
float p = 8.76;
a1.sexo = 'M';
a1.semestre = 6;
a1.promedio = p;
strcpy(a1.carrera,"MA");
strcpy(a1.matricula,matri);
strcpy(a1.nombre,nom);
printf("Ingresa tu nombre:");
fgets(a2.nombre, TAM, stdin);
printf(“¿Carrera?"); scanf("%s",a2.carrera);
printf("Ingresa tu promedio:");
scanf("%f", &a2.promedio);
printf("%s,%s,%c,%s,%hu,%.2f \n", a1.matricula, a1.nombre, a1.sexo, a1.carrera, a1.semestre, a1.promedio);
…
typedef sirve para crear sinónimos de tipos de datos ya definidos, pero NO crea un nuevo tipo
typedef struct alumno
{
char matricula[10];
char nombre[T], sexo, carrera[3];
unsigned short int semestre;
float promedio;
}Ralumno;
int main( )
{
Ralumno a1, a2,
a3 = {"201611111", "José García", 'M', "AC", 4, 9.64};
char matri[ ] ="201599999“;
char nom[TAM] = “Lucero Luna Salas";
float p = 8.76;
a1.sexo = 'M';
a1.semestre = 6;
a1.promedio = p;
strcpy(a1.carrera,"MA");
strcpy(a1.matricula,matri);
strcpy(a1.nombre,nom);
printf("Ingresa tu nombre:");
fgets(a2.nombre, TAM, stdin);
printf(“¿Carrera?"); scanf("%s",a2.carrera);
printf("Ingresa tu promedio:");
scanf("%f", &a2.promedio);
printf("%s,%s,%c,%s,%hu,%.2f \n", a2.matricula, a2.nombre, a2.sexo, a2.carrera, a2.semestre, a2.promedio);
…
Con esta forma de definición, es válido eliminar el identificador de la estructura, es decir, se puede borrar la palabra alumno
struct alumno
{
char matricula[10];
char nombre[T], sexo, carrera[3];
unsigned short int semestre;
float promedio;
}a1, a2, a3 = {"201611111", "José García Rojas", 'M', "AC", 4, 9.64};
int main( )
{
char matri[ ] ="201599999“;
char nom[TAM] = “Lucero Luna Salas";
float p = 8.76;
a1.sexo = 'M';
a1.semestre = 6;
a1.promedio = p;
strcpy(a1.carrera,"MA");
strcpy(a1.matricula,matri);
strcpy(a1.nombre,nom);
printf("Ingresa tu nombre:");
fgets(a2.nombre, TAM, stdin);
printf(“¿Carrera?"); scanf("%s",a2.carrera);
printf("Ingresa tu promedio:");
scanf("%f", &a2.promedio);
printf("%s,%s,%c,%s,%hu,%.2f \n", a1.matricula, a1.nombre, a1.sexo, a1.carrera, a1.semestre, a1.promedio);
…
Los miembros de una estructura son almacenados secuencialmente, en el mismo orden en que son declarados, similar a los arreglos.
matrícula promediosemestrecarrerasexonombre
Se puede asignar una estructura a otra y cuando esto sucede, se copian uno a uno todos los miembros de la estructura origen a la estructura destino, es decir, la estructura origen se duplica en la destino.
a1 = a3;
Las estructuras no pueden compararse por medio de operadores == y !=
Estructuras anidadas
Es posible que los miembros de una estructura sean a su vez estructuras previamente definidas, dando lugar a estructuras anidadas.
Una estructura no puede tener una instancia de sí misma, sin embargo, un apuntador a la estructura sí puede incluirse.
typedef struct nombreCompuesto
{
char nom[20], app[10], apm[10];
}nombreA;
typedef struct alumno
{
char matricula[10];
nombreA nombre;
char sexo, carrera[3];
unsigned short int semestre;
float promedio;
}Ralumno;
int main( )
{
Ralumno a1, a2,
char matri[ ] ="201599999“;
float p = 8.76;
a1.sexo = 'M'; a1.semestre = 6; a1.promedio = p;
strcpy(a1.carrera,"MA");
strcpy(a1.matricula, matri);
strcpy(a1.nombre.nom, “Lucero”);
strcpy(a1.nombre.app, “Luna”);
strcpy(a1.nombre.apm, “Salas”);
printf("Ingresa tu nombre:");
fgets(a2.nombre.nom, 20, stdin);
printf("Ingresa tu apellido paterno:");
fgets(a2.nombre.app, 10, stdin);
printf("%s,%s %s %s, %c,%s,%u,%.2f \n", a1.matricula, a1.nombre.nom, a1.nombre.app, a1.nombre.apm, a1.sexo, a1.carrera, a1.semestre, a1.promedio);
…
struct alumno
{
char matricula[10];
char nombre[T], sexo, carrera[3];
unsigned short int semestre;
float promedio;
struct alumno persona; /* ERROR */
struct alumno *apPersona /* CORRECTO*/
};
Estructura autorreferenciada
Arreglos de estructuras
Se pueden declarar arreglos cuyos elementos sean estructuras, es decir, crear arreglos de estructuras o arreglos de registros
typedef struct nombreCompuesto
{
char nom[20], app[10], apm[10];
}nombreA;
typedef struct alumno
{
char matricula[10];
nombreA nombre;
char sexo, carrera[3];
unsigned short int semestre;
float promedio;
}Ralumno;
int main( )
{
Ralumno alumnos[100];
strcpy(alumnos[0].matricula, “201522222”);
strcpy(alumnos[0].carrera, "MA");
strcpy(alumnos[0].nombre.nom, “Lucero”);
strcpy(alumnos[0].nombre.app, “Luna”);
strcpy(alumnos[0].nombre.apm, “Salas”);
alumnos[0].promedio = 8.47;
alumnos[0].semestre = 6;
…
Estructuras en funciones
Una estructura o los miembros individuales de la misma, pasan a una función automáticamente por valor.
Para pasar por referencia una estructura, se debe pasar la dirección de la variable estructura.
Un arreglo de estructuras se pasa automáticamente porreferencia (como todos los arreglos).
Para pasar un arreglo por valor, se debe generar unaestructura con el arreglo como miembro.
Es más eficiente pasar una estructura por referencia que por valor.
typedef struct
{
char nombre[32], s;
int edad;
float alt;
}jugador;
void modificarV ( jugador x )
{
x.edad = 50;
}
void modificar ( jugador *x )
{
x -> edad = 50;
}
int main()
{
jugador jug1;
printf("Introduce el nombre: ");
fgets(jug1.nombre,30,stdin);
printf("Introduce la edad: ");
scanf("%d", &jug1.edad); fflush(stdin);
printf("Introduce el sexo: "); scanf("%c", &jug1.s);
printf("Introduce la altura: "); scanf("%f", &jug1.alt);
modificarV(jug1);
//Mandar a imprimir
modificar(&jug1);
//Mandar a imprimir
…
Manu Ginobili40M1.98
Manu Ginobili50M1.98
typedef struct
{
char nombre[32], s;
int edad;
float alt;
float estadisticas[5];//min,pts,asistencias,rebotes,robos
}jugador;
void modificarV ( jugador x )
{
x.edad = 50;
x.estadisticas[0]=22;
}
void modificar ( jugador *x )
{
x -> edad = 50;
x->estadisticas[0] = 22;
}
int main()
{
jugador jug1;
printf("Introduce el nombre: ");
fgets(jug1.nombre,30,stdin);
printf("Introduce la edad: ");
scanf("%d", &jug1.edad); fflush(stdin);
printf("Introduce el sexo: "); scanf("%c", &jug1.s);
printf("Introduce la altura: "); scanf("%f", &jug1.alt);
modificarV(jug1);
//Mandar a imprimir
modificar(&jug1);
//Mandar a imprimir
…
Manu Ginobili40M1.980.000000
Manu Ginobili50M1.9822
typedef struct
{
char nombre[32], s;
int edad;
float alt;
float estadisticas[5];
//min,pts,asistencias,rebotes,robos
}jugador;
void modificarA(jugador x[ ])
{
x[0].edad = 50;
x[0].estadisticas[0] = 37;
}
int main()
{
jugador jugadores[2]=
{ {"Manu Ginobili", 'M', 40, 1.98},{"Rudy Gay", 'M', 31, 2.03} };
modificarA(jugadores);
for(i=0; i<2; i++)
{
printf("\n%s\n",jugadores[i].nombre);
printf("Edad: %d\n",jugadores[i].edad);
printf("Sexo: %c\n",jugadores[i].s);
printf("Altura: %f\n",jugadores[i].alt);
printf("Minutos jugados:
%f\n",jugadores[i].estadisticas[0]);
}
…
Manu Ginobili Rudy Gay50 31M M1.98 2.0337 0.000000
Punteros a estructuras Los punteros a estructuras se declaran igual que los punteros a
otros tipos de datos Para referirse a un campo de un registro apuntado por un
apuntador se utiliza el operador -> Recordar que cuando se declara un puntero a un objeto, casi
siempre es porque el objeto va a ser creado en tiempo de ejecución
Por tanto, declarar un apuntador a un objeto de cualquier tipo no sirve de nada mientras no le asignemos un bloque de memoria capaz de almacenar un objeto de ese tipo
typedef struct
{
unsigned int d;
unsigned int m;
unsigned int a;
}fecha;
void escribir (fecha *f)
{
printf ("Día %u del mes %u del año %u\n",
f->d, f->m, f->a);
}
void escribir2 (fecha *f)
{
printf ("Día %u del mes %u del año %u\n",
(*f).d, (*f).m, (*f).a);
}
int main ( )
{
// hoy es un puntero a una estructura
fecha *hoy;
// asignación de memoria para la estructura
hoy = (fecha *) malloc(sizeof(fecha));
printf ("Introducir fecha (dd-mm-aaaa) : ") ;
scanf ( "%u-%u-%u" , &hoy->d, &hoy->m, &hoy->a) ;
escribir(hoy);
escribir2(hoy);
free(hoy);
return 0;
}