Informática


Programació estructurada d'ordinadors


  • LA PROGRAMACIÓ ESTRUCTURADA

  • Sorgiment de la programació estructurada

  • És molt important alhora de construir un programa amb un llenguatge d'alt nivell, el control de la seva execució. Rarament un programa s'integra (totalment) amb un conjunt d'instruccions que s'executin successivament (instruccions seqüencials), una darrera l'altra, en canvi, és molt més freqüent haver d'executar varies vegades algunes seccions determinades del programa (instruccions repetitives) o bifurcar l'execució en funció del resultat de diferents condicions (instruccions selectives).

    Els llenguatges més antics, com Fortran, es basaven pràcticament en una sola instrucció per definir el control dels programes: la instrucció goto (de l'anglès “go to”, que vol dir “anar a”). Aquesta instrucció i les seves variants, acompanyats d'unes etiquetes numèriques, permetien variar l'orde d'execució del programa. Indica el nombre de la instrucció o línia de programa on ha de dirigir-se la transferència de control, és a dir, la línia a partir de la qual el programa s'haurà d'executar. Per exemple, “go to 10” volia dir que efectués l'execució a partir de la línia 10. Però les etiquetes numèriques i les transferències arbitràries fan que els programes siguin poc legibles i difícils de comprendre, ja que si el programador, desitja saber què fa realment el programa, no té més remei que mantenir en ment tota la seqüència d'instruccions anteriors i posteriors al salt originat per la sentència goto.

    Després d'haver fracassat intentant solucionar aquest problema, utilitzant etiquetes no numèriques, va sorgir una nova manera que reduïa notablement l'ús d'aquesta instrucció, substituint-la per altres de molt més comprensibles. La solució van ser dues instruccions de control:

    1a) La instrucció condicional if-then-else, que presenta la següent forma:if

    condició then instrucció-1 else instrucció-2”. Si la condició es compleix, s'executa “instrucció-1”, si no es compleix, s'executa “instrucció-2”.

    2a) Els bucles condicionals while i until, que presenten la forma: “while/until condició do instrucció”. La primera executa la instrucció repetidament mentre la condició es compleixi i la segona executa la instrucció fins que la condició es compleixi, és a dir, executa la instrucció mentre la condició no es compleixi.

    D'aquí podem afirmar que qualsevol programa pot escriure's únicament utilitzant els tres tipus d'instruccions, aquestes dues i el bloc seqüencial d'instruccions que s'executen successivament.

    Tots els programés que utilitzen únicament les tres instruccions bàsiques de control o les seves variants (els bucles for o la condicional case), però que no utilitzen la goto, s'anomenen “estructurats”. La programació estructurada o “programació sense goto” es va convertir durant els anys seixanta, en la forma de programació més estesa fins que va sorgir la POO (Programació Orientada a Objectes). Encara que el seu nom indiqui el contrari, la majoria dels llenguatges conserven la instrucció goto i les seves etiquetes, per utilitzar-los en casos molt especials.

  • Estructures de programació

  • Com hem dit abans, un programa pot escriure's utilitzant únicament tres tipus d'instruccions. Les estructures de programació reben el mateix nom que cada tipus d'instrucció ja que cada estructura utilitza un tipus diferent d'instruccions.

    Les estructures de programació son: seqüencials, selectives i repetitives

    Les estructures seqüencials estan formades per instruccions seqüencials (que s'executen seguidament). Un exemple el trobem a la figura 14.

    Les estructures selectives s'utilitzen per a prendre decisions lògiques (per això també es diuen estructures de decisió o alternatives) i els caracteritza l'ús d'instruccions selectives (la condicional if-then-else i la condicional case) que provoquen salts en l'execució del programa.

    La sentencia If (o if-then-else) es considera com una alternativa doble ja que ofereix sempre dues alternatives (positiva i negativa). Hem vist la representació d'aquest tipus de sentències en el disseny de l'algorisme (diagrames de flux (rombes), diagrames N-S (triangles) i en el mètode del pseudocodi). La sintaxi que segueix Pascal és la següent:

    Sintaxi (pseudocodi) Codi

    Si <condició> llavors if <condició> then

    <acció1> <acció1>

    si no <acció2> else <acció2>

    Si es compleix la condició, s'executarà “acció1” i si no es compleix s'executarà “acció2”.

    Quan la condició ofereix dues sortides s'utilitza l'estructura anterior. En canvi quan la condició que volem imposar és de múltiples sortides hi ha dos possibles solucions: la primera és utilitzar un If dins de l'altre, consecutivament, fins haver establert totes les possibles sortides. Per exemple:

    Si volem fer un programa que, en introduir un nombre de l'1 al 7 a una variable “n”, ens escrigui a la pantalla cada un dels dies de la setmana (l'1 serà dilluns, el 2 dimarts ...). En aquest cas les possibles sortides son 7 i l'estructura quedaria de la següent manera.

    If n = 1 then

    Escriptura (Dilluns)

    else

    If n=2 then

    Escriptura (Dimarts)

    Else

    If n=3 then

    Escriptura(Dimecres)

    Else

    If n = 4 then...

    Així fins al diumenge. Utilitzant aquest mètode en programes més complexes ens hi podem estar una bona estona i per a corregir un error ho podem passar bastant malament. Per això, en comptes d'aquesta estructura, és molt més còmode utilitzar la segona solució d'aquest problema: la sentència case (aquest és el nom que rep en Pascal), de manera més global (comprensible pels programadors de diferents llenguatges) s'anomena select. Aquesta solució es pot considerar un substitutiu de l'altra ja que fa exactament el mateix, però de manera molt més comprensible. La sintaxi utilitzada per Pascal en aquesta estructura és:

    Sintaxi (Pseudocodi) Codi

    Segons sigui <element> fer: Case <element> of

    Valor1: acció1 Valor2: acció2 Valor1: acció1; Valor2: acció2;

    Valor3: acció3... Valor3: acció3; ...

    end;

    En el cas anterior, el dels dies de la setmana, en comptes de “<element>” escriuríem “n”, els valors serien 1, 2, 3, 4..7 i les accions serien escriure els diferents dies de la setmana. La representació d'aquesta sentència (diagrama N-S) és exactament igual al pseudocodi separant línia per línia entre caixes. En l'organigrama es fa a base de rombes com si introduíssim un If dins de l'altre.

    Les estructures repetitives també denominades bucles s'utilitzen per a realitzar varies vegades el mateix conjunt d'operacions, normalment referents als diferents valors que pot adoptar una variable. Les sentències utilitzades són: la sentència for, la sentència while i la sentència repeat.

    La sentència for és un bucle controlat per un comptador*, denominat variable de control o índex. S'utilitza quan volem actuar sobre una variable quan aquesta pren uns determinats valors, normalment consecutius. La sintaxi que s'utilitza en Pascal és:

    Sintaxi (Pseudocodi) Codi

    Des de variable = V1 fins a Vn fer for variable : = V1 to Vn do

    Acció1 Acció1

    Acció2 Acció2

    Acció3... Acció3...

    On “variable” és el nom de la variable afectada, V1 és el valor inicial i Vn és el valor final. Les accions s'efectuaran quan la variable contingui els valors compresos entre V1 i Vn.

    Les representacions d'aquestes estructures també les hem vist al disseny de l'algorisme.

    Si volem fer un programa que ens digui si un alumne ha aprovat o no hauríem d'utilitzar aquest bucle, perquè des del 0 al 4 escrigui a la pantalla, “no apte”, del 5 al 10 “apte”. El programa tindria l'estructura següent.

    for n : = 0 to 4 do

    escriptura (no apte);

    for n : = 5 to 10 do

    escriptura (apte);

    Això també es podria fer utilitzant l'estructura selectiva anterior (case) però seria molt més llarg ja que hauríem d'escriure una mateixa instrucció (escriptura) cinc vegades.

    En els bucles while i repeat, les accions no es repeteixen una determinada quantitat de vegades sinó que es realitzen fins que es compleix una determinada condició. Les representacions d'aquestes estructures corresponen a la “repetitiva 1” i a la “repetitiva 2” dels diagrames N-S.

    En el cicle o bucle while la pregunta o condició s'imposa abans de començar a executar les accions mentre que en el repeat (també es coneix com a until) la condició s'imposa al final. La sintaxi dels dos cicles és la següent:

    While Repeat

    Mentre (while) condició fer (do) repetir (repeat)

    Acció 1 Acció 1

    Acció 2 Acció 2

    Acció 3... Acció 3...

    fins que (until) condició

    L'única diferència entre aquestes dues sentències és la sintaxi, ja que amb les dues podem realitzar exactament el mateix.

    Si volem fer un programa que calculi el sumatori de deu nombres introduïts per l'usuari, haurem de demanar a l'usuari que introdueixi un nombre, calcular el sumatori i demanar-li un altre nombre fins que el comptador que declarem arribi a 10. Per fer-ho haurem d'utilitzar una d'aquestes sentències. L'estructura quedaria així:

    begin

    Comptador := 0; {*declarem un comptador i el sumatori que comencen des de zero*}

    Sumatori := 0;

    Lectura de A; {*inicialment demanem un nombre*}

    While Comptador < 10 do

    Begin {*mentre el comptador sigui més petit de 10 farem el següent*}

    Comptador : = Comptador + 1; {*incrementem el comptador en 1*}

    Sumatori : = Sumatori + A; {*calculem el sumatori amb el valor que tenia anteriorment incrementant-li A*}

    Lectura de A; {* demanem a l'usuari un altre valor per a A*}

    end

    escriptura (Sumatori); {*quan la condició no es compleix s'escriu el valor que té en aquell moment la variable Sumatori*}

    end;

    Si haguéssim volgut utilitzar la sentència repeat l'únic que diferent que tindrien els codis és que en comptes d'escriure “Comptador < 10” hauríem d'escriure “Comptador=10” ja que en la repeat, la qüestió (until) vol dir “fins que” i va al final del cicle mentre que en la while la qüestió és “mentre” i va al principi del cicle.

  • Programació modular

  • La programació estructurada també es caracteritza per l'ús d'una quarta instrucció de control: la crida d'una subrutina o procediment que serveix per relacionar uns programes amb altres i permet descompondre les aplicacions en dues o més seccions (procediments o funcions). Això rep el nom de programació modular.

    La programació modular consisteix en dividir el programa en altres subprogrames o mòduls, que s'analitzen i es codifiquen de manera independent i realitzen una determinada tasca que és una part del problema total a resoldre.

    En tot programa fet a partir de mòduls existeix sempre un mòdul o programa principal que és en el que comença la transferència de control o l'inici de l'execució del programa i, aquest determina l'execució dels altres mòduls a partir de la crida d'ells.

    Si volem fer un programa més complex dels que hem fet anteriorment, és molt útil treballar amb mòduls ja que, a part de ser més ràpid d'escriure, també és més comprensible per al programador.

    Una de les característiques més importants d'aquest tipus de programació és, com hem dit abans, la crida d'un mòdul. Significa que es transfereix el control, és a dir, que es comença a executar a partir de l'inici del subprograma (mòdul) fins que aquest acabi i en acabar, retorna (l'execució o control) al mòdul que l'ha cridat, el qual seguirà executant la instrucció posterior a la crida del mòdul anterior (mirar figura 15).

    Per exemple, podem utilitzar tres mòduls per a realitzar una suma de nombres enters (encara que es pot fer més ràpidament amb un de sol, en aquest cas). Hauríem de crear dos mòduls (subprogrames), un per a l'assignació de variables i l'altre per a sumar-los. En el mòdul principal trobaríem la crida als altres dos mòduls (primer el d'assignacions i després l'altre) i la instrucció d'escriptura del resultat a la pantalla.

    “Suma de dos nombres enters”

    INICI

    Variables

    A, B, Suma: enters;

    Subprograma (1)

    lectura del nombre A;

    lectura del nombre B;

    Subprograma (2)

    Suma = A + B;

    Mòdul principal

    Subprograma1;

    Subprograma2;

    Escriptura del valor de “Suma”;

    FINAL

    FIGURA 15 Escriptura d'un pseudocodi aplicant la

    programació modular.

    En aquesta figura, l'execució del programa comença a l'últim mòdul (el principal) però la primera línia d'aquest, crida al subprograma 1, llavors el control fa un salt fins a la primera línia del subprograma 1, on s'assignen els valors a les variables A i B. Quan s'acaben les ordres al subprograma 1, el control torna al mòdul principal. Aquest, però fa una altra crida, al subprograma 2, llavors el control torna a saltar fins a la primera línia d'instruccions del segon mòdul on calcula la suma de A + B i ho assigna a la variable “Suma”. Com que no hi ha més línies de codi dins el segon mòdul, el control torna al principal i segueix llegint el codi fins al final.

    Tots els elements d'un mòdul que està sent utilitzat per un altre, són accessibles per aquest. I mai un mòdul pot cridar a un altre que també el crida, el fenomen que es pot produir en aquests casos s'anomena circular*.

    El més important dels mòduls no és la seva grandària (línies de codi) sinó que han de realitzar una única tasca molt concreta com ara les de la figura 15: assignacions, operacions... Els mòduls o subprogrames reben diferents noms, segons el llenguatge que s'utilitzi. En Basic es diuen subrutines i en Pascal s'anomenen funcions i procediments, que són els tipus principals de subprogrames.

  • Funcions i procediments

  • Funcions

  • Són aquells subprogrames que prenen un o varis paràmetres d'entrada i retornen un únic resultat. El punt de vista algorítmic que es té de funció, és molt semblant al matemàtic, ja que aquesta pren un o varis valors, realitza una sèrie d'operacions sobre ells i retorna un resultat.

    Hi ha dos tipus de funcions: les funcions internes i les funcions externes.

    Les funcions internes són les que estan predefinides pel llenguatge.

    Per exemple, la funció “Abs” retorna el valor absolut d'un nombre real o enter. La funció “Sqrt” retorna l'arrel quadrada d'un nombre, etc.

    Funció

    Argument

    Resultat

    Operació

    Abs(x)

    Real o enter

    Real o enter

    Valor absolut

    Arctan(x)

    Real o enter

    Real

    Arc Tangent

    Cos(x)

    Real o enter

    Real

    Cosinus

    Exp(x)

    Real o enter

    Real

    Exponenciació

    Int(x)

    Real o enter

    Real

    Part entera de x

    Frac(x)

    Real o enter

    Real

    Part decimal de x

    Ln(x)

    Real o enter

    Real

    Logaritme neperià

    Round(x)

    Real

    Enter

    Arrodoniment

    Sin(x)

    Real o enter

    Real

    Sinus

    Sqr(x)

    Real o enter

    Real

    Elevar al quadrat

    Sqrt(x)

    Real o enter

    Real

    Arrel quadrada

    Succ(x)

    Enter

    Enter

    X + 1

    Trunc(x)

    Real

    Enter

    Truncament

    FIGURA 16 Funcions internes de Pascal

    En aquesta figura podem observar la majoria de les funcions aritmètiques predefinides en Pascal, on l'argument és el valor (x) afectat per la funció.

    Per utilitzar les funcions internes de Pascal hem d'escriure el nom de la funció i, seguidament, entre parèntesi, el valor afectat (x). Per exemple: Abs(-165.432). Això ens tornarà com a resultat el valor absolut de “x” (165.432).

    Com que les funcions sempre ens han de tornar un valor, normalment les assignem a una variable o escrivim el resultat directament a la pantalla.

    Les funcions externes: Són aquelles definides (declarades) per l'usuari, qui els ha de donar un identificador o nom com el que ja els dóna Pascal a les seves funcions internes. Per exemple, si definim una funció com a la suma d'un nombre més el seu valor triplicat dividida per 2 i l'anomenem “SD” (de suma i divisió) cada cop que escrivim SD i un valor numèric (seguint una determinada sintaxi) obtindrem el valor resultant d'aquesta operació realitzada amb el nombre introduït.

  • Declaració de funcions externes

  • L'estructura d'una funció és semblant a la de qualsevol programa (té un encapçalament i un cos).

    A l'encapçalament s'escriu el nom que li atorguem a la funció (ha de ser significatiu) i la declaració dels paràmetres amb els que volem que treballi (paràmetres formals), és a dir, si volem que treballi amb dos valors d'un tipus determinat, hem de declarar dos paràmetres formals que representen els valors afectats.

    La sintaxi a seguir en Pascal és:

    Funció <nom_funció> (a: tipus; b: tipus, .. n: tipus): tipus funció;

    On “a”, “b” i “n” són identificadors (de caràcter arbitrari) dels paràmetres formals, i el tipus de la funció és el tipus del valor que obtindrem en aplicar-la sobre els valors afectats.

    Per exemple, en el cas anterior (en la funció “SD”) hem de declarar únicament un paràmetre formal, ja que el valor que s'ha de sumar dependrà d'aquest (el triple) i l'altre valor amb que s'opera és una constant literal (2) que no cal declarar. L'encapçalament, seguint la sintaxi de Pascal, quedada de la següent manera:

    Function SD (x: integer): real;

    En el cos de la funció escriurem les accions que volem que faci. Entre elles haurà d'haver la que retorna el valor de la funció (acció retorn) i la sintaxi que s'ha de seguir per executar aquesta acció és:

    Retorn : = <valor>

    Cada llenguatge té un identificador per aquesta acció. Pascal l'anomena “Result”. No cal definir-lo, perquè, com hem dit abans, el tipus de la funció és el tipus del valor resultant que s'obté. Per tant, sempre que escrivim “Result : = “ s'entén que estem definint el resultat de la funció i, automàticament, en aplicar-la sobre els valors afectats, el compilador entén que l'expressió (operació) que determinarà el valor retornat serà aquesta, i que el seu tipus és el que s'ha definit abans com el tipus de la funció.

    Després d'això, podem afirmar que no s'accepten funcions que no retornin res (en tota funció és obligat utilitzar la sentència retorn).

    Els paràmetres formals, són utilitzats com a variables locals (mirar figura 18) i dins de la funció també es poden fer declaracions d'altres variables locals que faran d'auxiliars per a realitzar les operacions (quan aquestes siguin molt complexes). El que els diferencia és que als paràmetres formals se'ls assignen uns valors al fer la crida de la funció i és obligatori fer-los constar. En canvi, a les altres, se'ls assigna un valor que no s'ha de fer constar en la crida i es pot prescindir d'elles (només fan d'auxiliars per a realitzar les operacions).

    Els valors que es fan constar en la crida reben el nom de paràmetres reals que substituiran als formals per a obtenir un valor determinat.

    Function SD (x: integer): real;

    var

    Triple: integer;

    Suma: integer;

    begin

    Triple : = 3*X;

    Suma : = X + Triple;

    Result : = Suma / 2;

    end;

    FIGURA 17 Declaració d'una funció

    En la figura anterior, les variables locals són “Triple” i “Suma” i el paràmetre formal “x” serà substituït per un paràmetre real quan la funció s'apliqui sobre un valor determinat.

  • Crida d'una funció

  • Per a realitzar la crida d'una funció enmig d'un programa o d'un subprograma s'ha de seguir la següent sintaxi:

    <nom_funció> (paràmetres reals);

    Els paràmetres reals poden ser: variables, constants, expressions, ... però sempre del mateix tipus que els paràmetres formals i ha d'haver el mateix nombre de reals que de formals, en cas contrari, el compilador produeix un error.

    A través dels paràmetres reals de la crida, es proporciona a la funció la informació que necessita ja que, com hem dit abans, substituiran als formals.

    Al fer la crida, la substitució es produeix mitjançant una associació automàtica entre els paràmetres reals i els formals. Aquesta associació es realitza seguint l'ordre d'aparició (d'esquerra a dreta). És a dir, el primer que fem constar en la crida s'associarà al primer que es fa constar en la declaració.

    Una funció sempre formarà part d'una expressió que en el punt on fa la crida a la funció es pugui col·locar qualsevol tipus de dada corresponent al d'aquesta, per això és important que el nom de la funció sigui significatiu.

    Si volguéssim cridar la funció que hem declarat abans (SD) no ens hauríem de preocupar de l'ordre d'aparició ja que només es treballa amb un paràmetre, però si de quin tipus és el paràmetre i de quin tipus de dada permet l'expressió de la que formarà part la funció. Per exemple:

    Imaginem que volem introduir el valor obtingut aplicant la funció “SD” sobre un valor en el programa “Suma de dos nombres enters” (figura 15). No podríem fer-ho ja que les variables A i B són del tipus enter i el valor que retorna la funció és real.

    A : = SD(m); (error del compilador)

    L'única solució seria afegir una funció interna del llenguatge que ens convertís el valor real obtingut en “SD” en un nombre enter. Per exemple la funció “round” que ens arrodoniria el resultat.

    A : = round(SD(m)); (compilació satisfactòria)

    On “m” és un valor enter qualsevol introduït per l'usuari.

  • Procediments

  • L'inconvenient de les funcions és que sempre han de tornar un valor i només pot ser un. Quan ens interessa retornar 0 o N valors (N també pot ser 1), hem d'utilitzar els procediments.

    Un procediment (subrutina per Basic) és un subprograma que executa una determinada tasca però, després de realitzar-la, no s'obté un resultat directament com en les funcions, sinó que si es torna informació es fa mitjançant paràmetres. És a dir, els valors que volem que retorni el procediment s'associen, normalment, a unes variables pròpies del mòdul al que el crida (o a les variables globals del programa).

    A diferència de les funcions, cap dels resultats retornats pel procediment s'associen al seu nom, és a dir, que els procediments no formen part de cap expressió. La crida d'un procediment és una instrucció que per si sola no necessita altres instruccions.

  • Declaració d'un procediment

  • L'escriptura d'un procediment és semblant a la d'una funció, té un encapçalament i un cos.

    L'encapçalament està format pel nom del procediment, que ha de ser un identificador significatiu, i entre parèntesis escriurem els paràmetres formals. Per a cada paràmetre s'ha d'indicar el seu tipus i el tipus de pas de paràmetres (mirar figura 19) que pot ser per valor o per referència (si no especifiquem pas de paràmetre es pren el tipus de pas per valor). Ho farem seguint la següent sintaxi:

    Procediment <nom_proced> (<tipus de pas> a: tipus, <tipus de pas> b: tipus, ...);

    On “a” i “b” són identificadors (arbitraris) dels paràmetres formals i on posa <tipus de pas> s'ha d'indicar de quin tipus serà el pas de paràmetre (per valor o per referència), en cas que sigui per valor no cal escriure res i en el cas que sigui per referència, en Pascal escriurem “Var”.

    FIGURA 19 Tipus de pas de paràmetres.

    En el cos del procediment s'hi escriuen les sentències, de les quals cap no serà l'acció retorn de les funcions. Però en el cas que el procediment torni resultats a través dels seus paràmetres (que s'hauran de passar per referència), hi haurà sentències d'assignació de valors a aquests paràmetres ja que el seu valor anterior al procediment es modificarà per contenir un valor resultant.

    El procediment de la figura 20 calcula l'arrel de tot nombre enter introduït, transformant els valors negatius en positius.

    Procedure Arrel (nombre: integer, Var A: real);

    var

    Positiu: Integer;

    begin

    Positiu := Abs (nombre);

    A : = Sqrt (Positiu);

    end;

    FIGURA 20 Declaració d'un procediment en Pascal

    El pas del paràmetre “nombre” és per valor (no hem escrit res davant). Això vol dir que en un altre mòdul podrem utilitzar el valor inicial del paràmetre (per calcular el quadrat, etc). En canvi, el pas del paràmetre “A” és per referència, això vol dir que si utilitzem aquest paràmetre en un altre mòdul, l'utilitzarem amb el valor final.

  • Crida d'un procediment

  • Per cridar un procediment en un mòdul en Pascal únicament haurem d'escriure el seu nom i, entre parèntesis, els paràmetres reals que, a l'igual que les funcions, han de seguir l'ordre establert en la declaració i han de ser del mateix tipus que els paràmetres formals (mirar figura 21). En altres llenguatges com el C escriuen la paraula “call” abans del nom.

    El que caracteritza la seva crida és que, a diferència de les funcions, no forma part de cap expressió, és una única instrucció que no s'assigna a res.

    Pascal també té uns quants procediments predefinits, igual que les funcions. Aquests són uns quants:

    Val: Transforma una cadena (string) a un nombre enter (integer). Si hi ha un error, detecta el caràcter no numèric i retorna en un altre identificador la posició incorrecta del caràcter.

    WriteLn: Escriu text en la pantalla i permet la transformació de qualsevol altre tipus de dada en string, un cop feta la transformació ho escriu a la pantalla.

    ReadLn: Assigna el que hi ha en pantalla a una variable.

    //Arrel de qualsevol nombre enter

    uses

    crt, dos; //llibreries

    var

    N, Resultat: integer;

    Procedure arrel (nombre: integer, Var A: real);

    begin

    nombre := Abs (nombre);

    A : = Sqrt (nombre);

    end;

    begin //mòdul principal

    clrscr; //Neteja de pantalla

    write (`Introdueixi el nombre: `);

    readln (N);

    arrel (N, Resultat); // crida del procediment arrel.

    writeln (`L''arrel de', N,' és: `, Resultat'); //escritura resultat

    end;

    FIGURA 21 Escriptura d'un programa amb procediments

    En aquest programa he modificat el procediment, per tal que es modifiqui el valor del paràmetre formal “nombre” i demostrar que no afecta al paràmetre real “N” tornant-lo a utilitzar després. Els dos apòstrofs seguits de l'última línia hi són, perquè s'escrigui un a la pantalla ja que si no es fa així el compilador ho detecta com un separador de cadenes.

    Quan el que volem, però, és segmentar el programa en parts (assignacions a variables, operacions, escriptura de resultats en pantalla) sense crear procediments que treballin amb determinats paràmetres, el que es fa és declarar procediments sense indicar-ne cap. Llavors, aquest procediment treballa amb tots els paràmetres globals del programa principal. Un exemple és el de la figura 15 que es veu introduït en un programa en la figura 22.

    //Suma de dos nombres enters

    uses

    ctr, dos; //Llibreries

    var

    A, B, Suma: Integer; //Variables

    procedure Assignacions;

    begin

    Write (`Introdueixi el primer valor');

    ReadLn(A);

    Write (`Introdueixi el segon valor');

    ReadLn(B);

    end;

    procedure Operacio;

    begin

    Suma := A + B;

    end;

    begin //inici del programa

    Clrscr;

    Assignacions;

    Operacio;

    WriteLn (`Resultat : `, Suma);

    end;

    FIGURA 22 Escriptura d'un programa mitjançant la crida de

    procediments sense paràmetres formals

  • LA Programació orientada a objectes

  • Factors que afavoreixen el seu sorgiment

  • Com a evolució dels llenguatges estructurats, van aparèixer els llenguatges orientats a objectes (OOL, Object Oriented Language, o LOO), que en molts casos no són més que una extensió i adaptació a aquest tipus de programació del llenguatge primitiu (com l'Object Pascal, Visual Basic, Visual Café).

    La programació orientada a objectes (OOP, Object Oriented Programming, o POO), és una nova forma de programar que considera els programes com a un conjunt d'objectes que interaccionen entre ells i va fomentar-se a partir de la dècada dels vuitanta.

    Un dels principals motius del seu sorgiment va ser l'anomenada crisi del software, cap al 1970.

    A mesura que els programes van anar adquirint complexitat, la dificultat de programar, amb la programació estructurada, va anar en augment fins al punt d'arribar a ser bastant pesat i dur per als programadors posar-se a escriure el codi durant hores. No només això, sinó que els programes cada cop eren més difícils de comprendre i de mantenir i encara més pesat era trobar els errors que s'han produït a l'escriure i corregir-los. Tot això descriu el que és la crisi del software.

    Per resoldre això, la programació ha anat creant mètodes per permetre al programador poder resoldre els errors i dur un bon manteniment del programa (un d'ells és la programació o plantejament modular). Però avui en dia, molts dels projectes de desenvolupament no poden ser afrontats mitjançant aquest plantejament, per això va sorgir la programació orientada a objectes (POO) que ofereix un nou plantejament de programació que permet l'implementació de grans projectes de software d'acord amb les necessitats que es plantegen actualment.

    Aquest nou tipus de programació inclou les millors idees de la programació estructurada (l'escriptura del codi és pràcticament igual però més entenedora) i les combina amb nous conceptes que permeten una nova visió del procés de programació. Permet descompondre un problema en grups o parts relacionades que són les unitats bàsiques de la POO, els objectes.

  • Característiques de la POO

  • La característica més important és que la POO consisteix en una nova manera de pensar i es basa en la idea natural de l'existència d'un món ple d'objectes i que la resolució dels problemes es realitza a partir d'aquests.

    L'element fonamental de la POO, com hem dit abans és l'objecte i les característiques principals d'un llenguatge orientat a objectes són:

    • Ha d'estar basat en objectes (evidentment).

    • Ha d'estar basat en classes.

    • Ha de ser capaç de tenir herència de classes.

    Més endavant anirem veient el significat d'aquestes característiques.

    La programació orientada a objectes es basa en entorns gràfics que fan millor la comprensió del programa i faciliten al programador la seva feina. Per exemple, totes les aplicacions de Windows estan programades a partir d'aquests tipus de llenguatges.

  • Concepte d'objecte

  • Un objecte és un conjunt complex de dades i programes que posseeixen estructura i formen part d'una organització.

    A partir d'aquesta definició podem deduir que: un objecte no és una dada simple, sinó que en el seu interior conté un cert nombre de components ben estructurats. En segon lloc, cada objecte no és una entitat aïllada, sinó que forma part d'una organització.

    La definició anterior, però, segueix sent molt abstracte. És a dir, que a partir d'ella és molt difícil imaginar-nos ben bé com deu ser un objecte.

    Els objectés que tothom coneix, en aplicacions de Windows, per exemple, són des dels botons: “Aceptar”, “Cancelar”, etc., les caselles on el programa ens deixa escriure un nom (ja pot ser per donar-li a un arxiu, com per introduir el nostre nick quan ens connectem a un chat ...), fins al “menú inicio” de l'escriptori i l'escriptori mateix és un objecte. Per això parlem d'una nova manera de veure el món i de resoldre els problemes.

    Totes les accions que feien els programes dels exemples de la programació estructurada es duien a terme a partir de la pulsació d'alguna tecla (per part de l'usuari). En canvi, programant amb objectes podem fer-los a partir de fer un click amb el ratolí sobre un objecte, o picant unes tecles determinades etc. Totes aquestes accions s'anomenen events.

    La simplificació del programa a escriure per al programador és molt notable. Amb un codi, una mica més extens que en els programes estructurats dels exemples anteriors es poden realitzar moltes més accions. També se simplifica la comprensió per par de l'usuari que, passa d'executar el programa en una pantalla on tot son línies d'escriptura a un programa amb una aparença molt més real. (mirar figura 24).

    Quan, en el segon paràgraf ens referim a què els objectes estan formats per uns components estructurats estem dient que, els objectes, a part d'organitzar-se en una jerarquia (majoritàriament), interiorment mantenen una estructura determinada.

    FIGURA 24 Sistema operatiu DOS de Microsoft (MS - DOS) i el sistema operatiu Windows 95 també de Microsoft.

    En aquesta figura podem comprovar com millora la comprensió dels entorns gràfics respecte als programes més antics.

  • Organització dels objectes

  • En principi, com hem dit abans, els objectes formen part d'una organització jeràrquica, en el sentit que hi ha objectes “superiors” a altres, en certa manera.

    La jerarquia o estructura simple, distingeix tres nivells d'objectes:

    • L'arrel de la jerarquia.

    Tracta d'un objecte únic i especial. Es caracteritza per estar en el nivell més alt de l'estructura i acostuma a rebre un nom molt genèric, que indica la seva categoria, per exemple “objecte mare” o “arrel”.

    • Objectes intermedis.

    Aquells que tenen descendència directament de l'arrel i que alhora tenen descendents. Representen conjunts o classes d'objectes. Reben un nom genèric que denota al conjunt d'elements que representen.

    • Objectes terminals.

    Tots aquells que són descendents d'una classe o subclasse però no tenen descendents. S'acostumen a nomenar ítems o instàncies ja que representen els elements que formen part del conjunt representat per la classe.

    Per exemple, el programa que he fet en aquesta recerca (Einstein's Maths) consisteix en un menú principal en el que podem escollir diferents operacions a realitzar amb rectes i vectors del pla. Cada operació (“trobar una recta a partir de dos punts”, “trobar un vector director a partir de dos punts”, etc.) es realitza en una finestra. Cada finestra té el nom de l'operació que realitza i el menú principal té el nom del programa. Dins de cada finestra, hi ha caselles per escriure, botons per operar, una barra d'estat, ...

    FIGURA 25 Aspecte visual d'Einstein's Maths (el meu programa).

    Tots aquests objectes es poden classificar en la jerarquia que he descrit en aquest punt.

    Arrel: Menú principal

    Objectes intermedis: Totes les finestres que s'obren a partir del menú.

    Objectes terminals: Els botons, les caselles, etiquetes que descriuen el que s'ha de fer, ...

  • Estructura d'un objecte

  • Com hem dit anteriorment, cada objecte té una estructura interna. Es pot considerar un objecte com a una càpsula dividida en tres parts:

    • Relacions

    • Propietats

    • Mètodes

    Cadascun d'aquests components desenvolupen un paper totalment diferent al dels altres:

    Les relacions permeten que l'objecte s'insereixi en l'organització.

    Les propietats distingeixen un objecte determinat de la resta d'objectés que formen part de la mateixa organització. Les propietats d'un objecte poden ser heretades als seus descendents en l'organització

    Els mètodes són les operacions que es poden realitzar sobre un objecte, que normalment estan incorporades en forma de programes (codi) que l'objecte és capaç d'executar i que també posa a disposició dels seus descendents a través de l'herència.

  • Relacions

  • Són els enllaços que permeten a un objecte relacionar-se amb aquells que formen part de la mateixa organització. Hi ha dos tipus principals de relacions: les relacions jeràrquiques i les semàntiques.

  • Relacions jeràrquiques

  • Són essencials per a l'existència de l'aplicació, ja que la construeixen. Són bidireccionals, és a dir, un objecte és pare d'un altre quan, en l'organització, el primer es troba situat immediatament sobre del segon. Tanmateix, el segon és fill del primer.

  • Relacions semàntiques

  • Són aquelles relacions que no tenen res a veure amb l'organització de la que formen part els objectés que les estableixen. És a dir, únicament depenen dels objectes en ells mateixos (el seu significat) i no de la seva posició en l'organització.

    Imaginem que volem construir un diccionari informatitzat amb el que l'usuari pugui obtenir la definició de qualsevol terme. Suposem que en aquest diccionari les paraules són objectes i que l'organització jeràrquica es basa en els coneixements que tenim nosaltres sobre el món. Així l'arrel es podria dir “temes” de la que descendirien tres grans grups d'objectes (vida, món i home).

    FIGURA 26 Organització jeràrquica

    Si el diccionari ens diu: “Newton va treballar l'òptica”, la relació és evidentment semàntica (treball) ja que no hi ha cap connotació jeràrquica entre “Newton” i “òptica”, el primer serà fill de “Història” (mirar figura 26) i el segon ho serà de “Física”. O sigui que la interpretació de la frase “Newton va treballar l'òptica” depèn únicament del significat dels dos objectes.

    Havent establert aquesta relació podem afirmar que Newton va treballar el pare “d'òptica” (física), el pare de “física” (món) i el pare de “món” (temes).

    La POO reconeix aquestes relacions a partir de la primera i ens estalviaríem el fet d'establir una relació semàntica entre l'objecte “Newton” i l'objecte “Física” i amb els altres mencionats anteriorment.

    FIGURA 27 Encapsulament i ocultació

  • Propietats

  • Cada objecte pot tenir un cert nombre de propietats. Les propietats d'un objecte corresponen a unes variables encapsulades dins l'objecte, juntament amb els programes i subprogrames, amb la diferència que no estan ocultes.

    La diferència entre les propietats d'un objecte i les variable és que les propietats es poden heretar d'un objecte a un altre. Conseqüentment hi ha dos tipus de propietats:

    • Propietats pròpies. Estan formades dins de la càpsula de l'objecte.

    • Propietats heretades. Es formen en un objecte diferent, avantpassat d'aquest.

    Per exemple. Amb Delphi (el llenguatge que he utilitzat per crear el programa) es pot treballar amb botons normals i ràpids (entre altres). Els botons ràpids són fills dels normals i tenen moltes de les propietats que tenen els seus pares com la visibilitat etc. En canvi una de les propietats que no han heretat dels seus pares és la possibilitat d'aparèixer seleccionats en l'execució del programa. Per accedir a aquestes propietats s'ha de seguir la sintaxi següent:

    <nom objecte>.<propietat>

    Per exemple, la propietat visible d'un botó (que en l'execució es vegi o no en la pantalla) es podria modificar de la següent manera:

    btnAceptar.Visible := false;

    D'aquesta manera hem ocultat l'objecte en l'execució immediata. L'invisibilitat ens pot interessar, per exemple, perquè l'usuari no pugui picar el botó fins que no hagi fet una determinada acció o altres coses semblants.

    Com seria molt difícil memoritzar totes les propietats que pot tenir un objecte i els seus descendents, Delphi, ens mostra totes les propietats de l'objecte que seleccionem en una llista que es troba en el que s'anomena “object inspector” o inspector d'objectes. On també es pot accedir a les propietats de cada component del programa, però si les volem modificar durant l'execució ho haurem de fer mitjançant la sintaxi anterior.

    En la figura 28, l'inspector d'objectes ens mostra les propietats d'un element TButton (botó simple).

  • Mètodes

  • Podem definir mètode com un programa procedimental escrit en qualsevol llenguatge que està associat a un objecte determinat, l'execució del qual només pot desencadenar-se mitjançant un missatge rebut per aquest o pels seus descendents.

    Tot i que siguin també procediments, funcions o rutines, és convenient utilitzar el terme “mètode” per distingir clarament les propietats especials que adquireix aquest programa en l'entorn de la POO, que afecta fonamentalment a la forma d'invocar-lo (cridar-lo). Es fa mitjançant un missatge i no com fèiem en la programació estructurada.

    Els mètodes, com les propietats, també poden ser propis o heretats. Segons si es formen dins de la càpsula de l'objecte o si es creen en la càpsula d'un avantpassat.

    Per tenir una idea més intuïtiva del que és un mètode el podem definir com les diferents accions que pot realitzar un objecte, que més endavant podran ser cridades des de qualsevol punt de codi del nostre programa. És a dir, des de qualsevol event d'un control o dins d'algun subprograma, podem invocar un mètode d'un altre control o objecte (mitjançant un missatge dirigit a ell).

    FIGURA 29 Events

    Per exemple, si volem tancar una aplicació quan l'usuari faci un click sobre un determinat botó, el que haurem de fer és: executar el mètode “tancar” (en Pascal s'anomena close) de la finestra principal o arrel de la jerarquia quan aquest botó sigui picat.

    En aquest exemple, l'event “click” es produeix en un botó i el mètode “close” és propi de la finestra principal del programa. Per això hem dit abans que es poden invocar mètodes d'un objecte des d'un altre.

  • Borland Delphi

  • Delphi (de la casa Borland) és el llenguatge que he utilitzat per a realitzar el programa.

    És un entorn de programació (Delphi 32) que aporta les característiques necessàries per aprofitar al màxim els sistemes operatius Windows 95/98 i Windows NT. Està basat en la programació orientada a objectes i utilitza el llenguatge Object Pascal, que és una variant especial de Pascal orientada a objectes. L'elecció del llenguatge Pascal com a base es deu, principalment a, que aquest llenguatge resulta més clar per al programador que altres (Basic, C o C++) sense perdre potència per a realitzar grans i complexes aplicacions.

    La seva adaptació entre la comunitat de programadors ha estat excel·lent ja que és molt complet i permet realitzar tot tipus d'aplicacions, alhora de ser molt senzilles.

    Aquests són alguns dels principals components de Delphi:

    TForm

    És el que en l'execució serà una finestra. Reben el nom de formularis. En ells se situen tots els altres components (botons, caselles per escriure, etiquetes ...)

    TButton

    En l'execució seran els botons. A partir d'ells, principalment, es desenvoluparà el programa.

    TEdit

    En ells, l'usuari podrà escriure la informació que se li demana per a poder dur a terme el programa.

    TLabel

    Reben el nom d'etiquetes, ja que, en elles, s'hi pot escriure informació que atorga el programador a l'usuari. Aquesta no és l'única funció que poden realitzar, però és recomanable que ho sigui.

    MainMenu

    És el que anomenem menú principal d'una aplicació. A partir de les seves seccions es despleguen altres requadres amb uns identificadors, que realitzen, principalment, l'obertura d'una finestra o formulari.

    TCheckBox

    Són aquelles caselles que, únicament, serveixen perquè l'usuari seleccioni o no una opció que li ofereix el programa.

    TRadioButton

    Sempre van en conjunt, ha d'haver-hi més d'un. Aquestes caselles de selecció obligaran a l'usuari escollir una opció o una altra proposada, mai podrà escollir-ne més d'una.

    Aquests són uns dels principals components amb els que s'acostumen a realitzar les aplicacions visuals.

    GLOSSARI

    Els següents conceptes estan ordenats, segons la seva aparició en el treball.

    Microprocessador:

    És com el cervell de l'ordinador. És on arriba la informació i, a partir d'aquesta realitza una sèrie d'accions comunicant-se amb els altres perifèrics (mirar figura 1). La seva velocitat de treball es mesura en “megaherzis” (MHz) i la seva capacitat de procés (processament de dades) pel nombre de bits que és capaç de manipular a l'hora (poden ser 16, 32 etc.).

    RAM:

    “Random Acces Memory” (Menoria d'accés directe). També s'anomena memòria de treball ja que consisteix en un espai de memòria lliure que l'ordinador sempre deixa lliure quan l'obrim, i quan es tanca l'ordinador, el que conté la RAM és borrat.

    Llenguatge de programació:

    Notació per escriure programes, a través del qual podem comunicar-nos amb el hardware i d'aquesta manera, donar les ordres adequades per la realització d'un determinat procés. Vé definit per una gramàtica o conjunt de normes que s'apliquen a un alfabet constituït per el conjunt de símbols utilitzats.

    Llenguatge màquina:

    L'únic llenguatge que entén, directament la computadora, utilitza l'alfabet binari integrat únicament per dos símbols, 0 i 1, denominats bits (abreviatura anglesa de dígits binaris).

    Compilador:

    Programa traductor, característic de cada llenguatge d'alt nivell, subministrat pel fabricant d'aquest, amb l'objectiu de transformar un programa executable, escrit en un determinat llenguatge, en llenguatge binari sigui la màquina que sigui en la que està instal·lat.

    Intèrpret:

    També es tracta d'un programa traductor d'un llenguatge d'alt nivell a llenguatge màquina, pròpi de cada tipus de llenguatge, però en comptes de generar un programa escrit en llenguatge màquina a partir del programa font, tradueix i executa simultàniament el programa.&

    Inteligència Artificial (IA):

    Part de la informàtica que estudia la simulació de la intel·ligència, mitjançant l'introducció d'un gran volum de dades en un ordinador.

    Variable:

    Són aquells elements d'un programa que el seu valor pot canviar durant la execució d'aquest.

    Byte:

    Unitat de mesura de la capacitat de memòria. És una cadena formada per vuit xifres binaries (8 bits), cada bit pot prendre el valor 0 o 1.

    Identificador:

    Paraula que no és pròpia del llenguatge. Com el seu nom indica serveix per a identificar algun element.

    Codi ASCII:

    American Standard Code for Information Interchange (Codi Estàndard Americà per a l'Intercanvi de la Informació). S'utilitza principalment en les comunicacions.

    Consisteix en un codi que assigna a cada lletra un nombre o signe utilitzat pels ordinadors amb la seva combinació d'uns i zeros. La taula bàsica de caràcters ASCII s'integra per 128 caràcters. La versió ampliada és de 256 caràcters.

    Comptador:

    És un element que incrementa en una unitat un determinat valor. Per exemple: si a una variable li assignem el valor 4, el que farà el contador és augmentar el valor en 5, 6, 7, 8 ... i si el que li assignem és un caracter (F), el que farà és modificar el caracter F en G, H, I, J ...

    Circular:

    Fenòmen que es produeix quan un mòdul, en un programa, crida a un altre mòdul i aquest, alhora, també crida al primer. Això, en casos molt senzills encara es podria fer, però gairebé sempre el compilador produïrà un error.

    Objecte:

    Aquell element o entitat a partir de la qual la programació orientada a objectes resol algorismes.

    Tots els exemples d'aques punt mostren la forma de la estructura, no són (a no ser que ho digui) ni el pseudocodi ni el codi d'un programa.

    Els editors de codi canvien automàticament el color dels comentaris per millorar la comprensió.

    Un cop fet el programa, corregir errors i fer les modificacions puntuals amb el pas del temps.

    Es diu així perquè pot ser representada mitjançant un arbre de generacions (com el familiar).

    Resultat de l'encapsulament (figura 27)

    Comunicació dirigida a un objecte ordenant-li que executiun dels seus mètodes, segueix una sintaxi.

    Degut a la capacitat de programar en 32 bits

    & La diferència entre intèrpret i compilador és que aquest, genera programes de més ràpida execució ja que la traducció i l'anàlisi es fan una sola vegada i l'altre els executa més lentament perquè va analitzant i traduïnt cada vegada que el programa és executat. Depèn de quins llenguatges exigeixen intèrpret o no.

    Programació d'ordinadors Artur Sales

    58

    Cada identificador té un àmbit, que és la part del programa on es coneix i per tant determina quan es podrà utilitzar o no.

    • Variables locals

    Aquelles variables que la seva zona està declarada i definida dins d'un subprograma i el seu àmbit coincideix amb l'àmbit del subprograma, és a dir, només podrà ser utilitzada dins d'aquest.

    Es declaren dins del subprograma al que pertànyen.

    • Variables globals

    Aquelles variables que estàn definides a nivell del programa. Conseqüentment , el seu àmbit coincideix amb el del programa i també poden ser utilitzades per tots els subprogrames.

    La seva declaració es realitza a l'encapçalament d'aquest.

    VARIABLES LOCALS I GLOBALS

    FIGURA 18 Variables locals i globals

    Pas de paràmetres

    Definir el pas de paràmetres consisteix en definir de quina manera afectaran els canvis del paràmetre formal al valor del paràmetre real.

    • Pas de paràmetres per valor

    Ho farem quan ens interessa mantenir el valor del paràmetre actual (real) d'entrada. En aquest cas mai els resultats es tornaran a través d'ell. Degut a això pot ser una constant, una expressió o una variable.

    El funcionament és el següent:

    S'associa el paràmetre real al formal i, si durant la execució del subprograma el paràmetre formal es veu modificat, al acabar l'execució, el paràmetre real segueix amb el valor que tenia inicialment.

    • Pas de paràmetres per referència

    En aquests casos, no es guarda el valor inicial del paràmetre real. Qualsevol modificació que es faci sobre el paràmetre formal durant l'execució del procedimenr afectarà també al valor del paràmetre real quan el control torni al mòdul que l'ha cridat.

    Hi ha més tipus de pas de paràmetre (resultat, valor-resultat).

    Programació estructurada d'ordinadors

    Programació estructurada d'ordinadors

    FIGURA 23 Diferents objectes

    Programació estructurada d'ordinadors

    Programació estructurada d'ordinadors

    Menú principal

    Finestra

    FIGURA 28 Inspector d'objectes de Delphi32

    Programació estructurada d'ordinadors

    Programació estructurada d'ordinadors

    Programació estructurada d'ordinadors

    Programació estructurada d'ordinadors

    Programació estructurada d'ordinadors

    Programació estructurada d'ordinadors

    Programació estructurada d'ordinadors

    Programació estructurada d'ordinadors

    Com hem vist abans, els objectes són un conjunt de programes relacionats entre ells. Com si aquests programes estiguéssin tancats dins d'una càpsula. Aquesta propietat s'anomena encapsulament.

    Els objectes són inaccessibles, és a dir, ni els altres objectes ni els usuaris, ni el programador poden saber com està distribuida la informació que contenen. Aquesta propietat s'anomena ocultació.

    Això si, no totes les dades estàn ocultes. És possible conèxier el necessàri de l'objecte per a realitzar el programa.

    La manera d'accedir a aquesta informació és mitjançant missatges dirigits a l'objecte. La resposta a les ordres del missatge serà la informació requerida, sempre que l'objecte consideri que qui envia el missatge està autoritzat per rebre la informació (normalment és el programador).

    Algunes de les propietats accessibles a l'objecte són: el títol que mostrarà en l'axecució del programa, la seva visibilitat o invisiblitat en l'execució de l'aplicació, la possibilitat d'estar sel·leccionat per defecte etc.

    ENCAPSULAMENT I OCULTACIÓ

    Programació estructurada d'ordinadors

    Un event és aquell succés que l'objecte pot rebre. Nosaltres li indiquem com ha de reaccionar (comportar-se) davant d'aquests succés.

    Els events són procediments que s'executen automàticament, com a resposta a una acció de l'usuari sobre l'objecte. Quan s'efectui un event, s'executarà el còdi que el programador hagi escrit en el procediment event de l'objecte.

    Un event, pot ser un click sobre una opció d'un menú o sobre un botó. També pot ser sel·leccionar un botó sense fer click, introduïr el cursor dins d'una casella etc. L'inspector d'objectes de Delphi (figura 28) té una segona llista que integra els events que poden afectar a l'objecte que tenim sel·leccionat.

    El codi que s'escriu en l'event és separat del programa principal amb un procediment ja que és un subprograma que s'executa quan es produeix l'event.

    EVENTS




    Descargar
    Enviado por:Artur Sales
    Idioma: catalán
    País: España

    Te va a interesar