77
Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

  • Upload
    others

  • View
    7

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

Codificació en C

Traducció de llenguatge algorí smic a C

Jordi Riera i Baburés P00/05009/00563

Page 2: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

..

Page 3: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 3 Codificació en C

Índex

Introducció.......................................................................................... 5

Objectius .............................................................................................. 6

1. Introducció a la programació en C .............................................. 7 1.1. El nostre primer programa en C......................................................7 1.2. Un programa més complet en llenguatge C...................................8

2. Introducció a l’algorí smica en C................................................ 10 2.1. Objectes elementals del llenguatge C............................................10

2.1.1. Tipus elementals en C ........................................................11 Tipus booleà........................................................................11 Tipus caràcter .....................................................................11 Tipus enter ..........................................................................12 Tipus real.............................................................................12

2.1.2. Declaració d’objectes en C .................................................12 2.1.3. Expressions en C .................................................................14 2.1.4. Definició de tipus. Tipus enumeratius en C .....................14 2.1.5. Funcions de conversió de tipus..........................................15

2.2. Especificació d’algorismes .............................................................15 2.3. Estructures algorí smiques .............................................................15

2.3.1. Estructura general d’un programa en llenguatge C .........16 2.3.2. Accions elementals: l’assignació........................................17 2.3.3. Composició d’accions.........................................................17

Composició seqüencial ......................................................17 Composició alternativa......................................................17 Composició iterativa ..........................................................18

2.4. Accions i funcions en C..................................................................19 2.4.1. Paràmetres en C ..................................................................21 2.4.2. Accions i funcions d’entrada i sortida de dades en C ......23

2.5. Exemples de codificació en C........................................................24 2.5.1. Algorisme arrelEntera ...........................................................24 2.5.2. Algorisme arrelEquacioSegonGrau .........................................24

3. Tractament seqüencial en llenguatge C..................................... 27 3.1. Exemple d’esquema de recorregut d’una seqüència en C ...........27 3.2. Exemple d’esquema de cerca en una seqüència en C..................28 3.3. Exemple d’esquema de recorregut aplicat a l’entrada en C........28 3.4. Exemple d’esquema de cerca aplicat a l’entrada en C.................29 3.5. Combinació d’esquemes en C........................................................30

Page 4: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 4 Codificació en C

4. Tipus estructurats de dades en llenguatge C ............................ 31 4.1. Taules en C......................................................................................31

4.1.1. Declaració de taules, matrius i taules de taules en C .......31 4.1.2. Funcions elementals d’accés ..............................................32 4.1.3. Accés seqüencial a una taula..............................................33 4.1.4. Accés directe a una taula....................................................34 4.1.5. Taules com a paràmetres d’accions i funcions .................35

4.2. Tuples en C......................................................................................38 4.2.1. Declaració de tuples en C ...................................................38 4.2.2. Funcions elementals d’accés ..............................................38 4.2.3. Taules i tuples......................................................................40

5. Introducció a la metodologia de disseny descendent en C ...... 42 5.1. Exemple: algorisme analisiCorreccions ............................................42

6. Construccions avançades del llenguatge C................................ 47 6.1. Operadors aritmètics avançats......................................................47 6.2. Funcions d’entrada/sortida............................................................48

6.2.1. Funció de sortida de dades printf........................................48 6.2.2. Funció d’entrada de dades scanf.........................................49

6.3. Inicialització de variables ..............................................................50 6.4. Apuntadors i matrius .....................................................................51

6.4.1. Concepte d’apuntador........................................................51 6.4.2. Operadors direcció i indirecció..........................................51 6.4.3. Aritmètica d’apuntadors ....................................................52 6.4.4. Relacio amb taules i matrius..............................................52

6.5. Cadenes de caràcters ......................................................................54

Resum................................................................................................. 56

Exercicis d’autoavaluació ................................................................ 61

Solucionari ........................................................................................ 63

Glossari .............................................................................................. 77

Bibliografia ....................................................................................... 77

Page 5: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 5 Codificació en C

Introducció

Al llarg de l’assignatura s’ha estat utilitzant el llenguatge algorí smic per a

descriure algorismes. Aquest llenguatge és fàcilment comprensible per

nosaltres, però no per l’ordinador. a

Per tal de poder executar els algorismes en l’ordinador, s’hauran de des-

criure en un llenguatge que aquest pugui entendre. En aquest mòdul

veurem com codificar algorismes en llenguatge C. De fet, si parlem en

propietat, l’ordinador encara no pot entendre els programes codificats

en llenguatge C. Cal tot un procés de compilació i enllaçat per tal de

traduir els programes escrits en C a un llenguatge que l’ordinador sigui

capaç d’executar. Si es disposa de les eines adequades, però, aquest pro-

cés és automàtic i no requereix intervenció, pel que, a efectes de

l’assignatura, es pot considerar que el llenguatge C és comprès per

l’ordinador.

Parlant del llenguatge C, es pot dir que és un llenguatge d’alt nivell,

imperatiu i estructurat, eficient en l’execució dels programes i molt usat,

especialment en l’enginyeria i els camps cientí fics. És clar que hi ha

altres llenguatges d’alt nivell igualment vàlids i amb una estructuració

major, o fins i tot orientats a objectes. Seria el cas del propi C++, per ci-

tar-ne un. El llenguatge C, però, té l’inestimable valor afegit de ser un

llenguatge senzill, proper al llenguatge algorí smic. A més, és fàcil dispo-

sar d’excel∙ lents compiladors de C, gratuï ts, per quasi qualsevol plata-

forma sobre la que es vulgui treballar i amb entorns de programació

clars i funcionals.

Aquest mòdul didàctic, de totes maneres, no pretén en cap cas ser

ni un manual, ni tampoc una guia de referència del llenguatge C.

Ben al contrari, l’enfocament del mòdul es dirigeix a cobrir només

aquella petita part del C necessària per a poder codificar la notació

algorí smica vista a l’assignatura. a

En aquest sentit, l’organització del present mòdul reflecteix la dels

mòduls didàctics anteriors de l’assignatura. Així , l’estudi de cadas-

cun dels diferents apartats d’aquest mòdul es farà a continuació de

la lectura del mòdul didàctic homònim de l’assignatura. Per tant, el

present mòdul s’anirà estudiant en paral∙ lel amb la resta de mò-

duls, i el coneixement del llenguatge C s’anirà completant a mesu-

ra que es completa també el coneixement del llenguatge algorí s-

mic.

L’entorn de programació en llenguatge C es tracta en “l’Annex de programari” de l’assignatura.

En altres assignatures al llarg de la carrera es com-pletarà el coneixement del llenguatge C.

Page 6: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 6 Codificació en C

Objectius

Els objectius d’aquest mòdul són bàsicament els següents:

1. Conèixer la codificació en llenguatge C de les construccions del llen-

guatge algorí smic.

2. Saber traduir a llenguatge C qualsevol algorisme expressat en llen-

guatge algorí smic.

Page 7: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 7 Codificació en C

1. Introducció a la programació en C

En aquest primer apartat veurem l’estructura bàsica d’un programa des-

crit en llenguatge C. No entrarem encara en detalls sobre la traducció de

la notació algorí smica a llenguatge C.

1.1. El nostre primer programa en C

El nostre primer programa en llenguatge C serà una breu, però emotiva,

salutació universal. El programa podria ser similar a:

/* Programa hola.c – Salutació universal Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> int main() {

printf( "Hola mon !\n" ); /* Escriu “Hola mon !” per pantalla */

system("PAUSE"); /* El programa espera una tecla */ return 0; }

Aquest senzill tros de codi ens serveix per il∙ lustrar algunes

caracterí stiques importants del llenguatge C, que comentarem tot se-

guit.

La primera lí nia del programa és un comentari. En C, els comentaris

estan delimitats entre els caràcters ”/*” i “*/”. Tal i com es veu en

l’exemple, poden ocupar vàries lí nies. Evidentment, els comentaris són

sempre opcionals, però recordeu que un programa ben documentat serà

molt més intel∙ ligible. Usarem el primer comentari per indicar el nom

del programa, una breu descripció del que fa, l’autor, etc...

En el nostre programa de salutació, després del comentari inicial, ens

trobem dues lí nies que inclouen dos fitxers de declaracions estàndards

del llenguatge C. Aquests fitxers de declaracions s’anomenen fitxers de

capçalera o fitxers d’include. Són proporcionats pel fabricant del compi-

lador i contenen declaracions de funcions, variables i constants que el

programador pot usar a partir de la inclusió del fitxer amb la directiva

#include. El fitxer stdio.h conté, entre d’altres, la declaració de la funció

printf que utilitzarem més tard, i el fitxer stdlib.h la declaració de la fun-

ció system.

Tot seguit ve el programa principal. Els programes en C sempre han de

declarar la funció main, que és la primera que s’executarà i que, opcio-

Vegeu el mòdul “Introducció a la programació” si teniu dubtes sobre algun dels conceptes usats en aquest apartat.

Podeu provar el programa usant l’entorn de progra-mació. Consulteu “l’Annex de programari” per saber-ne els detalls.

Alguns entorns de progra-mació que treballen en C++ i C accepten comentaris d’una sola lí nia delimitats pels caràcters “//” i el final de la lí nia. Però això no és C estàndard.

Les directives s’han Les directives s’han Les directives s’han Les directives s’han d’escriure sempre...d’escriure sempre...d’escriure sempre...d’escriure sempre...

... en la primera posició d’una lí nia, ja que sinó el compilador no les reconei-xeria. Totes les directives comencen sempre per “#”.

Page 8: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 8 Codificació en C

nalment, podrà cridar a altres funcions declarades. La funció main re-

torna un enter, per conveni un 0 per denotar un acabament correcte, i

no necessita paràmetres.

El cos de la funció està delimitat pels caràcters “{“ i “}”, que anomena-

rem claus. En ell hi trobem una sentència printf que imprimeix “Hola

mon !” per pantalla, una crida al sistema operatiu per tal que el progra-

ma esperi una tecla, i una sentència return que surt de la funció main i

acaba l’execució del programa.

El codi del programa de salutació universal mostra encara una impor-

tant caracterí stica més del llenguatge C:

El llenguatge C distingeix entre majúscules i minúscules.

Així , hem d’utilitzar la funció printf per escriure per pantalla. No podem

utilitzar ni la funció PRINTF, ni la Printf, ni la printF, que no estan decla-

rades en el fitxer stdio.h. De la mateixa manera, hem d’anar amb compte

amb l’ús del nom correcte de tot objecte declarat en el programa.

1.2. Un programa més complet en llenguatge C

Tot seguit es mostra la traducció a llenguatge C de l’algorisme mitjana

expressat en llenguatge algorí smic en l’apartat 1.2 del mòdul “Introduc-

ció a la programació”. L’algorisme calcula la mitjana de quatre números:

/* Programa mitjana.c - Mitjana de quatre nombres Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> int main() {

/* Declaració de variables */ int n, suma, i; float resultat; suma = 0; i = 1; while (i<=4) { scanf("%d", &n); /* Llegeix un numero decimal pel teclat */ suma = suma + n; /* Acumula la suma dels números llegits */ i = i + 1; } resultat = (float) suma / 4.0; printf( "%f ", resultat ); /* Imprimeix la mitjana per pantalla */ system("PAUSE"); /* Fem que el programa esperi una tecla */ return 0; }

Les claus “{“ i “}” serveixen per delimitar un bloc de co-di.

Page 9: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 9 Codificació en C

No us preocupeu pel funcionament de l’algorisme o pels detalls de com

s’ha fet la traducció. Tots aquests aspectes quedaran molt més clars en el

següent apartat. Aquí s’ha inclòs el programa mitjana per mostrar un

codi més complet que el programa de salutació universal.

Page 10: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 10 Codificació en C

2. Introducció a l’algorí smica en C

En aquest apartat es veuran els objectes elementals, així com les estruc-

tures algorí smiques, accions i funcions del llenguatge C, necessàries per

traduir a programes en C els algorismes del mòdul “Introducció a

l’algorí smica”.

2.1. Objectes elementals del llenguatge C

Tal com heu vist en el llenguatge algorí smic, un objecte té tres atributs:

nom o identificador, tipus i valor. Els noms o identificadors dels objectes

segueixen les mateixes normes que en el llenguatge algorí smic: han de

començar per una lletra, i després poden seguir lletres, números o el

caràcter “_”. Tampoc no es pot utilitzar cap paraula reservada del llen-

guatge C (com ara while) per identificar un objecte. La taula següent

conté noms correctes, incorrectes i un breu comentari.

Nom o identifNom o identifNom o identifNom o identifiiiicccca-a-a-a-dordordordor

És correÉs correÉs correÉs correccccte?te?te?te? ComentariComentariComentariComentari

ventes Si És recomanable escriure en minúscules.

_article No No comença per un caràcter alfabètic.

aux2 Si Poc recomanable. És millor usar noms descriptius.

1_article No No comença per un caràcter alfabètic.

nombre articles No Els espais en blanc no són permesos.

nombreArticles Si És un nom descriptiu.

peçaCamió No No es poden utilitzar caràcters especials ni accents (la “ç” es considera un caràcter especial, recordeu que els ordinadors provenen del món anglosaxó).

const No És una paraula reservada del llenguatge C.

A continuació anem a veure la traducció dels tipus elementals del llen-

guatge algorí smic al llenguatge C, així com els valors que aquests po-

den prendre.

Page 11: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 11 Codificació en C

2.1.1. Tipus elementals en C

El llenguatge algorí smic defineix quatre tipus elementals: booleà, enter,

caràcter i real. Tot seguit veurem com es tradueixen al llenguatge C.

Tipus booleà

El tipus booleà no existeix com a tal en el llenguatge C, però el podem

definir fàcilment usant la declaració següent:

typedef enum {FALSE, TRUE} bool;

A partir d’aquest moment podem utilitzar el nou tipus bool per a decla-

rar objectes de tipus booleà.

La següent taula resumeix les caracterí stiques del tipus booleà i la seva

traducció a llenguatge C.

Caracterí sticaCaracterí sticaCaracterí sticaCaracterí stica Llenguatge algLlenguatge algLlenguatge algLlenguatge algoooorírírírí s-s-s-s-micmicmicmic

Llenguatge CLlenguatge CLlenguatge CLlenguatge C

Identificador boolea bool

Rang de valors cert, fals TRUE, FALSE

Operadors interns no, i, o, =, •, <, •, >, • !, &&, ||, ==, !=, <, <=, >, >=

Tipus caràcter

En C els caràcters van delimitats per cometes simples com en el llen-

guatge algorí smic. La taula següent resumeix les caracterí stiques del

tipus caràcter i la seva traducció a C.

Caracterí sticaCaracterí sticaCaracterí sticaCaracterí stica Llenguatge algLlenguatge algLlenguatge algLlenguatge algoooorírírírí s-s-s-s-micmicmicmic

Llenguatge CLlenguatge CLlenguatge CLlenguatge C

Identificador caracter char

Rang de valors conjunt finit de valors conjunt finit de valors defi-nits pel codi ASCII

Operadors externs =, •, <, •, >, • ==, !=, <, <=, >, >=

Sintaxi de valors ‘a’, ‘W’, ‘1’ ‘a’, ‘W’, ‘1’

Aneu amb compte perque l’ordre dels elements (FALSE i TRUE) és important, com veurem més endavant.

Page 12: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 12 Codificació en C

Tipus enter

La següent taula resumeix les caracterí stiques del tipus enter i la seva

traducció a C.

Caracterí sticaCaracterí sticaCaracterí sticaCaracterí stica Llenguatge algorí smicLlenguatge algorí smicLlenguatge algorí smicLlenguatge algorí smic LlenLlenLlenLlenguatge Cguatge Cguatge Cguatge C

Identificador enter int

Rang de valors ENTERMIN a ENTERMAX -2147483648, 2147483647

Operadors in-terns

- (canvi de signe), +, -, *, div, mod

- (canvi de signe), +, -, *, /, %

Operadors ex-terns

=, •, <, •, >, • ==, !=, <, <=, >, >=

Sintaxi de valors 3, 465434, -2134567 3, 465434, -2134567

Tipus real

La següent taula resumeix les caracterí stiques del tipus real i la seva

traducció a C.

Caracterí stCaracterí stCaracterí stCaracterí stiiiicacacaca Llenguatge algorí smicLlenguatge algorí smicLlenguatge algorí smicLlenguatge algorí smic Llenguatge CLlenguatge CLlenguatge CLlenguatge C

Identificador real float

Rang de valors REALMIN a REALMAX (no tots) ±3.4E±38 (7 dí gits significatius)

Operadors in-terns

- (canvi de signe), +, -, *, / - (canvi de signe), +, -, *, /

Operadors ex-terns

=, •, <, •, >, • ==, !=, <, <=, >, >=

Sintaxi de valors 0.6, 5.0E-8, -49.2E+0.8, 1.0E5, 4.0 0.6, 5.0E-8, -49.2E+0.8, 1.0E5, 4.0

2.1.2. Declaració d’objectes en C

Abans d’utilitzar un objecte en un programa, cal haver-lo declarat prèvi-

ament. En el cas del llenguatge C, però, les declaracions no van delimi-

tades per paraules reservades com en el llenguatge algorí smic. Simple-

ment, es col∙ loquen les declaracions de constants i variables a l’inici del

cos de la funció corresponent (funció main si fem referència al programa

principal), abans de qualsevol instrucció.

El rang dels enters pot variar segons el compilador i l’ordinador on s’executi el programa.

El llenguatge C permet reals amb més dí gits significatius: els tipus double i long double.

Page 13: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 13 Codificació en C

Per a declarar una constant, s’utilitza la construcció:

const tipus nom = valor ;

Noteu que la paraula reservada const és obligatòria davant de cada de-

claració de constant. No serveix per definir tot un bloc de declaracions

de constants com en el llenguatge algorí smic, sinó només per declarar-

ne una.

Aquest tipus de constant és coneguda en temps d’execució. És a dir,

l’assignació del valor a la constant nom es farà durant l’execució del pro-

grama, i no durant la compilació.

De vegades és convenient definir constants amb valor conegut ja durant

la compilació. Es pot fer amb la directiva #define:

#define NOM valor

Observem que no s’indica el tipus de la constant que s’està definint. De

fet, el compilador únicament substitueix el nom pel seu valor cada cop

que el troba en el codi posterior a la declaració. Així mateix, és habitual

usar un nom escrit tot en majúscules al declarar una constant. D’aquesta

manera el codi del programa és més llegible, ja que es poden distingir

les constants de les variables amb un sol cop d’ull.

Per declarar una variable, s’usa la sintaxi següent:

tipus nom ;

Així es declara una variable de tipus tipus i nom nom. També es poden

declarar diverses variables del mateix tipus en una sola declaració, sepa-

rant els seus noms per comes (“,”). Per exemple, per declarar tres varia-

