Fundamentele programării (II) – C#

În cadrul acestui episod vom introduce noțiunile de variabilă și tip de date și vom lucra cu numere și texte. Vom presupune că deja știți să utilizați un mediu de programare (fie el și online); dacă nu, vă recomandăm să citiți din nou episodul anterior.

Variabile

Chiar și pentru cele mai simple programe, la un moment dat avem nevoie să păstrăm anumite informații. Nu am avut nevoie de acest lucru atunci când doar am afișat un mesaj, dar atunci când am avut nevoie de numele utilizatorului a trebuit să păstrăm informația respectivă. Să ne amintim ultimul program de data trecută:

În linia 8, avem o instrucțiune prin care preluăm informația introdusă de utilizator și o păstrăm în ceva de numit nume. Aceasta este o așa numită variabilă.

Variabilele pot fi văzute ca fiind niște recipiente care păstrează informații. Practic, cu ajutorul lor ajungem undeva în memoria calculatorului, luăm o mică parte din ea și îi dăm o denumire pentru a o putea folosi ulterior.

Avem nevoie de variabile pentru cele mai diverse scopuri. Dacă scriem un program care controlează un roboțel, vom avea nevoie de variabile care să conțină poziția acestuia, orientarea sa etc. În schimb, dacă programul nostru simulează un joc de fotbal, am avea nevoie de variabile pentru a păstra scorul.

În principiu, dacă trebuie să ținem minte ceva, cel mai simplu este să punem acel ceva într-o variabilă.

Majoritatea limbajelor moderne necesită declararea unei variabile înainte ca aceasta să poată fi utilizată. C# este un astfel de limbaj. Mai mult, limbajul C# ne permite să specificăm și ce tip de variabilă dorim. Putem alege să nu specificăm tipul, acesta putând fi determinat automat în anumite situații.

Dacă revenim la linia 8 a programului nostru, observăm că înaintea denumirii nume, apare cuvântul String. Acesta este tipul variabilei nume. Vom vedea exact ce înseamnă puțin mai încolo.

În C#, pentru a declara o variabilă, trebuie să precizăm tipul acesteia, urmat de denumirea sa. Pentru un meci de fotbal, am putea avea o variabilă declarată astfel:

Tipul este int (vom vedea ce înseamnă), iar denumirea este _goluriGazde (vom vedea și de ce denumirea arată oarecum ciudat). Urmează semnul ;, cel care separă instrucțiunile în C#. Deci, declararea unei variabile este o instrucțiune.

Termenul variabilă implică faptul că ea se poate modifica. Prin diverse mecanisme, informația conținută de o variabilă se poate schimba în timpul execuției programului. De exemplu, într-un joc de fotbal, la începutul unui meci variabila care ar păstra numărul golurilor marcate de echipa gazdă ar conține informația 0. Dar, dacă echipa marchează un gol, informația respectivă trebuie să devină 1. Dacă se mai marchează unul, variabila va conține informația 2 și așa mai departe. Dar, dacă începe un joc nou, informația redevine 0. Această informație păstrată de către variabilă poartă denumirea de valoare a variabilei.

În C#, este posibil ca în momentul declarării unei variabile să precizăm și ce valoare dorim să aibă la început. Pentru aceasta, după denumirea ei (înainte de ;) adăugăm semnul =, urmat de valoarea dorită. O astfel de declarație ar putea fi:

Spunem că o astfel de variabilă este inițializată.

Datorită faptului că specificăm o valoare, aceasta are deja un tip. Așadar, putem omite specificarea tipului variabilei dacă o și inițializăm. Spunem că tipul este implicit. Dacă decidem să specificăm tipul, acesta este explicit. Totuși, trebuie să indicăm faptul că dorim să declarăm o variabilă. Instrucțiunea care declară variabila _goluriGazde ar putea arăta astfel:

Tipuri

Am spus că în C# variabilele au tipuri. Tipul unei variabile indică ce fel de informație poate conține variabila respectivă. În exemplul nostru tipul este int; el arată că variabila noastră este un număr întreg. Dacă o variabilă are un anumit tip, atunci informația conținută trebuie să fie compatibilă cu acel tip. Putem scrie:

Chiar dacă este puțin probabil să găsim vreun sport în care o echipă să marcheze 2457 de goluri, instrucțiunea este corectă fiindcă, din punctul de vedere al calculatorului, _goluriGazde este un număr întreg și valoarea sa poate fi orice număr întreg acceptabil (vom vedea mai încolo că există anumite restricții).

Totuși, nu putem scrie:

GInfo este în acest caz un text (vom vedea puțin mai târziu rolul ghilimelelor) și variabila _goluriGazde nu poate conține decât numere întregi. Dar, este perfect corect să scriem:

