Programació I en C/C++: Fonaments, Algorismes i Matrius

Apunts de Programació I en C/C++: compilació g++, bucles, esquemes de cerca i recorregut, cadenes string.h, matrius multidimensionals i pas per referència.

Programació I · Universitat de Lleida · Grau en Enginyeria Informàtica · 1r curs

54 pàgines · 7 temes · 14 flashcards · 28 preguntes tipus test

Índex

  1. Fonaments — Entorn de desenvolupament, tipus bàsics i I/O · p. 4-10
  2. Estructures de control — Bucles i iteració bàsica · p. 10-16
  3. Esquemes algorítmics — Recorregut de seqüències · p. 16-18
  4. Esquemes algorítmics — Cerca en seqüències i combinació d'esquemes · p. 18-28
  5. Cadenes de caràcters — Vectors de caràcters i biblioteca string.h · p. 28-34
  6. Estructures multidimensionals — Matrius 2D, 3D i taules de cadenes · p. 34-37
  7. Modularitat i disseny funcional — Funcions, paràmetres i pas per referència · p. 38-53

Fonaments — Entorn de desenvolupament, tipus bàsics i I/O

Flashcards

Quin especificador de format cal emprar a printf per visualitzar un enter en base hexadecimal majúscula?
Cal emprar l'especificador %X.
Quina diferència d'ús existeix entre l'operador adreça & en llegir un int enfront de llegir una cadena de caràcters?
En un enter escalar cal posar & per indicar la seva adreça, mentre que amb una cadena s'omet perquè el nom del vector és directament l'adreça inicial.

Preguntes tipus test

  1. Quin flag activa la visualització de tots els avisos durant la compilació amb g++?
    • a) -g
    • b) -o
    • c) -Wall
    • d) -c

    Resposta: c) -Wall. El paràmetre -Wall fa que g++ mostri tots els avisos (warnings) potencials del codi.

  2. Quants bits es destinen al valor numèric en un int convencional de 32 bits?
    • a) 31 bits
    • b) 32 bits
    • c) 16 bits
    • d) 30 bits

    Resposta: a) 31 bits. Es reserva 1 bit de més pes per al signe i els 31 restants expressen la magnitud.

  3. Quin especificador de format mostra un enter en base octal amb printf?
    • a) %d
    • b) %f
    • c) %X
    • d) %o

    Resposta: d) %o. L'especificador %o correspon a la representació en base 8 o octal.

Estructures de control — Bucles i iteració bàsica

Flashcards

Per quina raó tècnica s'utilitza do-while per a validar la lectura de valors per teclat en comptes de while?
Perquè necessitem llegir la dada pel teclat com a mínim un cop abans de poder comprovar si compleix els requisits o si s'ha de repetir.
En el càlcul del factorial amb for, què succeeix si l'usuari introdueix n = 0?
La condició inicial 2 <= 0 és falsa d'entrada; el bucle no s'executa cap cop i el resultat final manté el valor inicial de f, que és 1.

Preguntes tipus test

  1. Quina estructura iterativa garanteix sempre com a mínim una execució del seu bloc d'instruccions?
    • a) for
    • b) switch
    • c) while
    • d) do-while

    Resposta: d) do-while. do-while avalua la condició de continuïtat en acabar el cos del bucle, executant-se com a mínim un cop.

  2. Què succeeix si s'omet l'actualització del comptador dins del bloc d'un while?
    • a) El compilador dóna un error sintàctic
    • b) El bucle s'executa exactament un cop
    • c) El programa entra en un bucle infinit
    • d) El bucle no s'executa mai

    Resposta: c) El programa entra en un bucle infinit. Si la variable de control no varia, la condició de sortida mai s'arribarà a complir.

  3. Quin és el resultat canònic de calcular 0! en programació?
    • a) 1
    • b) -1
    • c) 0
    • d) Error de domini

    Resposta: a) 1. Per definició matemàtica i canònica, el factorial de 0 és 1.

Esquemes algorítmics — Recorregut de seqüències

Flashcards

Quin índex del vector correspon al caràcter 'd' mitjançant l'expressió c - 'a'?
Correspon a l'índex 3, ja que es calcula el desplaçament relatiu respecte a la lletra 'a' (posició 0).
Què passaria si en comptes de doble lectura només es fes un scanf al principi del cos del while?
El centinella es processaria com si fos una dada vàlida de la seqüència i es perdria el control sobre el tractament d'una seqüència buida.

Preguntes tipus test

  1. Quin és l'objectiu principal de l'esquema algorítmic de recorregut?
    • a) Aturar-se quan es compleix una condició
    • b) Processar tots els elements fins al centinella
    • c) Calcular únicament la mida de la seqüència
    • d) Eliminar els caràcters espai de l'entrada

    Resposta: b) Processar tots els elements fins al centinella. El recorregut tracta tots els elements de la seqüència fins a trobar la marca de finalització.

  2. On s'ha de col·locar la lectura avançada de la següent dada?
    • a) En la condició de la sentència while
    • b) Fora del bucle després del processat final
    • c) Just a l'inici del cos del bucle
    • d) Al final del bloc intern del bucle

    Resposta: d) Al final del bloc intern del bucle. La lectura avançada ha d'anar al final del cos del bucle per no sobreescriure l'element que cal tractar.

  3. Com s'evita la divisió entera calculant la mitjana amb variables suma i n enteres?
    • a) Executant un bucle do-while per arrodonir
    • b) Usant suma / (float)n en l'operació
    • c) Multiplicant suma per 1 abans de dividir
    • d) Assignant el resultat a una variable char

    Resposta: b) Usant suma / (float)n en l'operació. Forçar la conversió explícita (cast) d'un operand a float produeix un quocient real amb decimals.

Esquemes algorítmics — Cerca en seqüències i combinació d'esquemes

Flashcards

Quin paper té la variable booleana 'trobat' en la condició del bucle while?
Actua com a flag o senyalitzador d'aturada: mentre sigui 'false' indica que l'element no s'ha localitzat i permet continuar explorant la seqüència fins a la marca.
Per què no s'ha de llegir un element nou quan s'executa 'trobat = true'?
Perquè si es llegeix una nova dada se sobreescriuria el valor de l'element trobat que es vol processar o mostrar un cop acabat el bucle.

Preguntes tipus test

  1. Quina és la condició correcta de continuïtat en un bucle de cerca seqüencial amb marca?
    • a) trobat == false || element != MARCA
    • b) trobat == true || element == MARCA
    • c) trobat == true && element != MARCA
    • d) trobat == false && element != MARCA

    Resposta: d) trobat == false && element != MARCA. El bucle ha de continuar mentre no s'hagi trobat l'element i alhora no s'hagi arribat a la marca final.

  2. On s'ha d'ubicar la lectura del següent element dins d'un esquema de cerca?
    • a) A l'inici del bucle sempre
    • b) Fora del bucle while
    • c) Just després de trobat = true
    • d) Dins de la branca else

    Resposta: d) Dins de la branca else. Només s'avança seqüència si l'element actual no és el cercat, preservant l'element bo quan es troba.

  3. Què indica que la variable 'trobat' valgui 'false' en sortir del bucle de cerca?
    • a) Que hi ha hagut un error de compilació
    • b) Que l'element s'ha trobat al final
    • c) Que la seqüència era infinita
    • d) Que s'ha arribat a la marca sense èxit

    Resposta: d) Que s'ha arribat a la marca sense èxit. Si trobat roman en fals en sortir, vol dir que el bucle ha acabat per haver assolit la marca de fi.

Cadenes de caràcters — Vectors de caràcters i biblioteca string.h

Flashcards

Quina és la capacitat física que necessita un vector auxiliar si s'han de concatenar dues cadenes de mida útil màxima N cadascuna?
Necessita una mida física de com a mínim 2 · N + 1 caselles per poder allotjar la totalitat dels caràcters d'ambdues cadenes i el caràcter delimitador nul final.
Com implementa internament la funció strlen el càlcul del nombre de caràcters d'un string?
Mitjançant un esquema de recorregut amb un bucle que comença a l'índex 0 i incrementa un comptador fins a trobar el valor sentinella 'backslash 0'.

Preguntes tipus test

  1. Quina mida ha de tenir un vector char per desar un text de 20 caràcters?
    • a) Exactament 19 caselles
    • b) Com a mínim 21 caselles
    • c) Un total de 40 caselles
    • d) Exactament 20 caselles

    Resposta: b) Com a mínim 21 caselles. Cal reservar N + 1 caselles per allotjar els 20 caràcters útils i el caràcter nul '\0'.

  2. Per què no es posa & en llegir una cadena amb scanf("%s", nom)?
    • a) Perquè el nom de l'array conté la seva adreça
    • b) Perquè el format %s no admet adreces
    • c) Perquè nom és una variable de tipus enter
    • d) Perquè el compilador genera un error sintàctic

    Resposta: a) Perquè el nom de l'array conté la seva adreça. El nom d'un vector avalua directament a l'adreça de memòria del seu primer element.

  3. Què indica un valor retornat per strcmp(s1, s2) inferior a zero?
    • a) Que s1 té menys lletres que s2
    • b) Que s1 és anterior en ordre lexicogràfic
    • c) Que s1 i s2 són cadenes idèntiques
    • d) Que s1 conté caràcters numèrics negatius

    Resposta: b) Que s1 és anterior en ordre lexicogràfic. Un retorn negatiu assenyala que s1 precedeix s2 d'acord amb el codi ASCII dels seus caràcters.

