Fins ara hem treballat amb variables que emmagatzemen una única dada: un títol, un nombre
de pàgines, un booleà. Però a la pràctica, gairebé qualsevol programa necessita gestionar
diverses dades del mateix tipus alhora —per exemple, tots els títols de llibres de
BiblioTech— i necessita també manipular text de forma més avançada que un simple
Console.WriteLine. En aquesta lliçó aprendràs a treballar amb arrays (d'una i
diverses dimensions), a recórrer-los amb foreach/for, i a explotar tota la potència de
la classe string: concatenació, interpolació, i els seus mètodes més habituals. Tancarem
amb StringBuilder, l'eina adequada quan es concatena text de forma repetida dins d'un
bucle.
Contingut
- Arrays d'una dimensió
- Arrays de diverses dimensions
- Arrays de mida fixa enfront de
List<T> - Recórrer un array amb
foreachi ambfor - La classe
string: immutabilitat, concatenació i interpolació - Mètodes habituals de
string StringBuilderper a concatenació eficient
Arrays d'una dimensió
Un array és una col·lecció d'elements del mateix tipus, emmagatzemats de forma
contigua i accessibles mitjançant un índex numèric que comença en 0. Es declara
indicant el tipus dels elements seguit de claudàtors []:
string[] titolsLlibres = new string[3];
titolsLlibres[0] = "Cent anys de solitud";
titolsLlibres[1] = "Rayuela";
titolsLlibres[2] = "Ficcions";
Console.WriteLine(titolsLlibres[0]); // Cent anys de solitudTambé es pot declarar i inicialitzar en un sol pas, indicant directament els valors:
string[] titolsLlibres = { "Cent anys de solitud", "Rayuela", "Ficcions" };
// Forma equivalent, mes explicita:
string[] titolsLlibresB = new string[] { "Cent anys de solitud", "Rayuela", "Ficcions" };Mida fixa i propietat Length
Una característica fonamental dels arrays en C# és que la seva mida es fixa en
crear-los i no pot canviar després. Per saber quants elements conté, es fa servir la
propietat Length:
string[] titolsLlibres = { "Cent anys de solitud", "Rayuela", "Ficcions" };
Console.WriteLine(titolsLlibres.Length); // 3Accés fora de rang
Intentar accedir a un índex que no existeix (per exemple, titolsLlibres[5] en un array
de 3 elements) no provoca un error en compilar, però sí que provoca un error en temps
d'execució (una excepció de tipus IndexOutOfRangeException, que estudiarem al Mòdul
2 en veure la gestió d'excepcions). Per això sempre cal assegurar-se que l'índex utilitzat
estigui entre 0 i Length - 1.
string[] titolsLlibres = { "Cent anys de solitud", "Rayuela", "Ficcions" };
// Console.WriteLine(titolsLlibres[3]); // Error en temps d'execucio: index fora de rang
Console.WriteLine(titolsLlibres[titolsLlibres.Length - 1]); // Ficcions (l'ultim element)Arrays de diverses dimensions
A més dels arrays d'una dimensió (una simple llista d'elements), el C# permet arrays de diverses dimensions, útils per representar dades organitzades en forma de taula o graella. El cas més comú és l'array bidimensional (files i columnes):
// Un array de 2 files (prestatges) x 3 columnes (forats per prestatge)
string[,] prestatgeria = new string[2, 3];
prestatgeria[0, 0] = "Cent anys de solitud";
prestatgeria[0, 1] = "Rayuela";
prestatgeria[0, 2] = "Ficcions";
prestatgeria[1, 0] = "El Aleph";
prestatgeria[1, 1] = "Pedro Paramo";
prestatgeria[1, 2] = "La casa dels esperits";
Console.WriteLine(prestatgeria[1, 2]); // La casa dels esperitsTambé es poden inicialitzar directament amb els seus valors:
string[,] prestatgeria =
{
{ "Cent anys de solitud", "Rayuela", "Ficcions" },
{ "El Aleph", "Pedro Paramo", "La casa dels esperits" }
};Per conèixer el nombre de files i columnes d'un array bidimensional es fa servir el mètode
GetLength, indicant la dimensió (0 per a files, 1 per a columnes):
Console.WriteLine(prestatgeria.GetLength(0)); // 2 (files / prestatges)
Console.WriteLine(prestatgeria.GetLength(1)); // 3 (columnes / forats per prestatge)En aquest curs els arrays multidimensionals apareixeran de forma puntual; la majoria d'exemples faran servir arrays d'una dimensió, que són de llarg els més habituals en el dia a dia.
Arrays de mida fixa enfront de List<T>
Com hem vist, un array té una mida fixa: un cop creat amb, per exemple, 3 elements, no es pot afegir un quart títol de llibre sense crear un array completament nou. En molts escenaris reals (com anar afegint llibres al catàleg de BiblioTech a mesura que es registren) aquesta limitació resulta incòmoda.
Per a aquests casos, .NET ofereix List<T>, una col·lecció la mida de la qual pot créixer
i encongir-se de forma dinàmica, amb mètodes com Add (afegir un element) o Remove
(treure'l). Aquí només la mencionem de passada: List<T> i la resta de col·leccions de
.NET s'estudien en profunditat al Mòdul 4 ("Col·leccions"), juntament amb LINQ, la potent
eina de consulta que farem servir per explorar el catàleg complet de BiblioTech. De
moment, queda't amb aquesta idea:
Array (string[]) |
List<T> (per exemple, List<string>) |
|
|---|---|---|
| Mida | Fixa en crear-se | Dinàmica (creix i decreix) |
| Quan usar-lo | El nombre d'elements es coneix de bestreta i no canvia | El nombre d'elements pot variar durant l'execució |
| S'estudia en detall a | Aquest mòdul | Mòdul 4 |
Recórrer un array amb foreach i amb for
Per processar tots els elements d'un array, un per un, hi ha dos bucles principals. Encara que els bucles s'estudien en profunditat al Mòdul 2 ("Bucles"), aquí veurem el seu ús bàsic aplicat a arrays, ja que és una combinació tan habitual que convé conèixer-la des d'ara.
foreach: recórrer tots els elements
foreach recorre tots els elements d'una col·lecció, un darrere l'altre, sense
necessitat de gestionar manualment un índex:
string[] titolsLlibres = { "Cent anys de solitud", "Rayuela", "Ficcions" };
foreach (string titol in titolsLlibres)
{
Console.WriteLine(titol);
}Aquest codi imprimeix, un per línia, cada títol de l'array. foreach és l'opció més clara
i recomanable quan simplement necessites llegir o processar cada element, sense
necessitar la seva posició (índex).
for: recórrer amb control explícit de l'índex
Quan sí que necessites l'índex (per exemple, per numerar els llibres, o per modificar el
mateix array durant el recorregut), es fa servir el bucle for, que dona control explícit
sobre un comptador:
string[] titolsLlibres = { "Cent anys de solitud", "Rayuela", "Ficcions" };
for (int i = 0; i < titolsLlibres.Length; i++)
{
Console.WriteLine($"{i + 1}. {titolsLlibres[i]}");
}Aquest exemple imprimeix cada títol precedit de la seva posició a la llista, començant en 1 (sumant 1 a l'índex, que comença en 0):
foreach |
for |
|
|---|---|---|
| Accés a l'índex | No (només el valor de cada element) | Sí, mitjançant el comptador (i) |
| Modificar l'array durant el recorregut | No recomanable | Possible, amb precaució |
| Llegibilitat | Més simple i directa | Més flexible però una mica més verbosa |
La classe string: immutabilitat, concatenació i interpolació
Immutabilitat
Una string en C# és immutable: un cop creada, el seu contingut no es pot modificar.
Qualsevol operació que "sembli" canviar una cadena (com concatenar-la amb un altre text)
en realitat crea una cadena nova en memòria, deixant l'original intacta:
string titolOriginal = "Rayuela";
string titolModificat = titolOriginal + " (edicio especial)";
Console.WriteLine(titolOriginal); // Rayuela (no ha canviat)
Console.WriteLine(titolModificat); // Rayuela (edicio especial)Aquesta propietat té implicacions importants de rendiment quan es concatenen moltes
cadenes dins d'un bucle, com veurem més endavant a la secció de StringBuilder.
Concatenació
Concatenar significa unir dues o més cadenes en una de sola. La forma més bàsica és amb
l'operador +:
string titol = "Cent anys de solitud";
string autor = "Gabriel Garcia Marquez";
string descripcio = titol + " - " + autor;
Console.WriteLine(descripcio); // Cent anys de solitud - Gabriel Garcia MarquezInterpolació de cadenes ($"")
La interpolació és una forma molt més llegible de construir cadenes que combinen text
fix amb valors de variables. S'anteposa el símbol $ abans de les cometes, i les
variables (o fins i tot expressions) s'insereixen directament entre claus { }:
string titol = "Cent anys de solitud";
int pagines = 471;
bool disponible = true;
string resum = $"El llibre '{titol}' te {pagines} pagines i esta disponible: {disponible}";
Console.WriteLine(resum);Resultat:
Dins de les claus { } d'una cadena interpolada es poden escriure fins i tot petites
expressions, no només variables soltes:
int paginesLlegides = 120;
int totalPagines = 471;
Console.WriteLine($"Progres de lectura: {paginesLlegides} de {totalPagines} pagines ({paginesLlegides * 100 / totalPagines}%)");| Tècnica | Exemple | Llegibilitat |
|---|---|---|
Concatenació amb + |
"Llibre: " + titol + ", pagines: " + pagines |
Es torna difícil de llegir amb moltes variables |
Interpolació $"" |
$"Llibre: {titol}, pagines: {pagines}" |
Clara fins i tot amb diverses variables |
En aquest curs preferirem la interpolació sempre que combinem text amb variables, per la seva claredat.
Mètodes habituals de string
La classe string inclou nombrosos mètodes ja construïts per a les tasques més habituals
de manipulació de text. Aquests són els més usats:
| Mètode | Què fa | Exemple |
|---|---|---|
Split |
Divideix una cadena en un array de subcadenes, segons un separador | "a,b,c".Split(',') → ["a", "b", "c"] |
Trim |
Elimina espais en blanc al principi i al final | " Rayuela ".Trim() → "Rayuela" |
Contains |
Comprova si una cadena en conté una altra | "Rayuela".Contains("ayu") → true |
Substring |
Extreu una part de la cadena, indicant posició (i opcionalment longitud) | "Rayuela".Substring(0, 3) → "Ray" |
ToUpper / ToLower |
Converteix tota la cadena a majúscules o minúscules | "Rayuela".ToUpper() → "RAYUELA" |
Els veurem aplicats a un exemple realista de BiblioTech: processar una línia de text amb diverses dades d'un llibre separades per comes, tal com podria venir d'un fitxer d'importació (cosa que tractarem en profunditat al Mòdul 5, "Entrada/Sortida de Fitxers").
string liniaImportada = " Rayuela, Julio Cortazar, 635 ";
string liniaNeta = liniaImportada.Trim(); // treu espais sobrers al principi/final
string[] camps = liniaNeta.Split(','); // separa per comes: [" Rayuela", " Julio Cortazar", " 635 "]
string titol = camps[0].Trim(); // "Rayuela"
string autor = camps[1].Trim(); // "Julio Cortazar"
string paginesText = camps[2].Trim(); // "635"
Console.WriteLine($"Titol: {titol}");
Console.WriteLine($"Autor: {autor}");
Console.WriteLine($"Pagines (text): {paginesText}");
// Cerca de text dins d'un titol
bool conteRay = titol.Contains("Ray");
Console.WriteLine($"El titol conte 'Ray': {conteRay}");
// Extreure les 3 primeres lletres del titol
string prefixTitol = titol.Substring(0, 3);
Console.WriteLine($"Prefix del titol: {prefixTitol}");
// Normalitzar a majuscules per a comparacions sense distingir majuscules/minuscules
string titolEnMajuscules = titol.ToUpper();
Console.WriteLine(titolEnMajuscules); // RAYUELAFixa't que cadascun d'aquests mètodes no modifica la cadena original (recorda: les cadenes són immutables), sinó que retorna una cadena nova amb el resultat. Per això sempre assignem el resultat a una variable (o el fem servir directament), en lloc d'esperar que la variable original canviï per si sola.
Comparació de cadenes ignorant majúscules/minúscules
Un cas d'ús molt habitual en cercar en un catàleg (com el de BiblioTech) és comparar text
sense que importin les majúscules o minúscules. Per a això es poden convertir totes dues
cadenes al mateix cas abans de comparar, o usar el mètode Equals amb una opció
específica:
string cerca = "rayuela";
string titolCataleg = "Rayuela";
bool coincideix = titolCataleg.Equals(cerca, StringComparison.OrdinalIgnoreCase);
Console.WriteLine(coincideix); // TrueStringBuilder per a concatenació eficient
Com que cada string és immutable, concatenar cadenes repetidament dins d'un bucle (per
exemple, per construir un informe amb tots els títols del catàleg) crea, a cada iteració,
una cadena nova completa en memòria, descartant l'anterior. Per a pocs elements això no
suposa cap problema, però si el bucle es repeteix moltes vegades (milers de llibres, per
exemple), pot afectar notablement el rendiment.
Per a aquests casos, .NET ofereix la classe StringBuilder, pensada específicament per
construir cadenes de text de forma eficient mitjançant successives modificacions, sense
crear una cadena nova completa a cada pas. Es troba a l'espai de noms System.Text.
using System.Text;
string[] titolsLlibres = { "Cent anys de solitud", "Rayuela", "Ficcions", "El Aleph" };
StringBuilder informe = new StringBuilder();
informe.Append("Cataleg de BiblioTech:");
informe.AppendLine(); // salt de linia
foreach (string titol in titolsLlibres)
{
informe.AppendLine($"- {titol}");
}
string informeFinal = informe.ToString();
Console.WriteLine(informeFinal);Resultat:
| Situació | Recomanació |
|---|---|
| Concatenar unes poques cadenes, fora d'un bucle | + o interpolació $"" |
| Concatenar dins d'un bucle que es pot repetir moltes vegades | StringBuilder |
No aprofundirem més en StringBuilder en aquest mòdul introductori; és una eina que anirà
apareixent de forma natural més endavant en el curs, especialment quan treballem amb grans
catàlegs de llibres i generació d'informes.
Errors Comuns i Consells
- Accedir a un índex fora de rang: recorda que els índexs d'un array van de
0aLength - 1. Accedir aarray[Length]és un error molt comú i provoca una excepció en temps d'execució. - Esperar que un array canviï de mida: els arrays tenen mida fixa. Si necessites
afegir o treure elements dinàmicament, necessitaràs
List<T>(Mòdul 4), no un array. Crear un array de mida més gran i copiar-hi les dades és possible, però feixuc i poc habitual a la pràctica. - Oblidar que les cadenes són immutables: escriure
titol.ToUpper();sense assignar el resultat a cap variable no modificatitol; cal fertitol = titol.ToUpper();(o usar el resultat directament on calgui). - Usar concatenació amb
+dins de bucles grans: per a pocs elements no passa res, però si el bucle processa moltíssims elements, és preferibleStringBuilder. - Confondre
Splitsense netejar espais: en dividir text ambSplit, cada fragment pot portar espais sobrers; convé aplicarTrim()a cadascun, com hem fet a l'exemple d'importació de dades. - Consell: quan treballis amb text que combini variables, prioritza sempre la
interpolació (
$"...") sobre la concatenació amb+: el codi resultant és molt més llegible i menys propens a errors.
Exercicis
-
Declara un array de tipus
string[]amb almenys 5 títols de llibres de BiblioTech. Recorre'l ambforeachi mostra cada títol en una línia. Després, recorre'l amb un bucleformostrant cada títol numerat, començant en 1 (per exemple:1. Cent anys de solitud). -
Donat l'array de títols de l'exercici anterior, escriu codi que recorri l'array i mostri només els títols que continguin la lletra
"a"(fent servir el mètodeContains, i convertint el títol a minúscules ambToLower()abans de comparar, perquè la cerca no distingeixi majúscules de minúscules). -
Fent servir
StringBuilder, construeix un informe de text amb tots els títols de l'array de l'exercici 1, amb el format:=== Cataleg BiblioTech === 1) <titol 1> 2) <titol 2> ...(Pista: pots combinar un bucle
forambStringBuilder.AppendLinei interpolació de cadenes per construir cada línia numerada).
Solucions
string[] titolsLlibres = { "Cent anys de solitud", "Rayuela", "Ficcions", "El Aleph", "Pedro Paramo" };
// Recorregut amb foreach
foreach (string titol in titolsLlibres)
{
Console.WriteLine(titol);
}
Console.WriteLine("---");
// Recorregut amb for, numerat des d'1
for (int i = 0; i < titolsLlibres.Length; i++)
{
Console.WriteLine($"{i + 1}. {titolsLlibres[i]}");
}
string[] titolsLlibres = { "Cent anys de solitud", "Rayuela", "Ficcions", "El Aleph", "Pedro Paramo" };
foreach (string titol in titolsLlibres)
{
if (titol.ToLower().Contains("a"))
{
Console.WriteLine(titol);
}
}
Tots els títols de l'exemple contenen la lletra "a" en algun punt (majúscula o
minúscula), per la qual cosa el resultat mostraria els cinc; l'exercici serveix per
practicar la combinació de ToLower() i Contains(), no tant per obtenir un
subconjunt reduït amb aquestes dades concretes. Pots provar amb altres títols que no
continguin la lletra per comprovar que sí que es filtren correctament.
using System.Text;
string[] titolsLlibres = { "Cent anys de solitud", "Rayuela", "Ficcions", "El Aleph", "Pedro Paramo" };
StringBuilder informe = new StringBuilder();
informe.AppendLine("=== Cataleg BiblioTech ===");
for (int i = 0; i < titolsLlibres.Length; i++)
{
informe.AppendLine($"{i + 1}) {titolsLlibres[i]}");
}
Console.WriteLine(informe.ToString());
Resultat esperat:
=== Cataleg BiblioTech ===
1) Cent anys de solitud
2) Rayuela
3) Ficcions
4) El Aleph
5) Pedro Paramo
Conclusió
En aquesta lliçó has après a treballar amb arrays d'una i diverses dimensions, a
recórrer-los amb foreach i for, i has vist per què List<T> (que estudiarem al Mòdul
4) resol la limitació de la mida fixa dels arrays. També has aprofundit en la classe
string: la seva immutabilitat, la concatenació, la interpolació $"", els seus mètodes
més habituals (Split, Trim, Contains, Substring, ToUpper/ToLower) i l'ús de
StringBuilder per concatenar text de forma eficient dins de bucles.
Amb això es tanca el Mòdul 1: Introducció al C#. Ja saps instal·lar i configurar el
teu entorn, escriure i executar programes de consola, aplicar correctament la sintaxi del
llenguatge, declarar variables de diferents tipus i treballar amb arrays i cadenes de text
—tot això aplicat, pas a pas, al projecte BiblioTech. Al Mòdul 2: Estructures de
Control aprendràs a prendre decisions al teu codi amb sentències condicionals, a
repetir accions amb bucles, a organitzar múltiples casos amb switch, i a gestionar
errors de forma robusta amb excepcions: peces imprescindibles perquè BiblioTech comenci a
comportar-se com una aplicació real, capaç de reaccionar a diferents situacions i dades.
Curs de Programació en C#
Mòdul 1: Introducció al C#
- Introducció al C#
- Configuració de l'Entorn de Desenvolupament
- Programa Hola Món
- Sintaxi i Estructura Bàsica
- Variables i Tipus de Dades
- Arrays i Cadenes de Text
Mòdul 2: Estructures de Control
Mòdul 3: Programació Orientada a Objectes
- Classes i Objectes
- Mètodes
- Constructors i Destructors
- Herència
- Polimorfisme
- Encapsulació
- Abstracció
- Structs i Records: Tipus per Valor i per Referència
Mòdul 4: Conceptes Avançats de C#
- Interfícies
- Delegats i Esdeveniments
- Pattern Matching i Característiques Modernes de C#
- Genèrics
- Col·leccions
- LINQ (Consulta Integrada en el Llenguatge)
- Programació Asíncrona
Mòdul 5: Treballant amb Dades
- Entrada/Sortida de Fitxers
- Serialització
- Connectivitat amb Bases de Dades
- Entity Framework
- Treball amb JSON i Consum d'APIs REST
Mòdul 6: Temes Avançats
- Reflexió
- Atributs
- Programació Dinàmica
- Gestió de Memòria i Recollida d'Escombraries
- Multifil i Programació Paral·lela
Mòdul 7: Construcció d'Aplicacions
Mòdul 8: Bones Pràctiques i Patrons de Disseny
- Estàndards de Codificació i Bones Pràctiques
- Patrons de Disseny
- Injecció de Dependències i Inversió de Control
- Proves Unitàries
- Revisió i Refactorització de Codi