bles i, j, k de tipus enter:

int i, j, k;

Les constants conegudes en temps de compilació seran útils per a la parametrització de tipus de dades estructu-rats, com ara les taules. Es comentaran en l’apartat 4.1.4. “Accés directe a una taula” del present mòdul.

El llenguatge C...El llenguatge C...El llenguatge C...El llenguatge C...

... permet indicar un valor inicial per la variable en la pròpia declaració, però evi-tarem aquesta construcció que no és permesa en el llenguatge algorí smic.

Page 14: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 14 Codificació en C

Finalment, remarcar que tot i que el llenguatge C no usa paraules reser-

vades per delimitar les declaracions de variables i constants, nosaltres

col∙ locarem els comentaris apropiats per fer el programa més llegible.

2.1.3. Expressions en C

Les expressions en llenguatge C segueixen les mateixes regles de cons-

trucció i avaluació que en el llenguatge algorí smic. En cas de dubte,

però, sempre és aconsellable posar un parèntesi de més per indicar cla-

rament l’ordre d’avaluació de l’expressió.

2.1.4. Definició de tipus. Tipus enumeratius en C

Tal com succeeix amb les declaracions de variables i constants, les decla-

racions de tipus en C tampoc no van delimitades per paraules reserva-

des. S’han de col∙ locar entre les declaracions de les constants i les de les

variables, indicant amb un comentari que es procedeix a fer declaraci-

ons de tipus.

El constructor de tipus enumeratius en C segueix la següent sintaxi:

typedef enum {valor1, valor2, ..., valorn} nom ;

Com al llenguatge algorí smic l’ordre en què s’enumeren els valors ser-

veix per establir les relacions de més petit a més gran i per tant l’ordre

en què s’enumeren els valors és important. En C es pot assignar un enter

a cada valor, per establir aquestes relacions, però nosaltres no utilitza-

rem aquesta caracterí sitca.

Recordeu que hem vist un exemple d’aquesta sintaxi en la definició del tipus boo-leà.

Page 15: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 15 Codificació en C

2.1.5. Funcions de conversió de tipus

Tal com passa amb el llenguatge algorí smic, de vegades calen funcions

de conversió de tipus per passar d’un tipus de número (o codi) a un altre.

Tot i que el llenguatge C sovint pot fer aquestes conversions automàti-

cament, el millor és indicar clarament en el programa el tipus de con-

versió desitjada.

La següent taula mostra la traducció de les funcions de conversió de

tipus del llenguatge algorí smic a C.

Llenguatge algLlenguatge algLlenguatge algLlenguatge algoooorí smicrí smicrí smicrí smic Llenguatge CLlenguatge CLlenguatge CLlenguatge C ExempleExempleExempleExemple

realAEnter (int) (int) –3.99

enterAReal (float) (float) 3

caracterACodi (int) (int) ‘A’

codiACaracter (char) (char) 65

2.2. Especificació d’algorismes

L’especificació d’algorismes, accions i funcions en llenguatge C es farà

amb la utilització de comentaris, tal com es feia en la notació algorí smi-

ca. En aquest cas, però, recordeu d’usar la sintaxi de C pels comentaris.

/* Pre: precondició */

algorisme

/* Post: postcondició */

2.3. Estructures algorí smiques

En aquest apartat es mostren els equivalents en C de les estructures bàsi-

ques del llenguatge algorí smic.

Page 16: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 16 Codificació en C

2.3.1. Estructura general d’un programa en llenguatge C

L’estructura d’un programa en llenguatge C és la següent:

/* Programa estructura.c – Estructura bàsica d’un programa en

C

Jordi Riera, 2001

*/

/* Inclusió de fitxers de capçalera */

#include <fitxer1>

#include <fitxer2>

...

/* Declaració de constants en temps de compilació */

#define NOM_DEFINE1 valor_define1

#define NOM_DEFINE2 valor_define2

...

/* Declaració de tipus */

typedef enum {FALSE, TRUE} bool; /* tipus booleà

*/

typedef definicio_de_tipus1 nom_tipus1 ;

typedef definicio_de_tipus2 nom_tipus2 ;

...

int main() {

/* Definició de constants */

const tipus_de_constant1 nom_constant1 = valor_constant1 ;

const tipus_de_constant2 nom_constant2 = valor_constant2 ;

...

/* Declaració de variables */

tipus_de_variable1 nom_variable1 ;

tipus_de_variable2 nom_variable2 ;

...

/* Cos del programa */

acció1

acció2

...

}

Observeu que les declaracions de tipus s’han fet fora de la funció main

del programa. Això és perquè habitualment és desitjable que els tipus de

dades estiguin disponibles en tot el programa i per totes les funcions

que s’hi puguin declarar. De totes maneres, també es poden fer declara-

cions de tipus locals, situant-les entre les declaracions de les constants i

les de les variables.

Page 17: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 17 Codificació en C

2.3.2. Accions elementals: l’assignació

L’acció d’assignació del llenguatge algorí smic, “:=” es tradueix en

l’operador d’assignació en llenguatge C, “=”. La distinció entre acció i

operador és molt important, ja que implica que el llenguatge C permet

fer assignacions en qualsevol punt del codi on una expressió sigui vàli-

da. Per exemple, és un error molt comú fer una assignació, enlloc d’una

comparació, en la condició d’una sentencia condicional per usar

l’operador d’assignació “=” enlloc de l’operador relacional d’igualtat

“==”, la qual cosa té greus repercussions de cara al bon funcionament

del programa.

2.3.3. Composició d’accions

Veurem ara com combinar accions elementals per poder construir pro-

grames més complexos.

Composició seqüencial

En C, la composició seqüencial es fa com en el llenguatge algorí smic,

escrivint una acció a continuació de l’altra i separant cada acció de la

següent amb un “;”.

Si voleu agrupar un conjunt d’accions en un bloc, les podeu col∙ locar

entre les claus “{“ i “}”.

Composició alternativa

La sintaxi de la composició alternativa d’accions en llenguatge C és la

següent:

if (expressió) {

accióa

} else {

acciób

}

Noteu que el parèntesi entorn de l’expressió és obligatori i forma part de

la sintaxi. Les accions a executar condicionalment (accióa i acciób,) són

blocs d’accions delimitats per claus (composició seqüencial). Si només

calgués executar una acció simple, es podrien eliminar les claus corres-

ponents.

Es recomanable utilitzar sempre les claus, encara que només calgui col∙ locar una acció. Potser més endavant caldrà afegir-ne de noves !

Page 18: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 18 Codificació en C

A l’igual que en el llenguatge algorí smic, es pot eliminar la part corres-

ponent al else si no desitgem executar cap acció en el cas que la condi-

ció sigui falsa.

Composició iterativa

La sintaxi de la composició iterativa en llenguatge C és la següent:

while (expressió) {

acció

}

Noteu que el parèntesi entorn de l’expressió és obligatori. També, com en

la composició alternativa, es poden eliminar les claus si només hi ha

una sentència en el cos del while, però és més recomanable posar-les

sempre.

El llenguatge C disposa també d’una variant de la composició alternati-

va que ens serà especialment útil quan coneguem exactament el número

de repeticions que cal fer. La seva sintaxi és la següent:

for ( í ndex = valor_inicial ; í ndex <= valor_final ; í ndex++ ) {

acció

}

Fixeu-vos que aparentment en aquesta sintaxi no s’especifica quin incre-

ment es farà en cada pas. De fet, s’està indicant que es farà un increment

unitari amb l’operació í ndex++. Si voleu un decrement unitari (incre-

ment = -1) heu de substituir í ndex++ per í ndex-- . Així mateix, per in-

crements no unitaris, positius i negatius, usareu les operacions í ndex +=

increment i í ndex -= increment respectivament.

Podrí em fer l’equivalent del for amb un while

index=valor_inicial;

while (index<=valor_final)

{

acció;

index++;

}

En el llenguatge algorí smic no apareix la condició d'acabament (només apareix "fins valor_final"); en canvi, en C apareix la condició completa "index <=valor_final".

Noteu Noteu Noteu Noteu la diferènciala diferènciala diferènciala diferència............

... ++, --, += i -= són opera-dors del llenguatge C. De fet, C té molts altres opera-dors encara. Nosaltres no els utilitzarem, ja que ens con-centrem en la manera més senzilla i sistemàtica de tra-duir la notació algorí smica al llenguatge C. Podeu, pe-rò, trobar-ne més informació en l’apartat “Construccions avançades del llenguatge C” d’aquest mateix mòdul.

Noteu que...Noteu que...Noteu que...Noteu que...

Page 19: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 19 Codificació en C

Usant la construcció for es pot codificar el programa que calcula el fac-

torial d’un número enter.

/* Programa fact.c - Calcula el factorial de n Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> int main() {

/* Declaració de variables */ int i, n, fact; scanf("%d", &n); /* Llegim un numero enter per teclat */ /* Pre: n=N i N>=0 i N<=16 */ fact = 1;

for (i=1; i<=n; i++) { fact = fact * i; } /* Post: fact es el factorial de N */ printf("%d\n", fact); /* Escrivim el resultat per pantalla */ system("PAUSE"); /* Fem que el programa esperi una tecla */ return 0; }

Observeu que hem afegit una nova condició en la precondició, concre-

tament N<=16. Aquesta condició no ve imposada per una limitació de

l’algorisme, sinó per la seva codificació en un programa en C. La limita-

ció està en l’enter més gran que es pot representar en l’ordinador. Ob-

serveu què passa si introduï u per teclat el número 17, per exemple.

2.4. Accions i funcions en C

El llenguatge C no disposa d’accions en el sentit de la notació algorí smi-

ca. En C, tot són funcions. Recordeu que fins i tot l’algorisme principal

s’escriu dins de la funció main. a

De totes maneres, en llenguatge C, també es pot distingir entre accions i

funcions. Es farà segons la manera de declarar els paràmetres i la forma

de fer les invocacions. En una funció només es declararan paràmetres

d’entrada, i s’invocarà dins d’una expressió. En una acció es declararan

paràmetres de tot tipus, i s’invocarà allà on una acció sigui vàlida.

Considerant aquestes restriccions, la sintaxi per a la declaració d’una

acció en C és:

void nom(param1, param2, ..., paramn)

{

... cos de l’acció

}

Teniu una altra solució a l’algorisme fact, usant whi-le enlloc de for, en l’apartat 3.3.3. “Composi-ció iterativa” (pàgina 41), del mòdul “Introducció a l’algorí smica” de l’assignatura.

Per una definició precisa del que són les accions i les funcions, consulteu l’apartat 4. “Accions i fun-cions” (pàgina 44), del mòdul “Introducció a l’algorí smica” de l’assignatura.

void...void...void...void...

... és un tipus especial del llenguatge C que indica que la funció no retorna cap va-lor.

Page 20: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 20 Codificació en C

I la corresponent invocació de l’acció és:

nom(obj1, obj2, ..., objn) ;

En el cas d’una funció, la sintaxi per a la seva declaració en C és:

tipus nom(param1, param2, ..., paramn)

{

... cos de la funció

return expressió ;

}

I la corresponent invocació de la funció és:

nom(obj1, obj2, ..., objn)

Tal com succeeix en el llenguatge algorí smic, les accions i funcions en C

poden declarar el seu entorn local, amb definicions de constants, tipus i

variables pròpies. La sintaxi és la mateixa que s’ha utilitzat en la funció

main.

També, al igual que les variables, en C cal declarar les accions i funcions

abans del seu ús. Una pràctica molt convenient és predeclarar totes les

funcions i accions al principi del fitxer (després dels includes,defines i

typedefs) amb la qual cosa podem declarar-les després allà on vulguem i

ens podrem despreocupar a l’hora d’utilitzar-les de si ja les hem declarat

o no.

La predeclaració de l’acció/funció és molt semblant a la primera lí nia

de la declaració, però, en lloc dels paràmetres es poden posar només els

seus tipus :

tipus nom(tipus1, tipus2, ..., tipusn) ; /* funció*/

void nom2(tipus1, tipus2, ..., tipusn) ; /*acció */

La invocació només serà và-lida dins d’una expressió on s’espera un valor del tipus que retorna la funció.

Page 21: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 21 Codificació en C

Igualment és més recomanable, per claredat, posar tot el paràmetre com

a la declaració:

tipus nom(param1, param2, ..., paramn); /* funció */

void nom2(param1, param2, ..., paramn); /* acció */

2.4.1. Paràmetres en C

El pas de paràmetres en llenguatge C segueix les directrius explicades en

l’apartat 4.2. del mòdul “Introducció a l’algorí smica”. És a dir, cal espe-

cificar el seu tipus en la capçalera de l’acció o funció, i l’ordre dels pa-

ràmetres actuals en la invocació ha de ser el mateix que el dels paràme-

tres formals en la declaració de la funció.

Quan cridem a la funció, el llenguatge C sempre fa una còpia de cadas-

cun dels paràmetres actuals i aquesta còpia és la que s’associa als parà-

metres formals. Per tant, les modificacions que fem al cos de la funció

no afecten als paràmetres actuals. Podrí em dir que és com si els parà-

metres fossin d’entrada. Aquest mecanisme de pas de paràmetres, en el

que passem una còpia de l’objecte, es coneix com pas de paràmetres per

valor.

La forma de simular paràmetres d’entrada/sortida consisteix en passar

l'adreça de memòria del paràmetre actual en lloc del paràmetre en sí .

D’aquesta manera, després, des de l’acció podrem accedir a memòria i

modificar el paràmetre actual. Aquest altre mecanisme de pas de parà-

metres, en el que passem l’adreça de memòria de l’objecte, és el que

s’anomena pas per referència.

Per últim, els paràmetres de sortida no existeixen pròpiament. En reali-

tat seran paràmetres d’entrada/sortida on el seu valor d’entrada s’ignora

o no interessa.

IMPORTANT: Per a treballar amb adreces de memòria en C fem servir

un nou tipus de dades que anomenem apuntador. Un apuntador no és

més que una adreça de memòria.

Mireu l'apartat 6.4 d’aquest manual per més informació sobre els apun-

tadors que us serà útil per a entendre bé el que ve a continuació.

A partir d’ara, quan parlem de paràmetres d’entrada/sortida ens referirem també als paràmetres de sortida.

Page 22: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 22 Codificació en C

La sintaxi dels paràmetres en la capçalera d’una acció o funció és:

per un paràmetre d’entrada: tipus nom

per un paràmetre de sortida: tipus *nom

per un paràmetre d’entrada/sortida: tipus *nom

Noteu com en la declaració de paràmetres d’entrada/sortida el nom va

precedit per un “*”. Això serveix per indicar que el paràmetre és un a-

puntador, és a dir, una adreça de memòria que conté un objecte del

tipus declarat.

Dins del cos de les accions/funcions, l'operador “*” s'ha de fer servir per

a accedir als objectes que es corresponen amb els paràmetres d'entra-

da/sortida, ja sigui per a actualitzar-los com per a obtenir el seu valor.

Com podeu veure hi ha dos usos ben diferenciats d'aquest operador "*":

• Declaració de la capçalera d'una acció amb paràmetres d'entra-

da/sortida.

• En el cos de l'acció per accedir a l'objecte corresponent als paràme-

tres d'entrada/sortida.

Per regla general en la crida a una acció tots els paràmetres reals

d’entrada/sortida han d’anar precedits per l’operador unari “&”. Aquest

operador "&", davant d'una variable, permet construir un apuntador a

l'esmentada variable (recordeu la crida a scanf per llegir un número del

teclat en el programa que calcula el factorial, per exemple). Hi ha però

una excepció: quan s'invoca una acció B des d’una altra acció A i algun

dels paràmetres d'entrada/sortida de la crida a B ja era un paràmetre

d'entrada/sortida en A. Vegeu-ho en el següent exemple:

/* Programa Exemple.c.- Serveix per il∙ lustrar l’ús dels paràmetres d’entrada/sortida */

#include <stdio.h> #include <stdlib.h> /* Predeclaracio de funcions */ void accio_A(int *param_ent_sort); /* Declarem un paràmetre d'entrada/sortida */ void accio_B(int *param_ent_sort); /* Declarem un paràmetre d'entrada/sortida */ void accio_C(int param_ent); /* Declarem un paràmetre d'entrada */ void accio_A (int *param_ent_sort) { int param_local; param_local=*param_ent_sort; /*param_local pren el valor de l’objecte apuntat per

param_ent_sort */ accio_B(param_ent_sort); /* Atenció:No posem & davant del param_ent_sort

perquè ja tenim l’ adreça del objece */ accio_C(*param_ent_sort); /* Hem de passar l’objecte com a paràmetre d'entrada */

De fetDe fetDe fetDe fet............

... & i * són operadors unaris de C que permeten, respec-tivament, obtenir l’adreça de memòria on es guarda un objecte i accedir a l’objecte contingut en una adreça de memòria.

Page 23: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 23 Codificació en C

accio_B(&param_local); /* Passem la variable com a paràmetre d'entrada/sortida*/ accio_C(param_local); /* Passem la variable com a paràmetre d'entrada */ } void accio_B(int *numero) { *numero=*numero + 1; /*Dins del cos de l’acció els paràmetres d'entrada/sortida

han d'anar precedits per * */ } void accio_C(int numero) { printf("%d",numero); } int main() { int numero; scanf("%d",&numero); /* Hem de passar l'adreça de la variable */ accio_A(&numero); /* l’acció A espera un paràmetre d'entrada/sortida per tant posem el & davant la variable.*/ system("PAUSE"); return 0; }

2.4.2. Accions i funcions d’entrada i sortida de dades en C

La taula següent mostra els equivalents del llenguatge C de les funcions

predefinides en el llenguatge algorí smic (suposem que tenim declarades

les variables e, r i c com enter, real i caràcter respectivament):

Llenguatge algLlenguatge algLlenguatge algLlenguatge algoooorírírírí s-s-s-s-micmicmicmic

Llenguatge CLlenguatge CLlenguatge CLlenguatge C

e = llegirEnter(); scanf(“%d”, &e);

r = llegirReal(); scanf(“%f”, &r);

c = llegirCaracter(); scanf(“%c”, &c);

escriureEnter(e); printf(“%d ”, e);

escriureReal(r); printf(“%f ”, r);

escriureCaracter(c); printf(“%c ”, c);

Noteu el darrer espai en el primer paràmetre del printf. Si no hi fos, la

sortida seria il∙ legible, ja que s’escriurien tots els objectes un a continua-

ció de l’altre, sense cap separació.

Per exemple:

... printf(“%d”, 1234); printf(“%d”, 567); ...

... són funcions d’entrada i sortida de dades del llen-guatge C, que permeten controlar molts detalls que el llenguatge algorí smic no contempla. Usarem les ver-sions simplificades de la tau-la adjunta per tal de concen-trar esforços en el disseny dels algorismes i deixar la codificació com una feina quasi mecànica de traducció a C.