Estructures multidimensionals — Matrius 2D, 3D i taules de cadenes

Flashcards

Com s'ha de declarar una llista capaç d'allotjar 15 paraules de fins a 30 lletres útils cadascuna?
S'ha de declarar com 'char llista[15][31];', sumant una unitat a la segona dimensió per reservar espai per al caràcter nul de terminació '\0'.
Quin comportament tindrà l'algorisme de cerca del màxim si inicialitzem el valor inicial a 0 en una matriu amb valors {-8, -3, -12}?
Donarà com a resultat màxim el valor erroni 0, ja que cap element negatiu serà superior al valor inicial de comparació.

Preguntes tipus test

  1. Quin és el rang d'índexs per a una matriu declarada com float taula[4][6]?
    • a) Files 1..3 i columnes 1..5
    • b) Files 1..4 i columnes 1..6
    • c) Files 0..3 i columnes 0..5
    • d) Files 0..4 i columnes 0..6

    Resposta: c) Files 0..3 i columnes 0..5. En C els índexs comencen a 0 i acaben estrictament a dimensió - 1.

  2. A quina dimensió correspon el primer índex en una matriu m3[P][F][C]?
    • a) A la fila de la matriu
    • b) Al plànol de l'estructura
    • c) A la columna de la matriu
    • d) Al byte físic de memòria

    Resposta: b) Al plànol de l'estructura. El primer índex de m3 selecciona el plànol tridimensional d'elements.

  3. Per què es declara char ll[10][21] per desar 10 paraules de 20 caràcters?
    • a) Per deixar espai al salt de línia
    • b) Per compatibilitat amb l'operador scanf
    • c) Per allotjar el terminador nul '\0'
    • d) Per alinear la memòria a múltiples

    Resposta: c) Per allotjar el terminador nul '\0'. Tota cadena en C necessita una posició final addicional per allotjar el caràcter nul '\0'.

Modularitat i disseny funcional — Funcions, paràmetres i pas per referència

Flashcards

Com s'especifica sintàcticament un paràmetre formal per referència en C++?
Afegint el caràcter & entre el tipus de dada i el nom de la variable al perfil del paràmetre (per exemple, int &v1 ).
Quina dimensió és estrictament obligatòria en passar una matriu bidimensional a una funció?
La dimensió de les columnes (m[][N]), mentre que la primera dimensió (nombre de files) es pot deixar buida.

Preguntes tipus test

  1. Quina característica distingeix una acció d'una funció convencional?
    • a) Retorna void i no fa return
    • b) Requereix bucles for obligatoris
    • c) Només admet números enters
    • d) No accepta paràmetres formals

    Resposta: a) Retorna void i no fa return. Les accions es declaren amb retorn de tipus void per indicar que no retornen cap valor concret.

  2. Què ocorre en passar un enter ordinari (int x) per valor a un subprograma?
    • a) Es copia el valor a la pila
    • b) S'altera automàticament el valor a x
    • c) S'enllaça l'adreça de x
    • d) El compilador genera un error

    Resposta: a) Es copia el valor a la pila. El pas per valor fa una còpia independent que s'allotja a la pila i s'esborra en acabar la funció.

  3. Quin requisit sintàctic tenen els paràmetres de matrius bidimensionals?
    • a) Posar sempre el caràcter &
    • b) Fixar obligatòriament les columnes: m[][N]
    • c) Definir-les sempre com a char
    • d) Ometre sempre totes dues dimensions

    Resposta: b) Fixar obligatòriament les columnes: m[][N]. El compilador necessita conèixer la mida de les columnes m[][N] per poder calcular la memòria de cada fila.

I 0 flashcards i 7 preguntes més al document.

Text del document

APUNTS PROGRAMACIÓ I Grau en Enginyeria Informàtica Universitat de Lleida AprenAI 2026-2027 Apunts de Programació I en C/C++: compilació g++, bucles, esquemes de cerca i recorregut, cadenes string.h, matrius multidimensionals i pas per referència.

APREN.AI Índex 1 Fonaments — Entorn de desenvolupament, tipus bàsics i I/O Cicle de treball: edició, compilació i execució Tipus de dades primitius i espai de memòria Operadors aritmètics i mecanisme d'assignació Entrada i sortida estàndard i control de condicions crítiques 2 Estructures de control — Bucles i iteració bàsica Classificació de les estructures iteratives El bucle while: condició de continuïtat i actualització El bucle do-while i la validació d'entrades L'estructura for i el càlcul del factorial Generació i filtratge de seqüències numèriques Esquemes algorítmics 3 Recorregut de seqüències Concepte de seqüència i marca de fi Estructura formal del recorregut Filtratge i funcions de caràcters amb <ctype.h> Seqüències numèriques: càlcul de mitjanes i múltiples Taules de comptadors per agrupació de freqüències 4 Cerca en seqüències i combinació d'esquemes L'esquema fonamental de cerca seqüencial Tractament de seqüències buides i primer element Cerca de patrons elementals Composició i encadenament d'esquemes algorítmics 5 Cadenes de caràcters — Vectors de caràcters i biblioteca string.h Estructura en memòria i caràcter delimitador Entrada i sortida de cadenes amb I/O estàndard Funcions de la biblioteca string.h Algorismes manuals sobre cadenes 6 Estructures multidimensionals — Matrius 2D, 3D i taules de cadenes Estructures bidimensionals: declaració i indexació Processament de matrius 2D amb bucles niats Matrius tridimensionals: organització per plànols Taules de cadenes de caràcters i redirecció d'I/O 7 Modularitat i disseny funcional — Funcions, paràmetres i pas per referència Programació I en C/C++: Fonaments, Algorismes i Matrius 1 1.

Concepte de subprograma: funcions i accions 2. Sintaxi, prototips i cicle d'execució d'una funció 3. Mecanismes de pas de paràmetres: valor enfront de referència 4. Pas d'estructures de dades: vectors, matrius i cadenes 8 Formulari Compilació, I/O i tipus bàsics Estructures iteratives i esquemes algorítmics Cadenes de caràcters i estructures multidimensionals Modularitat i pas de paràmetres Errors típics Solucions de les preguntes de repàs Aquests apunts poden contenir errors o omissions. Són un material de suport i no substitueixen el temari oficial ni el professorat: contrasta la informació important.

Programació I en C/C++: Fonaments, Algorismes i Matrius 2 1 Fonaments — Entorn de desenvolupament, tipus bàsics i I/O EN ACABAR SABRÀS Compilar i executar codi font en C/C++ des del terminal emprant g++ amb els paràmetres -o i - Wall. Distingir la representació interna dels tipus primitius en memòria i els seus rangs numèrics associats. Formatar l'entrada i la sortida estàndard mitjançant printf i scanf aplicant els especificadors de base adequats. Prevenir errors en temps d'execució derivats de divisions per zero i omissions de l'operador adreça. PENSA-HI ABANS DE LLEGIR 1 Per què un programa en C/C++ pot fallar immediatament en llegir un número si només oblidem posar un símbol '&'?

El desenvolupament de programari en C/C++ requereix transformar instruccions comprensibles per a humans en instruccions directament executables pel maquinari mitjançant un conjunt d'eines a la terminal.

ESQUEMA Estructura general de Programació I en C/C++ Cicle de treball: edició, compilació i execució La construcció d'un programa segueix un flux lineal de tres passos ben diferenciats: Fonaments i I/O Compilació g++, tipus primitius i format Estructures de control Bucles while, do-while i for Esquemes algorítmics Tècniques de cerca i de recorregut Estructures de dades Vectors, cadenes i matrius 2D/3D Modularitat Disseny de funcions i paràmetres Programació I en C/C++: Fonaments, Algorismes i Matrius 3 Esquema de l'anatomia d'un fitxer font amb nom i extensió. COMPROVA-HO 2 Quina funció té el paràmetre -Wall en compilar un programa amb g++?

Tipus de dades primitius i espai de memòria Les variables reserven cel·les de memòria amb una mida i codificació específiques segons la seva naturalesa bàsica: int: Representa valors enters tant positius com negatius. float i double: Permeten gestionar nombres reals amb part fraccionària i representacions en notació científica mitjançant exponent (per exemple, 32,7, o ). char: Emmagatzema caràcters individuals. bool: Guarda estats booleans de certesa o falsedat. Edició del fitxer font: Es redacta el codi mitjançant un editor de text com gedit . Per obrir l'editor i continuar utilitzant la línia d'ordres sense bloquejar el terminal, s'afegeix un ampersand al final: gedit nomArxiu.cpp & .

