Capítol 8
Matrius. Estructures. Unions
-
Les matrius de dues dimensions.
-
El pas de matrius de dues dimensions a funcions
-
Les estructures.
-
Variables vector d'estructures
-
Estructures niades
-
Exercicis
-
Les unions
8.1. Les matrius de dues dimensions.
Si mirem el quadre següent veiem que té 3 files de 5 columnes
cadascuna. Es a dir que és una matriu 3X5.
Així l'element (0,4) és 23 i l'element (2,3) és
178.
|
0 |
1 |
2 |
3 |
4 |
0 |
123 |
265 |
1 |
438 |
23 |
1 |
234 |
12 |
13 |
14 |
15 |
2 |
23 |
56 |
-12 |
178 |
2 |
Les matrius de tires de caràcters son en realitat matrius bidimensionals
com pots observar a la figura següent:
|
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
0 |
J |
i |
m |
e |
n |
e |
z |
, |
L |
o |
p |
e |
z |
; |
M |
i |
g |
u |
e |
l |
\0 |
|
|
|
|
|
1 |
B |
a |
s |
, |
O |
l |
i |
v |
a |
; |
A |
n |
n |
a |
\0 |
|
|
|
|
|
|
|
|
|
|
|
2 |
Z |
a |
m |
o |
r |
a |
, |
R |
i |
v |
e |
r |
a |
; |
R |
a |
m |
o |
n |
\0 |
|
|
|
|
|
|
3 |
P |
u |
i |
g |
, |
A |
d |
a |
m |
s |
; |
R |
i |
c |
a |
r |
d |
\0 |
|
|
|
|
|
|
|
|
4 |
C |
a |
b |
a |
l |
l |
e |
r |
o |
, |
M |
o |
n |
t |
a |
n |
c |
h |
e |
z |
; |
P |
e |
p |
e |
\0 |
5 |
L |
l |
u |
c |
h |
, |
P |
i |
; |
A |
l |
b |
e |
r |
t |
\0 |
|
|
|
|
|
|
|
|
|
|
6 |
\0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
\0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
\0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
En el programa següent vueràs com es declara una matriu
de dues dimensions i com s'assignen i usen les dades d'aquestes matrius.
#include <stdio.h>
#include <conio.h>
main(void){
int i,j;
/* Declaració de la variable bidimensional
Numero[3][5] de 3 files i 5 columnes.
Es dona valor a tots els
elements de la matriu. Es poden ometre elements però
seguint algunes regles.*/
int Numero[3][5] =
{
{123, 265, 1, 438,
23},
{234, 12, 13, 14,
15},
{ 23, 56, -12, 178,
2}
};
clrscr();
printf("Treballarem amb els elements d'una matriu
(3x5)\n");
printf("El número (0,4) és %d \n",Numero[0][4]);
printf("El número (1,2) és %d \n",Numero[1][2]);
printf("\nDona'm un número i el posaré
al lloc (0,4) ");
scanf("%d", &Numero[0][4]);
printf("Ara el número (0,4) és %d\n",Numero[0][4]);
printf("\nEl número (2,0) és %d \n",Numero[2][0]);
Numero[2][0]=-123;
printf("Ara el número (2,0) és %d\n",Numero[2][0]);
printf("\nAqui teniu tots els elements de la matriu\n\n");
for(i=0;i<3;i++)
{
for(j=0;j<5;j++) printf("%5d",Numero[i][j]);
printf("\n");
}
} |
Un programa que inicialitza la matriu de noms és el següent:
#include <stdio.h>
#include <conio.h>
#include <string.h>
main(void)
{
int i;
/*Declaració i assignació de part dels
noms de la variable Nom.*/
char Nom[9][26]=
{
"Jimenez,Lope;Miguel","Bas,Oliva;Anna",
"Puig,Adams;Ricard","Caballero,Montanchez;Pepe",
"Lluch,Pi;Albert"
};
clrscr();
printf("\nEscriu el teu nom i el posar‚ a la posició
6 ");
scanf("%[^\n]",Nom[6]);
printf("El teu nom est en Nom[6]: %s\n",Nom[6]);
strcpy(Nom[7],"Riera,Riuet;Reidor");
printf("\nAra he assignat a Nom[7] %s amb la funció
strcpy\n",Nom[7]);
printf("Els noms enmagatzemats a la matriu Nom són
\n\n");
for(i=0;i<9;i++) printf("%s \n",Nom[i]);
} |
8.2. El pas de matrius de dues dimensions a funcions
En el programa següent s'incialitza una matriu de dues dimensions
i es crea una funció per imprimir. Observa que per cridar la funció
es dona cada vegada un vector i el número d'elements d'aquest vector.
#include <stdio.h>
#include <conio.h>
void ImprimeLinea(int Elemento[],int NumElementos);
int main(void)
{
int Basura[3][4] =
{
{ 2, 4, 5, 8},
{ 3, 4, 6, 9},
{12, 10, 8, 6}
};
int i,j;
clrscr();
for(i=0;i<3;i++)
{
ImprimeLinea(Basura[i],4);
printf("\n");
}
return 0;
}
void ImprimeLinea(int Elemento[],int NumElementos)
{
int i;
for(i=0;i<NumElementos;i++) printf("%8d",Elemento[i]);
} |
8.3. Les estructures.
Quan es tracta d'enmagatzemar dades és molt normal utilitzar una
representació en format de fitxa, com les Fitxes d'una biblioteca
o les dades d'una persona al fitxer de dades personals d'una empresa. Son
allò que a las bases de dades es diuen registres.
![](imagenes/fichas01.jpg)
A la figura veiem un registre, d'una base de dades que es pot anomenar
agenda. És el registre número 123. Els camps són
Nom, Direcció, Telèfon, Ciutat,
Província, Codi Postal i Telèfon 2.
El número del registre també és un camp.
En C es poden declarar estructures per simular aquesta situació:
Primer es declara un nou tipus de dades i després es poden declarar
variables amb aquest nou tipus. El programa següent ens serveix per
explicar les estructures amb l'exemple agenda.
#include <stdio.h>
/*Defineix el nou tipus d'estructura de dades*/
struct RegistreAgenda
{
int Num;
char Nom[45];
char Adreca[35];
char Telefon[15];
char Poblacio[20];
char CodiPostal[5];
char Telefon2[15];
};
/*funció principal*/
main(void)
{
/*Declara RegistreDeTreball de tipus RegistreAgenda
*/
struct RegistreAgenda RegistreDeTreball;
printf("Número: "); scanf("%d",&RegistreDeTreball.Num);
fflush(stdin);
printf("Nom: ");
gets(RegistreDeTreball.Nom);
printf("Adreça: ");
gets(RegistreDeTreball.Adreca);
printf("Telèfon: ");
gets(RegistreDeTreball.Telefon);
printf("Població: ");
gets(RegistreDeTreball.Poblacio);
printf("Codi Postal: ");
gets(RegistreDeTreball.CodiPostal);
printf("Telèfon 2: ");
gets(RegistreDeTreball.Telefon2);
printf("\nLes dades que has entrat son:\n");
printf("Registre número %d\n", RegistreDeTreball.Num)
printf("Nom: %s\n", RegistreDeTreball.Nom);
printf("Adreça: %s\n", RegistreDeTreball.Adreca);
printf("Telèfon: %s\n", RegistreDeTreball.Telefon);
printf("Població: %s\n", RegistreDeTreball.Poblacio);
printf("Codi Postal: %s\n", RegistreDeTreball.CodiPostal);
printf("Telèfon 2: %s\n", RegistreDeTreball.Telefon2);
} |
En aquest programa hem definit un nou tipus de dades RegistreAgenda
i hem declarat i hem fet ús d'una variable d'aquest tipus RegistreDeTreball.
Per accedir a les dades d'una variable de tipus estructura es fa ús
del punt per indicar un camp com RegistreDeTreball.Nom.
Milorem ara aquest programa per fer funcions que ens realitzin dues
de les tasques més frequents quan es treballa amb dades: Presa de
dades de teclat i impressió en pantalla:
#include <stdio.h>
/*Defineix el nou tipus d'estructura de dades*/
struct RegistreAgenda
{
int Num;
char Nom[45];
char Adreca[35];
char Telefon[15];
char Poblacio[20];
char CodiPostal[5];
char Telefon2[15];
};
void EntraReg(struct RegistreAgenda *Reg);
void ImprimeReg(struct RegistreAgenda *Reg);
int main(void)
{
/*Declara RegistreDeTreball de tipus RegistreAgenda
*/
struct RegistreAgenda RegistreDeTreball;
EntraReg(&RegistreDeTreball);
printf("\nLes dades que has entrat son:\n");
ImprimeReg(&RegistreDeTreball);
return 0;
}
void EntraReg(struct RegistreAgenda *Reg)
{
printf("Número: "); scanf("%d",&Reg->Num);
fflush(stdin);
printf("Nom: "); gets(Reg->Nom);
printf("Adreça: "); gets(Reg->Adreca);
printf("Telèfon: "); gets(Reg->Telefon);
printf("Població: "); gets(Reg->Poblacio);
printf("Codi Postal: "); gets(Reg->CodiPostal);
printf("Telèfon 2: "); gets(Reg->Telefon2);
}
void ImprimeReg(struct RegistreAgenda *Reg)
{
printf("Registre número %d\n", Reg->Num);
printf("Nom: %s\n", Reg->Nom);
printf("Adreça: %s\n", Reg->Adreca);
printf("Telèfon: %s\n", Reg->Telefon);
printf("Població: %s\n", Reg->Poblacio);
printf("Codi Postal: %s\n", Reg->CodiPostal);
printf("Telèfon 2: %s\n", Reg->Telefon2);
} |
Observa les definicions de pas de paràmetres "struct RegistreAgenda
*Reg" en el moment de definir la funció i "&RegistreDeTreball"
en el moment de fer-ne ús des-de altra funció.
Aixó fa que en el moment de fer ús de les dades de una
variable definida com *Reg la sintaxi sigui de la manera Reg->Num.
8.4. Variables vector d'estructures.
A la figura de la pàgina anterior hi ha 5 registres. Per poder enmagatzemar
aquest 5 registres podem definir una variable matriu de manera que cada
element de la matriu sigui un registre. Observa el programa següent
i veuràs com es declara una matriu d'aquest tipus i com es fa ús
de les seves dades.
#include <stdio.h>
struct RegistreAgenda
{
int Num;
char Nom[45];
char Adreca[35];
char Telefon[15];
char Poblacio[20];
char CodiPostal[5];
char Telefon2[15];
};
void main(void)
{
/*Declara la matriu Agenda de tipus RegistreAgenda
*/
struct RegistreAgenda Agenda[5];
int i;
char ch;
for(i=0;i<5;i++)
{
printf("Número: ");
scanf("%d",&RegistreDeTreball.Num);
printf("\nIntrodueix el
registre nº %d\n",i+1);
printf("Nom: "); gets(Agenda[i].Nom);
printf("Adreça: ");
gets(Agenda[i].Adreca);
printf("Telèfon:
"); gets(Agenda[i].Telefon);
printf("Població:
"); gets(Agenda[i].Poblacio);
printf("Codi Postal: ");
gets(Agenda[i].CodiPostal);
printf("Telèfon 2:
"); gets(Agenda[i].Telefon2);
}
printf("\nLes dades que has entrat són:\n");
for(i=0;i<5;i++)
{
printf("Registre número
%d", RegistreDeTreball.Num);
printf("\nAquest ‚s el registre
nº %d\n",i+1);
printf("Nom: %s\n", Agenda[i].Nom);
printf("Adreça: %s\n",
Agenda[i].Adreca);
printf("Telèfon:
%s\n", Agenda[i].Telefon);
printf("Població:
%s\n", Agenda[i].Poblacio);
printf("Codi Postal: %s\n",
Agenda[i].CodiPostal);
printf("Telèfon 2:
%s\n", Agenda[i].Telefon2);
}
printf("Prem return per continuar ");
while(ch = getc(stdin) !='\n');
} |
Com veus la instrucció de declaració és molt semblant
a la de l'exercici de la pàgina 1 i per fer ús de les dades
es posa l'index davant el punt.
Així:
Agenda[1].Nom és el nom de l'element 1 de la matriu.
Agenda[3].Telèfon és el telèfon de l'element 3
de la matriu
Nota: En el moment de declarar una variable estructura o de definir
una variable matriu d'estructures es pot assignar valor a les dades de
l'estructura. Així podem posar les inicialtzacions del quadre:
Variable RegistreDeTreball inicialitzada |
Matriu Agenda inicialitzada |
struct RegistreAgenda RegistreDeTreball =
{
123,
"Riera,Riuet;Reidor",
"c) Llevador s/n",
"(93) 7.25.34.23",
"Sabadell",
"08230",
"93.7.25.09.09"
}; |
struct RegistreAgenda Agenda[5] =
{
{
123,
"Riera,Riuet;Reidor"
"c) Llevador s/n",
"(93) 7.25.34.23",
"Sabadell",
"08230",
"(93) 7.25.0909"
},
{
126,
"Gozalvez,Lopez;Regidor",
"c) Lavanderas 123",
"(93) 7.25.12.92",
"Sabadell",
"08231",
"(93) 7.26.12.12"
}
} |
Així podem entrar en el programa amb les dades de la variable
RegistreDeTreball inicialitzades o de la matriu Agenda. Això es
fa quan tenim unes dades constants que no s'han de variar al llarg de l'execució
del programa.
8.5. Estructures niades
Si es té definit un nou tipus d'estructura es pot utilitzar dins
d'una altra estructura. Un exemple pot ser el següent, en el que el
Nom d'una persona és una estructura inclosa dins de l'estructura
RegistreAgenda (Fem un versió incompleta).
#include <stdio.h>
struct Persona
{
char Nom[15];
char Pcognom[15];
char Scognom[15];
};
struct RegistreAgenda
{
int Num;
struct Persona PersonaRA;
char Adreca[35];
char Telefon[15];
char Poblacio[20];
char CodiPostal[5];
char Telefon2[15];
};
void main(void)
{
struct RegistreAgenda RegistreDeTreball;
printf("Número ");scanf("%d",&RegistreDeTreball.Num);fflush(stdin);
printf("Nom: "); gets(RegistreDeTreball.PersonaRA.Nom);
printf("Primer cognom: "); gets(RegistreDeTreball.PersonaRA.Pcognom);
printf("Segon cognom: "); gets(RegistreDeTreball.PersonaRA.Scognom);
printf("\nLes dades que has entrat són:\n");
printf("Número %d\n",RegistreDeTreball.Num);
printf("Nom: %s\n", RegistreDeTreball.PersonaRA.Nom);
printf("Primer cognom: %s\n", RegistreDeTreball.PersonaRA.Pcognom);
printf("Segon cognom: %s\n", RegistreDeTreball.PersonaRA.Scognom);
} |
8.6. Exercicis
-
Un programa ens demana cinc noms i els imprimeix després.
-
Declara una matriu 4x3 de números sencers i escriu els seus elements
multiplicats per 5.
-
Un programa ens demana els 8 elements d'una matriu 4x2. Després
ens demana els elements d'una altra matriu 4x2. Per últim ens contesta
amb una pantalla com la següent en la que la última matriu
és la matriu suma.
-
Un programa ens demana els elements d'una matriu 3x3 i ens escriu a la
matriu transposada i a suma de les dues matrius.
-
Un programa ens demana una llista de noms d'un número indeterminat
d'elements. Després els escriu tots i ens diu qual és el
primer i l'últim per ordre alfabètic i a més ens diu
en quina posició es troben.
-
Escriu els programes de les pàgines 4 i 5 a l'ordinador i executa'ls.
-
Fes un programa que declari un vector de com a mínim 19 elements
que han de ser els registres d'una base de dades personals de la classe.
Aquest programa tindrà les funcions següents:
Principal, Demanar(Reg), Imprimir(Reg)
Com que el programa ens ha de permetre editar tots els registres has
de fer un menú d'opcions.
-
Afegeix una opció d'ordenació dels registres.
-
Afegeix l'opció de cerca seqüencial.
-
Afegeix l'opció de cerca dicotòmica.
8.7. Les unions
Una unió és un instrument que permet guardar dades de diferents
tipus a la mateixa variable de memòria. Es fa us d'aquest tipus
de variable quan no se sap que tipus de dades es guardaran.
Les unions es preparen d'una manera molt semblant a les estructures.
Es defineix un nou tipus de dades i després es creen les variables
d'aquest tipus.
Nou tipus:
union Dat
{
int Petit;
doubel Gros;
char Lletra;
} |
Possibles declaracions de variables:
union Dat Dia;
union Dat Dies[100];
union Dat *Dia;
La primera declara la variable Mida del tipus union Dat, la segona és
una matriu del mateix tipus i la tercera un punter.
Quan el compilador es troba la instrucció union Dat Mida reserva
una zona de memòria del màxim número de bytes dels
tipus inclosos a la definició de la unió; Així un
char necessita un byte, un int 2 bytes y un double necessita 8. Per tant
es farà una reserva de vuit bytes.
Per assignar dades a la variable Dia hem de fer ús de l'operador
. al igual que en una estructura:
Dia.Petit=25;
Dia.Gros=3333333;
Dia.Lletra='h';
Hem de pensar que només pot aparèixer una informació,
així que la primera instrucció posa a Dia un 25. La segona
treu aquesta informació i la substitueix per 3333333. Al final queda
una h.
Quan es treballa amb punters es fa ús dels operadors & (direcció)
i ->.