scanf i printf...scanf i printf...scanf i printf...scanf i printf...

Page 24: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 24 Codificació en C

L’execució del programa escriu els caràcters “1234567” pel dispositiu de

sortida. Observeu com no es distingeix on acaba el primer nombre i co-

mença el segon... En canvi, si en el primer paràmetre del printf hi posem

“%d “ enlloc de “%d”, la sortida seria “1234 567 ”, que és la correcte.

2.5. Exemples de codificació en C

En aquest apartat veurem codificats en llenguatge C alguns dels exerci-

cis d’autoavaluació del mòdul “Introducció a l’algorí smica”.

2.5.1. Algorisme arrelEntera

La codificació de l’algorisme que calcula l’arrel entera d’un nombre en-

ter seria la següent:

/* Programa arrelEntera.c - Calcula l'arrel entera d'un enter Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> int main() {

/* Declaració de variables */ int n, arrel; scanf("%d", &n); /* Llegim un número enter per teclat */ /* Pre: n=N i N>=0 */ arrel = 0; while ( (arrel+1)*(arrel+1) <= n) { arrel = arrel + 1; } /* Post: arrel*arrel <= N < (arrel+1)*(arrel+1) */ printf("%d\n", arrel); /* Escrivim el resultat per pantalla */ system("PAUSE"); /* El programa espera una tecla */ return 0; }

2.5.2. Algorisme arrelEquacioSegonGrau

En aquest apartat veurem la codificació de l’algorisme que calcula les

arrels reals d’una equació de segon grau, donats els coeficients de la ma-

teixa. Codificarem l’acció arrelEquacio per trobar les arrels, mentre que en

l’algorisme principal farem l’entrada i sortida de dades i la invocació a

l’acció per resoldre el problema.

/* Programa arrelEquacioSegonGrau.c Calcula les arrels reals d'una equació de segon grau, donats els coeficients Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> #include <math.h> /* Necessària per a la funció sqrt() */ /* Definició de tipus */ typedef enum {FALSE, TRUE} bool;

Consulteu la solució a l’algorisme arrelEntera, cor-responent a l’exercici d’autoavaluació número 12 (pàgines 58 i 61), del mò-dul “Introducció a l’algorí smica” de l’assignatura.

Consulteu les solucions a l’algorisme arrelEquacioSe-gonGrau i a l’acció arrelEqua-cio, corresponents als exer-cicis d’autoavaluació números 19 i 20 (pàgines 59, 63 i 64), del mòdul “In-troducció a l’algorí smica” de l’assignatura.

Page 25: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 25 Codificació en C

/* Pre-declaracions de funcions */ void arrelEquacio(float a, float b, float c, bool *teSolucio, float *x1, float *x2); int main() {

/* Declaració de variables */ float a, b, c, x1, x2; bool enTe; scanf("%f", &a); /* Entrada dels coeficients per teclat */ scanf("%f", &b); scanf("%f", &c); /* Pre: a=A i b=B i c=C i A!=0 */ arrelEquacio(a, b, c, &enTe, &x1, &x2); /* Post: ((enTe=cert) i (A*x1*x1 + B*x1 + C = 0) i

(A*x2*x2 + B*x2 + C = 0)) o (enTe=fals) */ if ( enTe ) { printf("%f ", x1); printf("%f ", x2); } else printf("N\n"); system("PAUSE"); /* Fem que el programa esperi una tecla */ return 0; } void arrelEquacio(float a, float b, float c, bool *teSolucio, float *x1, float *x2) { float discr;

/* Pre: a=A i b=B i c=C i A!=0 */ discr = b*b - 4.0*a*c; if ( discr>=0.0 ) { *x1 = (-b + sqrt(discr)) / (2.0 * a); *x2 = (-b - sqrt(discr)) / (2.0 * a); *teSolucio = TRUE; } else * teSolucio = FALSE;

/* Post: ((teSolucio=cert) i (A*x1*x1 + B*x1 + C = 0) i A*x2*x2 + B*x2 + C = 0)) o (teSolucio=fals) */

}

L’algorisme arrelEquacioSegonGrau ens il∙ lustra algunes possibilitats o

caracterí stiques del llenguatge C, que es comenten a continuació. En

primer lloc, observeu la inclusió del fitxer math.h; en ell es troben les

declaracions d’algunes funcions matemàtiques, entre les quals es troba

la de l’arrel quadrada d’un número real (sqrt).

Noteu tot seguit la declaració del tipus bool. Aquesta no es fa dins del

programa principal (main), sinó a l’inici del programa, fora de qualsevol

acció o funció. Això permet que la definició sigui global al programa i,

per tant, ens serveixi per a qualsevol acció o funció posterior.

Observeu a continuació la predeclaració de l’acció arrelEquacio. Aquesta

declaració és necessària perquè sinó el compilador al trobar la invocació

de l’acció no sabria encara quin tipus de paràmetres formals té aquesta.

El millor és que la predeclaració coincideixi exactament amb la posteri-

or declaració.

... però cal evitar l’ús de va-riables globals, ja que tren-quen la metodologia de dis-seny descendent seguida a l’assignatura i fa els pro-grames menys llegibles.

Es poden declarar també Es poden declarar també Es poden declarar també Es poden declarar també constants glconstants glconstants glconstants gloooobals...bals...bals...bals...

Cal fer les predeclaracions de totes les funcions i acci-ons utilitzades en el pro-grama. Les predeclaracions de funcions de les llibreries de C es fan dins dels fitxers que incloem amb #include.

Page 26: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 26 Codificació en C

Cal destacar també que l’acció arrelEquacio té tres paràmetres de sortida.

Observeu com en la declaració dels paràmetres formals cal precedir el

nom amb un “*”, i també cal fer-ho en l’ús d’aquests paràmetres en el

cos de l’acció. De manera similar, en la invocació de l’acció els paràme-

tres actuals han d’anar precedits per un “&”.

Finalment, noteu que a l’hora d’escriure el caràcter “N” per pantalla no

s’ha utilitzat l’acció printf(“%c “, ‘N’) sinó printf(“N\n”). S’ha usat una va-

riació del printf que permet escriure directament una cadena de caràcters

per pantalla, col∙ locant com a paràmetre del printf els caràcters a escriu-

re (entre cometes). En aquest cas, s’escriurà el caràcter “N” i el caràcter

“\n”, que es correspon amb un salt de lí nia.

L’acció L’acció L’acció L’acció printf(“printf(“printf(“printf(“cadena_caràcterscadena_caràcterscadena_caràcterscadena_caràcters””””););););

... permet treure fàcilment per pantalla missatges com-plets que indiquin a l’usuari del programa el que aquest està fent o esperant.

Page 27: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 27 Codificació en C

3. Tractament seqüencial en llenguatge C

En el mòdul “Tractament seqüencial” de l’assignatura s’introdueix una

metodologia sistemàtica per plantejar solucions a problemes que es po-

den modelar amb una seqüència d’elements: són els esquemes de cerca i

recorregut. Aquesta metodologia no introdueix nous elements del llen-

guatge algorí smic i, per tant, els algorismes que l’empren es poden

codificar en llenguatge C amb el que s’ha vist fins ara en aquest mòdul.

En aquest apartat es mostrarà, a tall d’exemple, la codificació en llen-

guatge C d’alguns dels algorismes vistos en el mòdul “Tractament se-

qüencial” dels materials.

3.1. Exemple d’esquema de recorregut d’una seqüència en C

Com a exemple d’esquema de recorregut en una seqüència, codificarem

en C l’algorisme sumaDigits, que escriu en pantalla la suma dels dí gits

d’un número prèviament obtingut pel teclat. Recordeu que la seqüència

de dí gits es genera en el propi algorisme.

/* Programa sumaDigits.c Escriu per pantalla la suma dels dí gits d'un numero entrat pel teclat Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> int main() {

/* Declaració de variables */ int n, suma, d;

scanf("%d", &n); /* Pre: n=N i N>=0 */ d = n % 10; /* preparar seqüència */ suma = 0; /* inici tractament */ while (!(n==0)) { /* fi seqüència */ suma = suma + d; /* tractar element */ n = n / 10; /* avançar seqüència */ d = n % 10; } printf("%d\n", suma); /* tractament final */ /* Post: La suma dels dí gits de N s'ha escrit per pantalla */ system("PAUSE"); /* Fem que el programa esperi una tecla */ return 0; }

Tingueu en compte que...Tingueu en compte que...Tingueu en compte que...Tingueu en compte que...

... es veuran algorismes que tracten seqüències genera-des o obtingudes de l’entrada estàndard (teclat). El llenguatge C disposa de funcions per tractar direc-tament seqüències guarda-des en fitxers, però l’estudi d’aquestes queda fora de l’abast de l’assignatura.

Consulteu com s’obté la solució a l’algorisme suma-Digits en l’apartat 2.5.2. “Suma de les xifres d’un número” (pàgina 18), del mòdul “Tractament se-qüencial” de l’assignatura.

Page 28: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 28 Codificació en C

3.2. Exemple d’esquema de cerca en una seqüència en C

Com a exemple d’esquema de cerca en una seqüència, codificarem en C

l’algorisme cercarFibonacci9, que escriu en pantalla un dels mil primers

nombres de Fibonacci que a més acaba en 9, si és que existeix; si no e-

xisteix escriu un -1. Recordeu que la seqüència de nombres de Fibonacci

es genera en el propi algorisme.

/* Programa cercarFibonacci9.c Escriu per pantalla un dels primers mil nombres de Fibonacci, acabat en 9, si és que existeix; si no existeix, escriu un -1 Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> /* Definició de tipus */ typedef enum {FALSE, TRUE} bool; int main() { /* Declaració de variables */ int actual, seguent, seguent2; int i; bool trobat; /* Pre: cert */ actual = 0; /* preparar seqüència */ seguent = 1; i = 1; trobat = FALSE; /* inici tractament - és buit */ while ((i<=1000) && !trobat) { /* fi seqüència - i>1000 */ trobat = (actual % 10) == 9; /* actualitzar trobat */ if (!trobat) { /* tractar element - és buit */ seguent2 = actual + seguent; /* avançar seqüència */ actual = seguent; seguent = seguent2; i = i + 1; } } if (trobat) { /* tractament final */

printf("%d\n", actual); } else {

printf("%d\n", -1); /* Noteu: printf(“-1\n”) seria més simple */ }

/* Post: Per pantalla s'ha escrit un dels primers mil nombres de Fibonacci, acabat en 9, si és que existeix; si no existeix, s'ha escrit un -1 */ system("PAUSE"); /* Fem que el programa esperi una tecla */ return 0; }

3.3. Exemple d’esquema de recorregut aplicat a l’entrada en C

Com a exemple d’esquema de recorregut aplicat a l’entrada, codificarem

en C l’algorisme comptaLletraA, que escriu en el dispositiu de sortida

quantes vegades apareix la lletra “a” en una frase acabada amb un punt

que s’introdueix per l’entrada.

Consulteu com s’obté la solució a l’algorisme cercar-Fibonacci9 en l’apartat 3.5.1. “Nombres de Fibo-nacci” (pàgina 24), del mòdul “Tractament se-qüencial” de l’assignatura.

Consulteu com s’obté la solució a l’algorisme comptaLletraA en l’apartat 4.1.3. “Exemple” (pàgina 31), del mòdul “Tractament seqüencial” de l’assignatura.

Page 29: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 29 Codificació en C

/* Programa comptaLletraA.c Calcula el nombre de vegades que hi ha la lletra "a" a l'entrada Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> int main() { /* Declaració de variables */ char car; int n; /* Pre: A l’entrada s'hi llegeix una seqüència de caràcters

que no té cap punt, seguida d'un punt */ scanf("%c", &car); /* preparar seqüència - llegir() */ n = 0; /* inici tractament */ while (! (car=='.')) { /* fi seqüència - marca = '.' */ if (car=='a') n = n + 1; /* tractar element */ scanf("%c", &car); /* avançar seqüència - llegir() */ } printf("%d\n", n); /* tractament final */ /* Post: S'ha escrit per pantalla el nombre de vegades que

hi ha la lletra "a" a l'entrada */ system("PAUSE"); /* Fem que el programa esperi una tecla */ return 0; }

3.4. Exemple d’esquema de cerca aplicat a l’entrada en C

Com a exemple d’esquema de cerca aplicat a l’entrada, codificarem en C

l’algorisme surtLletraA, que escriu en el dispositiu de sortida “S” si a

l’entrada hi ha alguna lletra “a” i escriu “N” en cas contrari.

/* Programa surtLletraA.c Llegeix una seqüència de caràcters que no té cap punt, seguida d'un punt. Escriu "S" si a l'entrada hi havia alguna "a" i escriu "N" en cas contrari. Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> typedef enum {FALSE, TRUE} bool; /* Definició de tipus */ int main() { char car; /* Declaració de variables */ bool trobat; /* Pre: A l'entrada hi ha una seqüència de caràcters que no té cap punt, seguida

d'un punt */ scanf("%c", &car); /* preparar seqüència - llegir() */ trobat = FALSE; /* inici tractament - és buit */ while (!(car=='.') && !trobat) { /* fi seqüència – marca='.' */ trobat = car == 'a'; /* actualitzar trobat */ if (!trobat) { /* tractar element - és buit */ scanf("%c", &car); /* avançar seqüència - llegir() */ } } if (trobat) printf("S\n"); /* tractament final */ else printf("N\n"); /* Post: Pel dispositiu de sortida s'escriu "S" si a l'entrada hi ha alguna lletra "a", i

"N" en cas contrari */ system("PAUSE"); /* Fem que el programa esperi una tecla */ return 0; }

Consulteu com s’obté la solució a l’algorisme surtLletraA en l’apartat 4.2.3. “Exemple” (pàgina 35), del mòdul “Tracta-ment seqüencial” de l’assignatura.

Page 30: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 30 Codificació en C

3.5. Combinació d’esquemes en C

Finalitzarem aquest apartat sobre el tractament seqüencial codificant en

C un algorisme que combini un esquema de cerca amb un de recorregut.

S’ha escollit com exemple l’algorisme mitjanaSuspensos perquè en ell es

tracta amb una seqüència de números reals llegida del dispositiu

d’entrada estàndard (fins ara s’havien tractat només seqüències de ca-

ràcters).

L’algorisme mitjanaSuspensos llegeix del dispositiu d’entrada una seqüèn-

cia de reals entre 0.0 i 10.0 ordenada descendentment, seguida per un –

1, i escriu en el dispositiu de sortida la mitjana dels nombres entre 0.0 i

5.0, o bé 0.0 si no hi havia cap nombre que complí s aquesta condició.

/* Programa mitjanaSuspensos.c calcula la mitjana dels suspensos en una sèrie descendent de nombres reals Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> /* Definició de tipus */ typedef enum {FALSE, TRUE} bool; int main() {

/* Declaració de variables */ float x, sum, result; int n; bool trobat; /* Pre: A l'entrada s'hi llegeix una seqüència de reals

entre 0.0 i 10.0 ordenada descendentment, seguida per un -1.0 */ /* Esquema de cerca */ scanf("%f", &x); /* preparar seqüència - llegir() */ trobat = FALSE; /* inici tractament - és buit */ while (!(x==-1.0) && !trobat) { /* fi seqüència - marca=-1.0 */ trobat = x<5.0; /* actualitzar trobat */ if (!trobat) { /* tractar element - és buit */ scanf("%f", &x); /* avançar seqüència - llegir() */ } } /* tractament final - és l’esquema de recorregut */ /* Esquema de recorregut sobre la resta de la seqüència */ /* preparar seqüència - ja està a punt */ n = 0.0; /* inici tractament */ sum = 0.0; while (!(x==-1.0)) { /* fi seqüència - marca=-1.0 */ sum = sum + x; /* tractar element */ n = n + 1; scanf("%f", &x); /* avançar seqüència - llegir() */ } if (n>0) result = sum/(float) n; /* tractament final */ else n = 0.0; printf("%f\n", result); /* Post: A la sortida s'ha escrit la mitjana aritmètica dels nombres x tal que

0.0 <= x < 5.0, o bé 0.0 si no hi havia cap nombre que complí s la condició */

system("PAUSE"); /* Fem que el programa esperi una tecla */ return 0; }

Consulteu com s’obté la solució a l’algorisme mitjanaSuspensos en l’apartat 5.2.1. “Mitjana dels sus-pensos” (pàgina 40), del mòdul “Tractament se-qüencial” de l’assignatura.

Noteu que els números reals de la seqüència d’entrada es poden entrar separant-los per espais o salts de lí nia, gràcies a l’ús de l’acció scanf.

Page 31: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 31 Codificació en C

4. Tipus estructurats de dades en llenguatge C

En aquest apartat es mostrarà com es codifiquen en llenguatge C els

nous tipus de dades introduï ts en el mòdul “Tipus estructurats de da-

des” de l’assignatura. S’estudiarà la codificació en llenguatge C de taules

i tuples, així com les particularitats respecte la traducció directe des del

llenguatge algorí smic.

4.1. Taules en C

Igual que en el llenguatge algorí smic, les taules són un tipus de dades

estructurat, homogeni i d’accés directe. A continuació es veurà la seva

declaració i com utilitzar-les en llenguatge C.

4.1.1. Declaració de taules, matrius i taules de taules en C

La declaració d’una variable tipus taula en C obeeix la següent sintaxi:

tipus nom[mida];

La sintaxi per a declarar taules de taules és:

tipus nom[mida1][mida2] ...[midan];

El llenguatge C no permet declarar matrius de més d’una dimensió u-

sant la sintaxi del llenguatge algorí smic (separant els í ndex per “,”). En

el seu lloc, cal usar la sintaxi anterior, envoltant els í ndex per parèntesis

quadrats (“[í ndex]”). La funcionalitat, però, és la mateixa.

També podem declarar nous tipus amb els constructors:

typedef tipus nom[mida];

typedef tipus nom[mida1][mida2] ...[midan];

Consulteu la sintaxi de de-claració d’una taula i d’una taula de taules en llenguat-ge algorí smic en els apar-tats 2.1. “Declaració” (pà-gina 11) i 2.3. “Altres tipus de taules” (pàgina 17), del mòdul “Tractament se-qüencial” de l’assignatura.

En C...En C...En C...En C...

“tipus nom[mida1, mida2, ..., midan];” és una declaració vàlida equivalent a “tipus nom[mida1];”. L’operador “,” permet avaluar diverses ex-pressions i retorna el resul-tat de la primera d’elles.a

Page 32: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 32 Codificació en C

4.1.2. Funcions elementals d’accés

Tal com succeeix en el llenguatge algorí smic, les funcions elementals

d’accés a les taules, matrius i taules de taules en llenguatge C ens perme-