El fitxer resultant consta de dues parts principals: el nom base i l'extensió de codi. 1 Compilació i enllaç: El compilador és l'eina encarregada de traduir les instruccions en text a codi màquina binari (format per zeros i uns). El compilador estàndard g++ pot realitzar aquest procés en etapes separades (amb -c per obtenir l'objecte .o i després generar el binari) o en una sola línia mitjançant la comanda canònica: g++ nomArxiu.cpp -o nomExecutable -Wall L'opció -o especifica el nom del fitxer de sortida binari, mentre que el modificador -Wall activa tots els avisos (warnings) del compilador per detectar possibles defectes de codi durant la traducció.

1 Execució del binari: Un cop generat l'executable a la màquina, es posa en marxa des del terminal indicant la seva ruta relativa mitjançant ./nomExecutable . 2 45,04E 7 5,3E5 Programació I en C/C++: Fonaments, Algorismes i Matrius 4 Diagrama de distribució de bits per al signe i magnitud numèrica. Quan es treballa amb una representació d'enters en 32 bits, l'arquitectura reserva 1 bit de major pes per al signe numèric i destina els 31 bits restants a quantificar el valor absolut.

Aquesta codificació estableix l'interval útil de representació: Tipus Format de dades Rang / Format d'escriptura int Enter amb signe (32 bits) fins a float / double Reals en coma flotant Notació decimal o exponencial ( E / e ) char Caràcter individual Símbol alfanumèric codificat bool Booleà Veritable o fals Operadors aritmètics i mecanisme d'assignació C/C++ ofereix cinc operadors aritmètics fonamentals per a enters: suma ( + ), resta ( - ), multiplicació ( * ), divisió entera ( / ) i l'operador mòdul ( % ), que calcula directament el residu de la divisió sencera. Per exemple, en dividir el quocient és 3 i el mòdul avalua a 1.

L'assignació d'un valor mitjançant l'operador = és una ordre directa que opera en dos passos consecutius: COMPROVA-HO 3 Quin és el resultat numèric de realitzar les operacions 17 / 5 i 17 % 5 amb dades enteres? Entrada i sortida estàndard i control de condicions crítiques La biblioteca de capçalera <stdio.h> (Standard Input Output) proporciona les rutines fonamentals d'interacció amb el terminal: printf : Escriu dades amb format per pantalla. Per mostrar nombres reals, s'utilitza %f per a sortida decimal estàndard, %E per a notació exponencial o %G per delegar en el compilador la selecció del format més compacte. scanf : Llegeix dades del flux d'entrada estàndard i les diposita en memòria.

Per a variables escalars cal afegir l'operador adreça & davant del nom de la variable per passar la seva posició de [ 2 , 2 31 31 1] 231 2 31 1 7/2 7 mod 2 Es calcula el resultat final de l'expressió situada a la dreta del símbol d'assignació. 1 El valor obtingut s'emmagatzema a l'espai de memòria de la variable assignada a l'esquerra. 2 Programació I en C/C++: Fonaments, Algorismes i Matrius 5 memòria. En canvi, en llegir cadenes amb scanf("%s", cad) no s'utilitza & perquè l'identificador d'un vector referencia directament la seva adreça d'inici en memòria.

Especificador Funció i base numèrica Exemple d'ús %d o %i Enter en base decimal (base 10) printf("%d", valor); %o Enter en base octal (base 8) printf("%o", valor); %X Enter en base hexadecimal majúscula (base 16) printf("%X", valor); %f Nombre real en coma flotant printf("%f", real); %c Caràcter simple printf("%c", lletra); L'esquelet mínim d'un programa vàlid consta d'una funció d'entrada main() que retorna un enter ( return (0); ) per assenyalar una finalització correcta al sistema operatiu.

Programació I en C/C++: Fonaments, Algorismes i Matrius 6 EXEMPLE Llegir dos enters des del teclat, calcular les seves operacions bàsiques i protegir la divisió d'un divisor nul: #include <stdio.h> int main() { int x, y; int s, d, p, q, r; printf("Introdueix un valor enter: "); scanf("%i", &x); printf("Introdueix un valor enter: "); scanf("%i", &y); s = x + y; d = x - y; p = x * y; printf("%d + %d = %d ", x, y, s); printf("%d - %d = %d ", x, y, d); printf("%d * %d = %d ", x, y, p); if (y != 0) { q = x / y; r = x % y; printf("%d / %d = %d ", x, y, q); printf("%d %% %d = %d ", x, y, r); } else { printf("La divisió i el mòdul no es poden realitzar perquè no es pot dividir per 0 "); } return 0; } ERROR FREQÜENT Oblidar l'operador adreça & quan es llegeix una variable escalar amb scanf("%i", &x) .

Si s'escriu scanf("%i", x) , la funció interpreta el contingut actual de la variable com si fos una posició de memòria, provocant una fallada de segmentació (segmentation fault) immediata en temps d'execució. COMPROVA-HO 4 Per què és imprescindible avaluar y != 0 abans de calcular x / y o x % y? \n \n \n \n \n \n \n \n Programació I en C/C++: Fonaments, Algorismes i Matrius 7 IDEES CLAU La comanda estàndard de compilació a terminal és <code>g++ nomArxiu.cpp -o nomExecutable -Wall</code>. El tipus <code>int</code> de 32 bits reserva 1 bit per al signe i 31 bits de valor numèric, abastant des de fins a .

L'assignació d'un valor avalua primer l'expressió dreta i després transfereix el resultat a la cel·la de memòria de la variable esquerra. A <code>scanf</code> cal anteposar <code>&</code> en variables escalars per passar-ne l'adreça física, mentre que a cadenes no s'utilitza perquè el vector apunta ja al seu inici. Les operacions de divisió sencera (<code>/</code>) i residu (<code>%</code>) requereixen comprovar amb una condició que el divisor no sigui zero. COMPROVA EL QUE HAS APRÈS 5. Quin especificador de format cal emprar a printf per visualitzar un enter en base hexadecimal majúscula? 6.

Quina diferència d'ús existeix entre l'operador adreça & en llegir un int enfront de llegir una cadena de caràcters? Test Encercla la resposta correcta. Les solucions són al final. 7. Quin flag activa la visualització de tots els avisos durant la compilació amb g++? 8. Quants bits es destinen al valor numèric en un int convencional de 32 bits? 9. Quin especificador de format mostra un enter en base octal amb printf? 10. Què ocorre si s'omet l'operador & en llegir una variable enter amb scanf?

231 2 31 1 -g a) -o b) -Wall c) -c d) 31 bits a) 32 bits b) 16 bits c) 30 bits d) %d a) %f b) %X c) %o d) Produeix un error de segmentació a) Converteix el valor a octal b) Retorna sempre el valor zero c) Compila i funciona igualment d) Programació I en C/C++: Fonaments, Algorismes i Matrius 8 2 Estructures de control — Bucles i iteració bàsica EN ACABAR SABRÀS Distingir el funcionament i cas d'ús de les estructures iteratives while, do-while i for Implementar mecanismes de validació d'entrades mitjançant bucles do-while Construir acumuladors i comptadors per a calcular operacions com el factorial d'un nombre PENSA-HI ABANS DE LLEGIR 11 Per què no té sentit validar que l'usuari posi un número positiu fent servir un bucle for?

Classificació de les estructures iteratives Les estructures iteratives o bucles permeten executar un bloc d'instruccions de manera repetida mentre es compleixi una condició lògica determinada. El llenguatge C/C++ ofereix tres estructures iteratives bàsiques: while , do-while i for . L'elecció de l'estructura adequada depèn de si coneixem per endavant el nombre de repeticions i de si el cos s'ha d'executar com a mínim un cop.

Estructura Avaluació de la condició Execució mínima Cas d'ús habitual while Abans d'entrar al cos (precondició) 0 vegades Nombre desconegut d'iteracions segons l'estat do- while Després d'executar el cos (postcondició) 1 vegada Filtratge i validació d'entrades per teclat for Abans d'entrar al cos (precondició) 0 vegades Recomanat amb rangs coneguts o comptadors Programació I en C/C++: Fonaments, Algorismes i Matrius 9 PROCÉS Flux de decisions per a triar l'estructura iterativa El bucle while: condició de continuïtat i actualització L'estructura while avalua la seva expressió lògica abans d'iniciar cada cicle.

Si l'expressió resulta ser falsa en el primer intent, el bloc interior no s'executarà cap vegada. Per a controlar el progrés del bucle, s'utilitza una variable anomenada variable de control o comptador, la qual ha de canviar el seu estat en cada iteració. Considerem el cas de mostrar una salutació repetida cops: int n; scanf("%d", &n); // Enfocament decreixent while (n > 0) { printf("Bon dia! "); n = n - 1; // o n--; } // Enfocament creixent amb comptador auxiliar int i = 0; while (i < n) { printf("Bon dia! "); i++; // o i = i + 1; } Analitzar el problema Determinar iteracions i necessitat d'execució mínima 1 Cal executar mínim un cop?

Com ara llegir dades i comprovar la validesa 2 Emprar do-while Avalua la condició de repetició al final 3 Nombre conegut d'iteracions? Comptador des d'un inici fins a un final 4 Emprar for o while for per condensar o while amb condició prèvia 5 n \n \n Programació I en C/C++: Fonaments, Algorismes i Matrius 10 ERROR FREQÜENT Oblidar l'actualització de la variable de control (com i++ o n-- ) dins del cos del bucle és un error típic d'examen. Sense aquest pas, la condició mai canviarà de valor i el programa caurà en un bucle infinit, blocant l'execució. COMPROVA-HO 12 Què passa si a l'enfocament creixent n val 0 des de l'inici?

El bucle do-while i la validació d'entrades A diferència de while , l'estructura do-while avalua la seva expressió al final del cicle. Això assegura que el cos s'executi sempre com a mínim una vegada. Aquesta propietat la converteix en l'eina ideal per a la validació d'entrades, on cal sol·licitar una dada a l'usuari i repetir la petició si el valor introduït és incorrecte.

Per exemple, si un programa exigeix treballar exclusivament amb valors naturals ( ), el filtre de seguretat s'implementa repetint la captura mentre l'entrada sigui estrictament menor que zero: int n; do { printf("Introdueix un enter major o igual que 0: "); scanf("%d", &n); } while (n < 0); Observeu que la condició del while final expressa l'estat invàlid o condició de repetició: si es compleix , es demana una altra vegada.