În acest caz tipul implicit este String. Pare ciudat și nu este deloc intuitiv. Ne-am așteptat ca ceva numit _goluriGazde să fie un număr. Totuși, limbajul ne permite acest lucru. Trebuie să ne amintim că un calculator face ce îi spunem să facă, nu ce am vrea noi să facă.

Variabilele pot avea diverse tipuri: ele pot fi numere întregi, numere cu zecimale (acestea sunt denumite uneori numere reale, dar nu e chiar corect), texte etc. Dar putem avea și tipuri mult mai complexe; putem avea variabile care reprezintă clădiri, animale, galaxii, atomi și așa mai departe.

Unele tipuri sunt disponibile direct, altele trebuie inventate. Cele disponibile pot fi utilizate imediat; cele create deja de alții pot fi și ele utilizate. Dar, tipurile noi trebuie întâi definite.

În C#, tipurile disponibile imediat poartă denumirea de primitive. Acestea sunt Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, DoubleSingleChar și Boolean. Primele opt pot conține numere întregi (vom vedea de ce sunt mai multe), următoarele două au o semnficație mai specială și le vom întâlni în viitor, următoarele două pot conține numere cu zecimale, următorul un așa numit caracter, iar ultimul doar o valoare de adevăr (adevărat sau fals).

Multe dintre ele pot fi specificate folosind denumiri alternative (mult mai des folosite). Excepție fac cele două tipuri despre care am spus că au o semnificație specială. Alternativele pentru celelalte tipuri sunt byte, sbyte, short, ushort, int, uint, long, ulong, doublefloatchar și bool.

Iată câteva exemple de declarații (împreună cu inițializările):

Avem așadar un număr întreg a care are deocamdată valoarea 5, un număr cu zecimale b care are valoarea 5.1, un caracter c care are valoarea + și un așa numit boolean d cu valoarea true (adevărat), valorile booleene trebuie scrise în engleză și pot fi true sau false.

Mai avem un tip special, aproape primitiv din anumite puncte de vedere, numit String. Variabilele String conțin șiruri de caractere (mai multe caractere într-o anumită ordine). Există și alternativa string.

De obicei, string-urile conțin texte, iar caracterele sunt litere, cifre, semne de punctuație etc. Vom vedea în viitor că aceste caractere pot reprezenta și alte lucruri, dar deocamdată să considerăm string-urile ca fiind texte.

Un exemplu pentru declararea și inițializarea unei variabile de tip String ar fi:

Despre tipurile mai complicate vom discuta cu altă ocazie.

Numere

Am spus că în C# există mai multe feluri de numere și chiar mai multe feluri de numere întregi. Știm că avem o infinitate de numere întregi. Pentru numere foarte mari, noi am nevoie să scriem multe cifre; la fel, calculatoarele ar avea nevoie să folosească tot mai multă memorie pe măsură ce numerele sunt mai mari. Dar, memoria calculatoarelor este finită. Diferitele variante de numere întregi ne spun cam câtă memorie dorim să utilizăm. Din acest motiv, pentru fiecare tip vom putea avea valori care nu depășesc o valoare maximă, specifică tipului. Unele tipuri întregi ne permit să folosim și numere negative. Semnul unui astfel de număr întreg este și el în memorie. Dar, datorită memoriei limitate, numerele trebuie să fie mai mari decât o valoare minimă specifică tipului. Celelalte tipuri întregi (byte și cele care încep cu u) permit doar utilizarea numerelor pozitive (inclusiv 0); u este presecurtarea de la unsigned (fără semn).

Pare complicat și ciudat, dar nu e chiar așa. În practică nu utilizăm numere foarte mari. În cele mai multe situații este suficient tipul int (valoarea maximă este 231 - 1, adică două miliarde și ceva). Uneori nu este suficient și avem nevoie de long. Valoarea maximă este 263 - 1, adică aproape zece miliarde de miliarde. Dacă avem nevoie de valori și mai mari e mai complicat, dar sunt soluții.

Am văzut cum declarăm o variabilă și cum o inițializăm. Dar, am spus că valorile variabilelor se pot modifica. Pentru aceasta avem nevoie de o instrucțiune. O astfel de instrucțiune arată așa:

Valoarea variabilei a va fi acum 2457 indiferent care a fost înainte. Informația înlocuită se pierde. Nu vom ști cât a fost acea valoare înainte, deci dacă avem nevoie de ea, ar fi fost bine să o punem altundeva (într-o altă variabilă de exemplu).

Instrucțiunea anterioară este validă numai dacă a este într-adevăr o variabilă de tip numeric. Ea trebuie să fi fost declarată anterior (nu neapărat și inițializată).

Să nu credeți că a = 2457; este o ecuație sau ceva asemănător; este o comandă. Calculatorului i se spune ca în zona de memorie corespunzătoare variabilei a să fie pusă valoarea 2457. O astfel de comandă se numește atribuire.