ten accedir a un sol dels seus elements per consultar-lo o assignar-li un

valor. La sintaxi és la mateixa que la vista en el mòdul “Tipus estructu-

rats de dades” de l’assignatura.

Hi ha, però, una diferència en la numeració dels elements d’una taula en

el llenguatge algorí smic i els d’una taula codificada en C. Així , en el

llenguatge algorí smic el primer element és el corresponent a l’í ndex 1;

en canvi, en llenguatge C:

l’í ndex 0 identifica el primer element de la taula.

Aquesta diferència és petita, però molt important, i cal tenir-la ben pre-

sent en la codificació dels algorismes a llenguatge C. Habitualment no

comportarà més maldecaps que retrocedir una posició en els í ndexs

d’accés i decrementar en una unitat els lí mits dels processos iteratius.

Com a exemple dels canvis que caldrà fer, codificarem en C l’algorisme

freqLletres, que escriu en el dispositiu de sortida la freqüència d’aparició

dels caràcters “A” fins a “Z” en un text acabat en un punt introduï t pel

dispositiu d’entrada.

/* Programa freqLletres.c Freqüència d'aparició dels caràcters "A" fins a "Z" Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> int main() {

/* Declaració de variables */ float freq[26]; int ndc, i, codiBase; char c;

/* Pre: pel canal d'entrada llegirem una seqüència de caràcters en majúscules, de com a mí nim un, acabada en un punt */

scanf("%c", &c); /* preparar seqüència - llegir() */ ndc = 0; /* inici tractament */ for (i=0; i<26; i++) { /* Noteu que l'í ndex i va de 0 a 25 */ freq[i] = 0; } codiBase = (int) 'A'; while (c!='.') { /* fi seqüència - marca = '.' */ i = (int) c - codiBase; /* tractar element - no hi ha el +1 */ freq[i] = freq[i] + 1.0; ndc = ndc + 1; scanf("%c", &c); /* avançar seqüència - llegir() */ }

Consulteu l’algorisme fre-qLletres en l’apartat 2.2.2. “Lectura i escriptura” (pà-gina 15), del mòdul “Tipus estructurats de dades” de l’assignatura.

Page 33: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 33 Codificació en C

for (i=0; i<26; i++) { /* tractament final - Noteu i entre 0 i 25*/ freq[i] = freq[i] / (float) ndc; printf("%c", (char) codiBase + i); /* Noteu que no hi ha el -1 */ printf(":"); printf("%f\n", freq[i]); } /* Post: S’ha escrit pel canal de sortida la freqüència d’aparició

dels caràcters “A” fins a “Z” del text entrat pel canal d’entrada */ system("PAUSE"); /* Fem que el programa esperi una tecla */ return 0; }

Cal destacar que l’í ndex i va de 0 a 25 al fer el recorregut de la taula,

enlloc d’anar de 1 a 26 com en el llenguatge algorí smic. Per tant, en el

for s’ha modificat la inicialització de i, a 0 enlloc de 1, i la comparació

amb la posició final, que utilitza l’operador “<” enlloc de l’operador

“<=”. Pel mateix motiu, al calcular la posició de la taula que cal incre-

mentar, s’ha eliminat el “+1”, de tal manera que al caràcter “A” li cor-

respon la posició 0 enlloc de la 1, i així successivament.

4.1.3. Accés seqüencial a una taula

L’accés seqüencial a les taules permet aplicar els esquemes de recorregut

i cerca, vistos en l’apartat 2.4. “Accés seqüencial a una taula” del mòdul

“Tipus estructurats de dades” de l’assignatura. La codificació d’aquests

esquemes en llenguatge C és directe. Només cal tenir present la diferent

numeració en els í ndexs de les taules i fer la inicialització a 0 enlloc de

fer-la a 1 com en el llenguatge algorí smic. També cal retocar el lí mit del

recorregut o de la cerca en el cas de seqüències no marcades, que reque-

rirà un í ndex una unitat menor en C que en llenguatge algorí smic.

Com a exemple, codificarem l’algorisme infMitjana, que a partir d’una

seqüència d’enters amb les qualificacions de com a molt 50 estudiants

calcula la nota mitjana i el nombre d’estudiants que tenen una nota

inferior a aquesta. Codificarem la variant que usa una variable entera

per indicar quantes posicions significatives hi ha a la taula.

/* Programa infMitjana.c Calcula la nota mitjana i el nombre d'estudiants que tenen una nota inferior Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> int main() { /* Declaració de constants */ const int M = 50; /* Declaració de variables */ int t[M]; int quants; /* Indicarà quants elements hi ha a la taula */ int i, n; int suma, infMitjana; float mitjana;

Consulteu l’algorisme quali-ficacions en l’apartat 2.4.1. “Esquema de recorregut aplicat a taules” (pàgina 22), del mòdul “Tipus es-tructurats de dades” de l’assignatura.

Page 34: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 34 Codificació en C

/* Pre: Pel canal d'entrada es llegeix una seqüència no buida de com a molt 50 enters entre 0 i 10, seguida de -1 */

/* Recorregut sobre la seqüència d'entrada */ scanf("%d", &n); /* preparar seqüència - llegir() */ quants = 0; /* inici tractament */ suma = 0; while (!(n==-1)) { /* fi seqüència - marca = -1 */ t[quants] = n; /* tractar element */ suma = suma + n; /* accedir a n es més eficient que accedir a t[quants] */ quants = quants + 1; /* quants s'actualitza després de tractar l'element actual */ scanf("%d", &n); /* avançar seqüència - llegir() */ } mitjana = (float) suma / (float) quants; /* tractament final */ /* Recorregut sobre la taula */ /* preparar seqüència - i=0 en el for */ infMitjana = 0; /* inici tractament */ for (i=0; i<quants; i++) { /* fi seqüència - lí mit=quants */ if ((float) t[i] < mitjana) /* tractar element */ infMitjana = infMitjana + 1 ; /* avançar seqüència - i++ en el for */ } printf("%f ", mitjana); /* tractament final */ printf("%d\n", infMitjana); /* Post: S'ha escrit pel canal de sortida la mitjana dels elements de la seqüència i el

nombre d'elements amb un valor inferior a aquesta */ system("PAUSE"); /* Fem que el programa esperi una tecla */ return 0; }

Noteu com, a diferència del llenguatge algorí smic, la variable quants

s’actualitza després d’haver guardat la qualificació en la taula, i no a-

bans. Així , la primera qualificació es guarda en l’í ndex 0, la segona el

l’í ndex 1, i la darrera en l’í ndex quants-1.

Es pot observar com la utilització d’una instrucció for fa que diverses

parts del recorregut de la taula es facin en aquesta sentència. En concret,

s’inicialitza la variable amb la que es recorrerà la taula (i=0),

s’incrementa aquest í ndex per avançar en la taula (i++) i es comprova si

s’ha arribat al final del recorregut (i<quants).

4.1.4. Accés directe a una taula

L’accés directe és una de les caracterí stiques més importants de les tau-

les. Tot i que aquest tipus d’accés no incorpora cap element nou del llen-

guatge C, en aquest apartat es mostrarà un algorisme que n’aprofita els

avantatges. Es tracta de l’algorisme cercaDicotomica, que donada una

taula ordenada en forma creixent, respon si un enter donat està o no a la

taula, fent una cerca que descarta en cada pas la meitat dels elements

que queden a la taula.

/* Programa cercaDicotomica.c Comprova si un enter és en una taula ordenada, realitzant una cerca dicotòmica Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h>

Consulteu l’algorisme cer-caDicotomica en l’apartat 2.5.1. “Importància de les dades ordenades. Cerca dicotòmica” (pàgina 32), del mòdul “Tipus estructu-rats de dades” de l’assignatura.

Page 35: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 35 Codificació en C

/* Definició de constants conegudes en temps de compilació */ #define N 18 int main() { /* Declaració de variables */ int t[N] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 20, 27, 30, 50}; int donat; int inici, fi, mig; /* Pre: Pel canal d'entrada es llegeix un enter */ scanf("%d", &donat); inici = 0; /* Definim els lí mits inicials de la taula */ fi = N-1; while (inici != fi) { /* La cerca acaba quan els lí mits coincideixen */ mig = (inici + fi) / 2; /* Posició de l'element central de la taula */ if (t[mig] < donat) { /* Establim els nous lí mits de la taula */ inici = mig + 1; } else { fi = mig; } } if (t[inici]==donat) printf("S\n"); /* Comprovar si s'ha trobat l'element... */ else printf("N\n"); /* Post: s'escriu "S" pel canal de sortida si l'enter és a la taula

i "N" en cas contrari */ system("PAUSE"); /* Fem que el programa esperi una tecla */ return 0; }

En primer lloc, noteu la declaració de la constant N amb la directiva

#define. Observem que no s’indica el tipus de la constant que s’està

definint. De fet, el compilador únicament substitueix el nom, N, pel seu

valor, 18, cada cop que el troba en el codi posterior a la declaració. La

definició d’aquesta constant no es pot fer amb const int N=18, ja que el

valor de N seria assignat en temps d’execució del programa i, en canvi, el

compilador el necessita en temps de compilació per poder saber la mida

de la taula t i fer la inicialització corresponent. En l’algorisme infMitjana,

ben al contrari, la declaració de la constant M si que es pot fer amb

const int M=50, perquè el seu valor s’utilitza per declarar una taula que

no cal inicialitzar. En cas de dubte, sempre és millor usar la directiva

#define per declarar constants.

La inicialització de la taula t, precisament, correspon a una construcció

del llenguatge C que no haví em vist encara. La taula t s’inicialitza en

temps de compilació. Fixeu-vos com assignem un valor per cada posició

de la taula, separant els valors per comes, dins d’un bloc amb claus.

4.1.5. Taules com a paràmetres d’accions i funcions

En el llenguatge algorí smic, les taules es poden passar com a paràmetres

d’accions i funcions, o fins i tot ser retornades per una funció, sense cap

restricció. En llenguatge C, en canvi, només es permet passar una taula

per referència. És a dir, sempre es passa la taula original, i els canvis fets

Recordeu que la dRecordeu que la dRecordeu que la dRecordeu que la diiiirectiva rectiva rectiva rectiva #define...#define...#define...#define...

... s’ha d’escriure en la pri-mera posició d’una lí nia, ja que sinó el compilador no la reconeixeria. Totes les direc-tives comencen sempre per “#”.

En l’apartat “Construcci-ons avançades del llen-guatge C” d’aquest mateix mòdul podeu trobar més informació sobre inicialit-zació de taules en temps d’execució.

Page 36: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 36 Codificació en C

en la taula per l’acció o funció, es reflectiran en ella. Així mateix, tam-

poc no es pot retornar una taula sencera en una funció. a

La sintaxi per a la declaració dels paràmetres en la capçalera d’una acció

o funció quan tipus és una taula ha de ser:

per un paràmetre d’entrada: const tipus nom

per un paràmetre de sortida: tipus nom

per un paràmetre d’entrada/sortida: tipus nom

Fixeu-vos que al declarar una taula com a paràmetre d’entrada, afegim

la paraula reservada const a la declaració. D’aquesta manera indiquem

al compilador que no farem canvis en el contingut de la taula.

Noteu també que al declarar una taula com a paràmetre

d’entrada/sortida o de sortida, no hem de precedir el nom de la taula

amb “*” com fèiem amb la resta de tipus. Tampoc no usarem “*” davant

del nom en el cos de l’acció o funció, ni “&” en la invocació.

Això és degut a que el nom de la taula és ja per si una adreça, més con-

cretament és l’adreça del primer element de la taula i els parèntesis qua-

drats (“[í ndex]”) ens serviran per accedir als diferents elements que con-

té.

Com a exemple del pas de taules com a paràmetres, codificarem

l’algorisme quadrats, que calcula els quadrats dels elements d’una taula,

usant crides a accions i funcions i passant taules com a paràmetres.

/* Programa quadrats.c Calcula els quadrats d'una taula d'enters Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> /* Definició de constants en temps de compilació */ #define M 10 /* Definició de tipus */ typedef int t[M]; /* Declaració del tipus t com a taula d’enters */ /* Pre-declaracions de funcions */ void omplirTaula(t p); void escriureTaula(const t p); void quadratsTaula(const t p, t novap); int main() { /* Declaració de variables */ t taulaI, taulaF; /* Pre: Es llegirà pel dispositiu d'entrada una seqüència de M enters */ omplirTaula(taulaI);

El llenguatge C...El llenguatge C...El llenguatge C...El llenguatge C...

... no permet treballar amb taules com a paràmetres d’entrada, modificant el seu valor sense que es vegi afec-tada la taula original en la crida.

Consulteu l’algorisme qua-drats en l’apartat 2.2.2. “Lectura i escriptura” (pà-gina 16), del mòdul “Tipus estructurats de dades” de l’assignatura.

Page 37: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 37 Codificació en C

quadratsTaula(taulaI, taulaF); escriureTaula(taulaF); /* Post: S'ha escrit pel dispositiu de sortida el quadrat de cada

element de la seqüència llegida, en el mateix ordre */ system("PAUSE"); /* Fem que el programa esperi una tecla */ return 0; } void omplirTaula(t p) /* p és un paràmetre d’entrada/sortida */ { /* Declaració de variables */ int i; /* Pre: Es llegirà pel dispositiu d'entrada una seqüència de M enters */ for(i=0; i<M; i++) scanf("%d", &p[i]); /* Post: La taula p conté la seqüència llegida, en el mateix ordre */ } void escriureTaula(const t p) /* p és un paràmetre d’entrada */ { /* Declaració de variables */ int i; /* Pre: La taula p conté M enters */ for(i=0; i<M; i++) printf("%d ", p[i]); /* Post: S'ha escrit en el dispositiu de sortida el contingut

de la taula p, en el mateix ordre */ } void quadratsTaula(const t p, t novap) /* p és d’entrada, novap de sortida */ { /* Declaració de variables */ int i; /* Pre: La taula p conté M enters */ for(i=0; i<M; i++) { novap[i] = p[i] * p[i]; } /* Post: La taula novap conté els quadrats dels elements de p, en el mateix ordre */ }

La constant M i el tipus t es declaren fora de qualsevol funció, per tal que

estiguin disponibles en tot el programa. a Fixeu-vos en la declaració de la funció quadratsTaula. El paràmetre

d’entrada p va precedit per la paraula reservada const, indicant que no

farem canvis en la taula original. A més, s’ha afegit un segon paràmetre

per tal de poder retornar una taula amb els quadrats. Aquest segon pa-

ràmetre té el mateix tipus i nom, novap, que la variable que retorna

l’algorisme quadrats en llenguatge algorí smic. Això no és cap coincidèn-

cia. Com que el llenguatge C no ens permet retornar una taula en una

funció, afegirem un nou paràmetre de sortida per a fer-ho i, per a més

claredat, usarem el mateix nom que la variable que retornem en llen-

guatge algorí smic. a

Page 38: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 38 Codificació en C

4.2. Tuples en C

Igual que en el llenguatge algorí smic, les tuples són un tipus de dades

estructurat, heterogeni i d’accés directe. A continuació es veurà la seva

declaració i com utilitzar-les en llenguatge C.

4.2.1. Declaració de tuples en C

La declaració d’una variable tipus tupla en C obeeix la següent sintaxi:

struct {

tipus1 camp1 ;

tipus2 camp2 ;

...

} nom;

En ella es declara una variable tipus tupla, de nom nom, i camps camp1,

camp2, ... S’utilitza una sintaxi molt similar en el constructor de tipus:

typedef struct {

tipus1 camp1;

tipus2 camp2;

...

} nom;

4.2.2. Funcions elementals d’accés

Les funcions elementals d’accés a tuples i camps de tuples són equiva-

lents a les vistes en el llenguatge algorí smic. La sintaxi és la mateixa que

la vista en el mòdul “Tipus estructurats de dades” de l’assignatura.

Com a exemple, codificarem en C l’algorisme puntMija, que escriu pel

dispositiu de sortida el punt mitja entre dos punts entrats pel dispositiu

d’entrada.

/* Programa puntMija.c Calcula el punt mitjà entre dos punts donats pel dispositiu d'entrada Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> /* Declaració de tipus */ typedef struct { float x, y; } coordenades;

Consulteu l’algorisme puntMija en l’apartat 3.2.2. “Lectura i escriptura pels canals d’entrada/sortida estàndard” (pàgina 40), del mòdul “Tipus estructurats de dades” de l’assignatura.

Page 39: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 39 Codificació en C

/* PreDeclaració de funcions */ coordenades obtenirPunt(); void escriurePunt(coordenades p); coordenades calculPuntMitja(coordenades p1, coordenades p2); int main() { /* Declaració de variables */ coordenades a, b; /* Pre: Es llegeixen quatre reals del canal estàndard X1, Y1, X2, Y2

que representen les coordenades de dos punts A i B respectivament */ a = obtenirPunt(); b = obtenirPunt(); escriurePunt(calculPuntMitja(a, b)); /* Post: S'escriuen les coordenades del punt mitja entre A i B, que són (X1+X2)/2, (Y1+Y2)/2 */ system("PAUSE"); /* Fem que el programa esperi una tecla */ return 0; } coordenades obtenirPunt() { /* Declaració de variables */ coordenades p; /* Pre: Es llegeixen del canal estàndard dos reals X i Y */ scanf("%f", &p.x); scanf("%f", &p.y); return p; /* Post: p.x = X i p.y = Y */ } void escriurePunt(coordenades p) { /* Pre: p.x = X i p.y = Y */ printf("%f", p.x); printf(","); printf("%f ", p.y); /* Post: S'ha escrit al canal estàndard "X,Y " */ } coordenades calculPuntMitja(coordenades p1, coordenades p2) { /* Declaració de variables */ coordenades p; /* Pre: p1.x = X1 i p1.y = Y1 i p2.x = X2 i p2.y = Y2 */ p.x = (p1.x + p2.x) / 2.0; p.y = (p1.y + p2.y) / 2.0; return p; /* Post: p.x = (X1+X2)/2 i p.y = (Y1+Y2)/2 */ }

És important destacar que, a diferència del que passava amb les taules,

les tuples es poden passar com a paràmetre, tant per valor com per refe-

rència i, fins i tot, poden ser retornades per una funció. És a dir, que

segueixen la sintaxi dels tipus elementals del llenguatge C, i que no s’hi

apliquen les restriccions i consideracions que hem vist per les taules.

a

Retornar una tuplaRetornar una tuplaRetornar una tuplaRetornar una tupla en C en C en C en C............

... o passar-la per valor a una funció pot ser poc eficient. Cal pensar que una tupla pot contenir diversos camps (alguns poden ser fins i tot altres tuples i/o taules). Per tant, passar tuples per valor o retornar-les en una funció implica copiar una gran quantitat d’informació. El més eficient és passar les tuples per referència.

Page 40: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 40 Codificació en C