L'estructura for i el càlcul del factorial La sentència for condensa en una sola línia els tres elements indispensables per a la iteració: la inicialització, la condició de continuïtat i l'actualització: for (inicialització; condició; actualització) { // accions a repetir } Un problema matemàtic clàssic és el càlcul del factorial d'un nombre natural ( ), definit de manera general com: Aquest càlcul requereix una variable auxiliar anomenada acumulador, que emmagatzema el producte consecutiu i que cal inicialitzar a l'element neutre del producte, és a dir, . Per convenció canònica matemàtica, 0! = 1 i 1! = 1.

Podem resoldre aquest càlcul tant en sentit decreixent amb while com en sentit creixent amb for : n 0 \n n < 0 n! n!

= n (n 1) (n 2) 1 f = 1 Programació I en C/C++: Fonaments, Algorismes i Matrius 11 // Versió decreixent amb while int f = 1; int i = n; // variable auxiliar per a no modificar el valor original n while (i > 1) { f = f * i; i--; } // Versió creixent amb for int f = 1; for (int i = 2; i <= n; i++) { f = f * i; } Per a comprendre la variació de l'acumulador i del comptador, analitzem la traça d'execució de la versió creixent amb : Iteració Valor de i Condició ( i <= 4 ) Operació sobre l'acumulador Valor resultant de f Inicialització 2 Certa f = 1 * 2 2 1 3 Certa f = 2 * 3 6 2 4 Certa f = 6 * 4 24 Sortida 5 Falsa (5 <= 4 és fals) - 24 COMPROVA-HO 13 Per què la variable de control s'inicia en i = 2 i no pas en 1 en calcular el factorial?

Generació i filtratge de seqüències numèriques Els bucles també s'utilitzen per a generar seqüències que satisfan un cert patró matemàtic. Imaginem que volem mostrar tots els nombres enters parells estrictament menors que un nombre ( ), començant pel 0.

En lloc de fer un salt d'unitat en unitat comprovant la paritat en cadascun amb l'operador mòdul (vegeu «Fonaments — Entorn de desenvolupament, tipus bàsics i I/O»), podem augmentar el comptador de dos en dos directament ( ): n = 4 n n 0 i = i + 2 Programació I en C/C++: Fonaments, Algorismes i Matrius 12 int n; do { printf("Introdueix valor >= 0: "); scanf("%d", &n); } while (n < 0); int i = 0; while (i < n) { printf("%d ", i); i = i + 2; } L'efecte segons el valor de és el següent: Si , la sortida produïda és 0 2 4 . Si , la sortida produïda és 0 2 (el 4 queda exclòs per ser una desigualtat estricta i < n ). Si , la sortida produïda és 0 2 4 . Si , no s'imprimeix cap element.

Si o , només s'imprimeix 0 . COMPROVA-HO 14 Quina sortida genera el programa dels parells si l'usuari introdueix un 2? IDEES CLAU L'estructura <code>while</code> avalua la condició abans d'executar el cos, permetent 0 iteracions si la condició és falsa d'entrada. L'estructura <code>do-while</code> avalua la condició al final, garantint almenys una execució completa; és la forma estàndard de validar entrades. El bucle <code>for</code> compacta la inicialització, la condició i l'actualització de la variable de control. Oblidar l'actualització de la variable de control dins del cos d'un bucle provoca bucles infinits.

Canònicament, tant com donen com a resultat 1, valor que coincideix amb la inicialització de l'acumulador multiplicatiu. COMPROVA EL QUE HAS APRÈS 15. Per quina raó tècnica s'utilitza do-while per a validar la lectura de valors per teclat en comptes de while? 16. En el càlcul del factorial amb for, què succeeix si l'usuari introdueix n = 0? \n \n n n = 5 n = 4 n = 6 n = 0 n = 1 n = 2 0! 1! Programació I en C/C++: Fonaments, Algorismes i Matrius 13 Test Encercla la resposta correcta. Les solucions són al final. 17. Quina estructura iterativa garanteix sempre com a mínim una execució del seu bloc d'instruccions? 18. Què succeeix si s'omet l'actualització del comptador dins del bloc d'un while?

19. Quin és el resultat canònic de calcular 0! en programació? 20. Per a n = 4, quina seqüència de nombres parells menors que n genera la condició i < n iniciant a 0? for a) switch b) while c) do-while d) El compilador dóna un error sintàctic a) El bucle s'executa exactament un cop b) El programa entra en un bucle infinit c) El bucle no s'executa mai d) 1 a) -1 b) 0 c) Error de domini d) 0, 2, 4 a) 2, 4 b) 0, 2 c) 0 d) Programació I en C/C++: Fonaments, Algorismes i Matrius 14 3 Recorregut de seqüències EN ACABAR SABRÀS Implementar l'esquema de recorregut sobre seqüències aplicant el mecanisme de doble lectura.

Filtrar i comptabilitzar caràcters fent servir les funcions de la biblioteca ctype.h. Evitar el truncament per divisió entera en el càlcul de mitjanes aritmètiques mitjançant casting. Construir taules de freqüència indexades directament mitjançant aritmètica de caràcters. PENSA-HI ABANS DE LLEGIR 21 Com podem saber quan acaba una seqüència d'elements que l'usuari introdueix per teclat si no sabem prèviament quantes dades escriurà? Els algorismes que processen conjunts de dades que arriben de manera consecutiva des d'un canal d'entrada s'organitzen mitjançant patrons estructurats.

ESQUEMA Estructures per al tractament de seqüències Esquemes algorítmics 3 Recorregut de seqüències 4 Cerca en seqüències i combinació d'esquemes Esquemes algorítmics Patrons per a col·leccions de dades Recorregut Processament complet de la seqüència Seqüències amb centinella Finalització per marca Taules de freqüència Comptadors indexats per caràcters Cerca Localització amb possible sortida prematura Programació I en C/C++: Fonaments, Algorismes i Matrius 15 Concepte de seqüència i marca de fi Una seqüència és una successió finita d'elements que comparteixen el mateix tipus bàsic i que s'obtenen un darrere l'altre. La quantitat d'elements no es coneix a priori mitjançant un comptador fix.

Per determinar la finalització de les dades, la seqüència incorpora un element distintiu anomenat marca de fi o centinella. DEFINICIÓ El centinella és un valor especial situat al final de la seqüència que delimita el tancament de l'entrada i no forma part de les dades útils que s'han de processar. Alguns exemples típics són: Un flux de caràcters que es tanca en trobar el punt ( '.' ). Una sèrie d'enters positius o no nuls delimitada pel valor 0. Una seqüència de temperatures que finalitza quan apareix el primer nombre negatiu. En l'esquema algorítmic de recorregut, l'objectiu fonamental consisteix a processar tots els elements vàlids des de l'inici fins a assolir el centinella.

A diferència de l'esquema de cerca (vegeu «Esquemes algorítmics — Cerca en seqüències i combinació d'esquemes»), el recorregut no s'atura abans de la marca sota cap condició de troballa. COMPROVA-HO 22 Quina funció té la marca de fi o centinella en una seqüència d'elements? Estructura formal del recorregut Per garantir que cap dada quedi sense analitzar i que el centinella mai es processi per error, l'algorisme necessita una regla estricta: la doble lectura d'elements. Programació I en C/C++: Fonaments, Algorismes i Matrius 16 Esquema formal del bucle de recorregut amb doble lectura. Inicialització: establir els acumuladors o comptadors a zero abans d'iniciar el processament.

1 Primera lectura: capturar el primer valor fora del cicle per comprovar immediatament si la seqüència és buida. 2 Condició de control: avaluar en el bucle while (vegeu «Estructures de control — Bucles i iteració bàsica») si l'element actual és diferent de la marca de fi. 3 Tractament i lectura avançada: dins del bucle, processar la dada llegida i, just en l'última instrucció abans de tancar el bloc, llegir el següent element. 4 Processament final: presentar els resultats calculats o tractar les dades agregades després de sortir del bucle.

5 Programació I en C/C++: Fonaments, Algorismes i Matrius 17 PROCÉS Flux d'execució d'un recorregut amb centinella Aquesta distribució impedeix que la marca final modifiqui els càlculs i evita tractar valors indefinits si el canal s'obre buit des del primer instant. COMPROVA-HO 23 Per què cal llegir un element tant abans d'entrar al bucle com al final de cada iteració? Filtratge i funcions de caràcters amb <ctype.h> Quan la seqüència conté caràcters ( char ), sovint es volen comptabilitzar categories específiques de text.

La biblioteca estàndard <ctype.h> ofereix eines que simplifiquen aquestes comprovacions: Funció Condició que avalua Retorn islower(c) Comprova si el caràcter c és una lletra minúscula (de 'a' a 'z' ) Diferent de zero si és cert, zero si és fals isupper(c) Comprova si el caràcter c és una lletra majúscula (de 'A' a 'Z' ) Diferent de zero si és cert, zero si és fals tolower(c) Converteix el caràcter c a minúscula si és majúscula Caràcter convertit o el mateix c toupper(c) Converteix el caràcter c a majúscula si és minúscula Caràcter convertit o el mateix c Inicialització Posar a zero comptadors i acumuladors 1 Lectura inicial Obtenció del primer element 2 Comprovació centinella Verificar si l'element és distint de la marca 3 Processament de l'element Aplicar operacions, filtres o càlculs 4 Lectura avançada Llegir el següent valor abans de repetir 5 Processat final Presentar o consolidar resultats acumulats 6 Programació I en C/C++: Fonaments, Algorismes i Matrius 18 L'aplicació d'aquestes rutines permet avaluar textos acabats en punt per determinar, per exemple, si predominen les majúscules o les minúscules: EXEMPLE Comptabilització comparativa de caràcters acabats en '.' utilitzant scanf (vegeu «Fonaments — Entorn de desenvolupament, tipus bàsics i I/O»): int nMaj = 0, nMin = 0; char ele; printf("Introduir text acabat en .:"); scanf("%c", &ele); while (ele != '.') { if (islower(ele)) { nMin++; } else if (isupper(ele)) { nMaj++; } scanf("%c", &ele); } En acabar el bucle, una estructura condicional avalua si nMaj > nMin , nMaj < nMin o si ambdós comptadors són iguals.