Printr-o instrucțiune de atribuire, unei variabile i se dă o valoare. Tipul acestei valori trebuie să fie compatibil cu cel al variabilei (vom vedea ulterior de ce, în unele cazuri, e posibil ca tipurile să nu fie chiar identice).

Așadar, o instrucțiune de atribuire conține denumirea variabilei care va primi valoarea, urmată se semnul = și apoi de valoarea propriu zisă. În cazul nostru, valoarea a fost numărul 2457.

Există mai multe modalități de a reprezenta numerele; 2457 este varianta care ni se pare nouă naturală; nu e nicio șmecherie, e chiar numărul care urmează după 2456 și e înainte de 2458. Fără să explicăm de ce și doar pentru a arăta că se poate și altfel dacă chiar vrem, același număr poate fi reprezentat prin 0x999. Instrucțiunea următoare are exact același efect:

În C#, numerele sunt numere simple dacă nu apare nimic altceva lipit de ele. Alte simboluri sau caractere le modifică semnificația. Partea 999 din 0x999 nu reprezintă deloc numărul 999.

Lucrurile pot deveni și mai ciudate: 2, '2' și "2" sunt complet diferite. Primul este numărul 2, al doilea este un caracter care reprezintă cifra 2 și al treilea este un string. Mai multe despre caractere și string-uri în secțiunea următoare.

Numerele cu zecimale pot și ele fi reprezentate așa cum ni se pare nouă natural; 2.5 este o valoare corectă; dar, putem avea și ciudățenii ca 1e-4 sau 5D.

Nu dorim să explicăm aceste lucruri care par bizare; dorim doar să atragem atenția că în multe cazuri lucrurile nu sunt ceea ce par.

Caractere și string-uri

În C# un caracter reprezintă un simbol. Poate fi o literă, o cifră, un semn de punctuație, un operator matematic etc. În C# valoarea unui caracter este cuprinsă între apostroafe. În principiu, avem un apostrof, un semn și apoi un alt apostrof. De exemplu, caracterul + trebuie scris '+'.

Dar, ce ne facem dacă vrem să avem chiar valoarea apostrof? Ați putea crede că ''' este soluția, dar nu e chiar așa. Al doilea apostrof este interpretat ca fiind sfârșitul elementelor care descriu caracterul și al treilea nu mai este înțeles. Ca urmare, instrucțiunea c = '''; nu este corectă.

Ni se oferă o soluție… Putem marca al doilea apostrof cu un simbol special care să indice faptul că acesta nu trebuie interpretat ca sfârșit al descrierii caracterului, ci ca semn propriu-zis. Elementul special este \ (backslash). Varianta corectă a instrucțiunii este:

Ar părea că ni s-au rezolvat toate problemele, dar… dacă avem nevoie fix de backslash? c ='\'; nu e corect fiindcă backslash-ul indică faptul că următorul element trebuie interpretat ca fiind semnul apostrof. Soluți este să marcăm semnul backslash cu un alt backslash. Deci, pentru a atribui unei variabile valoarea \, va trebui să scriem:

String-urile sunt cuprinse între ghilimele. Ați ghicit probabil, dacă unul dintre caracterele string-ului este chiar @quot;, avem o problemă. Probabil intuiți soluția, vom marca astfel de caractere cu backslash. Dispare problema cu apostroful (nu mai trebuie marcat) și este în continuare prezentă cea cu backslash-ul (trebuie și aici dublat).

Dar… avem probleme suplimentare. Spuneam că string-urile sunt folosite în special pentru a păstra valori care reprezintă texte. Și textele pot avea mai multe linii. Cum facem?

Dacă scriem:

vom vedea că nu e corect.

Avem conceptul de caracter special de sfârșit de linie. Dacă dorim să avem textul Gazeta de Informatică scris pe trei rânduri (câte un cuvânt pe o linie), vom scrie:

Totuși, avem o alternativă. Dacă punem un @ în fața ghilimelelor care marchează începutul string-ului, atunci putem folosi mai multe linii. Iată un exemplu:

Dar, pentru a complica puțin lucrurile, prezența acestui @ face ca backslash-ul să nu mai aibă un rol special în interiorul string-ului. Este tratat ca fiind un caracter normal. Ajungem să avem din nou probleme cu ghilimelele. De exemplu, @"\"" nu mai este valid. Din fericire, ni se oferă o soluție. Trebuie să dublăm ghilimelele. Așadar, dacă vrem un string care să conțină un singur caracter, iar acest caracter să fie ghilimele, am putea scrie @"""".

Va urma

În cadrul episodului următor vom prezenta detalii referitoare la modul în care sunt efectuate operațiile (nu neapărat matematice) și vom vedea ce sunt și la ce sunt folosite comentariile.