Per accedir a un camp d’una tupla passada per referència, però, caldrà

posar un parèntesi al voltant del nom de la tupla, abans de l’operador

d’accés al camp “.”. Això és degut a l’ordre de precedència dels opera-

dors involucrats. La sintaxi és:

(*nom).camp

El llenguatge C disposa també d’un operador que estalvia l’ús del parèn-

tesi al accedir a un camp d’una tupla passada per referència. És total-

ment equivalent a l’anterior, i la seva sintaxi, més simple, queda com

segueix:

nom->camp

4.2.3. Taules i tuples

El llenguatge C, igual que l’algorí smic, permet que els camps d’una tu-

pla puguin ser de qualsevol tipus. En concret, poden ser també tipus

estructurats de dades, en concret, altres tuples o taules.

Així el tipus paraula vist en l’apartat homònim d’aquest en el mòdul

“Tipus estructurats de dades” de l’assignatura es definiria com:

typedef struct {

char lletres[40];

int l;

} paraula;

Noteu que en llenguatge C, guardar a paraula.l el número de caràcters de

la paraula, o guardar-hi l’í ndex del primer caràcter buit de paraula.lletres

és exactament el mateix, ja que els í ndex de les taules en C comencen

en la posició 0.

Finalment, per tal de veure un exemple complex de combinació de tau-

les i tuples, es codificarà en C la funció costProducte, que donada una es-

tructura de magatzem i composició del producte ens calcula el seu preu

de cost. Noteu les declaracions de tipus, on tenim taules de tuples, tuples

que contenen altres tuples, etc...

Evidentment, també podem tenir en C taules de tuples.

Consulteu l’exercici d’autoavaluació número 9 (pàgines 53 i 63), del mò-dul “Tipus estructurats de dades” de l’assignatura per a una especificació detalla-da dels tipus de dades invo-lucrats i de la manera de calcular el preu de cost d’un producte.

Page 41: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 41 Codificació en C

/* Declaracions de constants en temps de compilació */ #define MAXL 40 /* Declaració de tipus */ typedef struct { /* tipus paraula */ char lletres[MAXL]; /* la tupla conté una taula de caràcters */ int l; } paraula; typedef struct { /* tipus materia */ paraula referencia; /* la tupla materia conté una tupla paraula */ int preuCost, estoc; } materia; typedef struct { /* tipus producte */

paraula nom; /* la tupla producte conté una tupla paraula */ int costFabricacio; struct { /* la tupla producte conté la tupla composicio */

struct { /* element de la taula materies (tupla) */ int codiMat; int quantitat; } materies[10]; /* la tupla composicio té la taula materies */ int num;

} composicio; } producte; typedef struct { /* tipus magatzem */ materia materies[200]; /* la tupla magatzem conté una taula */ int numMat; } magatzem; typedef producte productes[15]; /* tipus productes */ /* taula de tuples producte */ int costProducte(producte p, magatzem m) { /* Declaració de variables */ int c, j; /* Pre: p=P i m=M */ c = p.costFabricacio; for(j=0; j<p.composicio.num; j++) { c = c + (m.materies[p.composicio.materies[j].codiMat].preuCost * p.composicio.materies[j].quantitat); } return c; /* Post: Retorna el cost calculat com P.costFabricacio, mes la suma del cost de les P.composicio.num materies de P.composicio.materies multiplicades per la quantitat de cadascuna d'aquestes */ }

Observeu que el programa no està complet, ja que hi manca la funció

main. En ella s’hauria d’inicialitzar la taula productes i el magatzem, fer la

crida a la funció costProducte (pel producte que ens interessi) i escriure el

resultat pel dispositiu de sortida.

Page 42: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 42 Codificació en C

5. Introducció a la metodologia de disseny descendent en C

En el mòdul “Introducció a la metodologia de disseny descendent” de

l’assignatura s’ha posat de manifest que per poder abordar problemes

complexos, del món real, cal aplicar una metodologia concreta, sistemà-

tica, consistent en l’abstracció de dades i/o codi i en el plantejament i

resolució de subproblemes cada cop més senzills.

La metodologia de disseny descendent no afegeix nous elements al llen-

guatge algorí smic, sinó que mostra una manera més efectiva d’usar els

elements disponibles. Per tant, la codificació en llenguatge C

d’algorismes resolts en base a la metodologia del disseny descendent no

implica, en realitat, cap canvi en la forma de treballar que venim apli-

cant, consistent en traduir directament les construccions del llenguatge

algorí smic als seus equivalents en C.

En realitat, tota la feina està en el disseny de l’algorisme, aplicant dis-

seny descendent i l’experiència adquirida fins al moment, mentre que la

codificació en llenguatge C resta com una feina purament mecànica.

5.1. Exemple: algorisme analisiCorreccions

Com exemple de codificació en llenguatge C d’un algorisme resolt apli-

cant disseny descendent, es mostra a continuació la codificació comple-

ta de l’algorisme analisiCorreccions, que serveix per analitzar els errors

d’un text presentat per un autor de materials.

/* Programa analisiCorreccions.c Analitza el percentatge de frases, la mitjana de paraules per frase i el maxim de paraules per frase que cal corregir en un text. Si no cal corregir res, no diu res. Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> /* Declaració de tipus */ typedef enum {FALSE, TRUE} bool; typedef struct { bool final; bool buit; bool calCorregir; } tMot; /* Definit en el 3er nivell */ typedef struct { int nMotsC; bool final; } tFrase; /* Definit en el 2on nivell */

Consulteu l’apartat 1.1. “Anàlisi de problemes complexos” (pàgina 10), del mòdul “Introducció a la metodologia del disseny descendent” de l’assignatura per a una es-pecificació detallada del problema a resoldre amb l’algorisme analisiCorrecci-ons. L’aplicació de la meto-dologia del disseny des-cendent al problema es fa al llarg de la resta del mò-dul.

Page 43: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 43 Codificació en C

typedef struct { int nFrases; int nFrasesCor; int nMotsPerCorregir; int maximMotsPerCorregir; } tDadesAnalisi; /* Definit en el 1er nivell */ /* Pre-declaracions de funcions */ void obtenirFrase(tFrase f); /* Funcions definides en el 1er nivell */ bool darreraFrase(tFrase f); void iniciResultatsAnalisi(tDadesAnalisi *a); void actualitzaResultatsAnalisi(tFrase f, tDadesAnalisi *a); void escriureResultatsAnalisi(tDadesAnalisi a); int motsPerCorregir(tFrase f); /* Definida en el 2on nivell – associada a tFrase*/ void obtenirMot(tMot m); /* Definides en el 2on nivell */ bool darrerMot(tMot m); bool motBuit(tMot m); bool calCorregirMot(tMot m); /* 1er nivell de disseny descendent. Recorregut sobre una seqüència de frases. Abstracció dels tipus tFrase i tDadesAnalisi. */ int main() { /* Declaració de variables */ tDadesAnalisi resultatsAnalisiText; tFrase frase; /* Pre: en l'entrada tenim una seqüència de frases, T, que pot ser buida. Cada frase de T conté informació per a saber si cal corregir-la o no */ obtenirFrase(&frase); /* preparar seqüència */ iniciResultatsAnalisi(&resultatsAnalisiText); /* inici tractament */ while (!darreraFrase(frase)) { /* fi seqüència */ actualitzaResultatsAnalisi(frase, &resultatsAnalisiText); /* tractar element */ obtenirFrase(&frase); /* avançar seqüència */ } escriureResultatsAnalisi(resultatsAnalisiText); /* tractament final */ /* Post: en el cas que no calgui corregir T, no s'escriu res. En el cas T sigui un text que calgui corregir, en la sortida

s'ha de generar una seqüència. R formada per tres elements: R1 R2 R3. R1 representa la mitjana de paraules que s'han de corregir per frase de T, R2 representa el percentatge de frases que s'han de corregir a T, i R3 representa el màxim de paraules que s'han de corregir per frase de T. */ system("PAUSE"); /* Fem que el programa esperi una tecla */ return 0; } /* 2on nivell de disseny descendent. Funcions associades al tipus tFrase. Abstracció del tipus tMot. */ void obtenirFrase(tFrase *f) { /* Declaració de variables */ tMot m; int nMots; /* Pre: a l'entrada tenim un text T representat com una seqüència de frases t. A la part dreta de t, DT, hi ha una seqüència de frases o la frase buida */ /* Recorregut sobre una seqüència de mots */ nMots = 0; /* inici tractament */ f->nMotsC = 0; /* f->camp equival a (*f).camp */ obtenirMot(&m); /* preparar seqüència */ while (!darrerMot(m)) { /* fi seqüència */ if (calCorregirMot(m)) { /* tractar element */ f->nMotsC = f->nMotsC + 1; } nMots = nMots + 1; obtenirMot(&m); /* avançar seqüència */ }

Page 44: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 44 Codificació en C

if ( !motBuit(m) ) { /* tractament final */ if (calCorregirMot(m)) { f->nMotsC = f->nMotsC + 1; } nMots = nMots + 1; } printf("nMots %d\n", nMots); f->final = nMots==0; /* Post: a f tenim representada la primera frase de DT. La frase representada està a la part esquerra de t */ } bool darreraFrase(tFrase f) { /* Pre: f = F */ return f.final; /* Post: darreraFrase(F) es cert si F es una frase buida. Ha de retornar fals en cas contrari */ } int motsPerCorregir(tFrase f) { /* Pre: f = F */ return f.nMotsC; /* Post: motsPerCorregir(F) dóna el nombre de mots que s'han de corregir en la frase F */ } /* 2on nivell de disseny descendent. Funcions associades al tipus tDadesAnalisi. */ /* Noteu les abreviacions següents: nFrases - nombre de frases del text nFrasesC - nombre de frases que s'han de corregir del text nMotsC - nombre de paraules que s'han de corregir del text mx - maxim de paraules a corregir per frase */ void iniciResultatsAnalisi(tDadesAnalisi *a) { /* Pre: cert */ (*a).nFrases = 0; (*a).nFrasesCor = 0; (*a).nMotsPerCorregir = 0; (*a).maximMotsPerCorregir = 0; /* Post: a a tenim nFrases, nFrasesC, nMotsC i mx d'un text buit */ } void actualitzaResultatsAnalisi(tFrase f, tDadesAnalisi *a) { /* Declaració de variables */ int nMotsPerCorFrase; /* Pre: a = A i f = F */ a->nFrases = a->nFrases + 1; /* a->camp equival a (*a).camp */ nMotsPerCorFrase = motsPerCorregir(f); if (nMotsPerCorFrase>0) { a->nFrasesCor = a->nFrasesCor + 1; a->nMotsPerCorregir = a->nMotsPerCorregir + nMotsPerCorFrase; } if (nMotsPerCorFrase > a->maximMotsPerCorregir) { a->maximMotsPerCorregir = nMotsPerCorFrase; } /* Post: a a tenim nFrases, nFrasesC, nMotsC i mx del text resultant d'afegir l’anàlisi de la frase F al text ja analitzat a A */ }

Page 45: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 45 Codificació en C

void escriureResultatsAnalisi(tDadesAnalisi a) { /* Pre: a = A */ if (a.nFrasesCor > 0) { printf("%f ", (float)a.nFrasesCor / (float)a.nFrases * 100.0); printf("%f ", (float)a.nMotsPerCorregir / (float)a.nFrasesCor); printf("%d ",a.maximMotsPerCorregir); } /* Post: si les dades de A són d'un text que s'ha de corregir, pel canal de

sortida s’escriu una seqüència R formada per tres elements: R1 R2 R3. R1 representa la mitjana de paraules que s'han de corregir per frase

present en el text analitzat en A, R2 representa el percentatge de frases que s'han de corregir en el text

analitzat en A, i R3 representa el màxim de paraules que s'han de corregir per frase

existent en el text analitzat en A. En el cas que A tingui les dades d'un text buit no s'escriu res */

} /* 3er nivell de disseny descendent. Funcions associades al tipus tMot. */ void obtenirMot(tMot *m) { /* Declaració de variables */ char c; int caractersLlegits; /* Pre: a l'entrada tenim la seqüència de mots, t, del text T, de la qual només

podem obtenir la part dreta DT i aquesta no ha arribat al final del text */ /* Cerca sobre una seqüència de caràcters. Busquem ‘*’. */ caractersLlegits = 0; /* inici tractament */ scanf("%c", &c); /* preparar seqüència */ while ( (c!='*')&&(c!=' ')&&(c!='.') ) { /* fi seqüència marca=’ ‘ o ’.’ */ caractersLlegits = caractersLlegits + 1; /* tractar element */ scanf("%c", &c); /* avançar seqüència */ } m->calCorregir = c=='*'; /* tractament final */ /* Recorregut sobre una seqüència de caràcters */ /* inici tractament – és buit */ /* preparar seqüència, no cal */ while ( (c!=' ')&&(c!='.') ) { /* fi seqüència marca=’ ‘ o ’.’ */ caractersLlegits = caractersLlegits + 1; /* tractar element */ scanf("%c", &c); /* avançar seqüència */ } m->buit = caractersLlegits==0; /* tractament final */ m->final = c=='.'; if ( (m->final) && !(m->buit) ) scanf("%c", &c); /* Post: m representa el primer mot que hi ha a DT. El mot obtingut estarà a la part

esquerra de la seqüència t */ } bool darrerMot(tMot m) { /* Pre: m = M */ return m.final || m.buit; /* Post: darrerMot(M) és cert si M representa el darrer mot d'una frase */ } bool motBuit(tMot m) { /* Pre: m = M */ return m.buit; /* Post: motBuit(M) és cert si M representa un mot buit */ } bool calCorregirMot(tMot m) { /* Pre: m = M */ return m.calCorregir; /* Post: calCorregirMot(M) és cert si el mot M s'ha de corregir. calCorregirMot(M) és fals si no cal corregir M */ }

Page 46: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 46 Codificació en C

Noteu com les definicions de nous tipus de dades es fan en ordre invers

al dels nivells de disseny descendent en el qual han estat introduï des.

Cal fer-ho així perquè els tipus de dades que es defineixen en nivells

inferiors poden ser utilitzats pels tipus de dades de nivells superiors per

tal de fer una bona abstracció de dades. En aquest algorisme en concret,

però, els nous tipus de dades associats a cada nivell únicament estan

basats en els tipus elementals del llenguatge C, pel que no hauria calgut

fer la declaració de tipus en ordre invers. Malgrat tot, és millor habituar-

se a seguir sempre la mateixa rutina.

Una altra bona costum de programació consisteix en col∙ locar les pre-

declaracions de les accions i funcions segons l’ordre de la seva definició

en cada nivell de disseny descendent. De manera similar, les accions i

funcions s’han d’implementar organitzant-les per nivells i segons el ti-

pus de dades amb el qual s’associen. Tot plegat contribueix a fer el codi

més llegible.

Page 47: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 47 Codificació en C

6. Construccions avançades del llenguatge C

En aquest apartat es veuran algunes construccions del llenguatge C que

no tenen equivalent en el llenguatge algorí smic, però que permeten una

codificació més simple, més eficient i de vegades més general. Tal com

ja s’ha comentat amb anterioritat, no es farà, ni molt menys, un manual

complet del llenguatge C, tampoc en aquest apartat. Només es comenta-

ran aquelles construccions senzilles de C que simplifiquen la codificació

dels nostres algorismes.

Aquest apartat és, evidentment, opcional i en cap cas necessari per a

codificar els algorismes desenvolupats en llenguatge algorí smic. a

6.1. Operadors aritmètics avançats

Els operadors aritmètics avançats de C permeten fer una operació entre

una variable i una expressió, guardant el resultat en la mateixa variable.

La taula següent en mostra les caracterí stiques:

OperOperOperOperaaaadordordordor ExempleExempleExempleExemple Equivalència en CEquivalència en CEquivalència en CEquivalència en C

+= variable += expressió ; variable = variable + expressió ;

-= variable -= expressió ; variable = variable - expressió ;

*= variable *= expressió ; variable = variable * expressió ;

/= variable /= expressió ; variable = variable / expressió ;

%= variable %= expressió ; variable = variable % expressió ;

++ variable++ ++variable variable = variable + 1 ;

-- variable-- --variable variable = variable - 1 ;

Els operadors aritmètics avançats es poden usar on l’equivalència en C

seria vàlida. Els operadors d’autoincrement “++” i d’autodecrement “--“

mereixen un comentari addicional. Es poden usar enmig d’una expressió

i es poden situar davant o darrera del nom. Si es situen darrera del nom,

l’expressió s’avalua primer i després s’aplica l’operador. Si es col∙ loquen

davant del nom, primer s’avalua l’operador i després l’expressió. Vegem-

ne un exemple:

... j = 0; t[j++] = 1; /* t[0] = 1 i j = 1 */ j = 2; t[--j] = 2; /* t[1] = 2 i j = 1 */ ...

Page 48: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 48 Codificació en C

6.2. Funcions d’entrada/sortida

La sintaxi de les funcions d’entrada/sortida scanf i printf és molt més

completa del que s’ha mostrat en les simples equivalències entre les fun-

cions de lectura i escriptura del llenguatge algorí smic i el C.

6.2.1. Funció de sortida de dades printf

La invocació de la funció de sortida de dades printf té la següent sintaxi:

printf(“cadena_de_format”, dada1, dada2, ..., dadan);

Observem que el primer argument de la invocació es correspon a una

cadena de format, gràcies a la qual s’indica el tipus de les dades que se-

gueixen en els arguments segon i posteriors. La funció printf accepta un

número variable de paràmetres, on l’únic paràmetre obligat és el primer.

La cadena de format està constituï da per una cadena de caràcters que

s’escriuen literalment en la sortida i uns codis de control que especifi-

quen el format de les dades que seran substituï des en el lloc precí s ocu-

pat pel codi de control. Així , per exemple:

printf(“El valor de pi es: %5.2f aproximadament\n”, 3.14);

Escriu per pantalla, a partir de la posició on es trobi el cursor:

El valor de pi es: 3.14 aproximadament

Un codi de control comença sempre pel caràcter “%” i el seu format és:

%[amplada][.precisió]tipus

On amplada és opcional i indica el número de caràcters que ocuparà la

sortida (inclòs el punt decimal i els decimals); precisió és també opcional

i especifica el número de dí gits decimals a mostrar; i finalment, tipus, és

un caràcter que indica el tipus de dada a mostrar. Els tipus possibles i el

caràcter que els identifica són: caràcter (“c”), enter (“d”), real (“f”) i ca-

dena de caràcters (“s”).

Per escriure alguns caràcters especials es requereixen codis compostos. És

el cas del salt de lí nia (“\n”), el tant per cent (“%%”), la barra invertida

En C, una cadena de cEn C, una cadena de cEn C, una cadena de cEn C, una cadena de ca-a-a-a-ràcters...ràcters...ràcters...ràcters...

... és equivalent a una taula de caràcters, però es pot manipular més fàcilment amb les funcions proporcio-nades en les llibreries del llenguatge.

Page 49: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 49 Codificació en C

(“\\”), el tabulador (“\t”), la cometa simple (“\’”) i la cometa doble

(“\””).

Com a exemple final, el codi:

printf(“El %5.2f%% de les %s te %d treballadors o menys.\n”, 85.32, “botigues”,

10);

Escriu per pantalla:

El 85.32% de les botigues te 10 treballadors o menys.

6.2.2. Funció d’entrada de dades scanf

La invocació de la funció d’entrada de dades scanf té la següent sintaxi:

scanf(“format”, dada1, dada2, ..., dadan);

Observem que el primer argument de la invocació es correspon a un

format, gràcies al qual s’indica el tipus de les dades que es llegiran sobre

els arguments segon i posteriors.

El format està constituï t per uns codis de control que especifiquen el

format de les dades que seran llegides del dispositiu d’entrada i guarda-

des en les adreces de memòria indicades pels arguments que segueixen.

Un codi de control comença sempre pel caràcter “%” i el seu format és:

%[amplada]tipus

On amplada és opcional i indica el número màxim de caràcters que s’han

de llegir i tipus, és un caràcter que indica el tipus de dada a llegir. Els

tipus possibles i el caràcter que els identifica són: caràcter (“c”), enter

(“d”), real (“f”) i cadena de caràcters (“s”).

Com exemple, el codi següent:

scanf(“%d %f %20s”, &i, &r, t);

Llegeix un enter i el guarda a la variable i; llegeix un real i el guarda a la

variable r i, finalment, llegeix una cadena de com a màxim 20 caràcters

i la guarda a la taula de caràcters t. Observem l’ús de l’operador “&” per

a obtenir l’adreça de memòria on es guarden les variables i i r. En canvi,

no s’utilitza amb la variable t, ja que es tracta d’una taula i, com hem

Page 50: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 50 Codificació en C

vist el nom d’una taula apunta al seu primer element. El mateix passaria

si ja tinguéssim l’adreça d’una variable, es a dir, un apuntador.

6.3. Inicialització de variables

El llenguatge C permet inicialitzar les variables en el moment de la seva

declaració. Per això, només cal utilitzar l’operador assignació i un valor

apropiat. Per exemple:

int i = 1, j = 0;

El valor assignat pot també ser una expressió, sempre i quan els valors

de les variables involucrades siguin coneguts (hagin estat inicialitzats

prèviament). En general, però, cal evitar aquest tipus d’inicialitzacions

que fan el codi menys llegible.

Si la variable és una taula, la inicialització es fa entre claus, separant

cada element per comes. Si els elements de la taula són taules o tuples, la

inicialització d’aquestes també es fa entre claus. En aquest cas, el llen-

guatge C accepta també una inicialització amb un número suficient

d’elements separats per comes, assignant-los per ordre. En el següent

codi, les dues inicialitzacions són equivalents:

int m[2][3] = { {0, 1, 2}, {3, 4, 5} }; int t[2][3] = {0, 1, 2, 3, 4, 5};

Si la variable és una tupla, la inicialització es fa entre claus, separant

cada camp per comes. Si els elements de la tupla són taules o altres tu-

ples, la inicialització d’aquestes també es fa entre claus. Així , per exem-

ple:

struct { char c; int d; float f[2]; struct { int i; float j; } dada; } reg = {'c', 10, {2.3, 5.2}, {3, 6.2} };

Page 51: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 51 Codificació en C

6.4. Apuntadors i matrius

6.4.1. Concepte d’apuntador

El valor de cada variable està emmagatzemat en un lloc determinat de la

memòria, accessible mitjançant una adreça. L’ordinador manté una

taula d’adreces que relacionen els noms de les variables amb les seves

adreces de memòria. Treballant amb aquests noms normalment no fa

falta que el programador es preocupi de l’adreça de memòria que ocu-

pen, però en certes ocasions és més útil treballar amb les adreces que

amb els propis noms de les variables.

El llenguatge C disposa d’un tipus especial de variables que permeten

contenir aquestes adreces, són els anomenats apuntadors.

La forma general per declarar una variable apuntador és:

tipus *nom;

on tipus pot ser qualsevol tipus vàlid de C (també denominat tipus base)

al que apuntarà la variable nom. A partir d’aquesta declaració la varia-

ble nom podrà contenir l’adreça de qualsevol variable del tipus base. Es

diu que un apuntador apunta a una variable quan el valor de l'apunta-

dor és l’adreça d’aquesta variable.

6.4.2. Operadors direcció i indirecció

Com ja hem vist el llenguatge C disposa d’un operador “&” que permet

determinar l’adreça d'una variable i un operador “*” que permet accedir

al valor contingut en la zona de memòria a la que fa referència l' apun-

tador.

Com a exemple veiem aquestes declaracions i sentencies

int i,j; /*i,j són variables enteres */

int *p; /* p és un apuntador a int */

p=&i; /* p conté l’adreça de i */

*p = 5; /* i toma el valor 5 */

p = &j; /* p conté ara l’adreça de j */

*p = 3; /* j toma el valor 3 */

Les constants i les expressions no tenen adreça pel que no es pot aplicar

el operador “&”. Tampoc es pot canviar l’adreça a memòria d’una varia-

ble.

Així un apuntador es una variable que permet contenir l’adreça d’una altre variable.

Page 52: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 52 Codificació en C

Els valors possibles per a un apuntador són totes les direccions vàlides de

memòria o el valor NULL que és una constant simbòlica predefinida

equivalent a 0 i que s’utilitza per indicar que l’apuntador no apunta

enlloc.

6.4.3. Aritmètica d’apuntadors

Les operacions permeses amb variables de tipus apuntador són:

Les binaries “+” i “– “ i les unàries “++” (autoincrement) i “--“ (autode-

crement)

Aquestes operacions actuen d'una forma una mica especial perquè tenen

en compte el tipus de dada a la que es refereix l’apuntador. Així , per

exemple, si sumen un 1 al valor d'un apuntador, tindrem l’adreça del

següent objecte emmagatzemat a la memòria. El mateix passa amb el

decrement.

6.4.4. Relacio amb taules i matrius

Els programes que treballen amb taules i matrius sovint realitzen opera-

cions molt similars, però sobre matrius que tenen í ndex de mides dife-

rents. Les dues possibles formes d’atacar el problema consisteixen en: o

bé codificar una funció especí fica per cada matriu de mida diferent; o

bé declarar totes les matrius amb la mida màxima i codificar una funció

que tracti matrius de mides variables, indicant-li per paràmetres les mi-

des reals de la matriu amb la qual cal treballar.

Les dues opcions tenen inconvenients. En la primera, calen múltiples

funcions que realitzen el mateix tractament; simplement canvien els

lí mits dels í ndexs. En la segona opció, hi ha una única funció, però

totes les matrius es declaren amb unes dimensions possiblement superi-

ors a les necessàries, malbaratant l’espai de memòria.

La solució, en C, consisteix en treballar amb apuntadors. Efectivament,

el nom d’una matriu és, en realitat, un apuntador a l’adreça on es troba

el primer element d’aquesta. Així , partint d’aquesta posició i usant

l’aritmètica d’apuntadors, que permet fer operacions aritmètiques amb

els apuntadors, es pot recórrer la matriu. Per exemple:

/* Programa apuntadors.c Demostra l'ús d'apuntadors per recórrer matrius Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h>

Page 53: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 53 Codificació en C

int main() { int i, j; int m[2][3] = { {0, 1, 2}, {3, 4, 5} }; /* Inicialització d’una matriu */ int *p; /* Recorregut usant accés directe a l'element de la taula */ for(i=0; i<2; i++) { for(j=0; j<3; j++) printf("%d ", m[i][j]); printf("\n"); } /* Recorregut amb apuntadors */ p = &m[0][0]; /* p apunta a l’adreça del primer element */ for(i=0; i<2; i++) { for(j=0; j<3; j++) printf("%d ", *p++); /* *p és l’element enter apuntat per p */ printf("\n"); } system("PAUSE"); /* El programa espera una tecla */ return 0;

}

Observem com en el programa es declara un apuntador al tipus

d’elements de la matriu que es vol recórrer. L’apuntador s’inicialitza a

l’adreça del primer element de la matriu i a continuació avança seqüen-

cialment gràcies a l’operador d’autoincrement.

Usant les idees introduï des en el programa apuntadors, és fàcil pensar en

codificar funcions generals que treballin sobre matrius de vàries dimen-

sions i de mides diferents. Caldrà passar com a paràmetres l’apuntador

al primer element de la matriu, i les mides de cadascun dels í ndex de la

matriu actual. Així es podrà declarar cada matriu en la seva mida justa,

sense ocupar més memòria de la necessària, i només hi haurà una sola

funció per cada tipus de tractament, independentment de la mida dels

í ndex de la matriu.

Es podria pensar que aquest tipus de solució només és vàlida si la funció

realitza un tractament seqüencial sobre la matriu. Ben al contrari,

l’aritmètica d’apuntadors permet accedir a qualsevol element de la ma-

triu, si sabem les mides màximes de cada í ndex. Ho veurem en un e-

xemple.

/* Programa apuntadorDirecte.c Demostra l'ús d'apuntadors per accedir directament a una posició de la matriu Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> /* Definició de constant en temps de compilació */ #define N 2 #define M 3 int main() { int m[N][M] = { {0, 1, 2}, {3, 4, 5} }; int *p;

Un exemple...Un exemple...Un exemple...Un exemple...

... de codificació de funcions generals per a tractament de matrius el podeu trobar en el programa producteMa-trius, de l’exercici d’autoavaluació número 8 d’aquest mòdul.

Page 54: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 54 Codificació en C

p = &m[0][0]; /* p apunta al primer element de la matriu */ printf("%d\n", m[1][2]); /* Accés directe a l'element m[1][2] amb matriu */ printf("%d\n", *(p + 1*M + 2)); /* Accés directe a m[1][2] amb apuntador */ system("PAUSE"); return 0; }

El programa apuntadorDirecte demostra que és possible l’accés directe a

un element d’una matriu a través d’un apuntador. Podrí em pensar que

aquest mètode és més complicat, ja que cal una multiplicació i dues

sumes per calcular l’adreça de memòria on es guarda l’element. En reali-

tat, aquesta mateixa operació es realitza en l’accés directe a través de la

matriu. Simplement, que en aquest darrer cas la sintaxi no ho posa de

manifest tant clarament.

Noteu, finalment, que les operacions aritmètiques amb apuntadors ens

retornen un apuntador. Per accedir efectivament a la dada guardada en

l’adreça de memòria, cal utilitzar l’operador “*”.

6.5. Cadenes de caràcters

En el llenguatge C, les cadenes de caràcters tenen un element més per

indicar el final de la cadena. Aquest element especial és el codi “\0”.

Totes les funcions que treballen amb cadenes de caràcters suposen que

aquestes acaben amb el caràcter “\0”. Cal tenir-ho present al fer entra-

des per teclat usant la funció scanf, ja que caldrà guardar aquest caràcter

addicional. Similarment, si es vol utilitzar la funció printf per escriure

una cadena de caràcters, caldrà assegurar que aquesta acaba amb el ca-

ràcter “\0”.

Les cadenes de caràcters que es manipulen en els programes codificats

en C es guarden en taules de caràcters. Per tant, l’accés a aquestes cade-

nes també es pot fer a través d’apuntadors. De fet, C incorpora múltiples

funcions per tractar amb cadenes de caràcters, però aquestes ens desvia-

rien dels objectius de l’assignatura.

Finalment, remarcar que les cadenes de caràcters es poden inicialitzar

fàcilment col∙ locant els caràcters desitjats entre cometes dobles. Vegem

el següent exemple:

char p[] = "Hola"; char q[] = {'H', 'o', 'l', 'a', '\0'}; char r[10] = "Hola";

Les variables p i q són taules de 5 posicions. Les dues inicialitzacions són

completament equivalents. La variable r és una taula de 10 posicions. El

contingut de les 5 primeres posicions és idèntic al de les taules de les

variables p i q, mentre que les 5 posicions restants de q no estan defini-

des.

El tipus El tipus El tipus El tipus tParaulatParaulatParaulatParaula............

... no guarda aquest caràcter especial. Per tant, no es pot llegir o escriure el tipus tPa-raula usant les funcions scanf i printf amb cadenes de ca-ràcters, sinó que caldrà fer l’accés caràcter a caràcter.

Page 55: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 55 Codificació en C

Observem que si al declarar una taula no especifiquem la seva mida,

aquesta s’ajusta a la inicialització que es faci. I, a l’invers, si la inicialit-

zació en la declaració no cobreix tots els elements de la taula, els ele-

ments restants es queden sense inicialitzar.

Page 56: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 56 Codificació en C

Resum

En aquest mòdul hem après com codificar en llenguatge C algorismes

descrits en la notació algorí smica estudiada en l’assignatura. De fet, la

codificació es realitza mitjançat una traducció quasi directe de les cons-

truccions del llenguatge algorí smic a C. Així , la codificació es redueix a

una senzilla i sistemàtica tasca de conversió entre llenguatges molt simi-

lars.

La sintaxi del llenguatge C s’assembla molt a del llenguatge algorí smic.

Així mateix, la traducció de les construccions del llenguatge algorí smic

a l’anglès ens apropa molt a les construccions del llenguatge C. Malgrat

això, ja en un petit programa en C apareixen diferències respecte del

llenguatge algorí smic.

A tall de resum del mòdul, ens centrarem en les diferències entre el llen-

guatge algorí smic i el llenguatge C. Així , en el llenguatge C:

• es distingeix entre les lletres majúscules i minúscules. Cal anar en

compte i usar el nom correcte dels objectes, funcions i accions. a

• es necessita accedir a fitxers de capçalera amb la directiva #include

per a tenir accés a funcions bàsiques del llenguatge (entrada/sortida

de dades, funcions matemàtiques, etc..). Les directives s’han

d’escriure sempre en la primera posició d’una lí nia de programa,

normalment en la capçalera del programa, abans de la funció main.

• s’utilitzen els caràcters “/*” i “*/” per delimitar els comentaris. En els

programes usarem comentaris:

− en la capçalera del programa, indicant el nom, la utilitat i l’autor del

programa;

− per delimitar les seccions del programa: declaracions de constants,

tipus i variables;

− per especificar les precondicions i postcondicions del programa i les

seves accions i funcions;

− per aclarir els esquemes aplicats en la resolució d’un subproblema,

així com per fer més llegibles aquelles parts del codi que puguin re-

sultar menys evidents.

Page 57: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 57 Codificació en C

• s’utilitza la funció main per codificar l’algorisme principal i, des d’ella

es poden invocar la resta de funcions i accions del programa.

• es poden utilitzar els tipus elementals d’objectes del llenguatge algo-

rí smic, amb les mateixes caracterí stiques. Cal recordar, però, que per

a poder utilitzar el tipus bool en llenguatge C, cal declarar-lo prèvi-

ament amb:

typedef enum {FALSE, TRUE} bool;

• es declararen objectes de manera similar al llenguatge algorí smic. La

sintaxi, però, varia lleugerament. En el cas d’objectes constants tenim

la possibilitat de declarar el seu valor en temps de compilació amb la

directiva #define, la qual cosa és útil per a dimensionar taules i ma-

trius. La definició de nous tipus en C segueix també una sintaxi lleu-

gerament diferent de la del llenguatge algorí smic.

• les funcions de conversió de tipus no són funcions pròpiament dites,

sinó que s’indica directament en l’expressió el tipus de variable desit-

jat.

• l’operador d’assignació “=” substitueix l’acció elemental d’assignació

“:=” del llenguatge algorí smic. Un conjunt d’accions es poden agru-

par en un bloc si es col∙ loquen entre les claus “{“ i “}”.

• les estructures elementals del llenguatge algorí smic (si..., mentre...,

per...) tenen un equivalent directe (if..., while..., for...). En el cas del

for, la sintaxi varia, però la funcionalitat és la mateixa.

• no hi ha accions, sinó que tot són funcions. Una acció es codificarà

com una funció que retorna el tipus especial void. La sintaxi per a la

declaració d’accions i funcions en C varia lleugerament respecte del

llenguatge algorí smic. Bàsicament, s’indica primer el tipus d’objecte

retornat i després el nom de la funció i els seus paràmetres.

• els paràmetres de sortida i d’entrada/sortida d’una funció requerei-

xen l’ús del caràcter “*” precedint el nom formal del paràmetre. En la

invocació, cal passar l’adreça de memòria del paràmetre, precedint

normalment el nom del paràmetre actual amb un “&”. Les taules no

segueixen aquesta regla, ja que sempre es passen per referència. En el

cas de les tuples, per a poder accedir a un camp dins de la funció, cal

envoltar el nom de la tupla (“*” inclòs) per parèntesis. Alternativa-

ment, podem usar l’operador “->”. Per exemple, és equivalent:

(*nom).camp; nom->camp;

Page 58: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 58 Codificació en C

• les funcions d’entrada i sortida de dades es fan amb les funcions scanf

i printf. El primer paràmetre indica el format i el tipus dels valors a

llegir o escriure. Habitualment traduirem directament les funcions

d’entrada sortida del llenguatge algorí smic als seus equivalents en C,

encara que la sintaxi de les funcions scanf i printf és molt més versàtil.

• permet fer tractament seqüencial, simplement codificant en C els

esquemes vistos en llenguatge algorí smic.

• les declaracions de taules i taules de taules segueixen una sintaxi

molt similar a la del llenguatge algorí smic, però simplement cal in-

dicar el tipus dels elements, sense especificar que es tracta d’una tau-

la. Això ja es dedueix al posar-hi la mida entre claudàtors “[“ i “]”. En

canvi, les matrius n-dimensionals no existeixen en C. Cal declarar-les

com a taules de taules, amb el que s’aconsegueix la mateixa funciona-

litat. L’accés als elements d’una taula, per assignació, consulta, lectu-

ra i escriptura, segueix els mateixos mecanismes vistos en el llenguat-

ge algorí smic.

• els í ndex de les taules comencen en la posició 0, i no en la 1 com en

el llenguatge algorí smic. Això implica canvis en:

− la inicialització de la variable í ndex amb la qual es recorre la taula,

que ha de ser a 0 enlloc de 1.

− el lí mit del recorregut d’un í ndex sobre la taula, que ha de ser una

posició inferior a la del llenguatge algorí smic. Habitualment, el que

es fa és comparar igualment amb la mida de la taula, però usant

l’operador “<” enlloc de fer-ho amb l’operador “<=” com en el llen-

guatge algorí smic.

− el tractament de l’element actual canvia lleugerament. Cal tenir pre-