COMPROVA-HO 24 Què passa si s'introdueix el text "." en el codi anterior? Seqüències numèriques: càlcul de mitjanes i múltiples En el processament de seqüències d'enters o reals amb centinella es presenten dos problemes habituals: el filtratge de valors mitjançant l'operador mòdul ( % ) i el càlcul de mitjanes aritmètiques acumulant valors en una variable acumulador (vegeu «Estructures de control — Bucles i iteració bàsica»). Per comptar múltiples d'un nombre com el 5 en una seqüència acabada en 0, s'insereix la condició if (ele % 5 == 0) dins del tractament del bucle.

En canvi, si es processa una seqüència de temperatures positives o nul·les delimitades pel primer valor negatiu (condició de continuïtat ele >= 0.0 ), cal calcular la suma total i el nombre total d'elements. ERROR FREQÜENT Si la suma i el comptador d'elements s'han definit com a enters ( int ), l'operació suma / n executa una divisió entera que descarta la part decimal del resultat. Per evitar aquesta pèrdua de precisió, cal forçar una conversió explícita de tipus (type casting) a real: (float)suma / n o bé suma / (float)n .

Programació I en C/C++: Fonaments, Algorismes i Matrius 19 COMPROVA-HO 25 Quina diferència produeix escriure (float)suma / n respecte a suma / n si ambdues són variables enteres? Taules de comptadors per agrupació de freqüències Quan cal comptar quantes vegades apareix cadascuna de les lletres minúscules d'un text acabat en punt, declarar 26 variables independents és inviable. La solució consisteix a utilitzar un vector d'enters de mida fixa que funcioni com a taula directa de comptadors. Aprofitant la codificació seqüencial dels caràcters, la quantitat total de lletres es defineix com a constant: El vector s'inicialitza a zero mitjançant int rlletra[N] = {0}; .

Cada caràcter minúscula llegit es transforma directament en una posició vàlida de l'array mitjançant l'aritmètica de caràcters: PER RECORDAR-HO L'expressió 'c - 'a'' converteix el caràcter 'a' a l'índex 0, 'b' a l'índex 1, i així successivament fins a 'z' , que correspon a l'índex 25. Aquesta correspondència estalvia cadenes d'estructures condicionals. Dins del bucle de recorregut, cada vegada que islower(c) és cert, s'executa la instrucció d'increment indexada: rlletra[c - 'a']++; Un cop assolit el punt final, un bucle for (vegeu «Estructures de control — Bucles i iteració bàsica») recorre les posicions de 0 a .

Per recuperar la lletra original associada a cada cel·la es realitza l'operació inversa: 'a' + i . IDEES CLAU Una seqüència és una successió finita de dades del mateix tipus finalitzada per una marca de fi o centinella. L'esquema de recorregut processa absolutament tots els elements de la seqüència sense fer cap aturada prematura. La doble lectura (abans d'entrar al bucle i al final de cada iteració) garanteix no processar el centinella i gestionar correctament seqüències buides. Per evitar el truncament propi de la divisió entera en el càlcul de mitjanes, cal aplicar un motlle o conversió de tipus explícita a float: .

L'aritmètica de caràcters mitjançant permet indexar directament una taula de freqüències de mida . N = ( z a ) + 1 N 1 suma/(float)n c a ( z a ) + 1 Programació I en C/C++: Fonaments, Algorismes i Matrius 20 COMPROVA EL QUE HAS APRÈS 26. Quin índex del vector correspon al caràcter 'd' mitjançant l'expressió c - 'a'? 27. Què passaria si en comptes de doble lectura només es fes un scanf al principi del cos del while? ESQUEMES ALGORÍTMICS 4 Cerca en seqüències i combinació d'esquemes EN ACABAR SABRÀS Formular correctament l'esquema de cerca seqüencial utilitzant variables booleanes de control. Distingir i gestionar adequadament el cas de seqüència buida respecte a una cerca fallida.

Combinar esquemes de cerca i de recorregut per resoldre problemes compostos de processament de dades. PENSA-HI ABANS DE LLEGIR 28 Per què en un algorisme de cerca no s'ha d'utilitzar un bucle de recorregut incondicional fins al final de la seqüència? L'esquema fonamental de cerca seqüencial A diferència del recorregut complet (vegeu «Esquemes algorítmics — Recorregut de seqüències»), l'objectiu d'un esquema de cerca és localitzar el primer element d'una seqüència que satisfaci una propietat determinada i aturar el procés immediatament sense inspeccionar innecessàriament la resta de les dades.

Per controlar aquesta execució s'empra una variable d'estat booleana, habitualment anomenada trobat, inicialitzada a fals ( false ). La iteració es manté activa mitjançant un bucle while (vegeu «Estructures de control — Bucles i iteració bàsica») condicionat per una expressió lògica composta: cal que no s'hagi assolit l'objectiu i que alhora no s'hagi arribat al final de les dades. trobat == false && element != MARCA Dins del cos del bucle, s'avalua la condició de cerca sobre l'element vigent. Si compleix el criteri cercat, la variable booleana canvia el seu valor a cert ( trobat = true; ), fet que provocarà la sortida a la següent avaluació de la capçalera sense consumir cap més dada.

Si no el compleix, s'avança cap al següent element mitjançant una nova lectura (vegeu «Fonaments — Entorn de desenvolupament, tipus bàsics i I/O»). Programació I en C/C++: Fonaments, Algorismes i Matrius 21 Esquema algorítmic de cerca seqüencial i gestió de seqüències buides. Un cop finalitzat el bucle, s'ha de distingir la causa de la sortida comprovant el valor final de trobat mitjançant una estructura condicional. Si és true , l'element conté el valor objectiu i es processa; si és false , significa que s'ha consumit tota la seqüència fins a la marca de fi sense èxit.

DEFINICIÓ L'avaluació de curtcircuit en C/C++ garanteix que a l'expressió trobat == false && element != MARCA , si trobat és cert, la segona part mai no s'avalua, evitant lectures o comparacions incorrectes sobre elements ja processats. COMPROVA-HO 29 Quina és la funció de col·locar la lectura del següent element exclusivament dins de la branca 'else' en l'esquema de cerca? Tractament de seqüències buides i primer element Una seqüència es considera buida si la primera lectura coincideix directament amb el valor sentinella o marca de fi (vegeu «Esquemes algorítmics — Recorregut de seqüències»).

Quan cal conservar el contingut del primer element per a comparacions o processos posteriors (denotat sovint com pele , primer element), és imprescindible comprovar immediatament si es tracta de la marca abans d'iniciar la cerca pròpiament dita.

Programació I en C/C++: Fonaments, Algorismes i Matrius 22 Situació Estat inicial Flux d'execució Resultat obtingut Seqüència buida primer == MARCA Entra a la branca d'error/avís immediatament Es notifica seqüència buida sense entrar al bucle Element trobat al principi primer == cercat Itera 1 cop, trobat passa a true Èxit immediat sense lectures posteriors Element a l'interior primer != cercat Avança pel else consumint elements Èxit en la posició exacta de coincidència Element inexistent Cap element coincideix Consumeix fins a element == MARCA trobat == false , missatge de no existència Quan la seqüència conté almenys una dada vàlida, aquest primer valor es pot guardar i, a continuació, es procedeix a l'avaluació o a la lectura del segon element segons l'objectiu del problema algorítmic.

ERROR FREQÜENT Confondre l'operador d'assignació ( = ) amb el d'igualtat ( == ) en inicialitzar o avaluar la condició, com escriure trobat == false; com a sentència d'inicialització en comptes de trobat = false; , fet que deixa la variable sense inicialitzar amb valors indeterminats en memòria. COMPROVA-HO 30 Què passa si una seqüència comença directament amb la marca de final i no s'aïlla prèviament el cas de seqüència buida? Cerca de patrons elementals L'aplicació d'aquest esquema permet detectar patrons específics dins de fluxos de dades heterogenis.

Considerem dos escenaris comuns de cerca directa: Detecció del primer dígit en un text: Es llegeixen caràcters fins a la marca de fi de text (per exemple el punt '.' ). Fent ús de la funció isdigit() (vegeu «Esquemes algorítmics — Recorregut de seqüències»), si el caràcter és numèric, es fixa trobat = true; . En cas contrari, es llegeix el següent caràcter. Primer senar superior a 20: En una seqüència d'enters finalitzada per un valor negatiu (la marca), la condició del predicat avalua simultàniament la paritat i la magnitud mitjançant l'expressió numeros % 2 != 0 && numeros > 20. Si cap element compleix ambdues condicions abans d'arribar al negatiu, l'estat final serà de cerca fallida.

Programació I en C/C++: Fonaments, Algorismes i Matrius 23 PROCÉS Flux de decisions en la cerca seqüencial PER RECORDAR-HO En una cerca, el bucle s'atura pel primer que passi: trobar l'element (èxit) o esgotar les dades arribant a la marca (fracàs). Si la variable trobat s'actualitza a true , MAI s'ha de fer una lectura addicional en aquella mateixa iteració.

Composició i encadenament d'esquemes algorítmics En problemes complexos, els esquemes bàsics no actuen de forma aïllada, sinó que es combinen de dues maneres fonamentals: PROCÉS Encadenament de cerca i recorregut 1 Cerca del patró Localitza el primer element vàlid de referència 2 Validació d'èxit Comprova si trobat == true abans de continuar 3 Inicialització de recompte Fixa acumuladors i llegeix següent dada 4 Recorregut complet Itera fins a la marca processant coincidències Inicialització trobat = false i primera lectura de dada 1 Comprovació de bucle Avalua trobat == false && element != MARCA 2 Avaluació de condició Comprova si element compleix el criteri cercat 3 Èxit o Avanç Si compleix: trobat = true; sinó: llegeix següent 4 Post-processament Discrimina resultat segons estat de trobat 5 Cerca imbricada amb acumulació: Un únic bucle de cerca incorpora acumuladors o comptadors (vegeu «Estructures de control — Bucles i iteració bàsica») a la branca else .

Per exemple, sumar tots els valors parells que apareixen abans de localitzar el primer senar superior a 20. Si l'element no és el senar cercat, s'aprofita abans de la següent lectura per sumar-lo si és parell. 1 Cerca prèvia que condiciona un recorregut: S'executa primer un esquema de cerca per identificar una referència inicial o patró, i si la cerca té èxit ( trobat == true ), s'inicia tot seguit un esquema de recorregut sobre la resta de la seqüència.

2 Programació I en C/C++: Fonaments, Algorismes i Matrius 24 Aquest segon model és habitual en tractament de textos o seqüències numèriques relatives: Comptatge de repeticions del primer caràcter alfabètic: Una primera cerca localitza el primer caràcter que compleix isalpha() (ignorant espais o símbols inicials) i l'emmagatzema a plletra . Si existeix, s'inicia el recorregut fins al punt final ( '.' ) comptant les ocurrències de dita lletra, normalitzant majúscules i minúscules amb tolower() .

Cerca de múltiples del primer enter: Es guarda el valor del primer element de la seqüència ( pele ) un cop verificat que no és buida, i després s'executa una cerca sobre els elements posteriors per trobar el primer múltiple mitjançant la comprovació ele % pele == 0 . COMPROVA-HO 31 Per què en encadenar una cerca i un recorregut cal comptar inicialment 'r = 1' en l'exemple de les lletres? IDEES CLAU L'esquema de cerca atura la iteració tan bon punt es troba el primer element que compleix la condició o en arribar a la marca de fi. La condició de permanència al bucle és invariablement .

L'avanç de seqüència mitjançant la lectura del següent element s'ha d'ubicar exclusivament dins de la branca <code>else</code>. Després del bucle, el valor booleà de <code>trobat</code> permet discriminar si l'element objectiu s'ha localitzat o no. Els esquemes es poden combinar integrant acumulacions a la branca <code>else</code> o executant un recorregut posterior guiat pel resultat d'una cerca prèvia. COMPROVA EL QUE HAS APRÈS 32. Quin paper té la variable booleana 'trobat' en la condició del bucle while? 33. Per què no s'ha de llegir un element nou quan s'executa 'trobat = true'? Test Encercla la resposta correcta. Les solucions són al final. 34.

Quin és l'objectiu principal de l'esquema algorítmic de recorregut? trobat == false && element = MARCA Aturar-se quan es compleix una condició a) Processar tots els elements fins al centinella b) Calcular únicament la mida de la seqüència c) Eliminar els caràcters espai de l'entrada d) Programació I en C/C++: Fonaments, Algorismes i Matrius 25 35. On s'ha de col·locar la lectura avançada de la següent dada? 36. Com s'evita la divisió entera calculant la mitjana amb variables suma i n enteres? 37. Quina expressió permet indexar un vector de freqüències per al caràcter minúscula c? 38. Quina és la condició correcta de continuïtat en un bucle de cerca seqüencial amb marca? 39.

On s'ha d'ubicar la lectura del següent element dins d'un esquema de cerca? 40. Què indica que la variable 'trobat' valgui 'false' en sortir del bucle de cerca? 41. En encadenar cerca i recorregut sobre caràcters, quin és el rol de la cerca prèvia?

En la condició de la sentència while a) Fora del bucle després del processat final b) Just a l'inici del cos del bucle c) Al final del bloc intern del bucle d) Executant un bucle do-while per arrodonir a) Usant suma / (float)n en l'operació b) Multiplicant suma per 1 abans de dividir c) Assignant el resultat a una variable char d) c % 26 a) c - 'a' b) 'z' - 'a' c) c + 'z' d) trobat == false "" element != MARCA a) trobat == true "" element == MARCA b) trobat == true && element != MARCA c) trobat == false && element != MARCA d) A l'inici del bucle sempre a) Fora del bucle while b) Just després de trobat = true c) Dins de la branca else d) Que hi ha hagut un error de compilació a) Que l'element s'ha trobat al final b) Que la seqüència era infinita c) Que s'ha arribat a la marca sense èxit d) Localitzar el patró que guia el recorregut a) Invertir l'ordre de la seqüència b) Comptar tots els caràcters c) Eliminar els caràcters repetits d) Programació I en C/C++: Fonaments, Algorismes i Matrius 26 5 Cadenes de caràcters — Vectors de caràcters i biblioteca string.h EN ACABAR SABRÀS Distingir la dimensió física necessària (N + 1) de la mida lògica d'un string delimitat per '\0'.

Utilitzar amb precisió les funcions bàsiques de la biblioteca string.h (strlen, strcpy, strcmp, strcat). Implementar algorismes d'inversió i concatenació manual garantint el tancament amb el delimitador nul. PENSA-HI ABANS DE LLEGIR 42 Per què un text que conté 4 lletres requereix un vector de 5 caselles de memòria en C? Una cadena de caràcters (habitualment anomenada string) és una seqüència finita d'elements de tipus char emmagatzemada en memòria contigua. A diferència d'altres llenguatges que gestionen el tipus de text de forma nativa com un objecte separat, el llenguatge C/C++ tracta les cadenes com a vectors tradicionals que incorporen una marca o delimitador de finalització.

ESQUEMA Estructures de dades lineals i multidimensionals Estructura en memòria i caràcter delimitador Per delimitar on s'acaba la informació útil d'un text sense necessitat de guardar una variable addicional amb la seva mida, C/C++ utilitza el caràcter nul, denotat com a literal amb . Aquest caràcter correspon exactament al valor numèric 0 de la taula ASCII (vegeu «Fonaments — Entorn de desenvolupament, tipus bàsics i I/O»).

Cadenes (strings) Vectors char finalitzats en '\0' Biblioteca string.h strlen, strcpy, strcmp, strcat Algorismes sobre text Inversió, concatenació, recorregut Matrius multidimensionals Taules 2D, 3D i taules de cadenes Modularitat funcional Pas per valor, referència i vectors \0 Programació I en C/C++: Fonaments, Algorismes i Matrius 27 DEFINICIÓ Un string és un vector de tipus char acotat obligatòriament pel delimitador nul , el qual senyala a qualsevol procés d'I/O o d'inspecció que la seqüència vàlida ha finalitzat. Quan es vol disposar d'espai per a un text de fins a símbols útils, cal reservar una dimensió física de N + 1 caselles.

La darrera posició disponible s'ha de reservar per a allotjar la sentinella de finalització. Per exemple, amb una capacitat teòrica màxima de caràcters, declarem un vector de dimensió 21: Esquema d'assignació d'un string de N caràcters amb terminador nul Existeix una diferència clau entre un caràcter aïllat i una cadena d'un sol caràcter. La constant de caràcter 'a' ocupa únicament un byte a la memòria. En canvi, el literal de cadena "a" està compost per dos elements consecutius: el símbol 'a' seguit immediatament del delimitador .

La inicialització d'una cadena es pot fer mitjançant un literal entre cometes dobles o bé enumerant els elements entre claus com en un vector estàndard: char nom[N + 1] = "tere"; (el compilador afegeix automàticament a l'índex 4). char nom[N + 1] = {'t', 'e', 'r', 'e', '\0'}; (definició explícita de cada casella). COMPROVA-HO 43 Quina mida física necessitem en un vector per desar el text "HOLA" i quin índex ocuparà el caràcter nul? Entrada i sortida de cadenes amb I/O estàndard La lectura i l'escriptura de cadenes es realitza mitjançant l'especificador de format de les funcions scanf i printf (vegeu «Fonaments — Entorn de desenvolupament, tipus bàsics i I/O»).

\0 N N = 20 \0 \0 %s Programació I en C/C++: Fonaments, Algorismes i Matrius 28 ERROR FREQÜENT Quan s'executa scanf("%s", nom); , no s'ha d'escriure l'operador & davant del nom de la variable. En C, l'identificador d'un vector avalua directament a l'adreça del seu primer element (posició 0). Posar &nom és un error conceptual de tipus de punter. Cal tenir present que el format atura la lectura quan troba el primer caràcter blanc (espai, tabulador o salt de línia), afegint immediatament després el terminador a la memòria.

Funcions de la biblioteca string.h Per manipular cadenes sense haver de gestionar manualment cadascuna de les cel·les a baix nivell, s'inclou la capçalera estàndard #include <string.h> , la qual proporciona funcions per a mesurar la mida, duplicar contingut, concatenar textos i establir relacions d'ordre lexicogràfic. Funció Paràmetres Retorn Efecte sobre el destí strlen const char s[] Nombre de caràcters (int) Cap (operació de només lectura). strcpy char dest[], const char orig[] Punter al destí Sobreescriu dest copiant-hi orig i el seu . strcmp const char s1[], const char s2[] Valor enter (< 0, == 0, > 0) Cap (compara l'ordre ASCII).

strcat char dest[], const char orig[] Punter al destí Afegeix orig al final de dest , reescrivint el seu antic . La funció strlen(s) computa la llargada efectiva de la informació: compta el nombre de símbols existents abans del caràcter nul. En conseqüència, el valor de retorn de strlen coincideix amb l'índex exacte on se situa el ' 0'. La comparació mitjançant strcmp(s1, s2) analitza les cadenes caràcter a caràcter segons el seu codi ASCII numèric i genera un resultat dividit en tres supòsits: Esquema dels valors de retorn de strcmp segons l'ordre lexicogràfic Retorn 0: les cadenes i són exactament idèntiques en contingut i mida.

Retorn negatiu (< 0): la cadena precedeix lexicogràficament ( ). Retorn positiu (> 0): la cadena és posterior a ( ). %s \0 \0 \0 \ s 1 s 2 s 1 s 2 s < 1 L s 2 s 1 s 2 s > 1 L s 2 Programació I en C/C++: Fonaments, Algorismes i Matrius 29 COMPROVA-HO 44 Què retorna strcmp("arbre", "bosc") i per què? Algorismes manuals sobre cadenes Sovint és necessari implementar operacions bàsiques o transformacions específiques aplicant els esquemes de recorregut vists anteriorment (vegeu «Esquemes algorítmics — Recorregut de seqüències»).

Implementació de la funció de llargada Per calcular la mida d'un text sense dependre de la biblioteca del sistema, recorrem el vector fins a localitzar la marca centinella mitjançant un bucle while: Concatenació amb ordenació lexicogràfica Suposem que es llegeixen dues cadenes i de capacitat màxima cadascuna, i volem emmagatzemar en un tercer vector la concatenació de totes dues situant en primer lloc la cadena menor segons l'ordre lexicogràfic. La cadena receptora ha de tenir espai suficient per contenir la totalitat de caràcters de totes dues fonts a més del caràcter nul comú: la seva mida física ha de ser de 2 N + 1 posicions.

EXEMPLE Si comparem amb if (strcmp(s1, s2) <= 0) , copiem primer la cadena menor mitjançant strcpy(s3, s1); i posteriorment hi afegim l'altra amb strcat(s3, s2); . Si la condició és falsa, s'inverteix l'ordre: primer es copia i després s'hi concatena . Inversió i col·locació explícita del terminador nul Si es desitja concatenar una cadena amb el reflex invertit d'una segona cadena , cal fer una còpia manual índex a índex des de la darrera lletra d'aquesta cap a la primera. En primer lloc, es copia dins de usant strcpy. Tot seguit, es fixa l'índex d'escriptura a la posició actual de finalització: i = strlen(s3); .

A continuació, un bucle de sentit descendent recorre la segona cadena des del darrer caràcter vàlid fins a la casella inicial: for (int j = strlen(s2) - 1; j >= 0; j--) . A cada cicle, copiem s3[i] = s2[j]; i incrementem i++ . Com que aquest procés manual escriu els símbols un per un, el terminador nul no s'insereix pas automàticament. Per tancar el text correctament i evitar que la memòria residual es llegeixi de manera errònia, és imprescindible finalitzar el procediment assignant s3[i] = '\0'; . Inicialitzem un índex de posició i = 0 . 1 Mentre el caràcter actual p[i] sigui diferent de , avancem incrementant l'índex i++ .

2 \0 Quan el bucle s'atura en assolir el centinella, el valor assolit per la variable i equival exactament a la quantitat de caràcters útils, la qual es retorna.

3 s 1 s 2 N = 20 s 3 s 3 s 2 s 1 s 1 s 2 s 1 s 3 Programació I en C/C++: Fonaments, Algorismes i Matrius 30 Esquema de recorregut orientat a paraula Quan s'ha de processar un text delimitat per una marca final (per exemple un punt '.') compost per fragments o paraules separades per espais en blanc, tabuladors (' ') o salts de línia, s'aplica una estructura de recorregut basat en la detecció d'alternances: Diagrama de l'alternança de senyal per al recorregut per paraules Aquest patró manté un bucle que analitza la seqüència mentre no s'arribi al final del text, encadenant la lectura de cada bloc separat de caràcters, el tractament de la paraula obtinguda i la preparació del bloc següent.

COMPROVA-HO 45 Per què és obligatori escriure explícitament s3[i] = '\0' en acabar de bolcar manualment els caràcters invertits? \t Programació I en C/C++: Fonaments, Algorismes i Matrius 31 IDEES CLAU Un string en C/C++ és un vector de tipus char la part útil del qual acaba amb el caràcter nul (ASCII 0). Per emmagatzemar un text de fins a caràcters és imprescindible declarar una mida física de posicions per encabir-hi el sentinella. A les crides a scanf amb el format %s no s'utilitza l'operador & davant del vector perquè el seu nom referencia directament la seva adreça d'inici a la memòria.

La funció strlen mesura els caràcters útils i coincideix amb l'índex de la posició on rau el caràcter nul . L'ordre lexicogràfic es calcula amb strcmp, la qual avalua les diferències numèriques ASCII entre caràcters corresponents. Tota manipulació o concatenació manual d'elements en un vector de caràcters requereix tancar la cadena assignant explícitament al darrer índex. COMPROVA EL QUE HAS APRÈS 46. Quina és la capacitat física que necessita un vector auxiliar si s'han de concatenar dues cadenes de mida útil màxima cadascuna? 47. Com implementa internament la funció strlen el càlcul del nombre de caràcters d'un string? Test Encercla la resposta correcta. Les solucions són al final. 48.

Quina mida ha de tenir un vector char per desar un text de 20 caràcters? 49. Per què no es posa & en llegir una cadena amb scanf("%s", nom)? 50. Què indica un valor retornat per strcmp(s1, s2) inferior a zero?

'\backslash0' N N + 1 '\backslash0' '\backslash0' N Exactament 19 caselles a) Com a mínim 21 caselles b) Un total de 40 caselles c) Exactament 20 caselles d) Perquè el nom de l'array conté la seva adreça a) Perquè el format %s no admet adreces b) Perquè nom és una variable de tipus enter c) Perquè el compilador genera un error sintàctic d) Que s1 té menys lletres que s2 a) Que s1 és anterior en ordre lexicogràfic b) Que s1 i s2 són cadenes idèntiques c) Que s1 conté caràcters numèrics negatius d) Programació I en C/C++: Fonaments, Algorismes i Matrius 32 51. Què ocorre si copiem caràcters a un vector manualment i oblidem el '\0'?

6 Estructures multidimensionals — Matrius 2D, 3D i taules de cadenes EN ACABAR SABRÀS Declarar i indexar matrius bidimensionals i tridimensionals en llenguatge C. Implementar recorreguts amb bucles niats per llegir, mostrar i calcular acumulats o màxims en taules. Gestionar taules de cadenes de caràcters reservant l'espai adequat per al terminador nul. Utilitzar la redirecció de l'entrada estàndard des d'arxius de text. PENSA-HI ABANS DE LLEGIR 52 Com sap el compilador quin element exacte d'una matriu volem consultar si la memòria física de l'ordinador és purament lineal?

Estructures bidimensionals: declaració i indexació Una matriu bidimensional és conceptualment una taula formada per files i columnes, estructurada com un vector on cadascun dels seus elements és un altre vector. A la memòria, les caselles es distribueixen de manera contigua fila rere fila. DEFINICIÓ Per definir una matriu en C cal especificar el tipus de dades dels elements, el nom de la variable i, entre claudàtors separats, el nombre de files i el nombre de columnes: tipus identificador[FILES][COLUMNES]; . En C, els índexs comencen sempre estrictament a 0 i finalitzen a la dimensió declarada menys u ( ).

Quan declarem, per exemple, una estructura per allotjar enters amb constants predefinides: #define F 3 #define C 4 int m[F][C] = {{1}, {2}, {3}}; Es produeix sempre una fallada en compilar a) Les operacions posteriors llegiran memòria no delimitada b) El programa afegeix el nul de forma automàtica c) La mida obtinguda per strlen serà immediatament zero d) 0 fins a N 1 Programació I en C/C++: Fonaments, Algorismes i Matrius 33 Aquesta declaració reserva espai per a enters en total. La inicialització amb claus imbricades assigna valors per files; les posicions no especificades s'inicialitzen automàticament a zero. Diagrama de representació lògica per files i columnes d'una matriu bidimensional.

ESQUEMA Estructures multidimensionals COMPROVA-HO 53 Quants elements té la matriu definida com 'int m[3][4]' i quin és el rang vàlid dels seus índexs de columna?

3 × 4 = 12 Matrius bidimensionals Taules 2D per files i columnes Bucles niats (f, c) Recorregut de 2 nivells Matrius tridimensionals Organització en plànols de matrius Bucles niats (p, f, c) Recorregut de 3 nivells Taules de cadenes Vectors de cadenes acabades en \0 Accés per fila ll[f] Tractament directe amb %s Programació I en C/C++: Fonaments, Algorismes i Matrius 34 Processament de matrius 2D amb bucles niats Per manipular cadascuna de les cel·les d'una taula bidimensional emprem bucles d'iteració niats (vegeu «Estructures de control — Bucles i iteració bàsica»). El bucle exterior governa l'avenç per les files i el bucle interior recorre les columnes corresponents a la fila activa.

