![]() |
Índex |
Suposeu que tenim una empresa que té 40 sucursals i que cada final de mes es dedica a recollir les vendes que ha fet cadascuna d'aquestes sucursals i a sumar-les amb la finalitat d'obtenir el total de vendes netes al llarg del mes. Per emmagatzemar les vendes de les 40 sucursals dins el nostre programa la primera solució que se'ns acudiria seria declarar-nos 40 variables de tipus 'int', demanar els seus 40 valors i fer la suma de les quaranta variables immediatament després.
A la pràctica mai es fa servir una solució així, i el que es fa és agrupar tots els valors dins una variable de tipus vector.
Un vector és una variable composta, que pot emmagatzemar molts
valors d'un mateix tipus. Però veiem un dibuix amb un exemple que
pot ajudar-nos a entendre el que és un vector
Nom del vector: VendesSucursal | ||||
Lloc: | 0 | 1 | i... | 39 |
Dada: | 1000 | 2565 | ... | 595 |
VendesSucursal[0] | VendesSucursal[1] | VendesSucursal[i] ... | VendesSucursal[39] |
En aquest cas la variable de tipus vector se'n diu VendesSucursal, i està com-posta de 40 posicions, cadascuna de les quals pot emmagatzemar un valor. Cadascu-na de les posicions del vector haurà d'emmagatzemar valors del mateix tipus. El primer valor emmagatzemat al vector l'anomenarem dins el programa per VendesSucursal [0] , el segon VendesSucursal [1] i així fins al darrer (en aquest cas fins a VendesSucursal [39]) . És a dir, mitjançant un índex tancat entre parèntesi, accedim als valors que composen el vector.
#include <stdio.h>
#define NRO_SUCURSALS 5 /*Dimensió del vector.*/ void main(void)
/*Introducció de les dades amb les vendes
de les sucursals */
/*Procés de les dades (Suma de les vendes
per calcular el total */
/* Escriptura del resultat */
|
Límits del salari brut | |||
IRPF | |||
salari <= | 1400000 | 8% | |
1400000 | < salari <= | 1800000 | 11% |
1800000 | < salari <= | 2200000 | 13% |
2200000 | < salari <= | 3000000 | 17% |
3000000 | < salari <= | 5000000 | 20% |
5000000 | < salari | 25% |
Cal dir que el compilador de C afegeix dins el vector un caràcter '\0' que serveix per assenyalar la fi de la cadena. A més cal tenir en compte que l'espai en blanc també ocupa posició, així com qualsevol caràcter emmagatzemable dins una variable de tipus char.
String en C és un vector amb un codi ASCII \0 en darrer lloc | |||||||||
Vector Nom | |||||||||
P | e | r | e | M | a | r | í | \0 | |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Exemple. Fem un programa que ens demana un nom i escriu els seus caràcters un a un dins un bucle for.
#include <stdio.h>
#include <string.h> main()
/*Tractament de nom amb funcions predefinides de
string*/
llargada=strlen(nom);
/*Tractament de nom amb els elemnts de vector*/
return 0;
|
També es convenient dir que si parlem de 'p' (amb cometes simples), estem parlant d'un caràcter i el compilador no coloca el caràcter '\0' al final. Així si per exemple tenim l'assignació,
s'estarà emmagatzemant el codi ASCII del caràcter 'c' (el 99) en la posició de memòria on estigui definida la variable caracter.
Exemple:
Tenim un programa que llegeix de l'entrada caràcters fins que s'introdueix un punt. A més, a mida que s'introdueixen caràcters s'examina si el caràcter introduït és un dígit numèric ('0', '1', '2',...,'9') comptant el nombre de cadascun dels dígits que s'han introduït.
Per emmagatzemar el número de dígits de cada tipus que
s'han introduït farem servir un vector. A la posició zero emmagatzemarem
els números zeros que s'han introduït a l'entrada. A la posició
1, els 1 i així successivament.
/*10 dígits diferents al sistema decimal*/
#define NRO_DIGITS 10 #include <stdio.h> void main(void)
int caracter, i, final;
/*Inicialització de variables*/
/*Entrada i tractament dels caràcters*/
/* Escriptura dels resultats per pantalla */
|
Per fer la crida a totes les funcions de string.h és necessari que els strings que es passin com paràmetres a les funcions tinguin el caràcter '\0' ficat al darrera.
Si tenim el vector,
en ell podrem emmagatzemar cadenes de caràcters de com a màxim 44 elements (numerats des de la 0 fins a la 43), ja que el caràcter de final d'string '\0' ocupa una posició dins el vector.
Per assignar valor a les variables de tipus vectors de caràcters es fa la crida a la funció strcpy. Aquesta funció rep una cadena de caràcters d'entrada i treu de sortida un altre cadena de caràcters que és una còpia exacta de la que ha entrat. Per assignar una variable vector de caràcters fem,
i després de la crida tindrem emmagatzemat "Pere Martínez Ablanedo" a nom.
Un exemple de programa que fa servir cadenes de caràcters podria
ser un programa que donat un vector de caràcters et compta el nombre
de lletres 'a' que hi ha dins del vector i t'ho retorna.
#include <stdio.h>
int CuentaAs (char cadena[]); void main()
/* Entrada de dades pel teclat */
/* Procés de les dades (crida a CuentaAs)
*/
/* Escriptura del resultat per pantalla */
int CuentaAs (char cadena[])
final = (cadena[i]=='\0');
return asFinsAra;
|
En aquest cas tenim un vector que es passa com paràmetre a una funció.
Aleshores per permetre que el vector que arriba a la funció pugui tenir qualsevol mida, el que es fa és declarar el paràmetre amb la dimensió ( nombre de posicions del vector) buida. D'aquesta forma la dimensió es determinarà en temps d'execució de la funció i pot ser diferent a cadascuna de les crides que es fan a la funció. Al nostre exemple es fa la crida CuentaAs(nom);, així doncs en el moment que s'executi la funció CuentaAs, la dimensió de cadena passarà a ser 45, que és la dimensió de nom.
Si després cridéssim la funció strlen amb un altre vector, cadena passaria a tenir tants elements com el nou vector passat.
Si la cridem per exemple amb els següents paràmetres, saltar_espais("La casa",2) ens haurà de retornar 3, que és el lloc de la cadena on comença la segona paraula.
Funció cerca_sequencial |
/*valor és l'element a cercar a dintre del vector.
v és el vector on tenim els valors on volem trobar el valor.*/ int cerca_sequencial (long v[], long tamany, long valor)
|
Exemple d'ús d'aquesta funció:
El següent programa llegeix pel teclat els 12 ingressos (mensuals) que ha tingut en Joan al llarg de l'any, després (i utilitzant la funció de cerca seqüencial a dintre del vector) cerca si Joan ha cobrat algun mes 115000 pessetes, finalment dóna un missatge informant del resultat obtingut.
Com utilitzar la funció cerca_sequencial |
#include <stdio.h>
#define TRUE 1
void main (void)
|
Com a resultat de la cerca el programa ens ha de dir si Joan ha rebut o no aquesta quantitat, i en cas positiu, ens digui en quin mes l'ha cobrat.
Nota: Haureu de modificar el resultat la funció de cerca
seqüencial. Aquesta funció haurà de retornar el següent:
0: | Si no hem trobat l'ingrés a dintre del vector. |
i+1 (el mes): | Si trobem l'ingrés a dins del vector. |
Si per exemple l'ordre és creixent tenim que:
El següent algorisme suposa que els valors del vector són ordenats de manera creixent. Divideix el vector en dues parts sensiblement iguals i per mig d'una comparació d'accés amb el valor de l'element del mig, elimina aquella de les dues parts que no pot contenir el valor cercat:
la part que precedeix l'element del mig, si l'element del mig és inferior al cercat, o la part que ve a continuació de l'element del mig si aquest és superior al element cercat.
La part no eliminada es torna a dividir en dos i així successivament fins trobat l'element o bé que la part no eliminada sigui d'un element.
/* valor és l'element a cercar a dintre del vector.
v és el vector on tenim els valors on volem trobar el valor. tamany és la llargària del vector. Nota: El vector donat ha de ser ordenat.*/ int CercaDicotomica(long v[], long tamany, long valor)
return trobat;
|
Observem ara com es comporta aquesta funció amb tres casos ben diferents:
Cas A) Paràmetres: Valor = 63; Tamany=10;
|
|
|
|
|
|
|
|
|
|
|
inf =0; sup =9; med=5; trobat = true;
|
inf |
|
|
|
|
med |
|
|
|
sup |
Cas B) Paràmetres: Valor = 31; Tamany=10;
|
|
|
|
|
|
|
|
|
|
|
inf =0; sup =9; med=5; trobat = false;
|
inf |
|
|
|
|
med |
|
|
|
sup |
inf =0; sup =4; med=2; trobat = true;
|
inf |
|
med |
|
52
|
|
|
|
|
|
Cas C) Paràmetres: Valor = 100; Tamany=10;
|
|
|
|
|
|
|
|
|
|
|
Pas 1:
inf =0; sup =9; med=5; trobat = false;
|
inf |
|
|
|
|
med |
|
|
|
sup |
Pas 2:
inf =6; sup =9; med=8; trobat = false;
V= |
|
|
|
|
|
|
inf |
|
med |
sup |
Pas 3:
inf =9; sup =9; med=9; trobat = false;
|
|
|
|
|
|
|
|
|
|
inf,sup,med |
Veiem que ha necessitat 3 iteracions per adonar-se que el valor a buscar
no es a dintre del vector.
Per cada element tractat (v[k],v[k+1]) s'intercanvien els seus valors si no són en ordre creixent.
Al final de la primera passada a tot el vector tenim en la posició
més alta del vector el element més gran. Desprès es
comença una segona passada sobre el subvector v(0..tamany-2) per
a posar en la posició v[tamany-2] l'element més gran d'aquest
subvector.
Pseudo codi per aquest problema: | Per i := (tamany-1) fins a 1 fer
Mitjançant intercanvis successius en els parells (v[1],v[2]),(v[2],v[3]), (v[3],v[4]),. . . , (v[i-2],v[i-1]), portar l'element més gran a la posició v[i]. Fi per |
Aquest algorisme amb el llenguatge C queda de la següent manera: | void ordenacio_bombolla (long v[], long tamany)
{ long i, k, aux; for (i=tamany-1;i>=1;i--) for (k=0;k<=i-1; k++) if (v[k]>v[k+1]) { aux = v[k]; v[k] = v[k+1]; v[k+1] = aux; } } |
Observem com actua aquest algorisme sobre el següent vector:
Posicions del vector | |||||||
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
Estat inicial | 23 | 10 | 75 | 5 | 37 | 49 | 53 |
Primer pas | 10 | 23 | 5 | 37 | 49 | 53 | 75* |
Segon pas | 10 | 5 | 23 | 37 | 49 | 53* | 75 |
Tercer pas | 5 | 10 | 23 | 37 | 49* | 53 | 75 |
Quart pas | 5 | 10 | 23 | 37* | 49 | 53 | 75 |
Cinquè pas | 5 | 10 | 23* | 37 | 49 | 53 | 75 |
Sisè pas (fi) | 5 | 10* | 23 | 37 | 49 | 53 | 75 |
Es veu clarament que en el tercer pas el vector ja és ordenat i en canvi nosaltres hem seguit efectuant tres passos més. Així la millora d'aquest algorisme consisteix en fer que aquest s'aturi en adonar-se de què el vector ja és ordenat. El següent algorisme incorpora una variable booleana on emmagatzemarem si durant el pas actual s'ha produït algun intercanvi de parelles.
Al finalitzar cada pas comprovarem la variable booleana i si aquesta ens diu que no em efectuat cap intercanvi vol dir que el vector ja és ordenat i per tant ja hem acabat.
La millora del mètode de la bombolla amb el llenguatge C queda
de la següent manera:
/*v és el vector on tenim els valors a ordenar.
tamany és la llargària del vector.*/ void ordenacio_bombolla_millorada (long v[], long tamany)
|
En tot moment el vector es compost de dues parts:
La solució es pot escriure així:
Per i de 1 fins a (tamany-1) fer
Insertar el valor de v[i] al lloc apropiat entre
els valors de v(0..i-1)
Fi per
Després d'aquesta insercció, els elements A[1],A[2], ....,A[i] quedan ordenants.
La solució per un vector de: A[1],A[2], ....,A[N] posicions es
pot escriure en pseudocodi així:
A[0] := -infinit;
Per i := 2 fins a N fer j := i; Mentre A[j]<A[j - 1] fer swap(A[j],A[j - 1]); j := j - 1; Fi mentre; Fi per |
En el pas i-èssim seleccionem el contingut més petit, d'entre els A[i],..., A[N], i l'intercanviem (swap) amb A[i].
Com a resultat , després de i iteracions els i continguts més baixos ocupen les posicions A[1],...,A[i], de forma ordenanada.
La solució per un vector de: A[1],A[2], ....,A[N] posicions es
pot escriure així:
Per i := 1 fins a N - 1 fer
k := i; x := A[i]; Per j := i + 1 fins a N fer Si A[j] < x llavors k := j; x := A[j]; Fi si; A[k] := A[i]; A[i] := x; Fi per; Fi per; |