sent que la posició de l’element actual en C és una unitat inferior a la

que té en la notació algorí smica. Tí picament, desapareix un possible

+1 que hi hagués en l’expressió del llenguatge algorí smic, o bé, si no

hi era, caldrà afegir un –1 en l’expressió equivalent en C. Sovint, en

un recorregut o cerca seqüencial sobre la taula, n’hi haurà prou en

canviar l’ordre de les accions corresponents a l’accés a la taula i

l’increment de l’í ndex.

• el pas de taules com a paràmetres d’accions i funcions es fa sempre

per referència, i no és possible retornar una taula en una funció. Així

en C, cal tenir present que:

− una taula passada com a paràmetre d’entrada es pot declarar com a

constant, per indicar al compilador que no s’hi faran canvis. La nota-

Page 59: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 59 Codificació en C

ció algorí smica permet canviar valors en la taula dins de la funció

sense que es vegi afectada la taula original en la crida, però aquesta

caracterí stica normalment no s’utilitza. Si calgués usar-la, s’hauria de

declarar una taula local a la funció i fer-hi una còpia de la taula pas-

sada com a paràmetre.

− una taula passada com a paràmetre d’entrada/sortida o sortida es pot

usar normalment. Segueix la notació dels tipus elementals, pel que el

seu nom no ha d’anar precedit del caràcter “*”. Tampoc cal precedir

el nom del paràmetre actual per “&” en la invocació.

− no podem tenir una taula com a valor de retorn en una funció. Po-

dem obtenir la mateixa funcionalitat, declarant un nou paràmetre de

sortida, el darrer en la funció. Per fer més llegible el programa, usa-

rem el mateix nom que la variable local retornada en el llenguatge

algorí smic.

• les tuples es declaren amb una sintaxi molt similar a la de la notació

algorí smica. L’accés als camps d’una tupla, per assignació, consulta,

lectura i escriptura, segueix els mecanismes ja vistos en el llenguatge

algorí smic. Al ser passades com a paràmetres d’accions i funcions, les

tuples segueixen les mateixes regles que els tipus elementals del llen-

guatge C (nom prefixat amb “*” i pas de l’adreça de memòria “&” en

cas de paràmetres de d’entrada/sortida). Cal recordar, però, l’accés a

un camp d’una tupla passada per referència (“(*nom).camp” o bé

“nom->camp), ja comentat en aquest resum. Així mateix el llenguatge

C permet usar tuples com a valor de retorn d’una funció, encara que

per raons d’eficiència s’hauria d’evitar.

• la metodologia de disseny descendent aplicada en el llenguatge algo-

rí smic suposa només haver de fer les predeclaracions de les accions i

funcions necessàries en cada nivell. Aquestes es fan abans de la fun-

ció main, usant la mateixa sintaxi que en la capçalera de la definició

de l’acció o funció corresponent.

Cal recordar que l’enfocament del present mòdul es dirigeix a co-

brir només aquella petita part del C necessària per a poder codifi-

car la notació algorí smica vista a l’assignatura. Malgrat això, s’han

comentat també alguns aspectes més avançats del C que permeten

obtenir codificacions més senzilles, sovint més eficients i de vega-

des també més generals. En concret, s’han comentat breument:

− els operadors aritmètics avançats, que permeten un codi més com-

pacte i eficient;

Page 60: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 60 Codificació en C

− la sintaxi estesa de les funcions d’entrada/sortida scanf i printf, que

permeten donar format a l’entrada/sortida dels programes;

− la inicialització de variables en la declaració, tant pels tipus elemen-

tals com per les taules i tuples;

− els apuntadors i la seva relació amb les matrius, que permeten un

codi més eficient i general;

− les cadenes de caràcters i la seva inicialització.

Page 61: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 61 Codificació en C

Exercicis d’autoavaluació

1. Codifiqueu l’algorisme potencia, resolt en l’exercici d’autoavaluació número 11 del mòdul “Introducció a l’algorí smica” de l’assignatura. Consulteu l’enunciat i la solu-ció de l’exercici a les pàgines 58 i 61, respectivament. 2. Codifiqueu l’algorisme sumaQuadrats, resolt en l’exercici d’autoavaluació número 13 del mòdul “Introducció a l’algorí smica” de l’assignatura. Consulteu l’enunciat i la solució de l’exercici a les pàgines 58 i 61, respectivament. 3. Codifiqueu l’algorisme fitaAprovats, resolt en l’apartat 4.3.3. “Nombre d’aprovats” del mòdul “Tractament seqüencial” de l’assignatura. Consulteu l’enunciat i la solució de l’exercici a la pàgina 38 del mòdul. 4. Codifiqueu l’algorisme longPrimPar, resolt en l’apartat 5.2.2. “Longitud de la prime-ra paraula” del mòdul “Tractament seqüencial” de l’assignatura. Consulteu l’enunciat i la solució de l’exercici a partir de la pàgina 42 del mòdul. 5. Codifiqueu l’algorisme valMax, resolt en l’exercici d’autoavaluació número 2 del mòdul “Tractament seqüencial” de l’assignatura. Consulteu l’enunciat i la solució de l’exercici a les pàgines 47 i 48, respectivament. 6. Codifiqueu l’algorisme esPerfecte, resolt en l’exercici d’autoavaluació número 4 del mòdul “Tractament seqüencial” de l’assignatura. Consulteu l’enunciat i la solució de l’exercici a les pàgines 47 i 49, respectivament. 7. Codifiqueu l’algorisme esCapicua, parcialment resolt en l’apartat 2.4.3. “Exemples dels esquemes de recorregut i cerca” del mòdul “Tipus estructurats de dades” de l’assignatura. Consulteu l’enunciat i la solució de l’exercici a partir de la pàgina 30 del mòdul. Observeu que l’algorisme no és complet i que caldrà completar-lo per poder fer l’entrada de dades i la sortida dels resultats. 8. Codifiqueu l’algorisme producteMatrius, resolt en l’apartat 2.4.3. “Exemples dels esquemes de recorregut i cerca” del mòdul “Tipus estructurats de dades” de l’assignatura. Consulteu l’enunciat i la solució de l’exercici a partir de la pàgina 31 del mòdul. Observeu que caldrà declarar i definir l‘acció omplirTaula. Penseu que caldrà adaptar-la per tractar amb matrius de diferent mida. 9. Codifiqueu l’algorisme seleccioDirecta, resolt en l’apartat 2.5.2. “Ordenació per selec-ció” del mòdul “Tipus estructurats de dades” de l’assignatura. Consulteu l’enunciat i la solució de l’exercici a partir de la pàgina 34 del mòdul. Observeu que caldrà decla-rar i definir la funció omplirTaula, i mostrar la taula ordenada en el dispositiu de sor-tida. 10. Codifiqueu l’algorisme codifica5En5, resolt en l’exercici d’autoavaluació número 3 del mòdul “Tipus estructurats de dades” de l’assignatura. Consulteu l’enunciat i la solució de l’exercici a les pàgines 51 i 56, respectivament. 11. Codifiqueu l’algorisme transposicioDeText, resolt en l’exercici d’autoavaluació nú-mero 5 del mòdul “Tipus estructurats de dades” de l’assignatura. Consulteu l’enunciat i la solució de l’exercici a les pàgines 51 i 58, respectivament. 12. Codifiqueu les funcions de tractament del tipus paraula, llegirParaula, escriureParau-la, paraulesIguals, resoltes en l’exercici d’autoavaluació número 7 del mòdul “Tipus estructurats de dades” de l’assignatura. Consulteu l’enunciat i la solució de l’exercici a les pàgines 52 i 61, respectivament. 13. Codifiqueu l’acció escriurePunts, resolta en l’exercici d’autoavaluació número 8 del mòdul “Tipus estructurats de dades” de l’assignatura. Consulteu l’enunciat i la solució de l’exercici a les pàgines 53 i 63, respectivament. Si voleu provar l’acció en l’ordinador, podeu simplificar el tipus tEquip i deixar només els camps nom, partits-Guanyats i partitsEmpatats. D’aquesta manera, les inicialitzacions en el programa prin-cipal seran més senzilles. 14. Codifiqueu l’algorisme comptarLA, resolt en l’exercici d’autoavaluació número 1 del mòdul “Introducció a la metodologia del disseny descendent” de l’assignatura. Consulteu l’enunciat i la solució (plantejament general 2) de l’exercici a les pàgines 35 i 39, respectivament.

Consulteu l’acció omplirTaula de l’algorisme quadrats en l’apartat 2.2.2. “Lectura i escriptura” (pàgina 16), del mòdul “Tipus estructurats de dades” de l’assignatura.

Consulteu l’acció invertirVector en l’apartat 2.4.3. “Exemples dels esquemes de recorregut i cerca” (pàgina 30), del mòdul “Tipus estructurats de dades” de l’assignatura.

Page 62: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 62 Codificació en C

15. Codifiqueu l’algorisme comptaCapicuesFrase, resolt en l’exercici d’autoavaluació número 3 del mòdul “Introducció a la metodologia del disseny descendent” de l’assignatura. Consulteu l’enunciat i la solució de l’exercici a les pàgines 36 i 43, res-pectivament.

Page 63: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 63 Codificació en C

Solucionari

1. Codificació del programa potencia :

/* Programa potencia.c Calcula la potencia d'un enter elevat a un enter. Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> int main() { /* Declaració de variables */ int n, exp, pot; scanf("%d", &n); scanf("%d", &exp); /* preparar seqüència */ /* Pre: n=N i exp=EXP i EXP>=0 */ pot = 1; /* inici tractament */ while (exp>0) { /* fi seqüència - exp=0 */ pot = pot * n; /* tractar element */ exp = exp - 1; /* avançar seqüència */ } /* Post: pot = N elevat a EXP */ printf("%d\n", pot); /* tractament final */ system("PAUSE"); /* El programa espera una tecla */ return 0; }

2. Codificació del programa sumaQuadrats :

/* Programa sumaQuadrats.c Llegeix n i suma els quadrats dels n primers naturals. Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> int main() { /* Declaració de variables */ int n, s, i; scanf("%d", &n); /* Pre: n=N */ i = 1; /* preparar seqüència */ s = 0; /* inici tractament */ while (i<=n) { /* fi seqüència - i>n */ s = s + i * i; /* tractar element */ i = i + 1; /* avançar seqüència */ } /* Post: s es la suma de quadrats entre 1 i N */ printf("%d\n", s); /* tractament final */ system("PAUSE"); /* El programa espera una tecla */ return 0; }

3. Codificació del programa fitaAprovats :

/* Programa fitaAprovats.c Comprova si el nombre d'aprovats no és inferior a una fita donada. Jordi Riera, 2001 */

Page 64: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 64 Codificació en C

#include <stdio.h> #include <stdlib.h> int main() { /* Definició de tipus */ typedef enum {FALSE, TRUE} bool; /* Declaració de variables */ bool trobat; char car; int fita, n; /* Pre: a l'entrada s'hi llegeix un enter FITA i una seqüència de

caràcters del conjunt {"A", "B", "C", "c", "D" } seguida per una "Z" */ scanf("%d", &fita); scanf("%c", &car); /* preparar seqüència */ trobat = FALSE; n = 0; /* inici tractament */ while (!(car=='Z') && !trobat) { /* fi seqüència - marca="Z" */ trobat = (car=='c') || (car=='D') || (n>=fita); /* actualitzar trobat */ if (!trobat) { n = n + 1; /* tractar element */ scanf("%c", &car); /* avançar seqüència */ } } if (n>=fita) { /* tractament final */ printf("N\n"); } else { printf("S\n"); } /* Post: pel dispositiu de sortida s'escriu "N" si el nombre d'aprovats

no és inferior a la FITA, i "S" en cas contrari */ system("PAUSE"); /* El programa espera una tecla */ return 0; }

4. Codificació del programa longPrimPar :

/* Programa lonPrimPar.c calcula la longitud de la primera paraula d'un text Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> int main() { /* Definició de tipus */ typedef enum {FALSE, TRUE} bool; /* Declaració de variables */ char car; int n; bool trobat; /* Pre: A l'entrada s'hi llegirà una seqüencia de caràcters que no conté cap punt,

seguida d'un punt */ /* Cerca la primera lletra majúscula. Salta els separadors inicials */ scanf("%c", &car); /* preparar seqüència - llegir() */ trobat = FALSE; /* inici tractament - és buit */ while (!(car=='.') && !trobat) { /* fi seqüència - marca='.' */ trobat = (car<='Z') && (car>='A'); /* actualitzar trobat */ if (!trobat) { /* tractar element - és buit */ scanf("%c", &car); /* avançar seqüència - llegir() */ } }

Noteu que ha calgut canviar els noms de les variables long i trob de l’algorisme ori-ginal en les declaracions, ja que no s’adeqüen als noms usats en el cos de l’algorisme.

Page 65: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 65 Codificació en C

/* tractament final - és buit */ /* Cerca sobre la seqüència el primer caràcter separador. Compta les

lletres de la paraula actual */ /* preparar seqüència - no cal */ trobat = FALSE; n = 0; /* inici tractament */ while (!(car=='.') && !trobat) { /* fi seqüència - marca='.' */ trobat = (car>'Z') || (car<'A'); /* actualitzar trobat */ if (!trobat) { n = n + 1; /* tractar element */ scanf("%c", &car); /* avançar seqüència - llegir() */ } } printf("%d\n", n); /* tractament final */ /* Post: Escriu la longitud de la primera paraula (seqüència de lletres

majúscules seguides, o 0 si no n'hi havia cap */ system("PAUSE"); /* El programa espera una tecla */ return 0; }

5. Codificació del programa valMax :

/* Programa valMax.c calcula el màxim d'una seqüència de reals marcada amb 0.0 Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> int main() { /* Declaració de variables */ float x, max; /* Pre: A l'entrada s'hi llegirà una seqüència no buida de reals

que no conté cap 0.0, seguida de 0.0 */ scanf("%f", &x); /* preparar seqüència - llegir() */ max = x; /* inici tractament */ scanf("%f", &x); while (x!=0.0) { /* fi seqüència - marca=0.0 */ if (x>max) { /* tractar element */ max = x; } scanf("%f", &x); /* avançar seqüència - llegir() */ } printf("%f\n", max); /* tractament final */ /* Post: Pel canal de sortida s'ha escrit el real més gran dels que

s'han llegit pel canal d'entrada */ system("PAUSE"); /* El programa espera una tecla */ return 0; }

6. Codificació del programa esPerfecte :

/* Programa esPerfecte.c Comprova si un nombre és perfecte, és a dir, si és igual a la suma dels seus divi-sors, excepte ell mateix. Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> int main() { /* Declaració de variables */ int x, i, sum;

Page 66: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 66 Codificació en C

/* Pre: A l'entrada hi ha un nombre enter més gran que zero, X */ scanf("%d", &x); i = 1; /* preparar seqüència */ sum = 0; /* inici tractament */ while (i<x) { /* fi seqüència */ if ((x % i)==0) { /* tractar element */ sum = sum + i; } i = i + 1; /* avançar seqüència */ } if (sum==x) printf("S\n"); /* tractament final */ else printf("N\n"); /* Post: Pel canal de sortida s'ha escrit "S" si la suma dels divisors de X menors que

X és igual a X, i "N" en cas contrari */ system("PAUSE"); /* El programa espera una tecla */ return 0; }

7. Codificació del programa esCapicua :

/* Programa esCapicua.c Comprova si una seqüència d'enters és capicua Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> /* Definicio de tipus */ typedef enum {FALSE, TRUE} bool; int main() { /* Declaració de constants */ const int N = 10; /* Declaració de variables */ int t[N]; bool trobat; int i; /* Pre: A l'entrada hi ha una seqüència de N enters */ for( i=0; i<N; i++) scanf("%d", &t[i]); /* Omplim el vector t */ /* Ceca sobre la meitat del vector. S'usa accés directe per comparar amb la posició simètrica */ i = 0; /* preparar seqüència */ trobat = FALSE; /* inici tractament - és buit */ while (i<=(N / 2) && !trobat) { /* fi seqüència - meitat del vector */ if (t[i]!=t[N-i-1]) { /* tractar element */ trobat = TRUE; /* actualitzar trobat */ } else { i = i + 1; /* avançar seqüència */ } } if (!trobat) printf("S\n"); /* tractament final */ else printf("N\n"); /* Post: Pel canal de sortida s'ha escrit "S" si la seqüència llegida pel canal d'en-trada

és capicua, i s'ha escrit "N" en cas contrari */ system("PAUSE"); /* El programa espera una tecla */ return 0; }

Page 67: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 67 Codificació en C

8. Codificació del programa producteMatrius :

/* Programa producteMatrius.c Calcula el producte de dues matrius Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> /* Declaració de constants */ const int N = 1; const int M = 2; const int P = 3; /* PreDeclaració de funcions */ void omplirMatriuA(int t[N][M]); void omplirMatriuB(int t[M][P]); void escriuMatriuC(int t[N][P]); int main() { /* Declaració de variables */ int a[N][M]; int b[M][P]; int c[N][P]; int i, j, k, v; /* Pre: A l'entrada hi ha una seqüència d'enters de N*M + M*P enters */ omplirMatriuA(a); omplirMatriuB(b); for (i=0; i<N; i++) /* Recorregut per les files de c */ for (j=0; j<P; j++) { /* Recorregut per les columnes de c */ v = 0; /* Recorregut amb tractament acumulatiu */ for (k=0; k<M; k++) v = v + a[i][k]*b[k][j]; c[i][j] = v; } escriuMatriuC(c); /* Post: Pel canal de sortida s'ha escrit la matriu resultant del

producte A*B, on A guarda els N*M primers enters llegits, i B els següents M*P */ system("PAUSE"); /* El programa espera una tecla */ return 0; } void omplirMatriuA(int t[N][M]) { /* Declaració de variables */ int i, j; /* Pre: A l'entrada hi ha una seqüència d'enters de N*M */ for (i=0; i<N; i++) for (j=0; j<M; j++) scanf("%d", &t[i][j]); /* Post: la matriu t guarda la seqüència de l'entrada */ } void omplirMatriuB(int t[M][P]) { /* Declaració de variables */ int i, j; /* Pre: A l'entrada hi ha una seqüència d'enters de M*P */ for (i=0; i<M; i++) for (j=0; j<P; j++) scanf("%d", &t[i][j]); /* Post: la matriu t guarda la seqüència de l'entrada */ }

Page 68: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 68 Codificació en C

void escriuMatriuC(int t[N][P]) { /* Declaració de variables */ int i, j; /* Pre: t=T */ for (i=0; i<N; i++) { for (j=0; j<P; j++) printf("%d ", t[i][j]); printf("\n"); } /* Post: a la sortida s'ha escrit el contingut de T */ }

Tal com es pot comprovar en el programa, el fet de tractar amb matrius de mides

diferents obliga a definir funcions especí fiques per omplir i escriure cadascuna de les

matrius. El llenguatge C, però, permet resoldre més eficientment aquest problema

gràcies a la utilització d’apuntadors. L’algorisme quedaria tal com segueix:

/* Programa producteMatriusApuntadors.c Calcula el producte de dues matrius Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> /* Declaració de constants */ const int N = 1; const int M = 2; const int P = 3; /* PreDeclaració de funcions */ void omplirMatriu(int *t, int Nmax, int Mmax); void escriureMatriu(int *t, int Nmax, int Mmax); int main() { /* Declaració de variables */ int a[N][M]; int b[M][P]; int c[N][P]; int i, j, k, v; /* Pre: A l'entrada hi ha una seqüència de N*M + M*P enters. */ omplirMatriu(&a[0][0], N, M); omplirMatriu(&b[0][0], M, P); for (i=0; i<N; i++) /* Recorregut per les files de c */ for (j=0; j<P; j++) { /* Recorregut per les columnes de c */ v = 0; /* Recorregut amb tractament acumulatiu */ for (k=0; k<M; k++) v = v + a[i][k]*b[k][j]; c[i][j] = v; } escriureMatriu(&c[0][0], N, P); /* Post: Pel canal de sortida s'ha escrit la matriu resultant del producte

A*B, on A guarda els N*M primers enters llegits, i B els següents M*P */ system("PAUSE"); /* El programa espera una tecla */ return 0; } void omplirMatriu(int *m, int Nmax, int Mmax) { /* Declaració de variables */ int i, j; /* Pre: A l'entrada hi ha una seqüència d'enters de N*M */ for (i=0; i<Nmax; i++) for (j=0; j<Mmax; j++) scanf("%d", m++); /* Post: la matriu m guarda la seqüència de l'entrada */ }

En l’apartat “Construcci-ons avançades del llen-guatge C” d’aquest mateix mòdul podeu trobar més informació sobre com uti-litzar apuntadors per fer tractaments eficients sobre taules i matrius.

Page 69: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 69 Codificació en C

void escriureMatriu(int *m, int Nmax, int Mmax) { /* Declaració de variables */ int i, j; /* Pre: m=M */ for (i=0; i<Nmax; i++) { for (j=0; j<Mmax; j++) printf("%d ", *m++); printf("\n"); } /* Post: a la sortida s'ha escrit el contingut de T */ }

9. Codificació del programa selecciodirecta :

/* Programa seleccioDirecta.c Ordenació d'un vector per selecció directa Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> /* Declaració de constants */ #define N 10 /* Declaració de tipus */ typedef int vector[N]; /* PreDeclaració de funcions */ void omplirVector(vector v); void escriureVector(const vector v); int main() { /* Declaració de variables */ vector t; int i, j, posMin; int aux; /* Pre: A l'entrada hi ha una seqüència de N enters */ omplirVector(t); i = 0; /* Primera posició del vector, 0 */ while (i<N-1) { /* N-1 passes sobre el vector */ posMin = i; /* Recorregut des de i+1 fins N */ j = i + 1; while (j<N) { if (t[j]<t[posMin]) posMin = j; j = j + 1; } aux = t[i]; /* Intercanvia posicions */ t[i] = t[posMin]; t[posMin] = aux; i = i + 1; } escriureVector(t); /* Post: Pel canal de sortida s'han escrit en ordre creixent els N enters llegits pel

canal d'entrada */ system("PAUSE"); /* El programa espera una tecla */ return 0; } void omplirVector(vector t) { /* Declaració de variables */ int i; /* Pre: A l'entrada hi ha una seqüència de N enters */ for (i=0; i<N; i++) scanf("%d", &t[i]); /* Post: el vector t guarda, en el mateix ordre, la seqüència de l'entrada */ }

Page 70: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 70 Codificació en C

void escriureVector(const vector v) { /* Declaració de variables */ int i; /* Pre: v=V */ for (i=0; i<N; i++) printf("%d ", v[i]); /* Post: a la sortida s'ha escrit el contingut de V, en el mateix ordre */ }

10. Codificació del programa codifica5En5 :

/* Programa codifica5En5.c Inverteix cada grup de 5 caràcters llegits de l’entrada. Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> /* Pre-declaració de funcions */ void invTaula(char t[5], int N); int main() { /* Declaració de variables */ char t[5]; int i, lon; char c; /* Pre: En el canal d'entrada hi ha una frase acabada en "." */ scanf("%c", &c); while (!(c=='.')) { lon = 0; while (!(c=='.') && (lon<5)) { t[lon] = c; lon = lon + 1; scanf("%c", &c); } invTaula(t, lon); for (i=0; i<lon; i++) printf("%c", t[i]); } /* Post: En el canal de sortida es genera una frase que correspon a la llegida pel

canal d'entrada de manera que els grups de 5 caràcters de la sortida corresponent al mateix grup que a l'entrada, però amb l'ordre invertit. Aquestes agrupacions no

són aleatòries sinó que corresponen a agrupacions de 5 caràcters correlatives des des de l'inici de la frase */

system("PAUSE"); /* El programa espera una tecla */ return 0; } void invTaula(char t[5], int N) { /* Declaració de variables */ int i, aux; /* Pre: t=T conté N valors enters */ i = 0; while (i<=(N/2)) { aux = t[i]; t[i] = t[N-i-1]; t[N-i-1] = aux; i = i + 1; } /* Post: per a i des d'0 fins N-1, t[i] = t[N-i-1] */ }

Page 71: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 71 Codificació en C

11. Codificació del programa transposiciodeText :

/* Programa transposicioDeText.c Fa una transposició de text usant una matriu de 10x10. Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> int main() { /* Declaració de variables */ char t[10][10]; int fila, col; int maxFila, maxColumna; char c; /* Pre: En el canal d'entrada hi ha una frase acabada en punt i d'una

longitud màxima de 100 caràcters */ fila = 0; col = 0; scanf("%c", &c); while (c!='.') { t[fila][col] = c; col = col + 1; if (col==10) { col = 0; fila = fila + 1; } scanf("%c", &c); } maxFila = fila + 1; if (maxFila>1) { while (col<10) t[fila][col++] = '-'; /* Cal omplir tota la darrera fila */ maxColumna = 10; } else { maxColumna = col; } for (col=0; col<maxColumna; col++) for (fila=0; fila<maxFila; fila++) printf("%c", t[fila][col]); /* Post: En el canal de sortida s'ha escrit una frase que resulta d'aplicar la

transposició de text segons una matriu de 10 files i 10 columnes a la frase llegida pel canal d'entrada */

system("PAUSE"); /* El programa espera una tecla */ return 0; }

12. Codificació del programa provaParaula :

/* Programa provaParaula.c Implementa i prova funcions de tractament del tipus paraula Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> /* Definició de constants */ #define MAXCAR 40 /* Definició de tipus */ typedef enum {FALSE, TRUE} bool; typedef struct { char lletres[MAXCAR]; int l; } paraula;

Page 72: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 72 Codificació en C

/* PreDeclaració de funcions */ paraula llegirParaula(); void escriureParaula(paraula p); bool paraulesIguals(paraula p1, paraula p2); int main() { /* Declaració de variables */ paraula p1, p2; /* Pre: a l'entrada hi ha una seqüència de caràcters acabada en un punt */ p1 = llegirParaula(); /* Lleguim dues paraules de l’entrada */ p2 = llegirParaula(); printf("\n"); escriureParaula(p2); /* Escrivim les paraules, i indiquem si són iguals */ printf(" == "); escriureParaula(p1); printf(" ? "); if (paraulesIguals(p1, p2)) printf("SI\n"); else printf("No\n"); /* Post: Les dues primeres paraules llegides s’han escrit pel dispositiu

de sortida, i s’ha indicat si eren iguals o no */ system("PAUSE"); /* El programa espera una tecla */ return 0; } paraula llegirParaula() { /* Declaració de variables */ paraula p; char c; /* Pre: Hi ha una seqüència de caràcters a l’entrada */ scanf("%c", &c); while (c==' ') scanf("%c", &c); p.l = 0; while ((c!='.') && (c!=' ')) { if (p.l<MAXCAR) { p.lletres[p.l] = c; p.l = p.l + 1; } scanf("%c", &c); } return p; /* Post: p.l=0 si es llegeix cap caràcter diferent de l’espai. sinó, p.lletres conté els caràcters diferents d’espai que s’han llegit fins al primer espai posterior

a algun caràcter diferent d’espai i p.l és el número de caràcters diferents d’espai */

} void escriureParaula(paraula p) { /* Declaració de variables */ int i; /* Pre: p=P */ for (i=0; i<p.l; i++) printf("%c", p.lletres[i]); /* Post: a la sortida s’han escrit els p.l primers caràcters de p.lletres */ } bool paraulesIguals(paraula p1, paraula p2) { /* Declaració de variables */ bool iguals; int j; /* Pre: p1=P! i p2=P2 */ iguals = p1.l==p2.l; if (iguals) {

Page 73: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 73 Codificació en C

j = 1; while ((j<p1.l) && (p1.lletres[j]==p2.lletres[j])) j++; iguals = p1.lletres[j]==p2.lletres[j]; } return iguals; /* Post: iguals serà cert si P1.l=P2.l i els P1.l elements de P1.lletres són iguals als P2.l

elements de P2.lletres i fals en cas contrari */ }

13. Codificació del programa escriurePunts :

/* Programa escriurePuntsSimplificat.c Prova l'acció escriurePunts Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> /* Definició de constants */ #define MAXCAR 40 #define MAXJUGADORS 25 #define MAXEQUIPS 20 /* Definició de tipus */ typedef struct { char lletres[MAXCAR]; int l; } paraula; typedef struct { paraula nom; int numGrogues, numVermelles; int partitsJugats; } tJugador; typedef struct { paraula nom; paraula ciutat; int partitsGuanyats, partitsPerduts, partitsEmpatats; int golsFavor, golsContra; } tEquip; /* Tipus tEquip simplificat per facilitar la inicialització */ /* tipus tEquip complet seria d’aquesta manera: typedef struct { paraula nom; paraula ciutat; int partitsGuanyats, partitsPerduts, partitsEmpatats; int golsFavor, golsContra; struct { tJugador jugador[MAXJUGADORS]; int num; } jugadors; } tEquip; */ typedef struct { tEquip equips[MAXEQUIPS]; int num; } lligaFutbol; /* Pre-declaració de funcions */ void escriurePunts(const lligaFutbol l); void escriureParaula(paraula p); int main() { /* Declaració de variables */ lligaFutbol lliga = { { /* Taula d'equips */ {{"F.C.Barcelona", 13}, {"Barcelona", 9}, 5, 3, 2, 12, 5}, {{"R.C.D.Espanyol", 14}, {"Barcelona", 9}, 3, 1, 4, 5, 15} }, 2}; /* Pre: a l'entrada hi ha una seqüència de caràcters acabada en un punt */ escriurePunts(lliga);

Page 74: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 74 Codificació en C

/* Post: Escriu per pantalla els noms i punts dels equips de la lliga */ system("PAUSE"); /* El programa espera una tecla */ return 0; } void escriurePunts(const lligaFutbol l) { /* Declaració de variables */ int j; /* Pre: l=L */ for (j=0; j<l.num; j++) { escriureParaula(l.equips[j].nom); printf(": "); printf("%d ", l.equips[j].partitsEmpatats + 3*l.equips[j].partitsGuanyats); printf("\n"); } /* Post: s’ha escrit al canal estàndard el camp nom dels L.num elements de

la taula L.equips junt amb els punts de cadascun. */ } void escriureParaula(paraula p) { /* Declaració de variables */ int i; /* Pre: p=P */ for (i=0; i<p.l; i++) printf("%c", p.lletres[i]); /* Post: a la sortida s’han escrit els P.l primers caràcters de P.lletres */ }

14. Codificació del programa comptarLA :

/* Programa comptarLA.c Compta el número de "LA que hi ha en una frase acabada en un punt Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> /* Definició de tipus */ typedef enum {FALSE, TRUE} bool; typedef char tParella[2]; /* Definit en el 1er nivell */ /* Pre-declaració de funcions */ void obtenirPrimeraParella(tParella p); /* Funcions definides en el 1er nivell */ void obtenirParella(tParella p); bool darreraParella(tParella p); bool esLA(tParella p); /* 1er nivell de disseny descendent. Recorregut sobre una seqüència de parelles. Abstracció del tipus tParella. */ int main() { /* Declaració de variables */ int nbDeLA; tParella parella; /* Pre: f=F i f és una frase acabada en punt i f està disponible en el canal d'entrada */ nbDeLA = 0; /* inici tractament */ obtenirPrimeraParella(parella); /* preparar seqüència */ while ( !darreraParella(parella) ) { /* fi seqüència */ if (esLA(parella)) nbDeLA++; /* tractar element */ obtenirParella(parella); /* avançar seqüència */ } printf("%d", nbDeLA); /* tractament final */ /* Post: s'ha escrit pel canal de sortida nbDeLA, que indica el nombre

Page 75: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 75 Codificació en C

de "LA" que hi ha a F */ system("PAUSE"); /* El programa espera una tecla */ return 0; } /* 2on nivell de disseny descendent. Funcions associades al tipus tParella. */ void obtenirPrimeraParella(tParella p) { /* Pre: s=S i s és una frase acabada en punt i la part esquerra de s és buida */ p[0] = ' '; scanf("%c", &p[1]); /* Post: p conté la primera parella de s i la part esquerre de s conté un caràcter */ } void obtenirParella(tParella p) { /* Pre: s=S i s és una frase acabada en punt i la part esquerra de s no és buida i la

part dreta de s tampoc no és buida i p=P i P és l'anterior parella obtinguda*/ p[0] = p[1]; scanf("%c", &p[1]); /* Post: p conté la parella següent de la seqüència de parelles i la part esquerra

de s conté un caràcter més */ } bool darreraParella(tParella p) { /* Pre: p=P */ return p[1]=='.'; /* Post: retorna CERT si p és la darrera parella de la seqüència */ } bool esLA(tParella p) { /* Pre: p=P */ return (p[0]=='L') && (p[1]=='A'); /* Post: retorna CERT si p és la parella "LA" */ }

15. Codificació del programa comptaCapicuesFrase :

/* Programa comptaCapicuesFrase.c Compta el número de mots capicues que hi ha en una frase acabada en un punt Jordi Riera, 2001 */ #include <stdio.h> #include <stdlib.h> /* Definició de constants */ #define MAXCAR 15 /* Definició de tipus */ typedef enum {FALSE, TRUE} bool; typedef struct { int lon; char c[MAXCAR]; char caracterLlegit; /* Conté el darrer caràcter llegit */ bool final; } tMot; /* Definit en el 1er nivell */ /* Pre-declaració de funcions */ void obtenirPrimerMot(tMot *m); /* Funcions definides en el 1er nivell */ void obtenirMot(tMot *m); bool motFinal(tMot m); bool motCapicua(tMot m); bool separador(char c); /* Funcions definides en el 2on nivell */ /* 1er nivell de disseny descendent. Recorregut sobre una seqüència de mots. Abstracció del tipus tMot. */

Page 76: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 76 Codificació en C

int main() { /* Declaració de variables */ int nMotsC; tMot mot; /* Pre: A l'entrada hi ha una seqüència de mots f de la frase F. F no és buida */ nMotsC = 0; /* inici tractament */ obtenirPrimerMot(&mot); /* preparar seqüència */ while ( !motFinal(mot) ) { /* fi seqüència */ if (motCapicua(mot)) nMotsC++; /* tractar element */ obtenirMot(&mot); /* avançar seqüència */ } if (motCapicua(mot)) nMotsC++; /* tractament final */ printf("%d", nMotsC); /* Post: s'ha escrit pel canal de sortida el número de mots capicues de F */ system("PAUSE"); return 0; } /* 2on nivell de disseny descendent. Funcions associades al tipus tMot. */ void obtenirPrimerMot(tMot *m) { /* Declaració de variables */ char c; /* Pre: A l'entrada hi ha la seqüència de mots f de la frase F. La part esquerra de f és buida. La part dreta, DF, no és buida */ /* Recorregut sobre una seqüència de caràcters */ m->lon = 0; scanf("%c", &c); while ( separador(c) && (c!='.') ) scanf("%c", &c); /* Salta els primers separadors */ m->caracterLlegit = c; obtenirMot(m); /* Post: m representa el primer mot de DF. El mot obtingut estarà

a la part esquerra de la seqüència f */ } void obtenirMot(tMot *m) { /* Declaració de variables */ char c; /* Pre: A l'entrada hi ha la seqüència de mots f de la frase F. La part dreta, DF, no és buida */ m->lon = 0; c = m->caracterLlegit; while ( !separador(c) && (c!='.') ) { /* Obtenim el mot */ m->c[m->lon++] = c; scanf("%c", &c); } while ( separador(c) && (c!='.') ) scanf("%c", &c); /* Salta els primers separadors */ m->caracterLlegit = c; m->final = c=='.'; /* Post: m representa el primer mot de DF. El mot obtingut estarà a la

part esquerra de la seqüència f */ } bool motFinal(tMot m) { /* Pre: m=M */ return m.final; /* Post: retorna cert si m és el darrer mot d'una frase */ } bool motCapicua(tMot m) { /* Declaració de variables */ int i, j;

Page 77: Codificació en Cxina.uoc.es/prestatgeries/PV01_05009_00669/mbasic/manualc.pdf · Codificació en C Traducció de llenguatge algorí smic a C Jordi Riera i Baburés P00/05009/00563

© Universitat Oberta de Catalunya • P00/05009/00563 77 Codificació en C

bool trobat; /* Pre: m=M */ i = 0; j = m.lon-1; trobat = FALSE; while (!trobat && (i<j)) { if (m.c[i]!=m.c[j]) { trobat=TRUE; } else { i++; j--; } } return !trobat; /* Post: retorna cert només si m és un mot capicua */ } bool separador(char c) { /* Pre c=C */ return (c==' ') || (c==',') || (c==';'); /* Post: retorna cert si C és un separador - espai, coma o punt i coma */ }

Glossari

compilació i enllaçat

Processos pels quals un programa escrit en un llenguatge d’alt nivell és

traduï t a un codi màquina que l’ordinador és capaç d’executar.

fitxer de capçalera (o include)

Fitxer que conté definicions de nous tipus i declaracions de constants,

accions i funcions que després podran ser utilitzades en el programa.

temps de compilació (d’un programa)

Perí ode en el qual el programa és compilat i traduï t a llenguatge mà-

quina.

temps d’execució (d’un programa)

Perí ode en el qual el programa s’està executant en l’ordinador.

Bibliografia

Kernighan, B.W.; Ritchie, D.M. (1991) El lenguaje de Programación C. 2a

Edición. Mèxic: Prentice Hall Hispanoamaricana.