Aquest patró permet resoldre de forma sistemàtica la captura de dades per teclat, la visualització per pantalla, l'acumulació de sumes i la cerca d'extrems com el valor màxim: ERROR FREQÜENT Inicialitzar la variable max a 0 o a un valor arbitrari en comptes de m[0][0] fa perdre punts. Si totes les dades emmagatzemades a la matriu són nombres negatius, una inicialització a 0 donarà un resultat completament erroni perquè 0 mai no forma part de les dades. COMPROVA-HO 54 Per què cal actualitzar les variables 'fila' i 'columna' en el mateix bloc condicional on s'actualitza el valor de 'max'?

Matrius tridimensionals: organització per plànols Una estructura de dades pot estendre's afegint dimensions addicionals. Una matriu tridimensional organitza les dades segons tres coordenades: plànol, fila i columna. Es declara formalment mitjançant int m3[P][F][C]; , on el primer índex selecciona el plànol bidimensional complet. Lectura de dades: Recorrem cada fila i columna aplicant la lectura per teclat amb l'operador d'adreça scanf("%i", &m[f][c]); . 1 f c Visualització tabulada: Imprimim el contingut de cada cel·la printf("%i ", m[f][c]); en el bucle intern, i fem un salt de línia printf(" "); en finalitzar cada fila.

2 \t \n Suma global: Inicialitzem una variable acumuladora a zero ( ) abans de començar els bucles i afegim el valor de cada posició S += m[f][c]; . 3 S = 0 Cerca de l'element màxim: Inicialitzem la variable de comparació amb el primer element existent de la matriu ( max = m[0][0] ) i registrem els índexs inicials ( fila = 0 , columna = 0 ). En trobar un element estrictament superior ( m[f][c] > max ), actualitzem el màxim i guardem la seva coordenada actual. 4 Programació I en C/C++: Fonaments, Algorismes i Matrius 35 Esquema d'indexació per plànols, files i columnes en una matriu 3D. Per processar estructures tridimensionals s'encadenen tres bucles niats.

Això permet dur a terme operacions per blocs independents, com ara obtenir la suma particular de cada plànol: #define P 3 #define F 4 #define C 4 int m3[P][F][C] = {0}; int S; for (int p = 0; p < P; p++) { S = 0; // Reinici de l'acumulador per a cada plànol for (int f = 0; f < F; f++) { for (int c = 0; c < C; c++) { S += m3[p][f][c]; } } printf("Suma plànol %d = %d ", p, S); } Reiniciar la variable acumuladora dins del cicle de plànols assegura que cada total reflecteixi exclusivament els elements del bloc que s'està avaluant en aquella iteració.

\n Programació I en C/C++: Fonaments, Algorismes i Matrius 36 COMPROVA-HO 55 Quantes vegades s'executa la línia 'S += m3[p][f][c];' si P=3, F=4 i C=4? Taules de cadenes de caràcters i redirecció d'I/O Una seqüència de text en C és un vector de caràcters acabat pel caràcter nul '\0' (vegeu «Cadenes de caràcters — Vectors de caràcters i biblioteca string.h»). Per gestionar una llista de múltiples paraules o frases es fa servir una taula de cadenes, que consisteix en una matriu bidimensional de caràcters declarada com char ll[L][M + 1]; .

Índex Funció estructural Mida declarada Motiu de la reserva Primer índex (files) Nombre màxim de cadenes L Defineix quantes paraules independents pot allotjar la taula. Segon índex (columnes) Capacitat per caràcter M + 1 Reserva espai per als caràcters útils més el terminador obligatori '\0' . Diagrama d'organització d'una taula de cadenes de caràcters amb terminadors nuls.

A l'hora de llegir o imprimir una paraula concreta de la llista, s'accedeix a la fila sencera mitjançant un sol índex ll[f] emprant l'especificador de format %s : Programació I en C/C++: Fonaments, Algorismes i Matrius 37 #define L 10 #define M 20 char ll[L][M + 1]; // Lectura de paraules for (int f = 0; f < L; f++) { scanf("%s", ll[f]); // No requereix & perquè ll[f] és el vector fila } // Mostra en sentit invers for (int f = L - 1; f >= 0; f--) { printf("%s ", ll[f]); } Per provar aplicacions que requereixen grans volums d'introducció de dades sense haver d'escriure manualment per teclat en cada execució, el sistema operatiu ofereix la redirecció d'entrada.

Mitjançant la sintaxi ./prog < dades.txt , el programa llegeix les entrades directament del fitxer de text indicat substituint el teclat de forma automàtica. PER RECORDAR-HO L'accés a una cel·la concreta d'un text requereix dos índexs: ll[f][c] (el caràcter en si). En canvi, per passar o tractar tota la paraula com una sola unitat amb %s s'escriu únicament el selector de fila: ll[f] . COMPROVA-HO 56 Per què a 'scanf("%s", ll[f])' no s'utilitza l'operador '&'? IDEES CLAU Les matrius bidimensionals s'indexen des de 0 fins a la dimensió menys u en cadascun dels seus eixos. El processament ordenat per files i columnes s'implementa habitualment mitjançant bucles 'for' niats.

Per cercar el valor màxim s'inicialitza la variable de comparació amb 'm[0][0]' i es guarden les coordenades 'fila' i 'columna' en detectar un valor estrictament més alt. En estructures 3D ('m3[P][F][C]') el primer índex governa el plànol, permetent càlculs aïllats reiniciant l'acumulador per a cada bloc. Una taula de cadenes ('char ll[L][M+1]') reserva 'M+1' caràcters per fila per encabir obligatòriament el terminador nul '\0'. La redirecció d'I/O mitjançant './prog < dades.txt' injecta el contingut d'un fitxer com a entrada estàndard del programa. \n Programació I en C/C++: Fonaments, Algorismes i Matrius 38 COMPROVA EL QUE HAS APRÈS 57.

Com s'ha de declarar una llista capaç d'allotjar 15 paraules de fins a 30 lletres útils cadascuna? 58. Quin comportament tindrà l'algorisme de cerca del màxim si inicialitzem el valor inicial a 0 en una matriu amb valors {-8, -3, -12}? Test Encercla la resposta correcta. Les solucions són al final. 59. Quin és el rang d'índexs per a una matriu declarada com float taula[4][6]? 60. A quina dimensió correspon el primer índex en una matriu m3[P][F][C]? 61. Per què es declara char ll[10][21] per desar 10 paraules de 20 caràcters? 62. Què fa la comanda './prog < dades.txt' al terminal?

7 Modularitat i disseny funcional — Funcions, paràmetres i pas per referència EN ACABAR SABRÀS Declarar prototips i definir subprogrames distingint funcions amb retorn d'accions void. Implementar el pas de paràmetres per referència amb & per modificar variables externes. Passar matrius bidimensionals respectant la sintaxi obligatòria de columnes m[][N].

Files 1..3 i columnes 1..5 a) Files 1..4 i columnes 1..6 b) Files 0..3 i columnes 0..5 c) Files 0..4 i columnes 0..6 d) A la fila de la matriu a) Al plànol de l'estructura b) A la columna de la matriu c) Al byte físic de memòria d) Per deixar espai al salt de línia a) Per compatibilitat amb l'operador scanf b) Per allotjar el terminador nul '\0' c) Per alinear la memòria a múltiples d) Copia el fitxer de dades a) Escriu la sortida al fitxer b) Comprova la sintaxi del codi c) Redirigeix l'entrada des del fitxer d) Programació I en C/C++: Fonaments, Algorismes i Matrius 39 PENSA-HI ABANS DE LLEGIR 63 Per què quan passem una variable simple a una funció no canvia el seu valor al main, però amb un vector sí que es modifiquen els seus elements?

La modularitat consisteix a descompondre un problema complex en diversos subproblemes més petits i concrets mitjançant subprogrames. ESQUEMA Estructura de la modularitat i disseny funcional 1. Concepte de subprograma: funcions i accions Un subprograma és un bloc de codi aïllat dissenyat per resoldre una tasca específica. Es distingeixen dues modalitats principals segons el seu propòsit: Funció: realitza un càlcul especialitzat i retorna un únic valor resultant mitjançant la sentència return .

Un exemple clàssic de biblioteca és isdigit (vegeu «Esquemes algorítmics — Recorregut de seqüències»), la qual rep un caràcter i retorna un booleà, o bé strcmp (vegeu «Cadenes de caràcters — Vectors de caràcters i biblioteca string.h»), que rep dues cadenes i retorna un enter (0, menor o major a zero). Acció (procediment): executa un processament o transformació sobre les dades i no retorna cap valor directe, utilitzant la paraula clau void com a tipus de retorn. Rutines conegudes com strcpy o strcat funcionen conceptualment com accions de modificació de dades. 2.

Sintaxi, prototips i cicle d'execució d'una funció L'estructura sintàctica general d'una funció requereix indicar el tipus del resultat, el seu identificador i la llista de paràmetres formals entre parèntesis: Tipus de subprogrames Descomposició de codi Funcions Retornen un valor concret Accions (void) Processament sense valor retornat Mecanismes de paràmetres Flux de dades a memòria Pas…

Més apunts de Programació I

Exàmens, temes i apunts de Programació I