M3 - Programació estructurada / Continguts UF1: Taules
De wikiserver
La revisió el 14:31, 17 feb 2018 per Rsort (Discussió | contribucions) (→Cerca seqüencial en taules ordenades)
Taules (Arrays)
- Conjunt de variables que conté valors tots del mateix tipus.
- El nombre de posició de l'element s'anomena l'índex.
- Conté N element.
- Per referir-se als diferents elements de la taula s'utilitza el nom de la taula seguit per l'índex entre claudàtors ([]).
- Primer element de la taula té índex 0.
- Els elements són: c[0], c[1], c[2]...
Contingut
Declaració i creació de taules
- La següent declaració i expressió crea una taula, que conté 12 elements int, i emmagatzema la referència
de la taula en la variable c:
int c[] = new int[12];
- Aquesta tasca també pot realitzar-se en dos passos, com es mostra a continuació:
int c[ ]; // declara la variable taula c = new int[12]; // crea la taula; ho assigna a la variable tipus taula
- En crear una taula, cadascun dels seus elements rep un valor predeterminat: zero per als elements numèrics, false per als elements boolean.
- Quan es declara un taula, el seu tipus i els claudàtors poden combinar-se al principi de la declaració per indicar que tots els identificadors a la declaració són variables tipus taula. Per exemple, la declaració
double[] taula1, taula2;
- indica que taula1 i taula2 són variables tipus “taula de double”. L'anterior declaració és
- equivalent a:
double taula1[]; double taula2[]; o double[] taula1; double[] taula2;
Inicialització de taules
- Es pot crear un taula i inicialitzar els seus elements amb una llista d'expressions separades per comes (llista inicialitzadora) tancada entre claus ({ i });
- la longitud de la taula es determina sobre la base del nombre d'elements en la llista inicialitzadora. Per exemple,
la declaració:
int arrayEnters[] = { 10, 20, 30, 40, 50 };
- crea un taula de cinc elements amb els valors d'índexs 0, 1, 2, 3 i 4. L'element arrayEnters [0] s'inicialitza amb 10, arrayEnters [1] s'inicialitza amb 20, i així en endavant.
- Aquesta declaració no requereix que new creï l'objecte taula.
- La grandària de la taula queda determinada pel nombre d'elements de la llista inicialitzadora.
Manipulació de dades
- No és possible usar l’identificador de l’array directament per invocar operacions i així manipular les dades contingudes.
- Per exemple, no és possible fer el següent:
int[] a = {10, 20, 30, 40, 50}; int[] b = {50, 60, 70, 80, 100}; int[] c = a + b;
- Les dades emmagatzemades dins d’arrays nomès es poden manipular de manera individual, posició per posició.
- Cada posició d’un array té exactament el mateix comportament que una variable de tipus primitiu.
Exemples
Inicialització de la taula mitjançant codi
L’aplicació següent crea una taula de 10 elements i assigna a cada element un dels enters parells del 2 al 20.
- La propietat length es dóna la longitud d’una taula
public class InicialitzacioTaula {
public static void main(String args[]) {
final int LONGITUD = 10; // declara la constant
int taula[] = new int[LONGITUD]; // crea la taula
// calcula el valor per a cada element de la taula
int comptador = 0;
while (comptador < taula.length) {
taula[comptador] = 2 + 2 * comptador;
comptador++;
}
}
}
Sumar els elements d’una taula
public class SumaTaula {
public static void main(String args[]) {
int taula[] = {87, 68, 94, 100, 83, 78, 85, 91, 76, 87};
int total = 0;
// suma el valor de cada elemento al total
int comptador = 0;
while (comptador < taula.length) {
total = total + taula[ comptador];
comptador++;
}
System.out.println("Total dels elements de la taula: "+ total);
}
}
Emmagatzematge de l’entrada de dades en una taula
- Els arrays són útils per emmagatzemar un nombre arbitrari de dades provinents del sistema d’una entrada (per exemple, des del teclat).
- Les dades s’aniran llegint una per una, i assignant a cadascuna de les posicions de l’array a partir del seu índex.
- Els esquemes dels exemples següent utilitzen el teclat com a sistema d’entrada de dades. Són aplicables a altres mecanismes d'entrada (per exemple, un fitxer).
Entrada de seqüències de valors per teclat
- Previ: : llegir seqüències de dades entrades des del teclat en una sola línia de text.
- Quan s’usa una instrucció lector.next... es pot introduir una seqüència de valors separats de la resta per almenys un espai. Es llegeix un valor i la resta queden pendents de noves instruccions de lectura, que llegiran automàticament el següent valor.
- Quan no quedin valors, la propera instrucció de lectura, ara si, esperarà la introducció d'un nou valor.
- lector.nextLine(); provoca que esdescartin tots els valors pendents de llegir de la seqüència actual.
- Es poden llegir seqüències de valors de diferents tipus de dades barrejats.
- lector.hasNext... Serveix per comprovar el tipus de dades del valor a llegir abans de llegir-lo.
- Per llegir múltiples valors s'utilitza una estructura de repetició que variarà en funció de si es coneix la quantitat de dades exactes que cal llegir o no.
Quantitat de dades coneguda
- S'utilitza un comptador. per controlar el nombre de lectures. Si se n’escriuen més dels esperats, la resta es descarten.
- L’exemple següent, mostra com cal fer la lectura d’un seguit de valors enters.
- No és necessari escriure tots els valors en una sola línia de text.
- Controla mitjançant una estructura de selecció si el valor que és apunt de ser llegit serà realment un enter o no.
import java.util.Scanner;
public class LectorValorsConeguts {
//Es llegiran 5 valors.
public static void main(String[] args) {
final int NUM_VALORS = 5;
int dades[] = new int[NUM_VALORS];
Scanner lector = new Scanner(System.in);
System.out.println("Escriu " + NUM_VALORS + " enters.");
//Es llegeixen exactament NUM_VALORS valors.
int numValorsLlegits = 0;
while (numValorsLlegits < NUM_VALORS) {
//Abans de llegir, comprovem si realment hi ha un enter.
if (lector.hasNextInt()) {
int valor = lector.nextInt();
dades[numValorsLlegits] = valor;
numValorsLlegits++;
System.out.println("Valor " + numValorsLlegits + " llegit: " + valor);
} else {
//Si el valor no és enter, es llegeix però s’ignora.
//No s’avança tampoc el comptador.
lector.next();
}
}
//Els valors que sobrin a la darrera línia escrita es descarten.
lector.nextLine();
System.out.println("Ja s’han llegit " + NUM_VALORS + " valors.");
}
}
Quantitat de dades desconeguda
- Quan el nombre de valors no és conegut a priori, es pot:
- Abans de llegir cap valor, demanar quants dades s’introduiran.
- Fer que el primer valor dins de la seqüència n’indiqui la longitud.
- Establir un valor especial que no forma part de les dades per tractar dins el programa, com a marca de final de seqüència. Per exemple, dins una llista de notes, qualsevol valor negatiu o major que 10 serviria
- Usar un valor d’un tipus de dada diferent. Per exemple, un programa que processa valors reals arbitraris per fer càlculs matemàtics podria usar un caràcter com a marca de fi.
- Quan no és possible ajustar exactament la mida del array a la llargària de la seqüència de valors, cal triar un valor concret prefixat intentant que en cap cas es superi. En el cas que hi hagués valors excedents, es perdrien. Per exemple, si ja sabeu que el nombre d’estudiants en una classe pot oscil·lar, però mai no es permetrà que n’hi hagi més de 80, es pot triar aquest valor com a mida de l’array.
- Quan la mida del array no s'ajusta a la seqüència de valors, cal anar en compte per tractar només les dades llegides des de l'entrada. L’atribut length només indica la capacitat de la taula. Per tant, serà necessari disposar d’una variable auxiliar addicional, de tipus enter, en què s’emmagatzemi el nombre de dades que realment hi ha dins de la taula.
import java.util.Scanner;
public class LectorValorsDesconeguts {
public static void main(String[] args) {
final int MARCA_FI = -1;
final int MAX_VALORS = 80;
int dades[] = new int[MAX_VALORS];
int elements = 0;
Scanner lector = new Scanner(System.in);
System.out.println("Escriu diferents valors enters. Com a màxim: " + MAX_VALORS);
System.out.println("Després del darrer valor escriu un " + MARCA_FI);
//Es llegeixen com a molt MAX_VALORS valors.
boolean marcaTrobada = false;
while (!marcaTrobada && elements < dades.length) {
//Abans de llegir, comprovem si realment hi ha un enter.
if (lector.hasNextInt()) {
int valor = lector.nextInt();
//És la marca de fi?
if (valor == MARCA_FI) {
//Sí que ho és.
marcaTrobada = true;
} else {
//No. És un valor que ha de ser tractat.
dades[elements] = valor;
elements++;
}
} else {
//Si el valor no és enter, es llegeix però s’ignora.
lector.next();
}
} //Els valors que sobrin a la darrera línia escrita es descarten.
lector.nextLine();
System.out.println("Ja s’han llegit tots els valors.");
}
}
Tractament seqüencial de taules
La sentència for
- Quan es coneix, a priori, la quantitat exacta de dades que cal llegir, es recomanable utilitzar la sentència for.
Sintaxi i estructura
for (inicialització comptador ; expressió booleana ; increment comptador) { Instruccions per la lectura i introducció de dades a la taula. } Exemple: for (i = 0; i<10; i++) { ........ }
Recorregut de taules
- Quan treballem amb taules, molt sovint haurem de fer càlculs en què estan implicats tots els valors emmagatzemats. En aquest cas, cal fer-ne un recorregut seqüencial de les posicions i anar-les processant per obtenir un resultat final.
- Exemple: calcular la mitjana aritmètica d’un seguit de notes, que requereix sumar els valors de totes i cadascuna i dividir el resultat entre el seu nombre.
public class MitjanaNotesRecorregut {
//Programa que fa un recorregut d’un array: càlcul de la mitjana aritmètica.
public static void main(String[] args) {
//Es parteix d’un array que conté tots els valors.
double[] arrayNotes = {4.2, 5.5, 9.1, 10, 4.9, 8, 8.5, 7, 6.6, 5, 9};
//Acumulador de la suma de valors.
double acumulat = 0;
double resultat;
//Cal recórrer tot l’array d’extrem a extrem.
for (int i = 0; i < arrayNotes.length; i++) {
acumulat = acumulat + arrayNotes[i];
}
resultat = acumulat / arrayNotes.length;
System.out.printf("La mitjana és: %.2f \n", resultat);
}
}
La sentència for millorada
- Itera a través dels elements d'una taula sense utilitzar un comptador (amb la qual cosa, evita la possibilitat de “sortir-se” de la taula).
- Simplifica el codi per iterar a través d'un array.
- Només pot utilitzar-se per obtenir elements de la taula; no pot utilitzar-se per modificar els elements.
- La sintaxi d’una instrucció for millorada és:
for (paràmetre: nomTaula) { instruccions }
- on:
- paràmetre té dues parts: un tipus i un identificador (per exemple, int numero)
- nomTaula és la taula a través de la qual s'iterarà.
- El tipus del paràmetre ha de concordar amb el tipus dels elements en la taula.
- Exemple: calcular la suma dels enters en una taula de qualificacions d’estudiants.
public class ForMillorat {
public static void main( String args[] ){
int taula[] = { 87, 68, 94, 100, 83, 78, 85, 91, 76, 87 };
int total = 0;
// suma el valor de cada element al total
for (int numero : taula)
total = total+numero;
System.out.printf( "Total d'elements de la taula: %d\n", total );
}
}
Cerca seqüencial en taules
La cerca seqüencial compara cada element del vector amb el valor desitjat, fins que el troba o acaba de llegir el vector sencer. En aquest cas donat que no sabem si arribarem al final de la taula NO s’ha d’utilitzar la instrucció for. Veiem el següent programa on donat un array de notes, ens interessa saber si algú ha tret un 10.
Cerca seqüencial en taules ordenades
- Donat que el vector està ordenat, si trobem un valor més gran que el que busquem, ja estem segurs de que no trobarem l’element desitjat i podem finalitzar la cerca.
- Exemple: Cercar si hi ha una nota de 7: