Sunteți pe pagina 1din 349

Povestea lui Bitulică

Într-o zi dintr-o întâmplare


Am descoperit informația
Declic

A fost o dată ca niciodată, că de n-ar fi fost, nici nu s-ar fi povestit.

Au fost odată un băiat și o fată care s-au cunoscut și s-au îndrăgostit pe când erau la
Facultatea de Științe. El - la Fizică, ea - la Matematică. Rodul dragostei lor sunt eu, Andrei.
Născut în 1970, când se crapă de vară.

De mic copil mi-a plăcut să mă joc în țărână și tot de pe atunci sunt fascinat de tot ce
sclipește. Găseam pietricele sclipitoare și le ascundeam în palmă.

Îmi plăcea să le ascund, iar oamenii să ghicească. Niciodată nu trișam. Nu ascundeam două
pietre sau nici una și niciodată nu le dădeam pietricica celor care ghiceau unde se ascunde.
Nu a trecut mult timp și mai toți cunoscuții mă strigau „Bitulică”.

Nu înțelegeam de ce, dar aveam să găsesc răspunsul ceva mai târziu.

Pe măsură ce am crescut, m-am apucat de alba-neagra și am rămas fascinat de tot ce


sclipește, doar că între timp am descoperit aurul.

Până nu demult, credeam că este și cel mai prețios lucru, judecând după valoarea lui în bani
și după faptul că nu se depreciază în timp, ca alte lucruri, dar de curând am făcut rost de o
bucata mai mare de aur și, deși credeam că nu m-a văzut nimeni cu ea, când am fost la
bijutier, am aflat că valorează 1000 de dolari, dar se pare că nu era chiar așa.

Au venit câțiva să le-o dau, însă eu nu am vrut. Am ascuns-o într-un loc sigur numai de mine
știut, iar celor care mă întrebau de ea le-am cerut câte 1.000 de dolari să le spun unde am
ascuns-o, adică exact cât valorează bucata mea de aur.

Nu i-am mințit, dar nici nu le-am dat-o. I-am pus s-o caute și, cine o găsește primul, a lui să
fie. Iar de s-or certa, nu e treaba mea.

Așa am făcut câteva mii de dolari și am descoperit că informația este mai valoroasă decât
aurul.

De atunci numai la asta m-am gândit. Cum să fac să produc informație.

Am întrebat în stânga și-n dreapta și toată lumea care se pricepea sau auzise de chestia asta
numită „informație” mi-a spus că ar trebui să devin programator.

© Bitulică 2020
Povestea lui Bitulică

În urma unei șanse imense


Am ajuns în Statele unite
Declic

Tot căutând cum să fac și ce să fac să pot produce informație despre care descoperisem că e
atât de valoroasă, pe când mergeam eu așa prins cu capul în ziar parcă de nicăieri în fața
mea a apărut un copac.

Era falnic, avea o coroană cum rar mi-a fost dat să văd și am văzut-o de jos în sus după ce
mi-am revenit din lovitură. Dădusem cu capul în el.

Am coborât ochii de pe crengi și chiar sub ele mi-au zăbovit pe un afiș pe care scria că o
companie americană organizează o tombolă cu premii la care pot participa doar tineri care
nu au avut niciodată de-a face cu domeniul IT.

Mă încadram pe jumătate. Căci doar habar nu aveam de tehnologie în general și cu atât mai
puțin de tehnologia informației dar nu eram chiar așa de tânăr încât să mă calific pe deplin.

Am lângă mine trei femei. Sunt însurat cu o femeie frumoasă și am două fete la fel de
frumoase și toate trei sunt pe atat de istețe pe cât le este frumusețea. Așa că fascinat de idee
am rugat-o pe fata noastră cea mare care tocmai terminase facultatea de limbi străine, să se
înscrie.

A acceptat, și nu știu cum a făcut dar a câștigat marele premiu care consta într-un job
fulltime de Full Stack Software Developer în companie și un pachet complet de relocare
pentru întreaga familie.

Nu am stat mult pe gănduri ne-am făcut bagajele și am decolat cu primul avion spre țara
tuturor posibilităților unde am fost așteptați la aeroport de o reprezentantă a companiei
care ne-a înmânat cheile casei pe a cărei terasă stau și scriu acum aceste câteva rânduri
răscolindu-mi amintirile și fiind încă o dată recunoscător, a câta oară oare, pentru tot ce mi
s-a întâmplat.

Cea care ne-a așteptat în sala de așteptare a aeroportului ne-a mai dat o mașină și o sumă
de bani cât să putem să ne descurcăm până la primirea primului salariu. Un fel de primă de
instalare.

Acum suntem cu toții în Silicon Valley, pe coasta de Vest a Statelor Unite. Orașul de numește
San Jose și este o suburbie a marelui San Francisco.

Am primit o casă, slujbe în cadrul companiei compatibile cu pregătirea noastră anterioară și


posibilitatea de a o trimite la o scoală privată pe fata noastră cea mică.

Pe mine m-au pus pe vânzări. Se pare că mă descurc, am talent înnăscut.

© Bitulică 2020
Povestea lui Bitulică

Dar nu renunț. Vreau să devin programator.

Soția mea lucrează în cadrul departamentului de resurse umane la fel ca în România iar fata
mea cea mică este înscrisă în clasa a IX-a. Primul an de liceu.

Mi s-a spus că în companie se fac mereu angajări și că sunt deschiși la orice oportunitate
însă mi s-a pus în vedere că eu spre deosebire de fata mea cea mare va trebui să susțin un
interviu riguros.

Apropo , când a ajuns aici fata mea a fost repartizată în cadrul diviziei Smart, departamentul
Classic Smart Things.

Adică fac lucruri clasice să devină inteligente. I-au dat să facă un proiect, Unul secret. Nu
știu nimic.

Cică e secret intern și nu are voie să spună.

© Bitulică 2020
Povestea lui Bitulică

RESURSE
Într-o zi pe asfințit
Am hotărât să programez
UMANE

Pentru că este o veche pasiune de-a mea pe care din diferite motive nu am pus-o încă în
practică azi am decis nu mai amân.

Am un gând care mă fascinează de ceva vreme şi pe care cred că dacă îl pun în practică m-ar
ţine conectat şi m-ar ajuta să nu dau înapoi.

M-am gândit că cel mai bine ar fi să încerc să fac un proiect complex, chiar dacă, acum nu
am nici o idee cum să îl realizez.

Îmi doresc o casă inteligentă făcută de mine fără să cumpăr chestii gata făcute. Așa voi
învăța lucrând și îmi voi dezvolta capacitățile și voi prinde experientă practică.

Consider că un lucru este inteligent atunci când este în stare să zică nu, adică să poată lua
singur decizii și chiar dacă primește o comandă care îi cere să facă ceva el să analizeze acea
cerință și să o execute doar dacă este conformă cu modul lui de gândire sau cu datele pe
care le are și cu care poate prevede și preveni o situație sau alta care s-ar ivi dacă respectiva
comandă ar fi executată.

Încerc să urmez drumul care mi se pare cel mai firesc. Dezvolt proiectul şi când mă lovesc
de lucruri pe care nu le ştiu mă opresc și aprofundez până când sunt sigur că le-am înţeles,
ştiu cum şi mai ales de ce să le folosesc. Apoi continui.

Am nevoie de limba engleză. Informaţia originală şi termenii folosiţi în industria IT sunt în


limba engleză iar dacă voi vrea să lucrez într-o companie multinaţională va trebui să știu să
vorbesc atât la nivel interuman, cât şi tehnic pentru a mă înţelege cu colegii.

Am ales să învăţ pe cont propriu dar vreau să mă certific.

Certificările mă vor ajuta în dobândirea încrederii în forțele proprii și în cariera de Full


Stack Software Developer.

Poate chiar în ceea ulterioară, de Project Manager.

© Bitulică 2020
Povestea lui Bitulică

RESURSE Întrebând pe cine trebuie


Am descoperit aptitudinile necesare
UMANE

Am întrebat prin împrejur și am înțeles că pentru a fi un bun programator am nevoie de


câteva lucruri care la unii sunt înnăscute iar alţii le dobândesc în timp.

Am nevoie de răbdare căci chiar dacă un computer executa fix ce îi spun şi nu ar trebui să
comenteze la ce îi spun să facă trebuie să am în vedere că nu eu sunt cel care scrie primul
program pe care trebuie să îl execute componentele hardware şi nu eu sunt cel care a făcut
aceste componente.

Componentele hardware sunt concepute de electronişti care le-au învăţat să ştie să facă
anumite lucruri şi sunt comandate de drivere care sunt programe scrise de alţi
programatori.

Driverele sunt comandate la rândul lor de sistemul de operare care este un program scris
de alţi programatori şi eu programez folosind un limbaj de programare care rulează pe
sistemul de operare și care este scris de alţi programatori.

Astfel este foarte posibil ca de multe ori când îi cer ceva unui computer acesta să zică că nu
poate să facă ceea ce îi cer pentru că nu i-am cerut ceva în concordanţă cu ce au fost
învăţate să facă componentele electronice, driverele, sistemul de operare şi limbajul de
programare în care încerc să îi spun ce vreau să facă.

Aşa că am nevoie de răbdare până reuşesc să îl fac să facă ce vreau eu.

Implicit am nevoie de perseverenţă pentru că dacă nu voi reuşi să îl fac să facă ce vreau eu
după încercări repetate nu e bine să renunţ ci să încerc până când va face exact ceea ce
vreau eu să facă, Iar asta poate dura.

Am înţeles că este bine să am o gândire tranşantă adică să pot spune clar că ceva este ori alb
ori negru fără să spun că este o combinaţie de mai mult sau mai puţin dintre cele două
culori, pentru că un computer este format din componente electronice care alternează două
stări clare.

Niciodată răspunsul unui computer nu va fi gri ci ori alb ori negru, nici măcar la computerul
cuantic nu se întâmplă asta pentru că deşi acolo calculele intermediare implica stări
ambigue în concordanţă cu principiul superpoziţiei cuantice, răspunsul final va fi tot o
singură stare pentru că intervine fenomenul de colaps cuantic.

Am mai înţeles că am nevoie de o gândire logică.

Adică să pot desluşi implicaţiile care rezultă în urma unei acţiuni.

© Bitulică 2020
Povestea lui Bitulică

De exemplu dacă eu arunc cu piatra în geam implicaţia acestei acţiuni este că geamul se va
sparge.

Am nevoie de o astfel de gândire pentru că pe acest principiu gândeşte şi un computer şi


este bine să gândim la fel dacă vrem să ne înţelegem.

© Bitulică 2020
Povestea lui Bitulică

RESURSE
Continuând să întreb
Am aflat deprinderile necesare
UMANE

Un computer gândeşte executând operaţii logice la fiecare pas. Gândirea logică este baza
unui alt tip de gândire pe care trebuie să o am şi anume gândirea raţională.

Gândirea raţională implica construirea de raţionamente logice prin care plecând de la o


idee pot ajunge la o altă idee.

De exemplu dacă ştiu că Alina are mere şi că Alina este mama mea atunci pe baza acestor
afirmaţii pot să construiesc raţionamentul prin care eu o să mănânc mere.

Am ajuns la acesta idee prin faptul că dacă Alina este mama mea îmi va da şi mie ce are ea
dacă îi voi cere fiindcă sunt copilul ei şi nu vrea să mă lase nemâncat.

Şi cum Alina are mere înseamnă că eu voi mânca mere.

Un alta deprindere pe care am înţeles că e bine să o am este să pot crea raţionamente logice
în perspectivă, adică pe termen lung în care să pot prezice cât mai multe din situaţiile logice
care pot apare în timp.

Cu alte cuvinte să fiu un şahist bun care îşi construieşte strategia de joc gândind cum va
putea muta adversarul dacă el face o mutare sau alta.

Am înţeles că programatorii buni sunt şi buni şahişti asta dacă ştiu să joace şah.

Prevederea situaţiilor ce pot apărea ulterior cred că ține şi de experiența acumulată şi poate
şi de un anumit grad de intuiţie.

Până la urma prevederile sunt o combinaţie de istorie, analiză a prezentului şi intuiţie.

Am înţeles că este necesară şi capacitatea de abstractizare adică să pot crea un model pe


care să se poată mula cât mai multe lucruri concrete.

De exemplu să pot crea un model de maşină pe care să se poată construi orice mașină,
modelul de bază permiţând asta fără ajustări.

Atunci când implementez un lucru el trebuie să iasă cât mai bine și asta am înțeles că
presupune să fiu atent la detalii pentru că din lucrurile mici bine făcute ies lucruri mari care
funcționează bine si un computer nu știe să facă nimic dacă nu îi spun eu așa că trebuie să
fiu atent să îi dau și cele mai mici detalii.

© Bitulică 2020
Povestea lui Bitulică

E clar că trebuie să îmi placă foarte mult ceea ce fac şi chiar să fiu îndrăgostit pentru că am
înţeles că este nevoie de o capacitate de învăţare continuă întrucât tehnologia evoluează cu
paşi repezi şi datele problemei se schimbă foarte repede.

Datorită evoluţiei tehnologiei un singur om nu poate să facă o aplicație complexă cap coadă
şi este nevoie şi de abilităţi de comunicare şi flexibilitate pentru a putea să mă încadrez în
echipă.

Am înțeles că mai important decât cum îi spun unui PC să facă ceva este ce îi spun să facă.

Adică important e algoritmul nu limbajul.

© Bitulică 2020
Povestea lui Bitulică

Când am început să știu ce am nevoie


Am ales tipul de computer
HARDWARE

Până ieri credeam că un calculator şi un computer sunt totuna, dar am aflat că un computer
este un calculator pe care pot să îl programez.

Primul computer a fost construit la Philadelphia în Statele Unite şi a fost botezat ENIAC.

John von Neuman a creat prima arhitectură standard a unui computer ca fiind formată din 4
module:

• UAL adică Unitatea Aritmetico-Logica


• UCC adică Unitatea de Comandă şi Control
• MC adică Memoria Computerului
• I/O adică dispozitivele de Intrare şi Ieşire

care comunică printr-o bandă numită Magistrală.Ulterior din 4 module au rămas 3 după ce
UAL şi UCC au format împreună UCP adică Unitatea Centrală de Procesare.

Există supercomputere care au o putere de procesare mare şi sunt voluminoase. Sunt


utilizate de companii ce au nevoie să calculeze volume mari de date în timp scurt.

Tot super computere sunt şi Main Frame-urile care spre deosebire de primele sunt
proiectate pentru a avea o putere de stocare mare fiind utilizate de companii care stochează
volume mari de date. Utilizatorii se conectează prin terminale la ele.

Am aflat că există şi minicomputere, care sunt mici semnificativ decât supercomputerele,


fiind utilizate în controlul şi automatizarea producţiei din fabrici şi marile depozite.

Există şi microcomputere. Acestea sunt computerele cu care sunt familiarizat şi sunt


computerele pe care le ştiu eu.

PDA-urile, al căror nume vine de la Personal Digital Assistant adică Asistent Personal Digital
sunt un fel de agenda electronică. Astea par să fie strămoşul telefoanelor mobile şi al
tabletelor.

Eu am nevoie de un microcalculator şi am înţeles că pot să aleg fie desktop fie laptop.

Am ales desktop pentru că am aflat că laptop-urile fiind mai compacte, au toate piesele sub
tastatură şi dacă vărs cafeaua pe ea risc să îl stric.

Deasemenea ecranul lor este rabatabil şi tot ridicându-l şi coborându-l îl pot deteriora. Am
înţeles şi că desktop-urile sunt mai puternice şi mai uşor de configurat şi că au ecranul mai
mare.

© Bitulică 2020
Povestea lui Bitulică

Pot avea mai multe monitoare și chiar dacă şi la laptop se pot lega mai multe monitoare, eu
vreau desktop pentru că deşi laptopul îmi oferă libertate de mişcare şi consumă mai puţin
curent mă simt mai comod când lucrez cu un desktop.

© Bitulică 2020
Povestea lui Bitulică

Citind pe net și întrebând oamenii


Am ales tipul de sistem
HARDWARE

Am înțeles că pot opta pentru una din două categorii de sisteme de calcul.

Pentru sistemele construite de firma Apple sau pentru sistemele construite de diverși alți
producători de sisteme de calcul.

Există argumente solide pro și contra în ce privește alegerea a uneia sau a alteia dintre cele
doua categorii de sisteme, argumente pe care am încercat să le analizez pentru a lua cea mai
bună decizie pentru nevoile mele.

PC-urile sunt mai ieftine și am o libertate de alegere mai largă.

Un sistem PC poate fi construit personalizat, în timp ce pentru Mac, configurațiile sunt


predefinite.

Un Mac vine și cu o garanție a calității, în timp ce PC-urile sunt produse de mai mulți
producători, fiecare cu propuneri specifice de calitate a materialelor și a configurației.

PC-urile sunt mult mai flexibile când vine vorba de upgrade-uri.

La dispozitivele Apple, pot fi făcute upgrade-uri, doar de RAM și unitatea de stocare. PC-
urile sunt preferate de gameri datorită acestei posibilități.

În general, există un volum mai mare de aplicații pentru PC-uri.

Cea mai mare parte a producătorilor de software se orientează către Windows.

Majoritatea utilizatorilor de computere folosesc

PC-uri cu sisteme de operare Windows, așa că există o comunitate puternică pentru suport
și sfaturi practice.

Modelele vechi de PC-uri au o compatibilitate mai bună cu sistemele de operare noi.

De exemplu, un PC vechi de cinci ani, poate funcționa foarte bine cu Windows 10, în timp ce
un Mac vechi de cinci ani va funcționa foarte bine doar cu varianta sistemului OS X de la
Apple pentru care a fost creat.

Am ales să îmi iau PC pentru a-mi face singur configurația, ocazie cu care o să învăț câte
ceva despre cum lucrează un computer în ansamblu, la ce folosește și cum funcționează
fiecare componentă în parte.

© Bitulică 2020
Povestea lui Bitulică

Pentru început
Am ales tipul de carcasă
HARDWARE

Înțeleg că trebuie să aleg o carcasă pe masura plăcii de bază și să țin cont că placa video
poate ocupa mai multe sloturi.

Există carcase tip care pot avea formatul

• CubeTower • Flex ATX


• FullTower • E-ATX
• MiddleTower • ATX
• Mini ITX • mATX
• MiniTower • mITX
• OpenCase • HPTX

fiecare format cu dimensiunile lui specifice.

Pentru sursă, predomină formatul ATX, însă există și surse tip SFX, pentru caracase ITX.
Majoritatea carcaselor folosesc surse care se montează în partea de jos, pentru a trage aer
rece de sub carcasă ce au ventilatorul în interior pentru a trage și evacua aer cald în
exterior.

O carcasă are multe ventilatoare, sau radiatoare dar obligatorii sunt ventilatoarele din față.

Ele creează presiunea pozitivă care scoate praful în afară și nu îl absorbe. În spate există un
singur ventilator.

Un model cu spațiu amplu și puncte de prindere în spatele panoului care susține placa de
baza este ideal pentru managementul firelor și că acest aspect asigură o răcire mai bună și
este mai estetic.

Observ că ar fi bine să am porturi și conectori accesibili în partea din față a carcasei.

O pereche de porturi USB 2.0 sau 3.0 și mufe pentru casti audio și microfon ar fi suficiente.
Poate chiar un port USB Type-C.

Pe partea estetică mai multe carcase oferă în partea de jos un PSU shroud care acoperă
sursa de alimentare și cablurile care ies din ea și deci rezolvă cumva problema wire
managementului.

Am ales o carcasă tip MiddleTower format ATX de culoare neagră, cu geam lateral
transparent din plexiglass, cu un sistem de led-uri, cu o sursă de 600 W, montată în partea

© Bitulică 2020
Povestea lui Bitulică

de jos, cu trei ventilatoare în partea din față, două în partea de sus și unul în partea din
spate.

Carcasa are doua lăcașuri Bays 3.5 și trei de 2.5 iar în partea din față trei porturi USB, dintre
care doua tip USB 3.0 și unul tip USB 2.0, precum și o mufă de ieșire tip jack mic stereo de
3,5 nm pentru căști sau orice sistem audio și una de intrare tip jack mic stereo de 3,5 nm
pentru microfon sau mixer, alături de butoanele de Power și respectiv Reset.

© Bitulică 2020
Povestea lui Bitulică

Când am decis să continui


Am ales placa de bază
HARDWARE

Am de ales între două platforme. Fie platforma AMD, fie platforma Intel. Ambele par
performante mai ales după apariția generației de procesoare Ryzen dezvoltate de AMD.

O placă de bază cu arhitectură Intel, suportă doar procesoare Intel, iar o placă AMD doar
procesoare AMD, pentru că între Socket, adică suportul procesorului, și procesor trebuie să
existe compatibilitate perfectă.

Modelele de procesoare suportate, numărul, tipul și viteza conectorilor, funcții precum


overclocking sau numărul de plăci video conectate în SLI și Crossfire, sunt dictate de
Chipset-ul plăcii de bază.

Înțeleg că formatele plăcilor de bază sunt:

• ATX
• mATX
• mITX
• XL-ATX
• E-ATX

și că formatul standard este ATX.

Pe placa de bază se montează memoria RAM, iar standardul este DDR4 pe 288 de pini.

Plăcile suportă o cantitate minimă de 32 de GB de RAM dual channel. Pe placă există porturi
USB și Serial ATA, conectorii m.2 pentru SSD, cu interfață PCI Express, sau SATA III,
Thunderbolt, conectori audio și video, ca VGA, DVI, HDMI sau Display Port, cip-uri integrate,
ca cip-urile audio și cip-urile de rețea, controller RAID, pentru hardisk-uri.

Placa mai contine conectorul sursei de alimentare, conectorul de 12 volti pentru procesor,
porturile PS/2 pentru tastatură și mouse, portul paralel, clock-ul adică ceasul care
sincronizează procesorul cu restul plăcii de bază și conectorii IDE.

Văd că placa de bază are un soft care se numeste BIOS adică Basic Input Output System și
care oferă opțiuni pentru controlul componentelor.

Am ales o placă de bază construită pe arhitectură Intel, format mATX, cu socket procesor
1151, cu cipset B360, care are doua sloturi PCI Expres x1, doi conectori m,2, un PCI Express
x16 și șase sloturi SATA III.

Suportă procesoare Intel 8th Generation Core i7/i3/i5/Pentium Celeron, are cipset video
integrat Intel HD Graphics și cipset audio 7.1 Audio with Realtek ALC887.

© Bitulică 2020
Povestea lui Bitulică

Cipsetul de rețea este Realtek RTL8111H care suportă viteze de 10/100/1000 Mbps.

Tipul de memorie este DDR4, iar placa de bază suportă maxim 64 GB pe patru sloturi de
memorie cu tehnologie dual channel.

Frecventele procesorului suportate de placa de baza sunt 2666/2400/2133 MHz.

© Bitulică 2020
Povestea lui Bitulică

După placa de bază


Am ales procesorul
HARDWARE

Este prescurtat CPU adică Central Processing Unit, și are ca și caracteristică frecvența de
lucru. Frecvența măsoară în Herți, de cate ori pe secundă se întâmplă ceva.

În cazul procesorului, măsoară momentele când ia o cantitate de biți. Adică tick-urile.

Procesorul are mai multe module și fiecare este specializat în anumite operații.

Poate fi:

• Single Core
• Dual Core
• Triple Core
• Quad Core
• Octa Core

în funcție de câte nuclee are. Unul Octa Core are 8 nuclee și poate să execute 8 operații în
paralel. Un procesor execută un program, adică o secvență de instrucțiuni stocate în
prealabil.

Când execută o parte din program, restul instrucțiunilor și datelor sunt stocate în memoria
cache. Memoria cache este o memorie care reține datele folosite recent evitând întoarcerea
lor în memoria principală, care este mai lentă și astfel datele sunt procesate mai rapid.

Există două arhitecturi ale procesorului.

• Arhitectura RISC care folosește un set redus de instrucțiuni executate rapid.


• Arhitectura CISC care folosește un set complex de instrucțiuni cu număr redus de
pași pe fiecare operație.

Procesorul contine:

• un sector pentru aritmetică


• un sector pentru decodare de instrucțiuni
• un sector care controlează viteza
• un sector care contine regiștrii, adică cea mai mică memorie posibilă din computer
• un sector care se ocupă cu grafica și mai nou northbridge-ul adică modulul din nord,
cu rol in coordonare care contine cipset-ul video.

Pentru ca am ales Intel, mă interesează procesoarele Intel, a căror generație Intel Core este
cea mai nouă și cuprinde Core 2 și Core i, care, la rândul ei, cuprinde procesoarele i3, i5, i7
și i9.

© Bitulică 2020
Povestea lui Bitulică

Procesoarele i3 sunt de regulă dual core. i5 quad core, i7 six core iar i9 octa core.

Am ales un procesor Intel i7 8700 adică generația a 8-a, cu 6 nuclee și 12 thread-uri adică 1
nucleu virtual pentru fiecare nucleu fizic.

Frecvența procesorului este de 3200 MHz iar tehnologia de fabricație 14 nm adică atât
măsoară un tranzistor folosit la fabricarea procesorului.

Memoria cache este de 12288 kB iar arhitectura procesorului este Coffee Lake.

© Bitulică 2020
Povestea lui Bitulică

Când am aflat că trebuie


Am ales memoria RAM
HARDWARE

Văd că este o memorie cu acces aleatoriu și permite accesarea directă a oricărei celule a ei,
oriunde ar fi, prin specificarea coordonatelor exacte. Cele mai folosite memorii de tip RAM
sunt DRAM și SRAM.

O memorie realizează următoarele funcții:

• identifică adresa fiecărei zone de memorie adică linia și coloana


reîmprospătează secvențial celulele utilizate, cu ajutorul contorului
• citește nivelul de electroni prin senzorul de amplificare
decide ce zonă de memorie trebuie încărcată
• identifică tipul, viteza, spațiul de memorie și verifică apariția erorilor prin cipuri.

Alte tipuri de memorie sunt:

• FPM DRAM
• EDO DRAM
• DDR SDRAM
• RDRAM
• CMOS RAM
• VRAM

Memoria DDR a ajuns la generația DDR4.

Memoria DRAM reprezintă o memorie dinamică cu acces aleatoriu compusă din celule.

Fiecare celulă este creată dintr-un tranzistor și un condensator, reprezentând un bit de


memorie care poate lua valoarea 1 sau 0. Tranzistorul funcționează ca un comutator, care
permite cipului de memorie să citească și să modifice starea condensatorului.

Condensatorul se folosește pentru a stoca electroni. Atunci când acesta se încarcă cu


electroni stochează valoarea 1 în bitul de memorie, respectiv 0 în cazul în care acesta este
gol. Celulele de memorie RAM sunt așezate ca elementele unei matrice.

Localizarea unui bit se face prin intersectarea liniei și coloanei pe care se găsește, aceasta
reprezentând adresa bitului.

Memoria statică SRAM, funcționează diferit față de cea dinamică. Un bit de memorie este
format din patru sau șase tranzistori interconectați și nu necesită reîmprospătare.

© Bitulică 2020
Povestea lui Bitulică

Astfel, viteza de scriere și de citire a unei memorii statice este mai mare decât a celei
dinamice. Însă datorită mulțimilor de tranzistori din care este făcută, aceasta ocupă mai
mult spațiu și este mai scumpă.

De aceea, memoria statică este folosită doar pentru crearea memoriei cache la procesoare,
iar memoria dinamică pentru crearea memoriilor RAM.

Am ales o memorie RAM ADATA Premier tip DDR4 cu o capacitate de 16GB care lucrează la
o frecvență de 2666 MHz, formată din 2 plăcuțe a cate 8 GB care ocupă doua sloturi pe placa
de bază.

© Bitulică 2020
Povestea lui Bitulică

Ca să am unde să îmi pun datele


Am ales unitățile de stocare
HARDWARE

Vreau să aleg o unitate de stocare și am la dispoziție trei variante: SSD, SSHD și HDD.
Diferența între ele constă în viteza de transfer.

Hardisk-urile conțin discuri rotative pe care sunt scrise datele. Cele pentru PC-uri au 5400
rpm, 7200 rpm și 10.000 rpm.

Interfețele folosite pentru harddisk-uri sunt de tip P-ATA, S-ATA, S-ATA II, respectiv S-ATA
III.

SSD-urile sunt mai rapide și dispun de o memorie flash, bazată pe tehnologie NAND.

Ele nu dispun de componente în mișcare, și deci sunt mult mai puțin vulnerabile la șocuri
mecanice.

Funcționează fără zgomot și au un consum mai redus de energie.

SSHD-urile, sunt o combinație între SSD și HDD, Conțin atât părți mecanice cât și memorie
flash, care are o capacitate mai mică decât partea mecanică.

Unitatea de stocare are un buffer, adică o memorie suplimentară integrată, pentru a nu se


citi des de pe ea datele utilizate frecvent.

Cand procesorul are nevoie din nou de acele date, unitatea de stocare nu le mai ia de la locul
unde se găsesc, ci din buffer. Astfel citirea funcționează mai rapid.

Marimea buffer-ului poate varia în funcție de tipul unității de stocare de la 64 MB la 4GB.

Prin operația de ștergere se șterge intrarea din tabela de alocare a fișierelor, fapt care face
ca fișierul să nu mai fie văzut, fără a șterge efectiv informația de pe unitatea de stocare, deci
fără a schimba biții adică polaritățile.

Apoi unitatea are undă verde să rescrie biții acelui fișier. Ștergerea reală înseamnă
suprascrierea cu informație vidă, adică mâzgălitură, care se poate face prin formatare, sau
cu programe speciale.

Un fișier este un bloc de date delimitat corespunzător pe unitatea de stocare.

Am ales o soluție HDD + SSD în care HDD-ul este WD Blue cu capacitate 1 TB, 7200 de
rotații pe minut și interfață SATA III iar SSD-ul este Kingston A400 cu capacitate de 240 GB
și interfață SATA III

© Bitulică 2020
Povestea lui Bitulică

Ca să observ ce se întâmplă
Am ales placa video
HARDWARE

Au fost dezvoltate pe un anumit standard pentru a fi compatibile cu placa de bază.


Funcționează pe PCI-express.

Au un procesor grafic, aproximativ ca cel de la procesor care se numeste Graphics


Processing Unit.

Pixel Pipelines este parte din placa video care transformă informația din pixeli.

Pot ajunge până la 3072 pixel pipelines.

Shader Model sunt instrucțiuni ca: Vertex, Geometry, Pixel, folosite de OpenGL și Direct3D
care ajută la utilizarea efectelor grafice.

BUS-ul este traseul dintre procesor și memorie iar o placă video poate avea până la 512 biți
pe BUS adică atâția biți pot circula între memorie și procesor.

Cu cât există mai multă memorie video, cu atat este mai bine dar o placă video cu BUS 512
și cu 1 GB VRAM este mai rapidă ca o placă video cu BUS 256 și 4 GB VRAM.

Răcirea este de două tipuri: activă sau pasivă. Cea pasivă este construită dintr-un radiator
de mari dimensiuni, iar cea activă are un radiator mai mic cu un ventilator care asigură
răcirea.

Plăcile cu răcire activă au temperaturile mult mai mici.

DirectX este o colecție de API dezvoltată de cei de la Microsoft prin care dezvoltatorii au
acces la funcțiile de nivel scăzut ale hardware-ului.

În momentul de față plăcile video sunt disponibile cu DirectX 11.

Plăcile video se conectează cu display-ul prin porturi ca:

• VGA care are semnal analogic


• DVI/HDMI sau Display Port care au semnal digital

Mai multe plăci se pot interconecta prin crossfire ATI sau SLI dacă sunt plăci produse de
Nvidia.

Am ales o placă video GTX 1660Ti cu 6 GB VRAM tip GDDR6 cu un port HDMI si 3 Display
Port

© Bitulică 2020
Povestea lui Bitulică

Ca să pot auzi
Am ales placa de sunet
HARDWARE

Pentru a permite funcționarea dispozitivelor de redare de sunet, un computer sau laptop


necesită o placă de sunet externă sau internă, numită și placă audio.

Plăcile se disting prin tipul de conexiune:

• USB
• PCI
• PCI-E
• FireWire
• ExpressCard
• PCMCIA.

Este responsabilă de crearea, convertirea, amplificarea și editarea sunetului redat de


computer.

Placa de sunet constă din mai multe sisteme hardware conectate, responsabile de
colectarea, producerea și procesarea datelor audio.

Scopul sistemelor audio este captarea audio, sinteza, și reproducerea acesteia.

Accesul la memoria dispozitivului se face direct printr-un cablu coaxial sau optic.

Sunetul este generat într-un procesor digital de semnal (DSP): redă anumite note, își
ajustează tonul, frecvența.

Puterea DSP și cantitatea totală de note disponibile se numesc polifonie.

Este necesară o placă de sunet pentru redarea corectă, precisă și la timp a sunetelor
solicitate de programele de calculator și de sistemul de operare al dispozitivului prin
difuzoare, căști.

Plăcile cele mai simple oferă calitatea CD, adică rata de eșantionare de 44,1 kHz, eventual
48 kHz la o rezoluție de 16 biți, cele de calitate mai mare au rata de eșantionare 96 kHz iar
cele de top 192 kHz.

În timp ce frecvența de 44,1 sau 48 kHz este în mod normal suficientă, altceva este la
adâncimea de eșantionare care determină calitatea digitalizării.

Sunt mai buni 24 biți, deoarece astfel sunt convertite mai calitativ și sunetele mai slabe iar
mixajul rezultat sună mai bine.

© Bitulică 2020
Povestea lui Bitulică

Conectorii de pe placa sunt:

• comutator pentru linia de intrare / instrument


• comutator pentru amplificarea semnalului de intrare
• comutator de alimentare Phantom pentru microfon condensator
• comutator principal pentru volumul monitoarelor de studio (difuzoare)
• comutator volum căşti
• ieșire căști
• comutator pentru audierea directă a instrumentului înregistrat
• intrare combinată pentru microfon (XLR) sau un instrument muzical (jack 1/4)

Am ales o placa de sunet Creative Sound BlasterX AE-5, cu funcție XAMP, led-uri
personalizabile, BlasterX Acoustic Engine, Dynamic Range (DNR): 122 dB.

Cu conectori pentru 1/8″ Front Out, 1/8″ (3.5mm) Headphone/Headset Out, 1/8″ (3.5mm)
Mic In/Line In, 1/8″ Center/Sub Out, 1/8″ Rear Out, TOSLINK Optical Out

© Bitulică 2020
Povestea lui Bitulică

Ca să pot comunica
Am ales placa de rețea
HARDWARE

Placa de reţea sau adaptorul de rețea, Network Interface Card, prescurtat NIC, este un
circuit electronic ce permite comunicarea între calculator şi reţea.

Se montează într-un slot PCI de pe placa de bază a calculatorului şi furnizează interfaţa de


conexiune cu reţeaua.

Tipul plăcii de reţea trebuie să corespundă cu mediul şi protocolul folosite în reţea.

Conexiunile pot fi twisted-pair, cablu coaxial, sau conexiuni pe fibră optică,

Tipul de conectare poate fi optică sau electrică.

Placa de reţea comunică cu reţeaua printr-o conexiune serială şi cu calculatorul printr-o


conexiune paralelă.

Fiecare placă de rețea poartă un identificator unic propriu, care îi permite să fie adresată și
regăsită chiar și în rețelele cele mai mari, de întindere globală maximă.

Miniaturizarea permanentă a redus necesitatea plăcilor de rețea ca piesă separată.


Funcționalitatea necesară a rămas aceeași, fiind acum integrată pe placa de bază.

Tipul de reţea utilizată poate fi

• Ethernet
• Token Ring
• FDDI

Rata de transmisie a biților poate fi 10/100/1000 de Mb/s, 10G sau 40G Tipul de conector
pe care placa îl acceptă pot fi Ethernet RJ45, LC, FC.

Tipurile de BUS folosite de stațiile de lucru și servere sunt PCI, PCI-X sau PCI-E.

Exisă cateva motive pentru a cumpara o placă de rețea separată, stand-alone.


Supratensiunile care afectează electronicele nu vin doar pe rețeaua de alimentare cu
energie.

Și cablul de rețea poate purta sarcină electrică dăunătoare.

Plăcile de baza moderne, în special cele de calitate, oferă un oarecare grad de protecție în
cazul supratensiunilor, însă ar fi păcat să fiu nevoit să inlocuiesc toata placa de bază în cazul
în care s-a defectat un singur cip, cum ar fi cel de rețea.

© Bitulică 2020
Povestea lui Bitulică

O placă de rețea pe fir Ethernet ar putea fi un grad de protecție în plus în acest sens.

Am ales o placă de rețea gigabit cu viteze de transfer de 10/100/1000 pentru a nu fi limitat


de placa de rețea atunci când îmi voi alege tipul de conexiune la internet.

© Bitulică 2020
Povestea lui Bitulică

Ca să pot vedea
Am ales un monitor
HARDWARE

Primele generații de monitoare au fost de tip digital , primind de la calculator toată


informația necesară afișării sub formă de semnale TTL adică Tranzistor Tranzistor Logic.

Sunt compatibile cu standardele IBM CGA și EGA și pot afișa un număr limitat de culori.

Monitoarele analogice pot afișa un număr nelimitat de culori și sunt cu mască de umbrire
sau cu grilă de apertură care au rolul de a filtra pixelii.

Un pixel este un punct luminos de pe ecran.

Monitorul este un dispozitiv de ieșire care primește informații de la placa video și poate fi

• CRT, adică cu tub catodic convențional


• LCD adică cu cristale lichide
• PDP, adică cu plasmă
• LED adică cu leduri

Azi toate monitoarele existente pe piață folosesc tehnologie LED. Modul în care este
implementată diferă.

Astfel, am de ales între

• tehnologia TN adică Twisted Nematic care oferă un răspuns rapid dar un unchi de
vizibilitate scăzut și culori mai sterse
• tehnologia IPS adică IN-PLANE SWITCHING care rezolvă problema unghiului de
vizibilitate și a culorilor dar consumă mai mult curent și timpul de răspuns este mai
mare
• tehnologia VA adică Vertical Alignment care este un hibrid între cele două având un
unghi de vizibilitate mai bun ca TN un contrast mai bun decat TN și IPS dar nu
reproduc culorile mai bine decât un IPS.

Rezoluția unui monitor este dată de numărul de pixeli pe orizontală înmulțită cu numărul
de pixeli pe verticală.

Există rezoluții ca

• SD adică Standard Definition care are 720 x 480 pixeli adică 480p sau 480i unde p
vinde de la progresive iar i de la interpolat și se referă la rata de refresh a imaginii
• HD adică High Definition care are 1280 x 720 pixeli
• Full HD adică Full High Definition care are 1920 x 1080 pixeli
• Quad FHD adică Quad Full High Definition sau 2k care are 2560 x 1440 pixeli

© Bitulică 2020
Povestea lui Bitulică

• UHD adică Ultra High Definition sau 4k care are 3840 x 2160 pixeli
• 8k care are 7680 x 5320 pixeli.

Timpul de răspuns este timpul in care un pixel trece din aprins în stins iar rata de
reimprospatare este frecvența cu care se reîmprospătează imaginea și e legata de cadrele
pe secunda, adică cu fps-urile pe care le au diferitele aplicații și care trebuie sa fie mai mici
ca rata de refresh pentru a nu apărea fenomenul de screen tearing, adică imagine sacadata
care se poate regla cu tehnologia sync.

Am ales monitor LED IPS Dell 27″, Wide, FullHD, SE2717H, la 75 Hz.

© Bitulică 2020
Povestea lui Bitulică

Ca să pot scrie
Am ales o tastatură
HARDWARE

Tastatura este o componentă periferică de intrare a computerului ce este conectată la


calculator printr-un fir introdus într-o mufă specială și îmi permite să introduc date cum
sunt litere, cifre şi semne speciale, prin apăsarea unor taste.

Cele mai folosite tastaturi sunt cele de tip QWERTY.

Un alt tip de tastaturi este tipul QWERTZ. Denumirile vin de la primele şase taste de pe
rândul al treilea.

Tipul QWERTY se foloseşte mai ales în ţările anglofone, iar celelalte folosesc mai ales tipul
QWERTZ.

Tastatura constã dintr-o serie de comutatoare montate într-o rețea, numitã matrice a
tastelor.

Când se apasã o tastã, un procesor aflat în tastaturã o identificã prin detectarea locației din
rețea care aratã continuitatea.

De asemenea, acesta interpreteazã cât timp stã tasta apãsatã și poate trata chiar și tastãrile
multiple.

Interfata tastaturii este reprezentatã de un circuit integrat denumit keyboard chip sau
procesor al tastaturii. Un buffer de 16 octeți din tastaturã opereazã asupra tastãrilor rapide
sau multiple, transmițându-le sistemului succesiv.

În cele mai multe cazuri, atunci când apãs o tastã, contactul se face cu mici întreruperi,
adică apar câteva clipuri rapide închis – deschis.

Acest fenomen de instabilitate verticalã a comutatorului se numește bounce, iar procesorul


din tastaturã trebuie sã îl filtreze, adicã sã îl deosebeascã de o tastare repetatã intenționat
de operator.

Lucrul acesta este destul de ușor de realizat pentru că întreruperile produse de


instabilitatea verticalã sunt mult mai rapide decât tastãrile repetate cele mai rapide.
WERTZ.

Există mai multe tipuri de tastaturi, însă cele mai răspândite sunt tastaturile cu 101 sau 104
taste, diferenţa între ele fiind dată, în principal, de prezenţa sau absenţa unor anumite taste.

De exemplu, tastatura 101 nu include tasta numită Windows Logo, în timp ce tastatura de
tipul 104 are inclusă această tastă.

© Bitulică 2020
Povestea lui Bitulică

Există tastaturi
• Standard
• tastaturi ergonomice
• tastaturi multimedia
• tastaturi fără fir
• tastaturi speciale.

Am ales o tastatură wireless Logitech MK235, USB, Grey.

© Bitulică 2020
Povestea lui Bitulică

Ca să pot arăta
Am ales un mouse
HARDWARE

Termenul mouse datează din 1965, când a fost găsit într-o publicație englezească.

A fost susținut de institutul Compact Oxford în dicționarul american Heritage.

Cercetatorul american Douglas Engelbart, de la Standford, a inventat primul mouse în 1963.

Acest mouse are exteriorul din lemn, și este voluminos, însă poate fi ținut cu o singură
mână. Mouse-ul folosește două rotițe așezate perpendicular pentru a putea detecta
mișcarea, având un singur buton.

În anul 1981 împreună cu sistemul Xerox 8010 Star Information, a fost comercializat
primul mouse pentru un sistem personal.

Mouse-urile au ergonomii diferite și sunt


• cu rotițe externe
• cu bilă
• optic
• cu laser
• mouse-ul cameră
• de picior
• trackball-ul
• mouse-uri touch.

Există mouse-uri concepute pentru persoanele cu dizabilitati.

Mouse-ul cu fir este mai ieftin ca cel wireless, nu are nevoie de baterii și este în general mai
rapid în transmiterea coordonatelor cursorului către PC, pentru că nu suferă de
interferențe electromagnetice.

Viteza unui mouse este exprimată în general prin DPI adică Dots Per Inch care reprezintă
numărul de pixeli al unui cursor atunci cand mouse-ul este mișcat un inch, adică 2,54 cm.

Un mouse laser performant are în general între 5000 DPI și 6000 DPI.

Majoritatea mousilor folosesc senzori optici, reprezentați de senzori CMOS care


fotografiază suprafața mousepad-ului iluminată cu un LED infrarosu sau cu un LASER.

O parte din precizia unui mouse vine din Pooling Rate, adică rata de raportare a poziției
cursorului.

© Bitulică 2020
Povestea lui Bitulică

Un senzor poate citi poziția de mii de ori pe secundă dar poate transmite coordonatele
calculatorului de mai puține ori pe secundă.

Un Pooling Rate bun suporta valori de 500-1000 Hz, chiar și la cele fără fir.

Am ales un mouse wireless Logitech MK235, USB, Grey.

© Bitulică 2020
Povestea lui Bitulică

Ca să îl pot folosi
Am asamblat sistemul
HARDWARE

Au ajuns componentele și am început să fac setup-ul.

Am montat procesorul ridicând levierul de pe socket.

Am potrivit colțul însemnat cu un triunghi al procesorului cu colțul însemnat al socket-ului


și am apăsat încet pe procesor să mă asigur că toți pinii au intrat, apoi am împins levierul
pentru a fixa procesorul.

Am aplicat peste procesor pasta termoconductoare de mărimea unui bob de mazăre și am


întins-o uniform pe toată suprafața pentru ca radiatorul să poate prelua mai ușor căldura
procesorului.

Peste ea, deasupra procesorului. am pus radiatorul. pe care l-am fixat cu ajutorul suportului
venit cu placa de bază. Peste radiator am pus ventilatorul.

Când m-am asigurat că orificiile pentru suruburi se potrivesc le-am insurubat fixând
ventilatorul.

Am montat memoria apasând clemele slotului de pe placa de bază și am avut grijă ca șanțul
de pe plăcuțe să se suprapună cu cele de pe sloturi.

Am apăsat pe plăcuțe pană când au intrat și le-am fixat ridicând clemele.

Am montat tăblița cu găurile pentru mufele plăcii de bază în carcasă și am asezat placa
astfel încât mufele să se potrivească cu găurile de pe tăbliță.

Am pus distanțierii cu rol în fizarea plăcii de bază dar și pentru a evita un scurtcircuit
produs dacă circuitele plăcii ating carcasa. Am fixat placa de bază în șuruburi.

Am scos protectia de pe slotul plăcii video și am montat placa pe slot apăsând pe ea apoi
așezând protecția în forma inițială.

Am montat hard-ul și SSD-ul cu conectorii în afară în sertărașele lor și le-am fixat în


șuruburi.

Am montat placa de sunet la fel ca pe placa video.

Am montat sursa de curent la locul ei.

Am conectat componentele pe placa de baza așezând mufele cu scrisul în jos, începând de


pe randul de sus.

© Bitulică 2020
Povestea lui Bitulică

Am montat POWER HDD , Power SW. Randul de jos RESET , HDD LED .

Am pornit sistemul. Merge.

© Bitulică 2020
Povestea lui Bitulică

Ca să îl pot utiliza
OS
Am ales sistemul de operare

Sistemul de operare, Operating System în engleză, prescurtat SO, este componenta sotware,
cu rol de gazdă pentru aplicațiile care rulează pe un computer. În 1950, General Motors a
realizat primul sistem de operare pentru IBM 701.

În anii 1970, erau folosite Microsoft MS-DOS pe IBM PC și pe procesoare Intel 8088, și UNIX
pe procesoarele Motorola 6899. În 1984, Apple a creat interfața grafică, care mapează pixe-
lii, îi convertește în informație și comunică cu mouse-ul.

Tot atunci, Microsoft a introdus ferestrele, windows în engleză, iar Linus Torvalds a adus
kernel-ul, care oferă posibilitatea dezvoltării open-source a distribuțiilor linux.

Sistemul de operare cuprinde

• kernel-ul, nucleu, în română, adică programele ce asigură funcțiile de bază și care


gestionează
• memoria
• procesele
• intrările și ieșirile
• funcțiile de comunicare.
• Interfața sistemului, permite lucrul cu el printr-un limbaj de control și permite unui
om să lucreze fără a avea habar despre componente.
• Sistemul de fișiere.

Sistemul de operare

• gestionează datele pe suport extern


• controlează memoria internă
• lansarea în execuție
• execuția
• încheierea execuției aplicațiilor
• mesajele de eroare.

Am de ales între Windows și Linux, MacOS iese din discuție pentru că am un PC.

Înțeleg că există o versiune neoficială a lui, pentru PC, numită Hackintosh, dar prefer să ur-
mez calea naturală. Windows lansat în 1985 a ajuns la versiunea Windows 10, apărută în
iulie 2015.

Linux creat în anii ’90 are cea mai accesibilă versiune pentru neinițiați Linux Mint.

Linux se folosește pe servere și de utilizatorii experimentați pe calculatoarele personale.

© Bitulică 2020
Povestea lui Bitulică

Linux este open-source, în timp ce Windows este comercial.

Utilizatorii Linux pot accesa codul și îl pot modifica, în timp ce utilizatorii Windows nu pot,
nu ușor.

Linux rulează mai repede decât Windows, în timp ce Windows tinde să devină lent pe mă-
sură ce trece timpul.

Windows colectează date pentru a îmbunătăți experiența în timp ce Linux nu.

Linux este mai fiabil. Există mai multe jocuri pentru Windows pentru că majoritatea sunt
create pentru el.

Linux este un sistem sigur, erorile și vulnerabilitățile pot fi rezolvate pentru că e open-so-
urce. Am ales Windows 10 Profesional

© Bitulică 2020
Povestea lui Bitulică

După ce l-am ales


OS
Am instalat Windows 10

Înțeleg că procesul implică să am un stick USB de minim 8 GB pentru a-l face bootabil, adică
să poată porni PC-ul de pe el, și un computer funcțional.

În acest scop, am scris în bara de adrese a browser-ului “descarca imaginea de disc win-
dows 10” și am accesat link-ul “Descărcați imaginea de disc Windows 10 (fișiere ISO)” care
m-a dus pe pagina dedicata a site-ului oficial Microsoft unde am apăsat butonul “Descărcați
instrumentul acum”.

După ce am salvat aplicația “MediaCreationTool” am lansat-o în execuție. A pornit cu acor-


dul să ruleze în mod administrator.

În aplicație am bifat că sunt de acord cu termenii și condițiile.

Am dat “Next” și am debifat că nu vreau să creeze un device optim pentru PC-ul curent pen-
tru că nu pe el voi instala.

Am selectat limba de instalare, ediția Windows 10 și arhitectura pe 64 de biți, pentru că am


peste 4 GB RAM pe computerul pe care va rula.

les apoi să creez un dispozitiv pentru alt PC, adică cel pe care voi instala Windows-ul, după
care am ales ca acest dispozitiv să fie un stick USB.

Am introdus stick-ul în computer și am apăsat pe “Next” iar aplicația l-a detectat și a pornit
procesul de descărcare a fișierelor necesare instalării. Când stick-ul a fost complet scris am
închis aplicația, am scos stick-ul și l-am băgat în unitatea PC-ului nou.

Am pornit PC-ul, am intrat în BIOS, am căutat opțiunile de BOOT, m-am asigurat că boot-
ează de pe stick și apoi când am ieșit din BIOS, s-a restartat, a pornit de pe stick-ul USB și
am apăsat o tastă pentru a începe procesul de instalare.

A apărut un formular de unde am ales limba de instalare, formatul datei și a monedei și con-
figurarea tastaturii.

Am apăsat “Next”, am apăsat pe butonul “Install now”, adică “Instalează acum”, am bifat că
momentan nu am o licentă, am ales versiunea “Windows 10 Pro”, am bifat că sunt de acord
cu termenii și condițiile de licențiere, apoi am ales că nu vreau să fac upgrade ci vreau o ver-
siune proaspătă a sistemului.

Am împărțit hard-urile în partiții, astfel SSD-ul una și HDD-ul alta, și am ales să instalez sis-
temul pe SSD.

© Bitulică 2020
Povestea lui Bitulică

A început procesul de instalare.

Imediat după, cel de configurare unde am ales regiunea, tipul tastaturii, m-am conectat la
net, am creat un user pentru PC, o parola, un cont Microsoft, și am fost de acord cu toate op-
țiunile avute, inclusiv Cortana.

A pornit.

© Bitulică 2020
Povestea lui Bitulică

Ca să fie totul legal


OS
Am activat Windows 10

Am înțeles că există câteva tipuri de licențe.

Licența tip Retail poate fi instalată pe orice computer de oricate ori este nevoie și vine cu
suport complet din partea Microsoft.

Cele tip Retail pot fi FPP adica Full Package Product, pachete complete ale produsului, inclu-
zând CD-uri sau USB-uri, ghiduri pentru utilizatorul final și materiale promoționale ale altor
produse Microsoft, sau poate fi ESD, adica Electronic Software Download, care este o licenta
livrata online.

Licența tip OEM este legată pentru totdeauna de un singur computer, mai precis de placa de
bază a acestuia și de procesor, și nu vine cu suport din partea Microsoft.

Licenta GGK adică Get Genuine Kit este mai scumpă și este destinata activării upgrade-uri-
lor din produse non-autentice.

Cea MSDN adica Microsoft Developer Network, este un tip de licență pe care Microsoft îl
oferă testerilor hardware și software ai produselor sale.

Cele de tip MAK, adica Multiple Activation Key, sunt utilizate de Microsoft pentru validarea
calculatoarelor unice sau multiple.

Licențele MOSP, adică licențele cu subscripție, sunt abonamente destinate organizațiilor dar
și persoanelor fizice așa cum este abonamentul Office 365.

Licențele cu activare online sunt chei electronice pentru activare descarcate printr-un link
și sunt atașate unui singur PC pe toata durata de viata a acestuia, putând fi reinstalate ori de
cate ori este nevoie.

Cele cu activare prin contul Microsoft sunt stocate în contul Microsoft și pot fi folosite și pe
un alt PC dacă cel pe care erau folosite s-a defectat.

Licențele se pot procura din magazinul Microsoft, adică Microsoft Store, sau de la diferiți co-
mercianți.

Am cumpărat o licență retail pentru Windows 10 Profesional și pentru a activa sistemul am


apăsat pe tasta Windows Home, am intrat în Setting la Update & Security și am ales opțiu-
nea Activate din panoul din stânga, unde am introdus cheia de activare primită atunci când
am cumpărat licența.

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să am și alte sisteme de operare


OS
Am descoperit virtualizarea

Am înțeles că atunci când am deja un sistem de operare dacă vreau să mai folosesc un alt
sistem de operare pe același computer pot să mă folosesc de soluția de virtualizare. Adică
să creez o mașină virtuală pe care să instalez ce sistem de operare vreau.

Am citit că o mașină virtuală este un program care emulează adică simulează comporta-
mentul unei mașini fizice pe o mașină fizică reală.

Sistemul de operare Windows 10 vine cu o serie de instrumente printre care și soluția de


virtualizare Hiper-V. Pentru a activa acest serviciu m-am dus bara de start a interfeței siste-
mului și am scris în căsuță de căutare „Control Panel” apoi am accesat utilitarul cu același
nume unde am mers la Programs.

În noul conținut care s-a afișat, de sub Programs and Features am accesat Turn Windows
Features on or off pentru a activa sau dezactiva unele sau altele din soluțiile cu care vine
sistemul de operare.

În fereastra care s-a deschis am derulat până la nodul Hyper-V pe care l-am bifat, semn că
vreau să îl selectez pentru o acțiune ulterioară care să îl includă.

Pliculețul pe care scrie Hyper-V este un pliculeț container care include nodurile Hyper-v
Management Tools și Hyper-Platform.

Le-am bifat și pe ele apoi am apăsat pe butonul OK. S-a deschis o fereastră unde am putut
observa cum sistemul de operare configurează alegerile mele și apoi mă îndeamnă să dau
restart la PC și implicit la sistemul de operare pentru a se activa noile setari.

Adică pentru a putea folosi Hyper-V. O altă soluție pe care o pot folosi pentru a instala o ma-
șină virtuală este să descarc și să instalez aplicația VirtualBox.

Pentru a descărca aplicația am intrat pe site-ul oficial aici și am apăsat butonul albastru din
mijloc care m-a dus către pagina de download a site-ului de unde am ales să descarc aplica-
ția corespunzatoare pentru sistemul meu de operare adică am dat click pe Windows Host.

După ce am descărcat aplicația am pornit procesul de instalare și am apăsat de fiecare dată


cand a aparut butonul Next iar cand a apărut Install am l-am apăsat de fiecare dată când a
apărut.

Am scris în căsuța de căutare din bara de start a sistemului de operare „Hyper-v” și a găsit
aplicația „Hyper-V Manager” pe care am de deschis-o.

© Bitulică 2020
Povestea lui Bitulică

Mi-a apărut o fereastră în care în panoul din partea stângă am un nod pe care scrie Hyper-V
Manager si pe care am dat click dreapta și din meniul de context am selectat opțiunea Con-
nect to Server.

Mi-a apărut o fereastră din care am ales Local Computer și am dat OK.

După ce m-am conectat la server care în cazul meu este computerul meu personal am trecut
în panoul din partea dreaptă unde am dat click pe Quick Create pentru a crea rapid o ma-
șină virtuală.

S-a deschis o nouă fereastră unde în partea stângă am cateva sisteme de operare pe care
pot să aleg să se instaleze de îndată ce va fi creată mașina virtuală.

Am ales varianta Ubuntu 20.04 și am apăsat pe butonul pe care scrie Create Virtual Machine
SIstemul de operare de pe PC a descarcat imaginea sistemului de operare Ubuntu de pe net,
a creat și configurat mașina virtuală după care m-a întrebat daca vreau să mă conectez la ea.

Am zis că da, am dat start și am putut lucra pe Ubuntu instalat pe o mașină virtuală.

© Bitulică 2020
Povestea lui Bitulică

Ca să pot comunica cu alții


REȚELE
Am ales o conexiune la net

Internetul a fost conceput în 1969 de o agenție a MApN al Statelor Unite pe nume DARPA.
Inițial s-a numit ARPANET și primele computere conectate atunci au fost cele ale universi-
tăților UCSB, UCLA, Utah și Stanford.

Internetul este o conexiune la nivel global, formată din mai multe rețele de calculatoare. O
rețea de calculatoare interconectează mai multe computere, astfel încât un computer poate
accesa datele unui alt computer conectat în aceeași rețea.

Există LAN adică Local Area Network care este o rețea locală acoperind o zonă mică ca
apartamente, firme, sau clădiri.

MAN adică Metropolitan Area Network care acoperă un oraș sau o parte a acestuia.
WAN adică Wide Area Network care se întinde pe o zonă mai mare ca județ sau țară.

Computerele care fac legatura intre rețele se numesc Gateway.

Datele care circulă pe internet au o dimensiune mare ceea ce înseamnă că trebuie împărțite
în pachete iar pentru asta este nevoie să fie rutate.

Router-ul este un dispozitiv ce conectează mai multe rețele între ele și permite rutarea da-
telor. Când pachetele sunt receptionate de router, acesta le trimite mai departe știind deja
locația și ordinea acestora.

In final, destinatarul primește pachetele puse cap la cap și poate citi întregul mesaj.

Computerele se leagă la internet prin DSL adică Digital Subscriber Line, ce este o conexiune
mai rapidĂ decât una standard de dial-up și este furnizată de o companie de telefonie, prin
cablu, cand furnizorul de servicii este o firmă de televiziune prin cablu.

Broadband unde semnalele de voce, date și video sunt transmise simultan pe același suport
fizic.

ADSL adică Asymmetric Digital Subscriber Line unde datele sunt trimise asimetric, pe linie
telefonică de cupru. ADSL lucrează prin utilizarea frecvențelor care nu sunt utilizate de un
apel telefonic vocal.

Prin Wireless adică fără fir folosind tehnologia Wi-Fi care reprezintă transferul de informa-
ții între două sau mai multe noduri ce nu sunt conectate printr-un conductor electric.

Prin fibră optică care permite transmiterea informațiilor pe distanțe și lărgimi de bandă
mai mari fată de alte tipuri de conexiuni.

© Bitulică 2020
Povestea lui Bitulică

Prin fibra optica nu circula curent electric ci lumină.

Există și internet mobil, ce utilizează un stick, dezavantajul acestei metode este acela ca te
poți confrunta cu lipsa de semnal, în funcție de zona de acoperire a operatorului, fiindcă da-
tele se trimit prin rețeaua mobila 3G, 4G sau 5G.

Standardul de viteză cu care circulă datele într-o rețea variază între 10, 100 și 1000 de Me-
gabiți pe secundă.

Standardul actual este Gigabit adică 1000 Mb/s.

Am ales o conexiune pe fibră optică tip Gigabit.

© Bitulică 2020
Povestea lui Bitulică

Ca să o pot folosi
REȚELE
Am instalat conexiunea la net

Firma de la care am contractat conexiunea la net a trimis o echipă de instalare care a racor-
dat casa în care locuiesc la rețeaua lor.

Echipa a adus cu ea un echipament care se numește ONT și în care intră fibra optică și con-
verteste semnalul optic în semnal digital pentru cablu UTP.

În cazul meu am primit un echipament care are și wireless.

Conexiunea cu serverele providerului va funcționa prin acest echipament pentru că echipa-


mentele din datacenter-ul operatorului sunt imperecheate cu aceste ONT-uri din casele uti-
lizatorilor și funcționează doar împreună.

Pe lângă acest echipament am primit și un mininod. Acest ONT este restricționat din
firmware și nu am drepturi de administrator pe el.

Pot schimba foarte puține lucruri și nu pot sa-l resetez să obțin cont de administrator pen-
tru că nu se va mai imperechea cu echipamentul central.

Vreau totuși să folosesc un alt router pe care îl voi achizitiona, așa că am rugat operatorul să
pună acest ONT în modul Bridge.

În acest mod, semnalul doar trece prin el și se face conversia.

Din el voi conecta cu un cablu UTP routerul meu și îl vei folosi pe acesta.

Tipul de abonament pe care îl am nu este cu linie garantată sau țeavă cum am înțeles că se
spune în limbajul IT așa că operatorul nu garantează viteza la net și oricum doar pe fir
poate ajunge în apropierea a 1000 Mb/s în timp ce pe wireless în funcție de router poate
bate spre 300 Mb/s ceea ce pentru mine în ambele cazuri este suficient.

Pe fir acum cu echipamentul lor am 923,4 Mb/s download și 473,8 Mb/s upload.

Tipul de conexiune de care dispun este PPPoE așa încât mi-au fost furnizate datele de co-
nectare constând dintr-un nume de utilizator și o parolă cu ajutorul cărora voi configura
routerul pe care îl voi achizitiona

© Bitulică 2020
Povestea lui Bitulică

Ca să pot partaja
REȚELE
Am ales un router

Pentru o casă smart trebuie să aleg un router wireless foarte bun pentru multi-streaming.

Când aleg trebuie să țin cont de aria de acoperire a semnalului și a device-urilor totale care
vor fi conectate la el, dar la fel de important este și tipul de aparatură smart care va fi conec-
tată la router.

Am înțeles că sunt importante în special procesorul și cantitatea de RAM pentru că route-


rele moderne au nevoie de mult mai multă putere de procesare. Am citit că trebuie să aflu
frecvența și dacă are un procesor cu mai multe nuclee.

Pentru o rețea rapidă care să poată face față mai multor clienți în același timp routerul ar
trebui să aibă un procesor cu cel puțin două nuclee, ca să poată lucra cu mai multe date si-
multan. Ideal ar fi să aibă 512 MB RAM sau 1 GB.

Unele modele de routere wireless pot comunica într-o singură bandă radio de transmisie, în
timp ce modelele mai recente, din 2019 folosesc 2 benzi radio. Routerele single band folo-
sesc o frecvență standardizată în banda 2.4 Ghz și vor interfera cu alte aparaturi din casă.

Cu toate acestea, rareori se va întrerupe semnalul și sunt perfect adecvate pentru navigare
pe net. Voi lua în considerare un router care folosește Dual-Band. Prima bandă de 2.4 Ghz
va fi folosită de device-urile care vor fi utilizate pentru navigare web sau pentru rețele de
socializare, iar banda de 5 Ghz o să fie folosită pentru streaming.

Există și routerele tri-band dar sunt recomandate pentru streaming masiv și momentan nu
am nevoie de unul. Ar trebui să fie cel puțin dual-band, adică să emită semnalul wireless pe
două frecvențe sau mai multe.

Una dintre frecvențe este întotdeauna banda de 2,4 GHz. Avantajul acestei benzii este com-
patibilitatea cu echipamentele mai vechi și aria de acoperire mare, însă este și lentă și aglo-
merarea este o problemă, în special în blocurile de locuințe și clădirile de birouri, unde toți
au Wi-Fi pe această bandă.

Routerele cu dual-band sau tri-band emit semnalul wireless și pe frecvența de 5 GHz. Banda
este mai rapidă decât 2,4 GHz și beneficiază de utilizarea standardelor moderne precum
Wi-Fi 5 802.11ac sau Wi-Fi 6 802.11ax. Banda de 5 GHz este utilizată mai puțin decât cea de
2,4 GHz, iar zona de acoperire este puțin mai scurtă.

Dacă vreau o casă inteligentă modernă, cu o rețea wireless rapidă mi-ar trebui unul dual-
band sau tri-band. Rețelele fără fir folosesc protocolul 802.11 pentru a trimite și primi da-
tele.

© Bitulică 2020
Povestea lui Bitulică

Cel mai des întâlnit protocol este 802.11ac, care teoretic, îmi permite să ating 5.4Gb/s și
operează în ambele tipuri de frecvențe, utilizează tehnologia M.I.M.O , care se folosește de
antene multiple pentru a face streaminguri multiple simultane și pot folosi până la 8 canale
simultane de rețea wireless pentru a face schimb de date. Protocolul 802.11g atinge viteza
maxima de 54 Mb/s adică 6.75 MB/s cu o raza de acțiune de 38 de metri în banda 2.4 Ghz.

Cel 802.11b atinge viteza maxima de 11 Mb/s adică circa 1.375 MB/s cu raza de acțiune sub
35 de metri în banda 2.4 Ghz

Device-urile care utilizează un protocol standard mai vechi ca 802.11b și 802.11g au limi-
tări de viteză și operează doar în banda de 2.4Ghz. Protocolul de 802.11n ajunge la viteza
maximă de 150 Mb/s adică 18.75 MB/s cu o raza de acțiune 70 de metri în ambele benzi 2.4
si 5 Ghz.

Cel mai folosit protocol este 802.11n, care asigură o viteză de până la 600 Mbps și operează
în ambele benzi de transmisie. Majoritatea device-urilor smart folosesc acest protocol.

Cel de 802.11ac atinge viteza maxima de 866.7 Mb/s adică 108.33 MB/sec cu o raza de acți-
une de 35 de metri în banda de 5 Ghz.Denumirile notate cu AC1200 și AC1750 semnifică vi-
teza routerelor și protocolul de transmisie.

De exemplu un router care atinge o viteza de 450 Mbps pe banda de 2.4 Ghz și 1.300 Mbps
pe banda de 5Ghz, va fi notat de producător cu AC1750 fiind suma totală a benzilor.Proto-
coalele sunt compatibile între ele, și voi putea folosi un router sau un device conectat cu
standard mai vechi dar va avea limita de viteză a protocolului de transmisie și recepție.Voi
alege un router cu porturi LAN 10/100/1000 care îmi permite să conectez prin cablu direct
de la un PC și care să aibă cel puțin un port USB.

Pentru un management bun al rețelei, voi alege un router cu opțiune de Control Parental și
care să aibă o rețea separată pentru vizitatori.

Toate routerele fără fir oferă securizare de mai multe tipuri ca WPS care îmi dă voie să
adaug device-uri compatibile prin simpla apăsare a unui buton, fără a mai fi nevoit să intro-
duc parole, WPA sau WPA2 care este cea mai comună metodă de criptare a rețelei, dar este
necesară introducerea unei parole.

Acum mai bine de un deceniu, puteam gestiona routerul wireless doar accesând firmware-
ul într-un browser web de pe un PC conectat la router.

Am citit că mulți utilizatori sunt intimidați de astfel de interfețe și doresc ceva mai simplu.
Drept urmare, producătorii au dezvoltat aplicații pentru telefon pe care le pot utiliza pentru
a-mi seta routerul.Se pare că a avea cel puțin un port USB pe router este o necesitate într-o
casă ca a mea.

Voi avea tot felul de dispozitive USB pe care trebuie să le conectez ca hard disk-uri externe,
imprimante, modemuri USB.Routerele noi au funcția QoS adică Quality of Service adică Cali-
tatea serviciului, dar, la majoritatea routerelor, este inutilă pentru că permite setarea manu-

© Bitulică 2020
Povestea lui Bitulică

ală a lățimii de bandă pe care o ofer fiecărui dispozitiv din rețea și nu mulți știu sau au ne-
voie să o folosească.Multe routere oferă funcții avansate precum servere VPN, antivirus și
alte unelte de securitate care pot proteja rețeaua Wi-Fi de malware și atacuri.

Ca regulă, dacă vreau funcții avansate, routerul ales ar trebui să aibă cel puțin un procesor
dual-core și 256 MB de memorie RAM. Am ales routerul Wireless ASUS AC1200G.

© Bitulică 2020
Povestea lui Bitulică

Ca să pot îl folosesc
REȚELE
Am configurat routerul

Pentru a configura routerul trebuie sa conectez cablul găsit în pachet în unul dintre portu-
rile LAN ale routerului și în PC.

Conectez de asemenea routerul cu portul WAN la portul LAN al echipamentului de la provi-


der.

Deschid browserul și accesez în bara de adrese, adresa 192.168.0.1 sau adresa 192.168.1.1
care diferă de la un model la altul.

În momentul în care se va stabili o conexiune, mi se cere un user și o parola.

Acestea sunt User:admin și Parola:admin.

Dupa autentificare, mi se deschide meniul routerului unde trebuie să configurez conexiu-


nea.

Pentru o configurare cât mai ușoară, o să aleg optiunea Quick setup.

Pașii de configurare a routerului pentru internet sunt:

• Mă loghez în meniul routerului cu userul și parola admin/admin;


• In meniu, pe partea stanga, selectez Quick Setup;
• In lista de conexiuni, selectez PPPoE și apăs pe butonul Next;
• In campul Username completez numele de utilizator oferit de providerul de internet
• În campul Password, completez parola.
• În câmpul Confirm password reintroduc parola și apăs pe Next;
• În fereastra apărută, modific câmpul de la Wireless Network Name cum vreau să se
numească rețeaua mea Wi-Fi;
• La Security bifez WPA2-PSK și în acel câmp completez parola de la WI-FI.
• Pentru că routerul e Dual-Band adică și cu 2.4Ghz și cu 5Ghz atunci repet procesul și
la 5Ghz;
• Apăs butonul Next și routerul se restartează automat.

Dupa restart, o să fie setat și configurat.

© Bitulică 2020
Povestea lui Bitulică

Pentru a dezvolta în C++ și C#


Am instalat Visual Studio
APLICAȚII

Azi am început să îmi instalez aplicațiile de care am nevoie.

Am descarcat Visual Studio de aici:


https://visualstudio.microsoft.com/downloads/

alegând versiunea dorită pentru descărcare.

Eu am ales community pentru ca e pentru persoane individuale și e gratis.

Am apăsat pe fișierul descărcat cu extensia .exe iar în ecranul care a apărut am apăsat buto-
nul Continue.

Visual Studio a început descărcarea fișierelor necesare pentru instalare.

Descărcare poate să dureze cateva minute în funcție de viteza conexiunii la internet.

În următorul ecran am apăsat butonul Install iar apoi în următorul am selectat “.Net
desktop development” apoi am apăsat butonul Install.

Visual Studio a instalat fișierele selectate la punctul anterior iar după ce se terminat descar-
carea, a trebuit să dau restartat la PC.

După restartare am deschis programul Microsoft Visual Studio să mă uit prin el

© Bitulică 2020
Povestea lui Bitulică

Pentru a dezvolta în Java si Javascript


Am instalat Intellij IDEA
APLICAȚII

Kit-ul de dezvoltare Java (JDK) îmi permite să codez și să rulez programe Java. Pot chiar să
instalez mai multe versiuni JDK pe același PC dar este recomandat să instalez doar cea mai
recentă versiune.

Ca să îl instalez am accesat linkul https://www.oracle.com/.../technolo.../javase-dow-


nloads.html unde am dat clic pe Download JDK, pentru cea mai recentă versiune Java.

Apoi am acceptat acordul de licență și am descărcat cea mai recentă versiune Java JDK pen-
tru versiunea mea de Windows adică pentru 64 biți.

De îndată ce descărcarea a finalizată, am rulat fișierul executabil pentru instalarea JDK iar
în prima fereastră apărută am dat clic pe Next.

Am selectat calea pentru instalarea Java și am dat clic pe Next după care am așteptat să se
finalizeze instalarea și am dat clic pe Finish.

După instalare am setat variabile de mediu pentru Java în Path și Classpath dând click
dreapta pe This PC apoi accesând Avanced system setting din panoul din dreapta pentru ca
în final să dau click pe butonul pe care scrie Enviroment Variabiles.Variabila de mediu sau
de sistem PATH oferă locația executabilelor precum javac și java.

Pot să rulez un program fără a seta variabila de sistem PATH, dar va trebui să dau calea
completă a executabilului, cum ar fi C: \ Program Files \ Java \ jdk-13.0.1 \ bin \ javac
A.java în loc de simplu javac A.java.

Unde A este programul , mai precis clasa principala a programului, pe care vreau să îl exe-
cut. Variabila CLASSPATH pe care am setat-o la fel ca pe PATH oferă locația fișierelor tip bi-
bliotecă sau altfel spus librărie în care sunt depozitate clasele deja create de alți dezvolta-
tori și din care eu pot să folosesc clase si metode în programul meu fără să mai fie nevoie să
le scriu eu.

După ce am setat variabilele am testat că să văd dacă îmi recunoaște comanda javac din li-
nia de comandă tastând-o în consola și dând enter.

După ce am instalat JDK am început să instalez IntelliJ IDEA.

Pentru a dezvolta aplicații în Java mai pot folosi și Eclipse și NetBeans, și ca și acestea, și in-
stalarea lui IntelliJ IDEA mi s-a părut că este destul de ușoară.

Adică a fost ușor să descarc, să instalez și să activez IntelliJ IDEA pentru a începe ulterior să
scriu programe.

© Bitulică 2020
Povestea lui Bitulică

Am înțeles că computerul meu. ar trebui să aibă cel puțin 4 GB RAM pentru a rula acest IDE
fără probleme.

Deși IntelliJ IDEA are inclus în pachet un JRE 8, trebuia să am mai întâi instalat JDK 8 sau o
versiune ulterioară pe computer.

Asta înseamnă că IDE rulează pe propriul JRE și necesită un JDK separat pentru dezvoltare
Java. Am accesat adresă https://www.jetbrains.com/idea/download/ pentru a deschide pa-
gina de descărcare.

Acolo am apăsat pe Download IntelliJ IDEA și am putut descărca ediția Ultimate sau Com-
munity Edition pentru Windows, Mac sau Linux.

Pe Windows, am putut descărca fie un program de instalare adică executabil, fie un pachet
Zip adică arhivă.

Am Instalat IntelliJ IDEA utilizând programul de instalare făcând clic pe Download .EXE
pentru a începe descărcarea programului de instalare iar după finalizarea descărcării, am
rulați programul de instalare și apărut ecranul cu Bun venit la configurare.

Am dat clic pe Next și l-am lăsat să utilizeze directorul de instalare sugerat. La următorul
pas am dat click pe Next și am ales să creeze comenzi rapide pentru desktop și să îmi asoci-
eze fișierele după extensie astfel încât să se deschidă cu acest IDE.

Am dat click pe Next pentru a începe instalare iar după ce s-a terminat instalarea mi s-a ce-
rut să aleg o temă preferată și ales Darcula adică pe culori nocturne. Apoi după ce am dat
click pe Next am ales plugin-urile implicite și explicite.

În final după ce am setat ce a fost de setat mi-a apărut ecranul de pornire așa numitul ecran
splash cu rol de a mă introduce în aplicație și ca eu să am la ce mă uita și să nu mă plictisesc
până porneste..

După ce a pornit a apărut fereastra de dialog de întâmpinare, care îmi permite să creez un
proiect nou sau să deschid un proiect existent.

© Bitulică 2020
Povestea lui Bitulică

Pentru a dezvolta aplicații Android


Am instalat Android Studio
APLICAȚII

Am înțeles că dezvoltarea aplicațiilor Android poate fi făcută în următoarele sisteme de


operare: Microsoft Windows 8/7 / Vista / 2003 (32 sau 64 biți), Mac OS X 10.8.5 sau o ver-
siune ulterioară și GNOME sau KDE Desktop.

Toate instrumentele necesare dezvoltării aplicațiilor Android sunt open source și pot fi des-
cărcate de pe Internet.

Așa că am căutat și am găsit următoarea listă a software

• Java JDK5 și versiunile ulterioare


• Java Runtime Environment 6
• Android Studio

Android Studio este IDE oficial pentru dezvoltarea aplicațiilor Android, bazat pe Intellij
IDEA. De pe site-ul oficial am descărcat Android Studio cea mai recentă versiune.

Pentru că eu instalez pe Windows am găsit și și descărcat fișierul denumite android-studio-


bundle-135.17407740-windows.exe și l-am rulat adică am rulat programul de instalare.

Înainte de instalare m-am asigurat că am deja instalat Java JDK.

Odată ce ați început instalarea Android Studio, a trebuit să setez calea JDK în programul de
instalare Android Studio.

Am verificat componentele necesare pentru a crea o aplicație, adică „Android Studio”, „An-
droid SDK”, „Android virtual machine” și „aspect (cip Intel)”.

A trebuit să specific calea unde vreau să instalez Android Studio pe mașină și calea SDK An-
droid iar apoi am specificat spațiul implicit necesar emulatorului Android pe care l-am setat
la 512M.

În cele din urmă, extras pachetul SDK pe mașina locală, a durat o perioadă de timp și a utili-
zat 2626M spațiu pe hard disk.

© Bitulică 2020
Povestea lui Bitulică

Pentru a crea și interoga baze de date


Am instalat SQL Management Studio
APLICAȚII

Am înțeles că SQL Server Management Studio este un instrument foarte util pentru
gestionarea serverului Microsoft SQL.

Acesta poate fi instalat pe computerul meu şi conectat la SQL Server sau poate fi instalat
direct pe server. Instrucţiunile de instalare pentru toate versiunile sunt foarte similare.

• Am deschis browserul şi am navigat la pagina de download a SQL Server


Management Studio 2019 (https://docs.microsoft.com/en-
us/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-
2019)
• După terminarea download-ului, am dat dublu click pe fişierul de instalare din
folderul unde acesta a fost descărcat
• S-a iniţia instalarea. Am dat click pe "Install" şi am aşteptat ca instalarea să se
finalizeze. Acest proces poate dura câteva minute.
• După afişarea mesajului "Setup Complete" am dat click pe butonul "Close"
• Apoi am dat click pe butonul Start şi am căutat programul numit “Microsoft SQL
Server Management Studio 19”, apoi am dat click pe el
• SQL Server Management Studio s-a lansat şi am putut începe utilizarea acestuia

Cu ajutorul acestei aplicații pot crea și manageria baze de date.

© Bitulică 2020
Povestea lui Bitulică

Tot pentru crea și interoga baze de date


Am instalat MySQL Workbench
APLICAȚII

Am citit că webmasterii folosesc MySQL pentru a rula bazele de date ale site-urilor
web create. Există versiuni de MySQL şi pentru Mac OS X, Linux sau Unix.

Am mers la site-ul MySQL Community Server şi anume


la https://dev.mysql.com/downloads/windows/installer/, unde este versiunea pentru
descărcare Windows (x86, 32-bit), MSI Installer (mysql-installer-community-… .msi). Deși
arată că este pentru un sistem de operare pe 32 de biți totuși el are inclus ambele versiuni
inclusiv cea pe 64 de biți.

Am lansat instalarea unde pentru început trebuie să accept License Agreement iar la Setup
Type am de ales 5 tipuri potrivit utilizării: Developer Default, Server Only, Client Only, Full
și Custom. Full cuprinde MySQL Server, MySQL Shell, MySQL Router, MySQL Workbench,
MySQL Connectors, documentații, eșantioane, exemple și mult mai multe.

Voi alege instalare Server Only pentru că nu voi dezvolta aplicații MySQL şi click pe Next.

La verificarea cerințelor pe un sistem nou o să ceară Microsoft Visual C++ 2015


Redistributable Package x64 să fie instalat. Nu trebuie decât să fie selectat iar această
cerință o să fie rezolvată automat de către instalatorul MySQL dând click pe Execute. Am
acceptat termenii și condițiile licenței Microsoft Visual C++ apoi Install.

Click Next după ce toate cerințele au fost verificate și instalate adică Status: INSTL DONE.
Pot naviga și la cele mai noi descărcări Visual C++ acceptate ca să descarc ultima versiune
de Microsoft Visual C++ 2015-2019 Redistributable x64 – 14.22.278.21 adică
x64: vc_redist.x64.exe și să o instalez pe aceasta, dar pentru acest lucru trebuie să
abandonez instalarea prin Cancel la MySQL Installer iar apoi după finalizarea instalării
versiunii noi de Microsoft Visual C++ reface pașii 2 și 3.

Când la următoarea fereastră apare produsul MySQL Server și Status Ready to


install apăs Execute.

Când Status este Complete, după Next voi configura acum MySQL adică Status Ready to
configure.

High Availability: Standalone MySQL Server / Classic MySQL Replication (Choose this
option to run the MySQL instance as a standalone database server with the opportunity to
configure classic replication later. With this option, you can provide your own high-
availability solution, if required); InnoDB Cluster (The InnoDB cluster technology provides
an out-of-the-box high availability (HA) solution for MySQL using Group Replication. Note:
InnoDB cluster requires a minimum of three MySQL server instances to provide a fully
automated HA solution. Members of a cluster should be located such that network

© Bitulică 2020
Povestea lui Bitulică

communication latency between servers is low); Am ales Standalone MySQL Server /


Classic MySQL Replication.

Type and Networking: Config Type Development Computer (This is a development


computer, and many other applications will be installed on it. A minimal amount of memory
will be used by MySQL) multe alte aplicaţii vor rula pe acest calculator iar MySQL va putea
să utilizeze o cantitate minimă de memorie; Server Computer (Several server applications
will be running on this computer. Choose this option for web or application servers. MySQL
will have medium memory usage) mai multe aplicaţii de server vor rula pe acest calculator,
această setare este pentru a utiliza serverele de web. MySQL va utiliza o cantitate medie de
memorie; Dedicated Computer (This computer is dedicated to running the MySQL database
server. No other servers, such as web servers, will be run, MySQL will make use of all
available memory) aici MySQL va fi singura aplicaţie din calculator care va utiliza toată
memoria disponibilă; Am ales Server Computer; La conectivitate (connectivity) portul
implicit este 3306 şi este recomandat să las acest lucru ca setare implicită pentru că este
portul desemnat pentru cele mai multe aplicaţii ce folosesc MySQL. Doar dacă îmi creez
propriile aplicaţii pot schimba portul şi implicit verificarea portului în aplicaţiile create. X
Protocol Port 33060 este folosit de către MySQL ca depozit de documente

Authentication Method: Use Strong Password Encryption for


Authentication (RECOMMENDED); Use Legacy Authentication Method (Retain MySQL 5.x
Compatibility)

Accounts and Roles: aleg parola pentru contul root prin MySQL Root Password, Repeat
Password, Password strength: Strong; de altfel pot seta și conturi pentru utilizatori (MySQL
User Accounts).

Windows Service: în Windows, serverul de MySQL poate rula ca serviciu (service) și poate
fi configurat să ruleze automat la pornirea sistemului de operare, deci las bifat
opțiunea Configure MySQL Server as a Windows Service și Start the MySQL Server at
System Startup. Pot seta, de asemenea, numele serviciului, care este util dacă am mai mult
de un exemplu de MySQL ce rulează, am setat Windows Service Name MySQL apoi Run
Windows Service as … Standard System Account.

Apply Configuration: Toate setările de configurare sunt aplicate pe serverul MySQL dând
click pe Execute și urmărindu-le în Configuration Steps: Writing configuration file, Updating
Windows Firewall rules, Adjusting Windows service, Initializing database (may take a long
time), Starting the server, Applying security settings, updating the Start menu link. Pentru a
vizualiza jurnalul apăs pe Log. Dacă apare mesajul „The configuration for MySQL was
successful” apas Finish pentru continuare.

Product Configuration: Product MySQL Server, Status Configuration complete, Next;


Installation Complete. Click Finish.

MySQL Installer cât și produsele MySQL instalate sunt adăugate în meniul Start de la
Microsoft Windows sub grupul MySQL.

© Bitulică 2020
Povestea lui Bitulică

Ca să pot lucra mai ușor


Am instalat aplicațiile utile
APLICAȚII

Pentru a-mi ușura munca de programator care presupune și operarea unui computer nu
numai programarea lui am instalat câteva aplicații utile.

Am instalat Microsoft Office pentru a scrie documente, prezentări și pentru a efectua


operații de calcul tabelar. Acesta suită cuprinde printre altele aplicațiile Word, PowerPoint
și Excel.

Suita Office cuprinde și un client de email dar eu am preferat să instalez Mozila


Thunderbird. Am instalat și browserele Google Chrome, Opera și Mozila Firefox pentru a
putea testa funcționalitatea aplicațiilor web pe fiecare din ele.

Am mai instalat și Adobe Acrobat Reader pentru a crea și vizualiza documente în format
PDF dar și Adobe Photoshop și Adobe Ilustration pentru a crea și edita imagini grafice.

Pentru a edita secvențe video am instalat Adobe Premiere iar pentru a adauga efecte la
aceste secvențe am instalat Adobe After Effect.

Pentru a putea testa funcționalitatea serviciilor web am instalat SoapGUI iar pentru a mă
conecta remote pe mașini pe care rulează sistemul de operare Linux am instalat aplicația
Putty.

Pentru a face captura pe placa de rețea pentru a intercepta și observa pachetele primite și
trimise am instalat aplicația Wireshark.

Pentru a face transfer de fișiere intre o mașină pe care rulează Windows și una pe care
rulează Linux am instalat aplicația WinSCP.

Pentru a proteja computerul de eventualele atacuri de orice fel am instalat un antivirus iar
dintre ofertele avute am preferat Bitdefender.

Pentru arhivarea și dezarhivarea pachetelor am instalat aplicația WinRar iar pentru


navigarea prin fișiere cu un navigator cu două panouri am instalat Total Commander.

© Bitulică 2020
Povestea lui Bitulică

Pentru a ști operații


MATE
Am asistat la aritmetică

Am fost la scoală la fata mea cea mică și pentru că face matematica cu mama mea am putut
să asist și eu la ore și să mă pun în temă cu noțiunile din aritmetică, cele care îmi trebuie ca
să pot să programez bine. Adică toate.

Am aflat că cifrele sunt sinbolurile unor cantități și că numerele sunt formate din una sau
mai multe cifre. Ele, adică cifrele, se numesc digit în engleză de la digitus în latină pentru că
oamenii numărau pe degete.

Cifrele latine I II III simbolizau 1 2 sau 3 degete iar IV o mână adică 5 degete fără unul. Cifra
V în latină este o mână iar VI VII și VIII o mână și mai multe degete. X înseamnă finalul ca
două săbii încrucisate care simbolizează că pe aici nu se trece și reprezintă numărul 10
adică finalul celor zece cifre. IX este numărul 10 fără un deget.

Cifra 0 a fost introdusă de arabi după ce a fost preluată de la indienii antici și este
reprezentarea nimicului. Întroducerea cifrei zero în sistemul de numerotație arab a permis
acceptarea existentei numerelor negative. Sistemul de cifraj arab are la bază unghiurile.
Cifra 1 are un unghi /|. cifra 2 are doua unghiuri Z și așa mai departe.

Simbolurile sunt acele desene pe care prinvindu-le mă fac să mă gandesc la altceva decât la
desenele însăși. De exemplu atunci când îl vad pe 2 mă gândesc la două boabe.

Numerele pot fi întregi adică nealterate și atunci reprezintă cantități netaiate ca de exemplu
2 mere sau 3 pere sau pot fi numere reale adică cantități atât întregi cât și alterate adică
tăiate ca de exemplu um mar jumate.

Numerele întregi pot fi pozitive adică cele care pot reprezenta un număr de ordine 1 , 5 sau
7 dar și negative adică cele care reprezintă datorii ca de exemplu am să îi dau cuiva 5 mere
deci acel cineva are -5 mere.

Numerele reale pot fi ratii adică rezultatul unui raport așa cum am primi o ratie din ceva
sau pot fi numere iraționale adică care nu pot fi scrise ca un raport adică ceva împărțit la
altceva.

Cel mai celebru număr irațional este numărul PI pentru care nu există două numere care
împărțite unul la altul să dea acest număr. Iar cea mai celebră ratie este salariu adică din cât
trebuie să luam pe un an se împarte la 12 luni și luăm pe fiecare lună.

Cifrele au apărut din dorința de a putea demonstra cantitatea deținută de cineva fără ca acel
cineva să care toată cantitatea după el. De aceea operațiile cu cifre sau cu numere se pot
face și numărând cantitățile care intră în operație.

© Bitulică 2020
Povestea lui Bitulică

Prin urmare 3 + 2 adica *** + ** fac 5 adică ***** tot așa cum 5 - 3 fac 2 adică ***** - *** = **
prin eliminare.

Așadar prin adunarea a două numere care se numesc termeni se adună cantitățile
reprezentate de acele numere

2+3 ** + *** = 5

iar prin scăderea a doua numere care se numesc descazut și respectiv scazator se înlătură
cantitatea scăzută din cantitatea din care se scade

5-3 ***** - *** = 2

Am observat că rezultatul unei scăderi adunat cu cantitatea scăzută dă exact cantitatea din
care s-a scăzut și am aflat că așa face un computer ca să poată scădea doua numere.

Prin înmulțirea unui număr cu alt numar se înțelege adunarea numărului cu el însuși de
atâtea ori cât înseamnă numărul cu care se înmulțește.

3 x 5 = 3 + 3 + 3 + 3 + 3 = 15

Această tehnică este folosită și de computer pentru a înmulți două numere.

Prin împărtirea a doua numere se înțelege divizarea numărului care se împarte în atâtea
părți câte reprezintă numărul la care se împarte. Adică trebuie să caut acel număr care
înmulțit cu numărul la care vreau să impart adică cu deimpartitul o sa obtin numărul din
care am împărtit adică impartitorul. Am aflat ca un computer folosește acesta tehnica
pentru că el nu știe nici să împartă nici să înmulțească și nici să scadă ci doar să adune și se
folosește de adunarea ca să poate să facă și celelalte operații.

10 : 5 ********** : ***** = ** ** ** ** ** adica 2

Se întâmplă ca uneori rezultatul unei impartiri să nu fie întreg. Adica daca impart 5 mere la
4 oameni să îmi mai ramana unul iar acest măr este restul împărtirii.

5 : 4 = ***** : **** = * * * * rest * adica 5 rest 1

Am observat că dacă înmulțesc câtul adică rezultatul întreg al împărțirii cu impartitorul


adică cu numărul la care se împarte și adun rezultatul cu restul obțin numărul din care am
împărțit.

Daca un număr se împarte exact la alt număr atunci evident ca restul împărțirii este 0 și
asta am înțeles că mă ajută la determinarea divizorilor acelui număr.

© Bitulică 2020
Povestea lui Bitulică

Pentru a găsi necunoscute


MATE
Am asistat la algebră

Am fost iar la scoală tot la matematică dar de data asta la algebră unde am învăţat că uneori
este nevoie să aflu ce număr lipseşte dintr-o expresie adică care este valoarea unei necu-
noscute şi am aflat că oamenii de ştiinţă au numit asta ecuaţie.

De exemplu dacă eu ştiu că am 5 mere şi că cineva a mâncat unele din ele şi mai sunt 3 pot
scrie

5 - x = 3 de unde rezultă că x = 5-3 adică 2

Am înţeles că astfel de expresie se numeşte ecuaţie de gardul 1 pentru că are o singură ne-
cunoscută şi nu este nici multiplicata.

Alteori se întâmplă să ştiu că am 5 mere şi 6 pere iar cineva a mâncat nişte mere şi nişte
pere şi mai sunt 3 mere şi 3 pere caz în care pot scrie

5-x=3
6-y=3

şi rezultă că x = 2 şi y = 3

Acest tip de expresie am înţeles că se numeşte sistem de ecuaţii cu mai multe necunoscute.
Două în cazul meu.

Şi am mai înţeles că pentru a putea fi rezolvat numărul de ecuaţii trebuie să fie egal cu nu-
mărul de necunoscute.

Am învăţat şi că se poate întâmpla să am o cantitate de mere şi cineva să îmi aducă de atâ-


tea ori aceeaşi cantitate iar altcineva să manânce din ele 1 şi să îmi rămână 3. În acest caz
pot scrie

x^2 - 1 = 3

ceea ce însemna că x^2 = 3+1 = 4 de unde rezultă că x = 2 sau x = -2

Am înţeles că acest tip de expresie se numește ecuaţie de gradul 2 şi că gradul este expo-
nentul la care este rificata necunoscută.

Chiar dacă se numesc la fel acest tip de ecuaţii au două necunoscute şi prin urmare şi două
soluţii

© Bitulică 2020
Povestea lui Bitulică

Astfel de ecuaţii care au una sau mai multe variabile se numesc polinoame şi sunt sunt alcă-
tuite din unul sau multe monoame.

4x^2+2x+1

Este un polinom format din două monoame adică monomul 4x^2 şi 2x.

Pe lângă numerele reale mai există şi numere imaginare care reprezintă mărimile care nu
se văd. De exemplu când mă uit la un cub eu văd doar partea din fată dar acel cub are şi în
partea în care nu pot vedea dimensiuni însă eu nu le pot măsura şi pot doar să îmi imaginez
cam cât ar fi.

Astfel că dacă mă întreabă cineva care este volumul cubului îi pot spune adevărul pe ju-
mate. Jumătate ce am măsurat eu real din ce am văzut şi jumate cât mi-am imaginar că ar
putea fi.

Aşa stând lucrurile numerele complex au o parte reală şi o parte imaginară şi pot fi scrise

Z = Ai + B

unde i este un număr imaginar iar A şi B numere reale. Pentru că A este înmulţit cu un nu-
măr imaginar expresia A x i nu poate fi reală şi atunci ea se numeşte partea imaginară a nu-
mărului complex în timp ce B este partea reală

Numărul i este rezultatul lui radical din -1 pentru și pentru că rădăcina pătrată reprezintă
inversul ridicării la putere rezultă că i este doar în imaginația matematicienilor și a noastră
pentru nu există un număr care ridicat la pătrat să dea un rezultat negativ.

De multe ori mi s-a întâmplat să fac lucruri în funcţie de ce am la dispoziţie. Adică dacă
aveam ouă făceam omletă dacă aveam carne făceam grătar şi azi am aflat că există în mate-
matică noţiunea de funcţie care face şi ea tot ca mine ceva în funcţie de ce are la dispoziţie.

Practic funcţia transformă ceva aşa cum eu transform ouăle în omletă sau cum maşina de
tocat carne tranforma carnea macră în carne tocată doar că funcţia din matematica tran-
sforma numere căci matematica lucrează cu numere nu cu carne şi ouă.

Funcţia se notează cu F adică prima literă de la numele ei şi că şi maşina de tocat sau robo-
tul de bucătărie are un orificiu unde se introduc numerele care este reprezentat de două pa-
ranteze închisă şi deschisă adică aşa ( ).

Numerele pe care le ia funcţia să le transforme se numesc valori de definiţie iar mulţimea


lor se numeşte mulţimea de definiţie iar mulţimea valorilor transformate de funcţie sunt
practic valorile pe care le ia funcţia pentru fiecare număr transformat adică rezultatul
funcţiei şi prin umrare mulţimea lor se numeşte mulţimea de valori

© Bitulică 2020
Povestea lui Bitulică

Dacă valorile care intră în funcţie sunt numere reale atunci mulţimea de definiţie a funcţiei
este mulţimea numerelor reale notată cu R iar dacă numerele care intră în funcţie sunt nu-
mere între mulţimea de definiţie este mulţimea numerelor întregi notată cu Z şi aşa mai de-
parte.

La fel şi pentru mulţimea de valori

O funcţie în matematică poate arăta aşa

F: Z -> R, F(x) = x+0.1

Unde F este numele funcţie Z este mulţimea de definiţie , R mulţimea de valori, x este argu-
mentul funcţiei adică cel care argumentează rezultatul funcţiei adică motivul pentru care
rezultatul funcţie este care este iar x+0.1 este expresia funcţie adică modul în care funcţia
transforma valorile din domeniul de definiţiei în valori din domeniul de valori

În cazul funcţiei de mai sus pentru cazul când x = 1 adică un număr întreg valoarea funcţie
F(1) este 1+0.1 adică 1.1 care este un număr real şi de aceea domeniul de valori este mulţi-
mea numerelor reale.

Atât valorile din domeniul de definiţie cât şi valorile rezultate în urma aplicării funcţiei pe
valorile din domeniul de definiţie pot fi reprezentate pe un grafic în care pe axa orizontală
sunt reprezentate valorile din domeniul de definiţie iar pe axa verticală sunt reprezentate
valorile luate de funcţie pentru fiecare valoare din domeniul de definiţie
F(x)
| /
| /
| /
| /
| /
| /
--|---------------------
O| x
|
Reprezentarea grafică a unei funcţii reprezintă vizualizarea comportamentului funcţiei pe
domeniul de definiţie adică cum schimba funcţia domeniul de definiţie.

© Bitulică 2020
Povestea lui Bitulică

Pentru a ști să analizez


MATE
Am asistat la analiză

Se pare că a început să îmi placă la scoală căci iar am fost. De data asta la analiză matema-
tică și am înţeles că între 0 şi 1 sunt o infinitate de numere ca de exemplu

0.00000000000000000000000000000000000000000000000000001

pentru că numărul de zero-uri care pot fi adăugate după virgulă este infinit.

Cu alte cuvinte pot împărţi un măr teoretic într-un infinit de bucăţi fără să mă oprească ni-
meni şi nimic dar practic cred că nu pot tăia atomul. Însă matematica este o ştiinţă teoretică
nu practică însă cu o largă aplicabilitate practică.

Aşa stând lucrurile dacă vreau să mă apropii de 1 plecând de la zero şi mergând cu paşi infi-
nit de mici o să îmi fie imposibil să mă apropii de 1 iar cine mă vede o să zică că sunt
aproape de limită pe care vreau să o ating dar nu am ajuns încă.

Am înţeles că acest caz este tratat de expresia

lim x->1 adică limita când x tinde la 1 şi x este variabilă într-o expresie.

Că tot a venit vorba de variabile , variabilele sunt acele lucruri care îşi schimbă valoarea.
Adică valoarea lor variază deci este variabilă.

De multe ori mărimile măsurate din imprejurul nostru nu îşi păstrează măsura în timp. De
exemplu un om care merge cu maşina la un moment dat are o viteză iar la alt moment are
altă viteză. Dacă vreau să ştiu ce viteze a avut în toate momentele îmi trebuie o mărime ma-
tematică care se numeşte vector şi care este un şir de numere reprezentând valori momen-
tane ale unor mărimi măsurate.

Vectorii pot fi unidimensionali sau mulţi dimensionali în funcţie de scopul pentru care sunt
folosiţi.

De exemplu dacă am nevoie de un vector pentru a şti ce coordonate gps a avut cineva pe un
traseu am nevoie de un vector bidimensional care se numeşte matrice pentru că trebuie să
reţin şi latitudinea şi longitudinea presupunând că nu mă interesează altitudinea iar dacă
vreau să văd ce coordonate a avut o navă spaţială în spaţiul cosmic am nevoie de un vector
tridimensional care se mai numeşte şi cub pentru că trebuie să reţin pe lângă latitudine şi
longitudine şi altitudinea.

Atunci când fac un fel de mâncare pot să îi mai adaug câteva condimente sau ingrediente şi
să ajung la un alt fel de mâncare plecând de la felul de bază. Când fac asta spun că am ajuns
la un fel de mâncare derivat din felul de bază.

© Bitulică 2020
Povestea lui Bitulică

Matematica lucrează cu numere şi cu expresii numerice şi că şi la felul meu de mâncare


dacă dintr-o expresie ajung la altă expresie pot spune că expresia la care am ajuns este deri-
vată din prima expresie. Matematicienii spun că expresia de bază este primitivă adică ea a
fost prima iar expresia la care am ajuns este expresia compusă.

În tot acest timp diferenţa dintre expresia de bază şi expresia la care am ajuns este expresia
derivată. Dacă expresia este o funcţie atunci pot vorbi despre funcţia primitivă , funcţia
compusă şi funcţia derivată.

Din punct de vedere grafic derivată unei funcţii este tangenta în fiecare punct la graficul
funcţiei adică cu cât variază valoarea funcţie în fiecare punct faţă de punctul de dinaintea
lui.

Modelul calculului diferenţial se foloseşte în informatică la învăţarea automată aşa numita


machine learning sau abreviat ML când maşinii i se dau câteva date care reprezintă funcţii
compuse iar aceasta calculează funcţia derivată care a produs acea funcţie compusă pentru
că apoi să determine funcţia primitivă adică modelul care stă la baza acelor date primite
spre învăţare.

Există mai multe formule de derivare stabilite de experţii în matematică ca de exemplu că


dacă există o funcţie

f : R -> R, f(x) = x^r unde r este un număr real atunci derivata funcţiei f(x) este rx^r-1

Pot să privesc primitivă ca pe un pătrat iar derivată ca pe două triunghiuri ataşate în părţile
alterale ale pătratului astfel încât să formeze un trapez. Trapezul este funcţia compusă.

Că tot a venit vorba de figuri geometrice dacă vreau să le calculez aria atunci dacă ele sunt
ideale cum sunt pătratul triunghiul cercul dreptunghiul sau hexagonul atunci îmi este uşor
pentru că există formule specializate care mă ajută să fac asta dar dacă figurile sunt neregu-
late şi de exemplu trebuie să calculez suprafaţa unui lac în care malurile şerpuiesc atunci
am înţeles că am nevoie de noţiunea de integrala care este inversul notiunii de derivată şi
care se foloseşte de forme regulate simple pentru a calcula forme neregulate complexe.
Acest model de calcul se numeste calcul integral.

Prin urmare Integrală din rx^r-1 este x^r.

În informatică integralele se pot folosi atunci când trebuie să calculăm ariile suprafeţelor
recunoscute de computer din realitatea augumentată.

© Bitulică 2020
Povestea lui Bitulică

Pentru a ști să desenez


MATE
Am asistat la geometrie

La orele de geometrie am înţeles că punctul nu are dimensiuni şi că prin două puncte trece
o dreaptă şi numai una singură aşa cum trei puncte determină un plan şi numai unul singur.

Eu ştiu că punctul de pe foaia de hârtie care este făcut de un creion foarte bine ascuţit este
totuşi vizibil cu ochiul liber şi deci are dimeniuni iar un punct pe ecran oricât de mic ar fi
dacă este luminos îl pot distinge cu ochiul liber.

Asta mă face să cred că geometricienii au presupus că foaia de hârtie poate fi scalată până la
infinit aşa cum putem scala harta pe google maps şi că oricât ai scala punctul tot este vizibil
deci practic la o scală de 1:1 punctul este aşa de mic încât putem spune că nu are dimensi-
uni.

Neavând dimensiuni înseamnă că pe o dreaptă sunt o infinitate de puncte aşezate unul


lângă altul astfel încât prin două puncte nu au cum să treacă mai multe drepte pentru că nu
au loc pe grosime.

Am văzut şi că o masă dacă are picioarele subţiri nu poate sta într-un picior şi nici în două şi
că îi trebuie minim trei picioare ca să fie stabilă ceea ce mă face să înţeleg de ce trei puncte
determina un plan şi numai unul singur.

Am văzut şi palete de vapor care îl face să înainteze prin apă și care sunt nişte plane înfipte
într-un ax şi am înţeles de ce printr-o dreaptă pot trece o infinitate de planuri.

Am înţeles că un triunghi este figura geometrică închisă cu cel mai mic număr de linii frânte
adică 3 şi că numărul maxim de linii frânte îl are cercul şi anume 2xPIxR unde R este raza
cercului iar linia se reduce la un punct.

Ştiu ce pe lângă triungi există şi pătrat care are patru laturi egale şi toate unghiurile de 90
de grade şi dreptunghi care are două laturi egale şi la fel are toate unghiurile de 90 de
grade.

Şi că aceste figuri sunt cazuri particulare de paralelogram adică acea figură geometrică care
are laturile două câte două paralele adică oricât le-aşi lungi nu voi reuşi să le unesc.

Am văzut că dreapta are o singură dimensiune , că planul are două şi că spaţiul are trei iar
că dacă ridicăm în sus triunghiul obţinem prisma sau piramida triunghiulară , dacă ridicăm
pătratul obţinem paralelipiped dreptunghic sau cub iar dacă ridicăm cercul obţinem cilin-
dru, con sau sferă.

Sfera este ca o minge şi orice punct de pe ea este egal depărtat de centrul său pentru că şi în
plan orice punct de pe cerc este egal depărtat de centrul său.

© Bitulică 2020
Povestea lui Bitulică

Distanţa de la centrul la oricare punct de pe cerc se numeşte raza cercului iar distanţa de la
oricare vârf al unei figuri geometrice la latura opusă este înălţimea acelei figuri geometrice.

Noţiunile de geometrie şi-a făcut loc în informatică mai cu seamă în desenarea grafurilor şi
rezolvarea problemelor legate de ele şi se reflectă mai ales în industria jocurilor video 2D şi
3D şi în cea a aplicaţiilor care beneficiază de interfaţă utilizator.

Punctul luminos de pe ecranul unui computer am înţeles că se numeşte pixel şi pe ecranul


unui computer care a fost setat în prealabil în mod grafic se poate desena tot ce este posibil
a fi desenat pe foaie inclusiv variante 3D ale desenelor însă că şi foaia ecranul este un plan
şi deci 3D este o iluzie.

© Bitulică 2020
Povestea lui Bitulică

Pentru a întelege ce desenez


MATE
Am asistat la trigonometrie

Mi-au spus cu după ce particip şi la orele de trigonometrie scap de matematică aşa că am


venit să asist şi la ele ca apoi să îmi văd de treabă adică să învăţ în continuare programare.

Aici am aflat că raportul dintre cateta opusă şi ipotenuza dintr-un triungi dreptunghic este
egal cu sinusul unghiului opus catetei şi că raportul dintre cateta alăturată şi ipotenuza este
egal cu cosinusul unghiului alăturat catetei iar raportul dintre cele două catete este tan-
genta unghiurilor opuse catetelor.

Dacă analizez numele observ că cosinus este co + sinus adică este cumva complementar si-
nusului ceea ce pot demonstra foarte uşor pentru că mă ajută teorema fundamentală a tri-
gonometriei în plan care zice că coş pătrat de x + sin pătrat de x = 1 şi care teorema rezultă
din teorema lui Pitagora.

Am aflat şi că cosinus de 90 de grade este 1 iar sinus de 90 de grade este 0 şi că pentru un


unghi de 0 grade valorile se inversează.

Am înţeles că tangenta la cerc este o dreaptă care întâlneşte cercul într-un singur punct iar
secanta la cerc este o dreaptă că secţionează cercul adică întâlneşte circumferința cercului
în două puncte.

Ecuaţia din care se pot afla coordonatele oricărui punct de pe o dreaptă care trece prin
două puncte numită şi ecuaţia parametrică a dreptei este

(y- yA)/(yB- yA)=(x- xA)/(xB- xA)

și mă ajuta în animatiile pe computer să mişc un punct pe o traiectorie liniara care pleacă


din punctul A şi ajunge în punctul B

Ecuaţiile parametrice ale cercului sunt

x = a + R cos(u)
y = b + R sin (u)

unde a şi b sunt coordonatele centrului cercului, R este raza iar u este unchiul sub care se
găsește raza dusă din centrul cercului spre punct în raport cu axa OX.

Am înţeles că ecranul este o suprafaţă plană iar la jocurile 3D trebuie să transform punctele
din spaţiu în plan şi că formulă de transformare este

X' = ((X - Xc) * (F/(Z-Zc))) + Xc


Y' = ((Y - Yc) * (F/(Z-Zc))) + Yc

© Bitulică 2020
Povestea lui Bitulică

unde Xc Yc sunt coordonatele camerei care se uită X, Y şi Z sunt coordonatele punctului din
spaţiu iar F este distanţa punctului faţă de cameră și am mai înțeles și că în baza acestei for-
mule se poate construi matricea de transformare a coordonatelor care mă ajută cand se
mișcă punctele prin spațiu sau când se deplasează camera.

© Bitulică 2020
Povestea lui Bitulică

Pentru a înțelege mișcarea


FIZICĂ
Am asistat la mecanică

Am înţeles că un computer este construit din circuite electrice prin care trece curent şi din
dispozitive mecanice iar noţiunile pentru a înțelege aceste aspecte sunt prezentate în fizică.

Aşa că am fost la şcoală la orele fiicei mele pe care le face cu tatăl meu ca să pot să înţeleg
aceste noţiuni mai ales că vreau să dezvolt o casă inteligentă şi va trebui să pot face meca-
nisme mecanice optice şi electronice care să facă di casa mea clasică o casă inteligentă.

Am asistat la orele de mecanică atât a solidelor cât şi a fluidelor şi am aflat că fizica studiază
şi încearcă să înţeleagă tot ce ne înconjoară şi că a descoperit un principiu fundamental care
stă la baza tuturor lucrurilor şi anume că energia se conservă.

Adică dacă las să cadă o minge din mâna de la nivelul umerilor ea nu va putea sări mai sus
de umeri mei după ce se loveşte de pământ. Acest lucru se întâmplă pentru că mingea dato-
rită greutăţii ei are o anumită energie potenţială adică ar putea să facă multe dar nu face
încă şi când o arunc aceasta energie potenţială se transforma în energie cinetică adică de
mişcare şi deci se consumă. Practic mingea oboseşte.

Am înțeles că orice acţiune are şi o reacţiune adică dacă eu lovesc pe cineva acel cineva
simte durerea şi poate reacţiona la durere bine sau rău.

Dacă reacţionează bine mă iartă dar dacă reacţionează rău îmi poate întoarce lovitura.
Forţa de reacţiune este egală şi de sens contrar cu forţa de acţiune.

Că tot a venit vorba forţa este mărimea fizică egală în modul aproximativ cu impulsul cu
care loveşte. Adică cu cât e mai impulsiv cu atât loveşte mai tare.

Totuşi o furnică loveşte mai uşor decât un elefant chiar dacă sunt la fel de impulsivi pentru
că furnica e mai mică deci are masă mai mică decât elefantul.

Am înţeles că impusul este masa unui corp înmulţită cu variaţia vitezei în unitatea de timp
adică cu cât îţi iei mai mult viteza şi loveşti cu atât loveşti mai tare.

Am aflat că un corp care se relaxează adică este în repaus se supără dacă cineva vrea să îl
pună în mişcare şi reacţionează cu o forţă care se opune celei care vrea să îl mişte şi care se
numeşte forţa de inerţie.

Aşa am dedus că dacă nu mă îndur să mă urnesc să învăţ câte ceva nu mă poate ajuta ni-
meni pentru că dacă forţa mea inerție este mare s-ar putea să nu poată nimeni a mă ur-
nească.

© Bitulică 2020
Povestea lui Bitulică

Am aflat că daca trag ceva pe o suprafaţă atunci el se freacă de ea şi cu cât se freacă mai
mult se face mai cald şi că forţa de frecare la alunecare depinde de suprafaţă.

Dacă e alunecoasa sau nu. De exemplu sania pe gheaţă aluneca repede dar pe pământ lasă
dâre adânci.

Am mai aflat că un corp solid este tare adică dur pentru că moleculele lui sunt legate strâns
unele de altele iar că un lichid curge pentru ca moleculele lui sunt legate mai slab în timp ce
la un gaz moleculele sunt legate foarte slab de nici nu îmi dau seama că sunt legate. Ca un
corp solid este un pietroi de exemplu, unul lichid este apă iar unul gazos este aerul.

Ştiu că dacă pun apa în vase care comunica atunci nivelul apei per total este acelaşi şi că apa
are toate stările de agregare. Lichidă solidă gazoasă şi plasmă.

Am mai înţeles că lichidele au aşa numita suprafaţa superficială la suprafața lor ceea ce face
că dacă pun un ziar pe apă şi sar lovitura va fi la fel de dură ca pe ciment iar dacă împing cu
o pompă într-un văd plin cu apă astfel încât să acopăr cu pompa toată suprafața lui nu voi
reuşi să presez apa.

Am înţeles că există şi mecanica cuantică care studiază mişcarea elementelor subatomice şi


care se ghidează după principiul superpoziţiei cuantice adică un electron este în mai multe
locuri simultan dar şi pe principiul colapsului cuantic adică cel care face că dacă mă uit la
electron eu să îl văd doar într-o poziţie în funcţie de poziţia în care l-am prins.

Un al treilea principiu este că zona unde are loc superpoziţia cuantică se măreşte cu viteza
luminii. Cu alte cuvinte un electron se află în mai multe poziţii simultan pe o suprafaţă care
se extinde.

Mi s-a spus că spaţiul are 3 dimensiuni dar ca o deplasare în spaţiu este inevitabil şi o de-
plasare în timp pentru că timpul se scurge.

În acest timp am studiat şi teoria conforma căreia masă şi energia sunt acelaşi lucru doar că
îmbracă forme diferite adică E=Mc^2 ceea ce face ca pentru deplasări cu viteza luminii tim-
pul să se contracte.

Am văzut că cu cât sunt mai mari şi mai dense corpurile atrag alte corpuri mai mici cu o
forţă care se numeşte forţa gravitaţională şi care face că spaţiul să se contracte pentru că ea
este o forţa care acţionează asupra spaţiului şi consecinţă acestui lucru este că rămânem cu
picioarele pe pământ.

© Bitulică 2020
Povestea lui Bitulică

Pentru a înțelege semnalele


FIZICĂ
Am asistat la electricitate

De la orele de fizică unde mi s-a explicat despre electricitate şi magnetism am învăţat că un


corp prin frecare poate fi încărcat cu sarcină electrostatică adică o sarcină electrică care stă
locului dar care are proprietatea oricărei sarcini electrice şi anume aceea de a atrage.

Forţa cu care ea atrage se numeşte forţa electrostatică şi pot reproduce acest comporta-
ment frecând intens un obiect cu o cârpă şi apoi apropiind de el o scamă. Am observat că
scama se lipeşte.

Am înţeles că în jurul unui astfel de obiect încărcat cu sarcină electrică se formează un câmp
de forţe care se numeşte câmp magnetic şi fiind un câmp de forţe îndreptate către obiect el
atrage orice corp care se găseşte în interiorul lui. Seamănă cu câmpul gravitaţional.

Am mai înţeles că un magnet produce în jurul său un câmp asemănător cu cel produs de un
corp încărcat cu sarcina electrică şi care se numeşte câmp magnetic având şi el proprietatea
de a atrage corpuri care sunt în interiorul lui.

Cu alte cuvinte dacă apropii un fier de un magnet acesta este atras de magnet.

Mi s-a explicat că dacă înfăşor pe un cilindru de fier nişte sârmă de cupru şi îl rotesc pe lun-
gime într-un câmp magnetic astfel încât capetele să vină când sus când jos se poate produce
un potenţial electric care se numeşte tensiune electrică şi că acest potenţial se poate pune
în valoare dacă leg nişte fire de capetele dispozitivului iar de celelalte capete ale firelor un
consumator electric cum ar fi un bec.

În acest caz numărul de electroni din dispozitivul care produce potential este mai mare ca
cel din bec care nu produce nimic şi atunci sistemul tinde la echilibrul şi electronii o iau la
vale spre bec ca să se echilibreze numărul lor iar deplasarea electronilor se numeşte curent
electric.

Practic particulele din dispozitivul care produce potenţial sunt încărcate electric şi vibrează
iar această vibraţie se tranmite şi particulelor din fir care la rândul lor transmit vibraţia că-
tre particulele becului care trecând prin filamentul acestuia îl fac să lumineze de atâta exci-
tare.

Filamentul este în interiorul unui bulb în care se găseşte un gaz care disipă lumina şi asta
face că becul să lumineze încăperea.

Am înţeles că doar unele materiale se pot comporta aşa pentru că doar unele sunt formate
din particule care se excită şi pot excita şi pe altele şi că aceste materiale se numesc materi-
ale conductoare electric în timp ce altele ori nu conduc deloc curent electric pentru că nu au
nicio particulă care să se poată excita şi care se numesc izolatori electrici ori conduc parţial

© Bitulică 2020
Povestea lui Bitulică

curentul electric pentru că au doar parţial astfel de particule care pot conduce curent elec-
tric şi atunci se numesc semiconductori.

Chiar şi materialele care conduc curent electric deţin particule care nu se pot excita şi care
se numesc impurităti însă acestea sunt în cantităţi mici dar joacă un rol important pentru că
dacă o particulă care se excită se găseşte lângă una care nu se poate excită curentul electric
pe acest traseu nu se mai transmite şi totalitatea traseelor unde curentul electric se blo-
chează se numeşte rezistență la înaitarea curentului electric.

Practic se pierd sarcini electrice pe aceste trasee.

Materialele cu număr redus de impurităţi se numesc supraconductori iar computerele sunt


confecţionate şi din astfel de materiale cum ar fi aurul dar şi din semiconductori cum ar fi
siliciu.

Denumirea zonei unde locuiesc eu Sillicon Valley vinde de la siliciu şi din faptul că este ma-
terialul de bază din care sunt confecţionate microprocesoarele.

Numărul de particule încărcate cu sarcină electrică în raport cu numărul de particule neîn-


cărcate într-o secţiune de fir adică dacă tai firul pe lăţime şi mă uit la microscop este inten-
sitatea curentului electric prin fir.

Adică cât de intens este curentul în acel loc.

Am înţeles că intensitatea curentului electric depinde de potențialul din sursa de curent şi


de rezistenţă la înaintare, mai precis este raportul celor două

I = U/R

Ansamblul format din sursa de curent din fire legate între ele şi din consumatori electrici se
numeşte circuit electric şi îşi desfăşoară activitatea sub incidenţa unor legi bine stabilite.

O porţiune din circuit sub formă de buclă adică un circuit mai mic se numeşte ochi de circuit
şi am înţeles că în cazul lor suma intensităților care intră în bucla este egală cu suma inten-
sităţilor care ies de aici rezultând că acelaşi lucru se întâmplă şi în cazul tensiunilor electro-
motoare adică omologul energiei cinetice din mecanica clasică.

Adică este energia în care se transformă energia potenţială de la priză când curentul începe
să curgă prin circuit.

Consumatorii pot fi aranjaţi în circuit atât înseriat adică unul după altul caz în care dacă se
arde unul adică nu mai trece curent electric prin el, curentul nu mai ajunge nici la celalat şi
atunci nu mai merg consumatorii din restul circuitului sau pot fi aranjaţi în paralel adică de
la sursa să plece câte un circuit pentru fiecare consumator şi atunci dacă curentul nu mai
curge printr-un circuit prin celalat curge fără să fie afectat.

© Bitulică 2020
Povestea lui Bitulică

Atunci când un circuit nu are consumator care să consume sarcinile electrice pentru că de
exemplu s-a ars consumatorul prin suprasarcină circuitul devine mai mic şi curentul se în-
vârte în el până încălzeşte firul care la un moment dat poate lua foc pentru că curentul are
pe lângă proprietățile magnetice şi proprietăţi calorice adică produce căldură pentru că
atunci când particulele excitate vibrează se încălzeşte aerul din jurul lor pentru că se agită
moleculele din aer iar agitaţia moleculelor produce caldură.

Acest proces în care curentul se învârte într-un circuit mai mic se numeşte scurt circuit.

Miezul de fier se roteşte în câmpul magnetic la o anumită perioadă de timp adică capetele
lui ajung când sus când jos de un anumit număr de ori pe secundă şi acesta periodicitate dă
frecvența curentului electric care din acest motiv se numeşte curent electric alternativ exis-
tând dispozitive şi mecanisme care îl pot transforma la nevoie în curent electric continuu.

© Bitulică 2020
Povestea lui Bitulică

Pentru a înțelege lumina


FIZICĂ
Am asistat la optică

La optică am învățat că lumina este o undă electromagnetică care are caracter dual adică
este şi undă şi corpuscul.

Corpusculul este un corp mai mic cu masa neglijabilă şi care în cazul luminii se numeşte fo-
ton iar unda electromagnetică este o radiaţie emisă de o sursă într-o anumită direcţie.

Practic radiaţia excita particulele din aer de pe o anumită direcţie făcându-le să vibreze cu o
anumită frecvenţă iar distanţa de pe graficul oscilaţiilor dintre două oscilaţii se numeşte
lungime de undă.

Am înţeles că lumina care cade pe o suprafaţă poate trece prin acea suprafaţă şi atunci spun
că se refractă iar dacă raza de lumină este deviată de acea suprafaţă înapoi spun că lumina
se reflectă.

Atât refracţia cât şi reflexia au loc sub un unghi de incidență la fel cum o bilă de biliard ri-
coşează din manta unei mese.

Lumina este absorbită de o suprafaţă în funcţie de culoarea acesteia adică a suprafeţei, as-
tfel că lumina este împrăştiată cel mai mult de suprafeţele albe şi absorbită cel mai mult de
suprafeţele negre.

Dacă suprafaţa lasa să treacă lumina prin ea atunci ştiu că suprafaţa este transparenta iar
dacă nu lasă să treacă lumina prin ea suprafaţa este opacă.

Suprafața care reflectă cel mai mult lumina este oglinda dar nici ea nu reflectă toate razele
ci doar aproximativ 99% dintre ele în timp ce aproximativ 1% re refractă.

Culoarea cu sensibilitatea spectrală cea mai mare pe timpul zilei este culoarea verde adică
ea poate fi observată prima dacă la o anumită distanţă sunt toate culorile iar cea cu sensibi-
litatea spectrală cea mai mare pe timpul nopţii este culoarea roşie.

Nu întâmplător culorile de la semafor sunt verde şi roşu iar stopurile de la autovehicule


sunt roşii.

Frecvenţele undelor electromagnetice dau spectrul undelor care porneşte de la infraroşu


până la ultraviolet între care există domeniul vizibil adică acele frecvențe ale lumii pe care
ochiul uman le poate percepe.

Şi sunetul este tot o undă numită unda sonoră şi ea are frecvențe iar domeniul său de frec-
venţe cuprinde pe lângă sunetele pe care le putem auzi şi ultrasunetele.

© Bitulică 2020
Povestea lui Bitulică

Atunci când lumina trece printr-o suprafaţă curbată fie că e concavă adică scobită în jos sau
convexa adică scobită în sus măreşte sau micşorează obiectele privite prin acea suprafaţă
aşa rezultând ochelarii lentilele de contact şi telescopul iar acea suprafaţă curbată se nu-
meşte lentilă.

Lumina cu toate culorile adică cu culorile curcubeului se numeşte lumina plină şi ea poate fi
filtrată dacă este trecută printr-o suprafață vopsită într-o anumită culoare.

Practic o suprafaţă roşie lasă să treacă doar lumina roşie iar dispozitivul pentru separarea
culorilor din lumină se numeşte prisma optică.

Culorile fundamentale ale televiziunii din care se poate forma orice culoare sunt roşu verde
şi albastru şi sunt culorile fundamentale ale oricărui dispozitiv care produce imagini iar
prin combinarea lor cantitativă se poate produce orice nuanţă de culoare.

Umbră se formează atunci când un obiect opac este pus în calea unei surse de lumină pen-
tru că razele de lumină ocolesc obiectul iar dacă obiectul are găurele atunci prin acele gău-
rele care se numesc fante lumina îşi poate face loc fără probleme.

Această tehnică este folosită la monitoarele din generaţia anterioară celor cu cristale lichide
şi led.

© Bitulică 2020
Povestea lui Bitulică

Pentru a gândi tranșant


LOGICĂ
Am asistat la logică

Am înţeles că pentru a programa un computer am nevoie de câteva noţiuni de logică aşa că


am fost la orele fetei mele pentru a mă pune la punct cu noţiunile acestei materii.

Am aflat că o propoziţie este un enunţ cu subiect şi predicat atribut şi complement dar că


pentru a se înţelege ceva din propoziţie adică ce vrea să spună este suficient ca ea să aibă
subiect şi predicat.

Predicatul este acţiunea care se exercită asupra subiectului.

Am înţeles că o propoziţie adică un enunţ poate fi adevărată sau falsă adică atunci când
afirm ceva pot să mint sau să fiu sincer.

Valoarea de adevăr a unei propoziţii este stabilită prin consens de comunitate și pentru a
vedea dacă o propoziţie este adevărată trebuie să pun întrebarea predicatului să văd dacă
acţiunea este adevărată şi abia apoi dacă într-adevăr acţiunea se reflectă asupra subiectului
sau nu, asta pentru că subiectul poate fi nedeterminat şi atunci doar valoare de adevăr a
predicatului dă valoarea de adevăr a întregii afirmaţii.

De exemplu dacă spun că: "cineva a mâncat gogoaşa", trebuie să văd dacă gogoaşa într-ade-
văr este mâncată căci nu pot determina cine a mâncat-o.

Prin urmare în logica o condiţie mai poartă numele şi de predicat.

Predicatul poate fi adevărat sau fals niciodată şi adevărat şi fals în acelaşi timp.

O propoziţie poate fi negată dacă în faţa ei se pune semnul care semnifica negarea şi care îi
schimbă valoarea de adevăr. De exemplu dacă eu spun : "mănânc mere" şi pun în faţă pe
"nu" iese "nu mănânc mere". Dacă prima propoziţie este adevărată atunci a doua este falsă
şi invers.

Dar de cele mai multe ori noi oamenii nu rostim doar o singură propoziţie ci de cele mai
multe ori ne exprimăm prin fraze mai scurte sau mai lungi adică prin înşiruiri de mai multe
propoziţii legate.

În funcţie de legăturile dintre propoziţii şi de valoarea de adevăr a propoziţiilor putem să


determinăm dacă cineva ne minte sau nu.

Dacă propozițiile sunt legate prin "şi" atunci ca să ni se spună adevărul trebuie că toate pro-
poziţiile să fie adevărate. Dacă cel puţin una nu e atunci fraza în ansamblu este o minciună.
Adevărul spus pe jumătate este o minciună.

© Bitulică 2020
Povestea lui Bitulică

Dacă frazele conţin propoziţii legate prin conjuncția „şi” atunci înseamnă că poate aduna
adevărul pe bucăţele spus în fiecare propoziţie şi deci face o conjuncţie de adevăruri din
care rezultă un adevăr mai mare fiind ca o reuniune între propoziţiile frazei.

Eu am mere şi sunt înfometat. Dacă chiar am mere şi mi-e şi foame atunci spun adevărul.

Dacă mi-e foame dar nu am mere ci alte fructe sau dacă am mere dar sunt sătul atunci mint.

Dacă o frază conţine propoziţii legate prin „sau” atunci înseamnă că adevărul final este o
disjuncție între propozițiile frazei deci este cumva intersecţia dintre mulţimea propozițiilor
adevărate şi cele false din frază.

Pentru ca o frază care are propoziţiile legate prin „sau” să fie adevărată este suficient ca mă-
car una dintre propoziţii să fie adevărată pentru că celelalte nu contează chiar dacă sunt
minciuni pentru că prin „sau” vorbitorul se scuză că nu ştie care propoziţie este adevărată.

Eu am mere sau sunt înfometat. Dacă fie mi-e foame fie am mere atunci nu mint pentru că
nu ştiu sigur nici dacă am mere nici dacă sunt înfometat. Sunt indecis. Indecizia nu e min-
ciună.

Mai există şi varianta când se pune întrebarea dacă sunt indecis că nu ştiu ce să aleg sau că
nu am din ce alege. Dacă de exemplu zic: "Am 10 ani sau sunt la şcoală", atunci ambele pro-
poziţii sunt adevărate şi nu am din ce alege dar dacă zic: "Am 10 ani sau sunt la facultate"
atunci una e falsă şi am din ce alege. Acest tip de frază include un sau exclusiv care este ade-
vărat doar dacă ai din ce alege.

Dacă ambele propoziţii sunt adevărate sau ambele false nu ai de unde alege şi rezultatul e
fals.

Dacă în urma unei acţiuni ia naştere un rezultat atunci acel rezultat este o implicația logică
a acelei acţiuni. Dacă eu dau cu piatră şi sparg geamul, faptul că geamul se sparge este im-
plicația logică că am dat cu piatră în el.

Ai spart geamul! Logic! Pentru că am dat cu piatră în el!

© Bitulică 2020
Povestea lui Bitulică

Pentru a lucra cu piese


Am asistat la electronică
ELECTRO

Pentru a putea creea o casă inteligentă este necesară o cunoaştere foarte bună a componen-
telor electronice utilizate așa că nu aveam cum să scap de orele de electronică.

Aici am înțeles că placa de bază adică PCB care vine de la printed circuit board este suportul
din material nonconductiv de obicei fibra de sticlă care conţine unul sau mai multe straturi
de trasee conductive ca pad-uri, vias-uri şi pth-uri. Partea superioară a plăcii de bază se nu-
meşte TOP iar partea inferioară se numeşte BOTTOM.

PAD-ul este aceea porţiune sau insuliţa de circuit imprimat pe care se montează terminalele
componentelor de tip SMD. Land este inelul metalizat de la capătul PTH-ului de care se cosi-
toresc terminalele adică picioruşele componentei THD.

Circuitul imprimat reprezintă ansamblul de trasee conductive de obicei din cupru de pe


PCB care vor face legătura între toate componentele electronice iar VIAS sunt găuri metali-
zate în PCB care fac legătura între trasee conductive aflate pe diferite straturi ale PCB-ului.
PTH este gaura metalizată în PCB prin care trec terminalele componentelor de tip THD iar
Amprenta este desenul de contur al componentei şi ea se găseşte pe placă.

Simbolul literar este litera în sistemul internaţional corespunzătoare unei componente elec-
tronice iar simbolul grafic este desenul specific pentru componente şi dispozitive electro-
nice.

Există două mari categorii de componente electronice. Componente de tip THD adică Thro-
ugh Hole Device și componente de tip SMD adică Surface Mount Device.

Componentele de tip THD sunt componente ale căror terminale străpung placă, iar tehnolo-
gia de montare a acestora se numeşte THT adică Through Hole Technology adică Tehnolo-
gie de montare prin găuri.

Componentele de tip SMD sunt componente care se montează pe suprafaţa plăcii, iar tehno-
logia de montare a acestora se numeşte SMT adică Surface Mount Technology adică Tehno-
logie de montare pe suprafaţa.

În funcţie de forma avem există componente THD de forma axială, radiala, de forma Single
în Line Package adică SIL sau ŞIP și componente THD şi SMD de forma Dual în Line Package
adică DIL sau DIP.

Am înțeles că o componentă are orientare, dacă pe corpul ei găsesc un semn distinctiv.


Acest semn distinctiv poartă denumirea de CHEIE iar ceasta cheie poate fi: o adâncitura, o
linie, un punct, o teşitură sau chiar o proeminentă.

© Bitulică 2020
Povestea lui Bitulică

O astfel de componenta este montată corect pe placă dacă semnul de pe corpul componen-
tei este în concordanţă cu semnul de pe placă.

Pe placă pot întâlni semne că: *, +, -, A. În cazul în care pe placă nu există astfel de semne
care să indice orientarea , trebuie să mă uit pe schema de amplasare. Aceasta va substitui
semnele distinctive adică amprenta de pe placă.

Am studiat că pot vorbi de polarizare la acele componente care au un terminal pozitiv adică
este încărcat cu sarcini electrice pozitive şi un terminal negativ adică este încărcat cu sar-
cini electrice negative. Toate componentele care au polarizare, implicit au şi orientare. In-
versul afirmaţiei nu este adevărată. Exemplu: dioda și condensatorii polarizaţi.

Rolul unui rezistor în circuit este acela de a limita intensitatea curentului electric. Cu cât un
rezistor are o rezistenţă mai mare, cu atât intensitatea curentului electric din acel circuit va
fi limitată mai mult pentru că conform legii lui Ohm, aceste mărimi sunt invers proporţio-
nale.

Rezistorul este caracterizat de mărimea fizică numită rezistenta. Unitatea de măsură pentru
rezistenţa este ohmul iar simbolul pentru ohm este W. Simbolul literar din schemele de am-
plasare este R, iar la reţelele de rezistori întâlnim RN adică Resistor Network sau RP adică
Resistor Pack. Reţelele de rezistori sunt formate din mai mulţi rezistori încapsulaţi în ace-
eaşi capsula adică corp de componentă. În funcţie de modul de amplasare a acestora, unele
reţele de rezistori au orientare, altele nu.

În cazul unui rezistor luat independent nu se ţine cont de orientare sau polarizare. În
această situaţie el poate fi montat în orice poziţie, cu condiţia să facă contact cu pădurile
respectând standardul IPC A610-C.

În cazul unui grup de rezistori format din rezistori independenţi, de aceeaşi valoare ampla-
saţi simetric faţă de axul longitudinal al componentei, încapsulaţi în aceeaşi piesă, nu se ţine
cont de orientare pe când în cazul unui grup de rezistori format din rezistori interconectaţi,
de valori diferite, amplasaţi nesimetric faţă de axul longitudinal al componentei, încapsulaţi
în aceeaşi piesă, se ţine cont de orientare

În cazul reţelelor de rezistori de tip DIL, la care se ţine cont de orientare, pinul numărul 1
este cel din stânga jos, dacă se ţine componentă cu scrisul citibil înspre operator, cheia în
acest caz găsindu-se întotdeauna în partea stânga. Numerotarea celorlalţi pini se face în
sens invers acelor de ceasornic.

Există rezistori sau reţele de rezistori atât de tip THD cât şi de tip SMD.
Rolul unui condensator în circuit este acela de a înmagazina sarcini electrice, pe care apoi,
le returnează acestuia. Descărcarea condensatorului se face mai lent sau mai rapid, în
funcţie de rezistenta circuitului din care face parte.

Capacitatea este cantitatea de sarcini electrice per volt stocată de un condensator. O capaci-
tate de 1F este foarte mare şi se atribuie capacităţii pământului. Condensatorul este carac-

© Bitulică 2020
Povestea lui Bitulică

terizat de o mărime fizică numită capacitate. Unitatea de măsură pentru capacitate este fa-
radul notat cu F. Simbolul literar al condensatorului în schemele de amplasare este C, iar
pentru reţele de condensatori întâlnim CN sau CP.

Există două mari grupe de condensatori: condensatori polarizaţi - au polarizare adică impli-
cit orientare și condensatori nepolarizaţi care nu au orientare.Din categoria condensatori-
lor polarizaţi fac parte condensatorii electrolitici şi condensatorii cu tantal iar din categoria
condensatorilor nepolarizaţi fac parte condensatorii de tip chip şi condensatorii de tip mol-
ded. Condensatorii ceramici pot să aibă sau nu polarizare.

Un condensator polarizat este format din două armaturi, separate printr-un material izola-
tor numit dielectric, fiecare dintre acestea fiind încărcate cu sarcini electrice. Condiţia ca o
componenţa să aibă polarizare este aceea de a avea două părţi, una încărcată cu sarcini
electrice pozitive, iar cealaltă încărcată cu sarcini electrice negative. Evident că un conden-
sator polarizat nu poate fi montat oricum pe placă. Regula de montare corectă este aceeaşi
ca şi în cazul reţelelor de rezistori la care se ţine cont de orientare adică de semnul de pe
componenta adică cheie care trebuie să fie în dreptul semnului de pe placă adică amprentă.
Rolul unei bobine în circuit este acela de a concentra câmp magnetic în jurul ei.

Bobina este caracterizată de mărimea fizică numită inductanţa. Unitatea de măsură pentru
inductanţa este henry notat cu H.

Bobina este alcătuită dintr-un grup de spire, înfăşurate în jurul unui miez ferromagnetic
adică de tip cilindric sau toroidal în general. După cum se cunoaşte sensul curentului elec-
tric care trece printr-o sârma, determina sensul liniilor de câmp magnetic. De aceea este
foarte important sensul de bobinaj. În funcţie de acest lucru putem spune dacă acea bobină
are sau nu orientare. Oricum o bobină care are priză adică prize intermediară iar aceasta nu
este mediană are şi orientare.

Distanța dintre priza intermediară şi capătul superior al bobinei este diferită în cele două
situaţii. De aceea trebuie să ţin cont de orientare. În orice caz, dacă am o componentă la
care trebuie să ţin cont de orientare, aceasta va avea întotdeauna un semn distinctiv adică
cheie care să indice acest lucru.

Simbolul literar al bobinei din schemele de amplasare este L, dar putem întâlnim şi FB.
Dioda conduce curentul electric într-un singur sens, motiv pentru care se ţine cont de pola-
rizare (are un terminal încărcat cu sarcini electrice positive şi unul încărcat cu sarcini elec-
trice negative). Spre deosebire de alte componente, marcarea polarităţii se face pentru ter-
minalul negativ (catod). O diodă conectată în sens invers se comportă ca un circuit deschis.
Din acest motiv nu este permisă conectarea inversă a acestei componente.

Simbolul literar cu care apare aceasta componentă în schemele de amplasare este D sau CR.
O diodă este montată corect dacă semnul de pe componenta este în dreptul vârfului săgeţii
de pe simbol. Formele constructive în care pot să apară acestea sunt foarte variate, atât în
construcţie de tip THD cât şi de tip SMD.

© Bitulică 2020
Povestea lui Bitulică

Tranzistorul este o componentă semiconductoare, fără unitate de măsură. Ea are 3 sau mai
multe terminale, în acest din urmă caz doar 3 având rol funcţional, celelalte având rol de ră-
cire. Denumirea terminalelor funcţionale este baza, emitor şi colector. Rolul unui tranzistor
în circuit este acela de amplificare în circuitele analogice sau de comutaţie în circutele digi-
tale. În cazul unui tranzistor este obligatoriu să se ţină cont de orientare.

Circuitul integrat este o componentă electronică care conţine o multitudine de componente


electronice mai simple (rezistori, condensatori, tranzistori, etc.) cuprinse în aceeaşi capsula.
Rolurile pe care le poate avea un circuit integrat sunt foarte variate, însa nu este scopul
acestui curs de a le trata.

Simbolul literar cu care întâlnim circuitul integrat în schemele de amplasare sunt: U sau IC.
În cazul unui circuit integrat se ţine cont de orientare, aceasta indicând pinul numărul 1, ce-
ilalţi pini numerotându-se în sens invers acelor de ceasornic

Cristalul este o componentă electronică cu rol de oscilaţie. Acesta creează frecvenţa de osci-
laţie care controlează temporizarea în echipamentele electronice cum sunt calculatoarele,
receptoarele de televiziune. Mărimea fizică ce caracterizează cristalul este frecvenţa. Unita-
tea de măsură pentru frecvenţa este herţul adică Hz.

Simbolul literar al cristalului în schemele de amplasare poate fi .

Cel mai răspândit cristal este cristalul de cuarţ, dar se mai întâlneşte şi mică. Există mai
multe forme constructive de cristale: axial, radial, cu două sau mai multe terminale, forma şi
dimensiunile componentei variind în funcţie de aplicaţie şi te tipul plăcii. În cazul cristalului
cu mai mult de 2 terminale se ţine cont de orientare, la cele cu 2 terminale neţinându-se
cont. Oscilatoarele mici sunt introduse în învelişuri de plastic sau metal.

Conectorul este o componentă care face legătura între 2 circuite.


Simbolul literar al conectorului, în circuitele electronice poate fi: J, P sau E sau SK.
În unele cazuri adică de cele mai multe ori se ţine cont de orientare, iar în altele nu. De cele
mai multe ori forma conectorului indica orientarea corectă a acestuia, nefiind posibilă mon-
tarea lor în mod greşit.

Cheia adică semnul care indica orientarea poate fi o tăietură pe un colţ, o fantă pe o latură,
un număr (numărul 1), acesta indicând pinul numărul 1.

Există conectori de tip mama şi respectiv de tip tata. De obicei și am înțeles că asta este o
regulă conectorii de tip mamă sunt fixaţi într-un circuit alimentat, iar conectorii de tip tata
se leagă la un circuit nealimentat.

© Bitulică 2020
Povestea lui Bitulică

Pentru a crea module logice


Am asistat la circuite logice
ELECTRO

Mi s-a spus că dacă tot am trecut pe la orele de electronică e bine să stau si la cele unde se
explică circuitele logice. Am stat si am aflat că porțile logice sunt folosite în circuite digitale
pentru a implementa operațiile din algebra booleană. Fiindcă sunt foarte multe moduri în
care o anumită funcție logică poate fi realizată nu numai ca design de circuit, ci și ca mod de
fabricație al circuitelor integrate, porțile sunt grupate în familii logice.

Wired logic adică logică cablată cu diode sunt circuite extrem de ușor de realizat, folosind
numai diode și rezistențe de pull-up/pull-down. Sunt circuite pur pasive care nu au etaj fi-
nal de amplificare, așa că nivelele logice de la ieșire sunt degradate spre exemplu 0.6V în loc
de 0V, 4.4V în loc de 5V.

RTL adică resistor-transistor logic sunt prima formă de logică digitală ce foloseşte elemente
active, și anume tranzistori bipolari. Logica este efectuată în etajul de intrare, utilizând re-
zistențe. Dezavantajul acestei familii de porți logice este consumul foarte mare, din cauza
tranzistorilor folosiți și a rezistențelor.

DTL adică diode-tranzistor logic sunt o familie de circuite ce combină logica cablată cu un
etaj final cu tranzistori bipolari.

TTL adică transistor-transistor logic reprezintă un avans față de DTL, folosind tranzistori
bipolari, în general multiemitor, inclusiv în etajul de intrare. Etajul de ieșire este realizat fo-
losind 2 tranzistori, unul NPN și unul PNP, într-o conexiune ce poartă denumirea de stâlp
totemic sau push-pull.

ECL adică emitter-coupled logic este o familie circuite de mare viteză, ce folosește tot tran-
zistori bipolari, însă care nu intră niciodată în saturație.

Din acest motiv, marginea de zgomot (diferența dintre tensiunea în starea LOW și tensiunea
în starea HIGH) este foarte mică, deci aceste circuite sunt susceptibile la zgomot.

NMOS adică N-type metal-oxide-semiconductor logic spre deosebire de familiile anterioare,


NMOS se folosește de tranzistori cu efect de câmp adică FET și de rezistențe de pull-up.
CMOS adică complementary metal-oxide-semiconductor logic nu folosește deloc rezistențe,
ci tranzistori de tip nMOS și pMOS. Este tehnologia folosită În prezent la fabricarea majori-
tății dispozitivelor electronice.

Am văzut că aproape toate formele de logică digitală conţin, într-un mod sau altul, tranzis-
tori.

© Bitulică 2020
Povestea lui Bitulică

Din motive tehnice, este mai ușor să realizez porți logice pentru funcțiile NAND și NOR de-
cât pentru echivalentele lor în logica pozitivă, AND și OR. Din această cauză, va trebui să
rescriu funcțiile logice astfel încât să folosesc numai aceste operații.

Nu este ieșit din comun ca procesoare întregi să fie implementate utilizând doar porți
NAND sau doar porți NOR.

Inversorul NMOS funcționează astfel: în starea HIGH pe intrare, tranzistorul se deschide și


trage tensiunea la masă iar în starea LOW pe intrare, tranzistorul se închide și este tras la
rezistența numită rezistență de pull-up.

Inversorul CMOS funcționează astfel: cei doi tranzistori sunt legați în stâlp totemic: având
intrările conectate în paralel, niciodată cei doi tranzistori nu vor fi deschiși în același timp.

În starea LOW pe intrare tranzistorul pMOS este deschis iar cel nMOS este închis. Ieșirea
este legată la sursă. În starea HIGH pe intrare tranzistorul pMOS este închis iar cel nMOS
este deschis. Ieșirea este legată la masă.

Circuitele logice combinaționale sunt circuitele reprezentate prin porți logice ce aplică o
funcție pe intrări. Valorile de ieșire depind doar de valorile de intrare, nu și de stări de reac-
ție adică feedback, iar când starea unei intrări se schimbă, se reflectă imediat la ieșiri.

Un circuit combinațional poate fi descris printr-o schemă de interconectarea a unor porți


logice, prin funcția adică expresia)în logica booleană ce este aplicată pe intrări și prin tabele
de adevăr dacă nu au un număr prea mare de intrări.

Circuitele combinaționale sunt folosite în procesoare în cadrul componentelor de calcul, iar


cele mai des întâlnite sunt: multiplexoare și demultiplexoare, sumatoare, codificatoare și
decodificatoare, comparatoare, memorii ROM adică read-only și nu păstrează starea.

Un multiplexor digital este un circuit combinațional care implementează o funcție de selec-


ție a uneia dintre intrările sale.

Alegerea semnalului de ieșire se face pe baza unor intrări suplimentare care reprezintă în
baza 2 numărul intrării ce trebuie selectate, astfel un multiplexor cu 2 la n intrări va avea
nevoie de n semnale de selecție.

Funcția logică corespunzătoare unui multiplexorului 4:1 este următoarea: ouţ =


¬S1∧¬S2∧I1 ∨ S1∧¬S2∧I2 ∨ ¬S1∧S2∧I3 ∨ S1∧S2∧I4. Folosind această expresie pot descrie
circuitul combinațional pentru multiplexor, având nevoie conform formulei de 4 porți lo-
gice AND cu trei intrări, o poartă OR cu 4 intrări și porți NOT pentru negarea semnalelor de
selecție.

Sumatoarele adică adders, sunt folosite cel mai mult în unitățile aritmetice logice ale proce-
soarelor, realizează adunări pe un număr dat de biți, furnizând la ieșirea circuitului suma și
transportul adică carry rezultat în urma operației.

© Bitulică 2020
Povestea lui Bitulică

Există mai multe tipuri de sumatoare pentru adunarea numerelor pe n biți, iar acestea se
bazează pe sumatoare simple de 1 bit ce pot fi de două tipuri: Half-adder care însumează
doi operanzi pe 1 bit și oferă la ieșire suma acestora și un transport și Full-adder care însu-
mează doi operanzi pe 1 bit și un transport și oferă la ieșire suma acestora trei și un tran-
sport.

Spre deosebire de circuitele logice combinaționale, cele secvențiale nu depind exclusiv de


starea curentă a intrărilor, ci și de stările anterioare ale circuitului. Circuitului combinațio-
nal format din porți logice i se adaugă un element de memorare a stărilor.

Circuitele secvențiale sunt de două tipuri: asincrone care se mai numesc și latch și care sunt
rar folosite și țin cont de ordinea în care se schimbă intrările, elementul de memorare fiind
de fapt căi de feedback și sincrone care se folosesc pentru memorarea stării.
Bistabili sau Flip-Flop, își schimbă valoarea stocată doar la schimbarea semnalului de ceas
primit la intrare.

Pe scurt, latch-urile sunt transparente: ieșirea se actualizează în timp real, odată cu modifi-
carea vreuneia dintre intrări. În contrast, bistabilele sunt sincrone, deci își schimbă starea
numai pe frontul crescător (sau descrescător) al semnalului de ceas.

Latch-ul SR are două intrări: S adică Set care pune Q pe HIGH, deci stochează valoarea HIGH
și R adică Reset care pune Q pe LOW, deci stochează valoarea LOW.

Funcționarea sa este următoarea: S = R = LOW ⇒ Q nu se schimbă. S = HIGH, R = LOW ⇒ Q =


HIGH, R = HIGH, S = LOW ⇒ Q = LOW, S = R = HIGH ⇒ stare nedeterminată.

Bistabilul JK este similar celui SR, având două intrări J și K, însă elimină starea ambiguă
adică ambele intrări HIGH funcționând în felul următor: J = K = LOW ⇒ Q nu se schimbă, J ≠
K ⇒ Q = J, J = K = HIGH ⇒ Q basculează

Bistabilul D pornește tot de la eliminarea stării ambigue de la bistabilul SR, și reușește acest
lucru prin a nu mai permite ca S și R să fie egale. Bistabilul D are o singură intrare, D, conec-
tând cele două intrări SR printr-un invertor astfel: D = 0 ⇒ Qt+1 = 0, D = 1 ⇒ Qt+1 = 1.

Acest tip de bistabil este cel mai des utilizat, datorită proprietății sale de a se comporta ca o
celulă de memorare. Este folosit pentru realizarea registrelor procesoarelor.

© Bitulică 2020
Povestea lui Bitulică

Pentru a crea o aplicație


Am învățat să o gândesc
ARHI

Am stat și m-am gândit cum să proiectez, adică să fac arhitectura aplicației, am citit, am în-
trebat în stânga și în dreapta și am înțeles că proiectarea unei aplicaţii se poate face în două
feluri mari şi late, cât şi prin combinarea lor.

Dacă nu cunosc toate detaliile, ci doar ştiu în mare despre cum o să arate şi să funcţioneze,
atunci aplic aşa numita metoda FRONT-END, şi construiesc cadrul, apoi îl umplu cu detalii -
de la cele mai mari până la cele mai mici. Exact cum fac arhitecţii când nu ştiu ce materiale
urmează să folosească sau / și care vor fi condiţiile de mediu şi amplasament. Se numeşte
aşa, pentru că pornesc din fața aplicaţiei de acolo de unde este utilizatorul ajungând pe ulti-
mul nivel de detaliu.

De exemplu, dacă am de făcut kitul care face dintr-o casă clasică una inteligentă, dar nu ştiu
încă toate detaliile cum ar fi , cât de multe chestii va ști să facă fiecare lucru în parte, dacă
fiecare lucru va fi inteligent sau vor face parte dintr-un sistem inteligent, dacă pot vorbi cu
fiecare lucru sau doar cu casa, urmând ca sistemul central să comunice fiecărui lucru ce are
de făcut.

În acest caz, sunt obligat să pornesc de la lucrurile mari spre detaliu, şi atunci mă apuc şi fac
interfaţa cu elementele comune tuturor aplicaţiilor, apoi o bază de date cu tabele care
conţin doar câmpurile comune unei tabele şi indispensabile, urmând apoi pe măsură ce am
şi celelalte informaţii să implementez şi detaliile - cum ar fi să adaug câmpurile din tabela
de membri ai casei pe care nu le ştiam, că nu le aveam în casă, sau / şi funcţionalităţi în in-
terfaţa care ţin de informaţiile primite ulterior.

Dacă cunosc toate detaliile, atunci construiesc aplicaţia în sistem piramidal de la bază la
vârf, folosind aşa-numita metoda BACK-END şi implementez întâi cele mai rudimentare
proceduri şi funcţii sau elemente ale mediului de persistență, urmând ca, utilizându-le pe
acestea, să construiesc cu ele elemente şi mai complexe până ajung în vârful piramidei. Se
numeşte aşa, pentru că pornesc cumva din spatele aplicaţiei şi ajung în faţa ei, adică acolo
de unde o vede utilizatorul. Persistența înseamnă acţiunea de a stoca datele că bazele de
date sau xml sau fişiere.

De exemplu, pentru acelaşi proiect care implementează kitul pentru o casă inteligentă, dacă
am toate detaliile, pot începe de la crearea tabelelor cu toate câmpurile lor. Apoi aceste ta-
bele să le leg între ele şi să formez schema bazei de date. Adică schema entităților sistemu-
lui, fără a scrie însă efectiv codul, adică fără a crea baza de date.

Apoi pe baza acestei scheme, să îmi creez o aplicaţie kernel, apoi aplicația kernel să o leg de
un core, apoi core-ul de o aplicație web, apoi din aplicaţia web să generezi interfaţa utiliza-
tor. Adică pe sistemul - componentele mici vor forma ulterior o componentă mai mare care

© Bitulică 2020
Povestea lui Bitulică

va intra în componenţa uneia şi mai mari şi, în final, toate vor forma aplicaţia. Aşa cum nu-
cleonii formează nucleul, nucleul şi electronii formează atomul, mai mulţi atomi formează
molecula, mai multe molecule formează celula, mai multe celule formează organul, mai mult
organe formează omul sau ca în piesa de teatru IONA - cu peştii.

În realitate, însă, cele două metode se întrepătrund, pentru că, în realitate, cea de-a doua
metodă este aproape imposibil de aplicat curat, pentru că clienţii care cer produsul la cheie
nu ştiu în detaliu ce vor, dar, odată cu experiența în proiectare / programare, cele două me-
tode se întrepătrund şi se face un schelet al aplicaţiei mental, apoi se construiește un UML,
adică schema logică, apoi se începe cu implementarea modulelor elementare şi cu ele se
contruiesc altele mai complexe, până se ajunge la forma finală a aplicaţiei.

De exemplu, dacă nu eu voiam să implementez acest proiect pentru propria casă și îmi ce-
rea altcineva să fac asta, care să arate cam ca o alta casă pe care a văzut-o şi i-a plăcut,
atunci ar fi fost necesar să observ acea casă, ca să îmi fac în minte un model şi, cum aș fi
ştiut din experienţa cam ce ar necesita ceea ce vrea acea persoană şi ea nu avea de unde să
știe asta, m-aș fi apucat să implementez aplicaţia pornind de la cele mai mici module.
Proiectarea unei aplicaţii trebuie să ţină seama de componentele scheletului ei, fără a omite
nici un os, pentru că, altfel, aplicaţia va deveni schiloadă, iar dezvoltarea ei ulterioară este
îngreunată.

Componentele unei aplicaţii cuprind modulul de intrare / ieşire, adică UX, care este o inter-
faţă cu mediul înconjurător de unde se preiau şi unde se aruncă datele prelucrate. De cele
mai multe ori, aceste module sunt interfeţe grafice pentru utilizator, adică GUI, dar pot fi şi
simple interfeţe cu alte aplicaţii sau module. De exemplu, la kitul pentru casa inteligentă, o
interfaţă sunt senzorii - ca senzorul de temperatură sau de presiune.
Nucleul sau kernel-ul, care este componenta centrală a aplicației, care ia deciziile, adică cre-
ierul, folosindu-se de un algoritm şi/sau de resurse şi le transmite apoi către dispozitivele
de intrare ieşire.

De exemplu, în proiectul meu, nucleul este aplicaţia implementată în C++ și care va rula pe
microcontrollerul Raspberry Pi, care ia deciziile în funcţie de datele primite de la interfaţa
și senzori şi în funcţie de datele din bazele de date și structura internă, precum și de modul
de implementare al algoritmului, ia o decizie sau alta.

Core-ul sau ansamblul de motoare este componenta aplicaţiei care leagă nucleele între ele
printr-un flux şi/sau executa operaţiile comandate de acestea.

De exemplu, în proiectul meu, Core-ul este reprezentat de o aplicație server care rulează pe
un server web, implementată în Java cu Spring Integration și care interfațează cu sistemul
printr-un rest api.

Resursele sunt componentele care deţin informaţiile într-o aplicaţie. De exemplu, în proiec-
tul meu, resursele sunt reprezentate de datele din baza de date, de imagini și de sunete.

În proiectarea şi mai ales ulterior în implementarea aplicaţiei, cele patru tipuri de compo-
nente nu trebuie să se calce pe bătături pentru că, altfel, o să fac o ciorbă de varză şi s-ar pu-
tea să provoace în timp indigestie.

© Bitulică 2020
Povestea lui Bitulică

Aşa că este bine să urmez câteva sfaturi în acest sens, ca faptul că în interfaţă nu are ce că-
uta nici o logică legată de ce trebuie să se întâmple cu datele. Interfaţa trebuie să ştie doar
să primească şi să afişeze nişte date, iar în momentul primirii să le valideze din punct de ve-
dere structural, nu ca și conţinut.

De exemplu, în proiectul meu, utilizatorul trebuie să introducă o comandă prin care să


stingă becul din bucătărie. În spatele butonului prin care se trimite comanda, trebuie să va-
lidez dacă utilizatorul a introdus un text corect din punct de vedere lexical și sintactic. Atât.

Adică să fac doar o validare de structură. Este total greşit să validez aici şi dacă becul e ars și
nu se poate aprinde și să fac asta prin interogarea sistemului care să interogheze baza de
date şi să vadă dacă scrie acolo că becul e ars. Asta, pentru că se îngreunează lucrul cu inter-
faţa. Acesta verificare o fac numai după ce utilizatorul a completat toată comandă şi știu si-
gur că această comandă e scrisă corect. Abia atunci procesez conţinutul comenzii. Până
atunci, doar mă asigur că nu a comandat gogoşi într-un magazin de pantofi.

Mă gândesc mereu că, atunci când mănânc ciorba de legume pe limbă şi pe buze am nişte
senzori care îmi spun dacă să înghit ciorba sau nu. Îmi spun dacă arde sau dacă e stricată. Și
mă gândesc cum ar fi să nu îi fi avut şi să vomit mereu sau să îmi ard mucoasa stomacală.
Am înțeles că nu trebuie să încarc niciodată resursele în memoria RAM, mapandu-le la o
structură, oricât de tentant ar fi, dat fiind timpul mai rapid de execuţie. Nu ştiu niciodată
câtă memorie folosesc de exemplu serverele web apache, tomcat, asp şi e posibil să am sur-
prize neplăcute.

Uneori, preluarea informaţiilor din baze de date foarte mari este anevoioasă şi durează mai
mult şi atunci ar fi tentant ca, la pornirea aplicaţiei, să încarc într-o structură de date în me-
morie toată baza de date ca, de exemplu, într-o matrice şi să caut în matrice fără să mai inte-
roghez. Acest lucru este greşit, iar dacă se face se face ferestruit.

Adică se încarcă o parte, iar când se ajunge la aproape de limită, se mai încarcă o bucată şi
aşa mai departe. Aşa am înțeles că se fac jocurile, de-aia arată că încarcă nivelul 1, nivelul 2.
Se numeşte ferestruire, pentru că e ca şi cum m-aș uita pe geam şi când dau capul mai în jos
văd şi mai sus şi, când îl cobor, văd şi mai jos, dar tot aceeași bucată văd, ca dimensiuni.

De exemplu, atunci când voi vrea să afişez toate acțiunile care au avut loc în decursul unei
anumite perioade în casă în sub formă de loguri într-o listă, dar sunt mai multe decât încap
pe ecranul monitorului, utilizatorul vede din lista aia doar cât e ecranul - să zicem 200 de
acțiuni. Atunci, eu încarc în memorie 300, din care 200 se văd şi 100 sunt ascunse în josul
paginii. Când utilizatorul dă scroll, mai apare câte una, iar, când ajunge pe la a 250-a, mai
încarc din baza de date vreo 50 şi tot aşa.

Aşa face Facebook, cred. Am văzut că eu când dau în jos pe telefon foarte repede stă puţin să
îţi mai încarce. Asta, pentru că mişcarea mâinii e mai rapidă decât se încarcă din baza de
date uneori, dar, de regulă, ai impresia că nu se mai termină postările. Pentru că el merge pe
principiul descris mai sus.

© Bitulică 2020
Povestea lui Bitulică

Am înțeles că e bine să învăţ kernelul, core-ul și interfața să lucreze asincron. Adică, dacă un
utilizator apasa pe un buton că vrea ceva, nu trebuie să nu mai poată face nimic în interfaţă
până îi vin datele.

De exemplu, dacă un utilizator dă o comandă, până acesta se procesează, poate vrea să se


mai uite pe niște date în interfață.

© Bitulică 2020
Povestea lui Bitulică

Pentru a crea o casă inteligentă


Am studiat microcontrollerele
MICRO

Am înțeles că e bine să încep să dezvolt aplicația pe un microcontroller așa că am luat unul.


Raspberry Pi.

Este o placă de dezvoltare de tip SBC adică Single Board Computer adică un sistem de calcul
nemodular implementat pe un singur cablaj electronic. Chiar dacă are dimensiuni reduse
măsurând 85mm x 56mm, este un calculator complet permițând funcționalități obișnuite
precum rularea unui sistem de operare adică Linux sau Windows și rularea de aplicații uti-
lizator adică jocuri, editoare de text, medii de programare, redarea de muzică și filme, apli-
cații de teleconferință, sau aplicații Internet.

Diferențele între o placă Raspberry Pi și un calculator personal PC sau laptop constau atât
în dimensiunea redusă a plăcii cât și în puterea mai mică de calcul a acesteia adică nu are
aceleași performanțe de calcul precum un PC desktop care are un cost și o dimensiune de
câteva ori mai mari.

Pot compara placa Raspberry Pi cu o tabletă sau cu un sistem de tip NetBook dar fără a dis-
pune de ecran și tastatură. În plus, placa oferă posibilitatea de a conecta diverse compo-
nente electronice specifice sistemelor embedded adică senzori, butoane, ecrane LCD sau pe
7 segmente, drivere de motoare, sau relee.

Posibilitatea de a personaliza sistemele de programe adică sistemul de operare și aplicațiile


și posibilitatea de interconectare cu alte componente electronice fac din placa Raspberry Pi
un sistem de calcul ce poate sta la baza proiectului meu pentru că este un calculator ce
poate fi integrat în sisteme electronice și mecanice proiectate și realizate de utilizator.

În ciuda dimensiunii reduse placa Raspberry Pi dispune de numeroase periferice integrate


acoperind complet funcționalitatea unui sistem de calcul cu audio, video, porturi USB și co-
nectivitate de rețea.

Are procesor SoC pe 64 de biți din familia ARMv8-A, Broadcom BCM2837, ce lucrează la o
frecvență de 1.2GHz și dispune de 4 nuclee de tip ARM Cortex-A53. Are 1GB de memorie
RAM folosită și ca memorie video, partajată cu procesorul grafic.

Include procesor grafic Broadcoam VideoCore IV 3D integrat pe aceeași pastilă de siliciu ca


și procesorul principal; Are ieșire digitală video / audio HDMI, ieșire analogică video cu
composite video sau audio mixtă prin intermediul unei mufe jack 3.5mm.

Mai are mufă de rețea RJ45 Ethernet 10/100 Mbit/s, conectivitate WiFi 802.11n, conectivi-
tate Bluetooth 4.1 / BLE, 4 porturi USB 2.0, 40 de pini de intrare / ieșire GPIO, Slot card de
memorie microSD (utilizat pentru instalarea sistemului de operare), conectori dedicați pen-
tru cameră video (CSI) și afișaj DSI.

© Bitulică 2020
Povestea lui Bitulică

Pentru a pune în funcțiune placa Raspberry Pi am nevoie de unele componente suplimen-


tare ca un cablu HDMI și un monitor / televizor cu intrare HDMI. În cazul în care nu dispu-
nem de un monitor / televizor cu intrare HDMI pot utiliza un adaptor HDMI-DVI sau un
adaptor HDMI-VGA depinde de intrarea monitorului pe care îl voi utiliza. Mai am nevoie de
un alimentator de rețea cu ieșire de 5V, minim 2.5A și mufă microUSB.

Este recomandată utilizarea alimentatorului oficial sau a unui alimentator de calitate care
asigură o tensiune corectă și un curent suficient pentru alimentarea plăcii Raspberry Pi. În
cazul în care utilizăm un alimentator ieftin putem distruge placa din cauza fluctuațiilor de
tensiune sau putem întâmpina probleme în utilizare din cauza curentului insuficient debitat
de sursa de tensiune.

Tastatură și mouse USB. Sunt necesare pentru instalarea și configurarea inițială a sistemu-
lui. Dacă, ulterior, se utilizează sistemul de la distanță, tastatura, mouse-ul și monitorul nu
mai sunt necesare. O variantă mai simplă, și mai comodă, este utilizarea unui dispozitiv
mixt tastatura / touchpad fără fir.

Are card de memorie microSD, capacitate minimă 8GB dar eu am pus 16GB că așa e reco-
mandat, clasa de viteză 10. Cardul de memorie va stoca sistemul de operare la fel ca și hard-
disk-ul în cazul unui sistem de calcul de tip PC sau laptop.

Este foarte importantă utilizarea unui card microSD de calitate și de viteză adecvată din ca-
uză că utilizarea unui card de calitate îndoielnică poate conduce la probleme de funcționare
extrem de neplăcute: blocări în funcționare, resetarea aleatorie a sistemului, pierderi de
date etc. Dacă este posibil, se recomandă utilizarea cardului microSD oficial.

Dacă sistemul va fi utilizat într-o rețea locală pe cablu este necesar și un cablu de rețea UTP
– patch-cord. Dacă se utilizează placa într-o rețea locală WiFi nu este necesar. Conectivita-
tea de rețea sau conectivitatea Internet nu este obligatorie pentru funcționarea plăcii dar
este recomandată deoarece altfel nu se pot realiza actualizările de securitate ale sistemului
de operare, nu se pot menține corect setările de dată și oră și, bineînțeles, se pierde o funcți-
onalitate importantă a sistemului.

Opțional, dar recomandat, este utilizarea și a unei carcase pentru placa Raspberry Pi.

Manipularea plăcii fără nici un fel de protecție poate conduce la deteriorarea acesteia dato-
rită descărcărilor electrostatice adică descărcarea sarcinii electrice statice a corpului uman
în circuitul electronic prin atingerea componentelor conductoare a acestuia, a șocurilor me-
canice și a murdăriei adică praf, lichide, grăsimi.

© Bitulică 2020
Povestea lui Bitulică

Pentru a vedea cum funcționează


Am instalat un microcontroller
MICRO

Următorul pas, necesar înainte de punerea în funcțiune a plăcii Raspberry Pi, este pregăti-
rea cardului microSD pentru instalarea sistemului de operare.

Placa poate rula diverse distribuții ale sistemului de operare Linux și o versiune minimală a
sistemului de operare Microsoft Windows 10. Prin versiune minimală înțeleg o variantă ce
nu poate fi folosită ca platformă desktop ci doar ca platformă pentru aplicații Windows 10
IoT Core.

Voi instala distribuția Linux Raspbian, sistemul de operare oficial al plăcii Raspberry Pi, sis-
tem de operare foarte ușor de utilizat și recomandat pentru începători.

Pentru că utilizez cardul microSD oficial al plăcii Raspberry Pi instalarea sistemului de ope-
rare este foarte simplă deoarece cardul de memorie conține utilitarul NOOBS adică New
Out Of Box Software ce facilitează instalarea diverselor sisteme de operare specifice plăcii
Raspberry Pi.

Pentru pornirea instalării sistemului de operare inserez cardul în slotul microSD al plăcii și
se pornește sistemul. Înainte de asta m-am asigurat că am toate echipamentele conectate
corect: tastatură, mouse, cablu HDMI. După inițializare utilitarul NOOBS îmi permite alege-
rea sistemului de operare pe care vreau să-l instalez.

În cazul în care placa nu era conectată la Internet prin cablu sau prin WiFi singura opțiune
de instalare ar fi fost sistemul de operare Raspbian al cărui kit de instalare se află deja pe
cardul de memorie.

Toate celelalte sisteme de operare necesită conectivitate Internet pentru instalare. Conexiu-
nea la Internet se poate realiza prin conectarea cu un cablu la o rețea ce oferă setări auto-
mate DHCP sau configurând accesul WiFi.

După confirmarea sistemului de operat dorit, utilitarul NOOBS va instala automat sistemul
de operare iar acest proces durează câteva zeci de minute.

După finalizarea procesului de instalare sistemul va reporni și pot deja să lucrez cu placa
Raspberry Pi.

În cazul în care nu aș fi dispus de un card microSD cu NOOBS preinstalat puteam utiliza un


card microSD de calitate pe care să copiez utilitarul NOOBS adică să îl downloadez și să îl
dezarhivez pe cardul microSD.

O alternativă la utilizarea programului NOOBS este copierea directă a sistemului de operare


pe cardul microSD. Copierea nu se poate face direct, ca în cazul NOOBS, ci se realizează prin

© Bitulică 2020
Povestea lui Bitulică

transferul unui fișier imagine cu ajutorului unui utilitar specializat, de exemplu: Etcher sau
Win32DiskImager.

Se downloadează imaginea de sistem de operare dorit varianta LITE nu include interfața


grafică și se copiază pe cardul de memorie.

După această operație cardul de memorie va conține sistemul de operare deja instalat, gata
de utilizare.

Cardul de memorie se poate introduce în slotul plăcii și se poarte porni sistemul.

© Bitulică 2020
Povestea lui Bitulică

Pentru a vedea fi funcțional


Am configurat un microcontroller
MICRO

Există două metode de configurare a plăcii Raspberry Pi. Folosind utilitarele puse la dispo-
ziție de interfața grafică a sistemului de operare Raspbian sau folosind utilitarele în linie de
comandă, adică Terminal.

Utilitarul principal de configurare se numește „raspi-config” și poate fi accesat atât prin in-
termediul interfeței grafice, cât și în linie de comandă.

În linie de comandă, după ce am accesat aplicația „Terminal” din bara de aplicații, introduc
comanda:

sudo raspi-config

Comanda „sudo” permite execuția de utilitare sistem privilegiate care pot fi executate doar
cu drepturi de administrare a sistemului.

Chiar dacă contul de conectare inițial are drepturi depline asupra sistemului, adică drepturi
de administrator sau root, sistemul de operare nu permite execuția unor comenzi sau utili-
tare importante, fără a fi precedate de comanda „sudo”, pentru a preveni accidentele de
configurare.

Accesarea utilitarului în linie de comandă este utilă mai ales când sistemul este administrat
de la distanță prin intermediul utilitarului „ssh”.

Prin intermediul utilitarului „raspi-config” pot configura majoritatea setărilor de sistem ale
plăcii Raspberry Pi, dar o să fac următoarele setări esențiale pentru a putea lucra mai de-
parte.

Modificarea credențialelor implicite ale sistemului. Datele de conectare implicite ale siste-
mului Raspbian sunt: utilizator: pi / parolă: raspberry . Se recomandă modificarea parolei
implicite pentru ca sistemul să nu fie accesat în mod neautorizat.

Notați noua parolă, fără aceasta este posibil să nu mai puteți accesa sistemul și să trebu-
iască să reinstalați sistemul de operare.

Am realizat setările de rețea, pentru ca placa să se poată conecta la Internet. Conexiunea la


Internet este importantă pentru funcționarea corectă a plăcii. Cel mai simplu este să confi-
gurez conexiunea WiFi, accesând icon-ul specific din bara de aplicații.

Dacă folosesc o conexiune pe cablu, aceasta se configurează în mod automat, dacă sistemul
este introdus într-o rețea ce oferă DHCP.

© Bitulică 2020
Povestea lui Bitulică

Am dat să instaleze update-urile pentru pachetele software din distribuție, pentru a mă bu-
cura de ultimele facilități oferite de sistemul de operare Raspbian și pentru a beneficia de
corecțiile de securitate.

Pentru a face acest lucru voi tasta în aplicația „Terminal” următoarele comenzi:

sudo apt-get update


sudo apt-get dist-upgrade

Am activat serviciile de acces la distanță, pentru că vreau să utilizez placa fără periferice
proprii, adică tastatură, mouse și monitor.

Cele mai cunoscute programe de acces la distanță sunt VNC pentru accesul în mod grafic și
ssh pentru accesul în linie de comandă.

Ambele sunt instalate implicit în distribuția Raspbian și pot fi activate prin intermediul uti-
litarului raspi-config.

De multe ori este mai comod sau pur și simplu natura proiectului impune accesul la dis-
tanță pentru utilizarea plăcii Raspberry Pi.

Prin acces la distanță, nu se înțelege neapărat faptul că placa se află la mare distanță, ci că
nu este accesată de la o tastatură și un monitor direct conectate.

În acest fel, pot utiliza placa fără a bloca un set de periferice dedicate.

Pentru a putea să mă conectez la placa Raspberry Pi prin intermediul rețelei este necesar să
cunosc adresa IP a acesteia. Dacă alocarea adreselor IP în rețeaua locală în care se utilizează
placa se realizează în mod static este suficient să îmi notez adresa alocată după instalarea
sistemului de operare, utilizând comanda ifconfig în aplicația Terminal.

Dacă placa se conectează într-o rețea locală ce alocă dinamic adresele IP, asta înseamnă că
la fiecare repornire este posibil ca adresa IP să se modifice și nu am altă posibilitate decât
să ”scanez” rețeaua pentru a descoperi ce adresă a fost alocată pentru placa Raspberry Pi.

Scanarea se face cu aplicații specifice, de exemplu: Angry IP Scanner sau nmap.

După instalare, aplicația Angry IP Scanner permite verificarea întregii plaje de adrese dintr-
o rețea locală și raportează ce adrese IP sunt active, adică alocate și ce servicii rulează siste-
mele de calcul respective.

Pentru accesul la distanță în linie de comandă am utilizat programul ssh ce permite deschi-
derea unei sesiuni de tip terminal de pe un alt sistem de calcul. Este necesară instalarea
unui client ssh pe sistemul de pe care se va face accesul.

Cel mai cunoscut client ssh pentru Windows este putty, sistemele Linux au clientul ssh in-
stalat implicit.

© Bitulică 2020
Povestea lui Bitulică

Pentru accesul la distanță, beneficiind de interfața grafică pusă la dispoziție de sistemul de


operare, voi putea utiliza programul VNC.

La fel ca și în cazul ssh, este necesară instalarea pe sistemul de pe care se face accesul a unui
client specific. Unul dintre cei mai cunoscuți clienți VNC este RealVNC.

© Bitulică 2020
Povestea lui Bitulică

Pentru a începe să programez


PRO
Am creeat un proiect

Pentru a creea un program am nevoie de un editor în care să scriu text conform cu un lim-
baj ales după dorință sau după cerință și un compilator sau un interpretor care să tran-
sforme ce am scris în cod mașină sau să interpreteze și facă ce am scris.

Editorul poate fi un simplu editor de text dar pentru că tehnologia a evoluat și programato-
rii și-au dezvoltat propriile aplicații în care să scrie cod, să-l compileze și să-l execute adică
să-l ruleze este indicat să folosesc aceste aplicații pentru crearea de noi aplicații.

Am înțeles că sunt multe limbaje care se pretează pe diferite nivele de implementare și care
sunt utilizate în diferite locuri de pe harta dezvoltatorilor de soft.

Așa că programatorii au implementat așa numitele IDE-uri adică integrated sau interactive
development enviroment sau enterprize cu ajutorul cărora se poate scrie cod în cele mai
utilizate limbaje la ora actuală.

Cele mai utilizate IDE-uri sunt Visual Studio, NetBeans Eclipse sau Intelij IDEA.
După ce am instalat mediul de dezvoltare Visual Studio pot începe să scriu programe.
Un program este un proiect , deci pentru a începe să scriu un program trebuie să prealabil
să creez un proiect.

Pentru a creea un proiect nou indiferent de IDE-ul folosit trebuie să accesez meniul File-
>New al aplicației.

Acolo am găsit tipuri de proiecte adică template-uri și am filtrat pentru un proiect scris in
limbajul C++ pentru sistemul de operare Linux pentru că va rula pe Raspberry PI și care să
fie tip consolă.

Mi s-a generat un proiect și implicit nişte fișiere pe care momentan le pot ignora că nu știu
ce e cu ele și la ce folosesc iar în editor mi-a apărut deschis un fișier care conține un cod.
Codul generat am înțeles că cuprinde definiția funcției main care este funcția principală a
oricărui program.

Momentan mă opresc din implementarea proiectului și mă duc să aprofundez ca să înțeleg


ce este scris și mai ales de ce este scris asa.

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să înțeleg cum să fac


PRO
Am descoperit algoritmul

Când vine vorba de conceperea unui program pe care sa îl execute un PC majoritatea oame-
nilor se sperie pentru că nu îi înțeleg limbajul. Eu nu m-am speriat.

Am înțeles că este ca și cum i-ai spune cuiva pe limba ta ce să facă doar că unui PC îi spui pe
limba lui pe care o înveți ca pe o limbă străină.

Am văzut că trebuie să privesc calculatorul ca pe cineva care nu știe să facă nimic dar înțe-
lege tot ce ii spun.

Trebuie să îi explic totul pas cu pas in cele mai mici detalii. Cu cat va ști mai multe detalii cu
atat va fi mai eficient.

Dacă trebuie sa îl învăț să îmi aducă pantofii cu toc care sa se asorteze la un costum de gală
atunci în limbaj natural îi pot spune așa

1. Mergi inainte.
1.1 Dacă în calea ta găsești un scaun uitat ocoleste-l
1.1.2 Dacă nu poți să îl ocolești sare-l
1.2 Dacă găsești ușa închisă deschide-o
1.2.1 Dacă e încuiată anunță-mă să vin să o deschid
1.2.2 Dacă tot vin mi-i iau singur
1.2.3 Ești liber
1.3 După ce ieși închide ușa
2. Ia-o la dreapta
3. În fața ta este un suport de pantofi
3.1 Pantofii sunt ultimii din stanga
3.1.1 Dacă nu îi găsești acolo înseamnă ca sunt ultimii din dreapta
3.2 Dacă nu îi găsești nici acolo adu-mi-i pe cei cu talpă plată
4. Ia pantofii
5. Vino în hol
6. Dă-mi-i
7 Terminat. Multumesc.

Am înțeles că limbajul natural în care scriu un program se numește pseudo-cod pentru că


nu e cod dar e ca și cum ar fi un cod.

De fapt e chiar un cod pentru cei neinițiați pentru că până la urma și scrisul în sine este un
cod. Un cod al cuvintelor.

Literele sunt simboluri care codifica sunetele.

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să arăt la alții


PRO
Am descoperit schema logică

După ce programul este scris în pseudo-cod, el este împărțit pe module logice, sub forma
unei scheme logice, în componența căreia intră figuri geometrice legate prin segmente de
dreaptă.

Ideea pseudo-cod-ului este de a schiţa ideile, iar a schemei logice de a arăta ideile și altora
care nu știu să scrie cod, dar pot înțelege o schemă, cum ar fi project managerii sau a clien-
tului care cere implementarea unui produs software.

Pentru că schemele logice sunt înțelese de majoritatea oamenilor, aceste scheme logice se
numesc UML-uri, adică Unified Modeling Language, adică limbaj de modelare unificat.

Prin convenție s-au stabilit și acceptat figuri geometrice care corespund anumitor tipuri de
operații ca elipsa care simbolizează start program sau subprogram.

„Dreptunghi” care simbolizează operații de atribuire valori, „trapez” cu latura mic în jos
care înseamnă operații de citire, adică operații de intrare în program, de aceea e și ca o să-
geată ruptă orientată în jos, că intră ceva în schema logică, „trapez” cu latura mare în jos
care simbolizează operații de scriere, adică operații de ieșire din program, de aceea e și ca o
săgeată ruptă orientată în sus, că iese ceva din program.

„Paralelogram”, adică figura geometrică cu două laturi drepte și două pe diagonală, adică
două așa / / și două = , care simbolizează operații de citire scriere și este alternativa la cele
două tipuri de „trapez”, „romb”, care simbolizează condiții.

Aceste figuri geometrice sunt legate prin segmente de dreaptă și au ca direcție direcția sus -
jos , adică programul începe de sus și se termină jos.

În blocurile condiționale, opțiunile se trasează din vârfurile laterale sau cel de jos al rombu-
lui pentru că orice bloc condițional are maxim 3 opțiuni.

În cazul secvențelor care se repetă, adică al ciclurilor sau, altfel spus, secvențelor repetitive,
se trasează linii, astfel încât să se formeze un circuit închis, guvernat de un bloc condițional.

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să traduc


PRO
Am descoperit limbajul

Limbajul este cheia înțelegerii şi între oameni şi între maşini şi deci şi între oameni şi
maşini.

Am înțeles că un calculator hard-ul fără soft înţelege doar că are intensitate mare la bornele
circuitelor sale electronice sau are intensitate mică care poate fi şi inexistentă.

Un astfel de circuit se numeşte circuit logic pentru că atunci când la bornele sale există cu-
rent se poate considera că semnalul este real sau adevărat iar când nu există intensitate se
poate spune că semnalul este fals.

Pionierii calculatoarelor au codat prezenta intensităţii cu cifra 1 şi lipsa ei cu cifra 0 şi astfel


a apărut noţiunea de bit.

Bitul poate fi ori 0 ori 1 și niciodată și unu și zero în același timp.


În primii ani de la apariţia calculatoarelor acestea erau programate prin scrierea a unei suc-
cesiuni de 1 şi 0 şi astfel a apărut primul limbaj de programare a unui calculator numit cod
mașină.

Cum acest mod de a programa era anevoios şi devenea aproape inutilizabil când trebuia să
repari o eroare în cod şi deci să schimbi nişte 1 şi 0 dintr-un ocean de 1 şi 0 programatorii
şi-au adus aminte că matematica le dă soluţia să îşi facă munca mai uşoară.

Astfel bazându-se pe mulţimea numerelor binare atât pe cifrele ei cât şi operaţiile permise
de ea şi mai ales pe transformările de bază de numerotaţie din matematica , aceştia au tran-
sformat codul din baza 2 în baza 10 şi au creat o tabelă de mapare între semnalul venit pe
biţi şi nişte numere în baza 10 astfel a apărut caracterul şi odată cu el codul ascii de repre-
zentare a caracterelor, convenindu-se ca orice caracter să poate fi scris pe maxim 8 biţi,
adică un Octet sau Byte în engleză.

Un caracter este un desen grafic , un simbol.

Odată cu apariţia caracterelor a fost deschisă o poarte largă spre a comunica cu calculatorul
printr-un limbaj cât mai apropiat de limba naturală.

Primul astfel de limbaj a fost Fortran şi a fost dezvoltat de firma IBM , însă era undeva mai
jos decât limbajul de asamblare adică assembler deci foarte rudimentar.

Treptat limbajele au evoluat , unele au dispărut prin neutilizare ca Basic iar altele au rămas
pentru că au răzbit prin flexibilitate chiar dacă sunt destul de low level ca C/C++.

© Bitulică 2020
Povestea lui Bitulică

Azi în funcţie de cât de apropiat de codul maşina sau limbajul de asamblare sunt limbajele
se împart în trei categorii:

• limbajele low level sunt cele mai rudimentare limbaje dar din cauza asta şi cele mai
flexibile adică pot să fac ce vreau eu în ele , cel mai cunoscut e C şi C++ care mai este
cunoscut şi că C cu clase
• limbajele middle level care sunt limbajele de nivel mediu care nu sunt aşa flexibile
ca primele dar nu sunt nici dedicate pe anumite segmente de dezvoltare . Acestea
sunt cele mai multe şi cele mai utilizate ca Java, PHP, C#.

Limbajele high level care sunt limbajele de nivel înalt sau limbajele dedicate ca FOXPRO de
exemplu sau chiar SQL , toată gama MSSQL , MYSQL, SQLLite.

În funcţie de cum sunt înţelese limbajele de către calculator acestea se împart în alte trei ca-
tegorii:

• limbaje de compilate, pentru că interacţionează direct cu componentele calculatoru-


lui adică cu procesor şi memorie fără intermediar iar pentru a putea face asta nece-
sită compilare. Acestea sunt limbaje ca C/C++.
• Limbaje de interpretate, pentru că sunt interpretate de alte aplicaţii care aplicaţii la
rândul lor interacţionează direct cu componentele calculatorului cu procesorul şi
memoria. Acestea sunt limbaje ca HTML, JAVASCRIPT, SQL.
• limbaje hibrid, pentru că sunt mai întâi compilate şi apoi o parte interpretate pentru
a interacţiona cu componentele calculatorului. Acestea sunt limbaje ca C#,JAVA,
PHP, ASP. JAVA este un caz aparte în acesta clasificare pentru că el rulează pe o
maşină virtuală ceea ce îi conferă portabilitate cross sistem de operare. Adică o apli-
caţie scrisă în java nu trebuie rescrisa ca să ruleze şi pe Windows şi pe Linux şi pe
MAC ci doar există o mașină virtuală compilata pe fiecare sistem de operare în parte.

Este bine de ştiut că un cod sursa scris într-un limbaj de programare nu este portabil pe
orice sistem de operare pentru că fiecare sistem de operare are particularitățile lui în a ges-
tiona resursele atât procesorul cât şi memoria, însă se poate scrie cod portabil de exemplu
prin folosirea directivelor de precompilare #ifdef şi #endif care încadrează secvenţa de cod
pentru fiecare sistem de operare în parte.

Există şi o clasificare a limbajelor în funcţie de tipul de aplicaţie pe care îl pot scrie cu ajuto-
rul lor.

pentru aplicaţii desktop atât standalone cât şi client - server pot folosi limbaje că C/C++,
JAVA, C# , PHP, Delphi sau Pascal sau FreePascal dar numai dacă în aplicaţiile de tip client
server folosesc pentru transmisia datelor protocolul bidirecţional SOCKET care este bazat
pe protocolul TCP/IP.

Pentru aplicaţii web server pot folosi limbaje ca JAVA cu tomcat-servlet sau rest api, PHP cu
apache2, ASP .NET cu IIS, unde ce am scris după limbaj sunt ce aplicații servere dedicate fo-
losesc fiecare. Acestea folosesc protocolul HTTP care şi el înglobează protocolul TCP/IP.

© Bitulică 2020
Povestea lui Bitulică

Pentru aplicaţii client în browser pot folosi JAVASCRIPT, FRONTPAGE, FLASH, HTML5, CSS
toate încorporând singurul limbaj de bază cunoscut de browser şi anume HTML.

Am pus mai jos care limbaje am înțeles că se pretează pe fiecare modul al unei aplicaţii în
general și al aplicației pe care o dezvolt în mod special.

Interfaţa (UI)
Desktop
c/c++, c#, delphi, java chiar şi php are un modul
Web
HTML , CSS, JAVASCRIPT, FRONTPAGE
Nucleu adică Kernel
C/C++, PHP, JAVA, ASP
Core
Desktop
C/C++,JAVA. Delphi, C#, PHP
WEB
la web se folosesc aplicaţiile standard Apache sau Tomcat sau IIS
Resurse
MSSQL, MYSQL, SQLLite

Când voi implementa aplicaţia aleg limbajul cu care sunt familiarizat dintre cele care sunt
pe acelaşi nivel de potrivire, dar uneori şi în funcţie de necesităţi.

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să implementez


PRO
Am descoperit funcția main

Un PC poate rula la un moment dat un singur program iar acesta este pentru că a devenit în
timp sistemul de operare. Că e Linux dezvoltat de Linus Torvalds, că e MacOS dezvoltat de
Apple că e Windows dezvoltat de Microsoft nu contează.

Programele pe care le dezvolta programatorii în cadrul unui sistem de operare sau altul ,
atunci când ele rulează adică se execută nu sunt altceva decât niște subprograme adică pro-
grame mai mici ale unicului program care rulează pe un PC deci ale sistemului de operare.
Îmi închipui că am un aragaz cu un singur ochi pe care fierbe o oală plină cu apă. Fiertul
apei este programul principal adică sistemul de operare care rulează pe aragaz adică ma-
șina fizică.

Că să fac ciorba , trebuie să tai morcovi , să tai carnea că fără carne nu e bună pe care le tai
separat pe tocător iar aceste procese sunt procese secundare sau sub programe.

Când termin de tăiat ceapa mă întorc la oala și vers rezultatul adică ceapa mărunțită în ea.

Când tai ceapă o tai pe tocător dar în prealabil iau ceapă din cămară o desfac , o spăl și apoi
tai pe tocător .

Tocătorul este cadru unde se execută procesul de tăiere a cepei care după finalizarea proce-
sului își varsă rezultatul în oală.

Dacă oala este sistemul de operare și procesul de tăiere a cepei este programul făcut de noi
atunci tocătorul este cadrul unde rulează programul nostru.

Cadrul unde rulează un program este un subprogram al sistemului de operare. Subprogra-


mele sau subrutinele că programul se mai numește și rutina , de la ceva care face același lu-
cru mereu după un anumit tipar ca rutina zilnică.

Aceste subrutine pot fi funcții sau proceduri. O funcție este ceva care transformă ceea ce i se
dă în altceva după ce îl trece printr-un proces. O procedură este ceva care execută un proces
adică niște pași fără să transforme nimic. O metodă este o funcție sau o procedură care
aparține cuiva. Este metoda acelui cuiva de a face ceva.

Cadrul în care rulează un program se numește main iar main în engleză înseamnă principal.
Se numește neapărat main pentru că sistemul de operare ca să le ruleze are nevoie să ştie
cum se numesc. Să ştie cum să strige la ele și s-a convenit să fie numite așa.

Prin urmare un program făcut de noi pentru sistemul de operare este o funcţie care trebuie
neapărat să se numească main adică principal pentru că sistemul de operare să ştie să o gă-
sească şi să înceapă rularea programului de la prima linie a ei.

© Bitulică 2020
Povestea lui Bitulică

În cadrul limbajelor care nu sunt Full OOP deci permit scrierea de cod liber care nu aparține
unei clase așa cum este și limbajul C++ cadrul în care rulează un program se numește func-
ția main.

În cadrul limbajelor care sunt Full OOP și deci nu permit decât scrierea de cod care aparține
unei clase cadrul în care rulează un program se numește metoda main.

Cadrul în care rulează un program nu este procedura ci funcție pentru că programul poate
primi la execuție nişte parametrii de intrare și deci funcția main îi transformă pe acei para-
metrii deci transforma ceva deci e funcție.

În funcție de limbaj funcția sau metoda principală se diferențiază prin sintaxa.

Termenul de funcţie este preluat din matematica şi înseamnă un mecanism care transforma
ceva în altceva. Adică face altceva în funcție de acel ceva. Îmi poţi imagina o funcţie ca pe o
maşină de tocat carne. Bag carnea macră şi iese tocată. Adică maşina transforma carnea. O
taie. Aşadar o funcţie primeşte ceva la intrare şi scoate ceva la ieşire după ce ce a primit
este trecut printr-o serie de operaţii. Are deci nişte parametrii de intrare şi un rezultat de
ieşire.

Pot percepe o funcţie şi ca o staţie audio în care bag mufe de microfon şi de chitară şi scoate
sunetul procesat în boze. Găurile alea unde bag mufele sunt parametrii de intrare ai funcţiei
iar mufele sunt valorile parametrilor de intrare.

Ce aud în boxa este rezultatul funcţiei.

în matematică funcţia arata aşa f:R->R f(x)=x+1 adică numele funcţiei este f mulţimea de de-
finiţie este mulţimea numerelor reale iar mulţimea de valori este tot mulţimea numerelor
reale, și parametrul este x. care poate lua valori 1 2 -1 5 şi după ce aceste valori sunt trecute
prin funcţie ajung 2 3 0 6.

în informatică se păstrează scrierea din matematică.

int main(int argc, char** argv)


{
return 0;
}

sau mai simplu dacă nu vreau parametrii de intrare în program

int main()
{
return 0;
}

Adică funcţia se numeşte main are ca parametri de intrare sau argumente adică argumen-
tează motivul pentru care rezultatul este cel care este, numărul de argumente și un şir de
șiruri de caractere şi scoate la ieşire o valoare de tip întreg.

© Bitulică 2020
Povestea lui Bitulică

Valoarea de ieşire a funcţie main ajuta sistemul de operare să ştie dacă funcţia s-a executat
cu succes sau nu.

Dacă e diferit de zero atunci sunt erori iar dacă e zero e succes. Dacă erorile sunt negative
sunt erori de sistem adică s-a încercat accesarea unei locaţii de memorie aiurea de exemplu.
iar dacă sunt pozitive sunt erori ce ţin de politica aplicaţiei adică a mers ok dar nu am făcut
ce aveam de făcut că nu am putut, de exemplu nu am găsit ce căutam.

Corpul funcţie este cel care conţine instrucţiunile , în cazul de faţă afişează pe ecran valoa-
rea parametrului introdus.

Limbajele interpretate ca HTML CSS Javascript SQL nu au funcție main sau metodă în cazul
lui java și c#, pentru că sunt interpretate de un program iar funcția main o are acel pro-
gram.

În cazul PHP , Python și Javascript se pot crea funcții sau metode care să fie metode princin-
cipale dar nu sunt obligatorii pt că și ele adică aceste limbaje sunt interpretate nu compi-
late.

Deci metoda main este obligatorie doar la limbajele compilate.

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să văd ce face


PRO
Am descoperit cum să execut

Odată ce am scris funcția main, chiar dacă nu i-am spus să facă ceva, am scris codul unui
program care nu face nimic, dar care poate fi lansat în execuție.

Pentru a-l lansa în execuție, programul trebuie întâi compilat, pentru a fi transformat în cod
mașină.

Prin transformarea a ce scrie într-un fișier text în cod mașină, înțelegem crearea unui fișier
binar executabil, că există fișiere binare și care nu pot fi executate, că nu au funcția „main”,
adică un fișier cu extensia .exe.

Extensia este grupul de trei litere de după numele fișierului și este despărțită de numele fi-
șierului prin punct. Adică

Nume_fisier.extensie

Numele fișierului acum poate avea câte caractere se dorește, dar în trecut era limitat la 8.

Extensia poate avea și ea acum câte caractere dorim, dar în trecut era limitată la 3.

Limitările veneau din cauză că PC-urile erau slabe ca performanță, iar performanta se mă-
sura în numărul de biți. Erau PC pe 8, pe 16, acum sunt pe 32 și 64 de biți.

Pentru crearea fișierului executabil, dacă folosesc IDE-uri, se apasă pe butonul sau opțiunea
de meniu „Build”.

Dacă nu folosesc IDE-uri, se execută în consolă, adică fereastra aia neagră, programului
compilator dându-i-se ca argument fișierul text în care este scris codul sursă.

Extensiile fișierelor sursă depind de la limbaj la limbaj și nu au extensii comune pentru a se


diferenția, iar pentru c++ extensia este cpp pentru fișiere care conțin implementarea si .h
pentru fișierele de tip header ce conțin declarațiile.

De fapt, acesta este și rolul extensiilor și anume acela de a fi recunoscute fișierele de către
aplicații sau sistemul de operare.

© Bitulică 2020
Povestea lui Bitulică

Extensiile pentru principalele limbaje sunt:

• c pt C
• cpp pentru C++
• java pentru Java
• CSS pentru CSS
• html pentru Html
• php pentru Php
• py pentru Python
• cs pentru c# (sharp adică ascuțit. diez ridica un sunet cu o jumate de ton adică îl as-
cute)
• js pentru Javascript

După ce fișierul executabil a fost creat, pentru lansarea în execuție se apasă butonul RUN
sau EXECUTE dacă se folosesc IDE-uri, iar dacă nu se folosesc se scrie direct în consolă nu-
mele fișierului executabil și se apasă tasta „enter” sau se da dublu click pe numele fișierului
executabil, dacă se folosește interfața grafică.

Execuția unui program este durata de timp dintre momentul lansării în execuție și până la
momentul în care programul se termină.

Dacă programul nu are interfață grafică, atunci vom vedea rezultatul rulării lui în consolă,
adică în ferestra aia neagră, iar dacă are interfață grafică atunci vom vedea rezultatul rulării
lui într-o fereastră a interfeței grafice a sistemului de operare.

Exista și programe ale căror execuții nu pot fi urmărite vizual pentru că ele rulează în
background.

În timpul rulării unui program pot apărea erori.

Timpul în care un program rulează se numește RUNTIME în engleză, iar erorile care pot
apărea se numesc erori de runtime sau de execuție, în timp ce cele care apar în timpul com-
pilării se numesc erori de compilare.

© Bitulică 2020
Povestea lui Bitulică

Când am încercat să fac


C++
Am aflat simbolurile unui limbaj

Un limbaj de programare este o colecție de simboluri și semnificații. Aceste simboluri nu au


fost visate noaptea ci importate din realitatea înconjurătoare păstrându-li-se sensul.
Cel mai important simbol al unui limbaj de programare este cuvântul cheie adică keyword
în engleză.

Toate cuvintele sunt importate din limba engleză pentru că pe deoparte atunci când a fost
inventat primul limbaj de programare engleză era deja cea mai importantă limba de circula-
ție internațională iar pe de altă parte limbajele au fost inventate de americani care așa cum
știu sunt vorbitori nativi de limba engleză pentru că cândva au fost sub dominația imperiu-
lui Britanic deci au fost colonie engleză.

Cuvintele cheie sunt acele cuvinte pe care le știe un compilator sau un program oarecare și
cu ajutorul cărora deslușește ce vreau să îi transmit adică descuie fraza, cuvintele alea ju-
când un rol de cheie.

Mă gândesc că nu sunt vreun expert în limba engleză și nu cunosc toate expresiile ca neolo-
gisme, arhaisme și nici toate cele de bază care sunt din limba engleză iar dacă stau de vorbă
cu cineva născut și crescut aici , și din 10 cuvinte spuse eu știu 5 dar esențiale în frază ros-
tită de el , pot să înțeleg ce vrea să îmi transmită dacă acele cuvinte pe care le știu sunt cu-
vinte cheie cu care pot descifra fraza.

Cuvintele cheie au fost importate din engleza fie păstrându-li-se forma fie prescurtate. S-a
optat pentru prescurtare pentru ca textul unui program să fie mai ușor de scris și pentru că
una e să scriu character și alta e să scriu char, e mai ușor.

Cuvintele cheie definesc

• Nume de tipuri de date


• Nume de funcții
• Nume de operatori
• Nume macrouri
• Nume de instrucțiuni

Cuvintele cheie se scriu totdeauna cu literă mică și sunt și cuvinte rezervate adică nu le mai
pot folosi în alt sens. Apropo de asta limbajul se programare nu are sinonime , o să țin minte
asta. Toate cuvintele din vocabularul lui au doar sensul de bază și nu există două cuvinte cu
același sens. E programare nu e literatură.

În editoarele moderne incluse în IDE-uri aceste cuvinte sunt colorate diferit de obicei cu
grena sau cu albastru sau cu alte culori complementare dacă tema este una dark.

© Bitulică 2020
Povestea lui Bitulică

Un alt simbol important este paranteza acolada atât închisă cât și deschisă adică { }. Paran-
tezele acolade semnifică un grup , ceva adunat laolaltă .

Spațiul dintre acolada deschisă și acolada închisă se numește scop adică interval de timp în
care ai un ţel de a face ceva.

Un alt simbol la fel de important este paranteza rotundă atât închisă cât și deschisă adică ( ).
Parantezele rotunde semnifică un cuplaj și au același rolul din matematica adică acela de a
cuprinde o listă ca de exemplu (a+b+c) sau f(x,y,z).

Un alt simbol sunt operatorii aritmetici adică + - * / , logici și booleeni ! & | && || , compara-
tivi == < > >= <= , cel de atribuire și cei pentru biți << >>.

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să fac mai multe


C++
Am descoperit datele unui limbaj

Totul se învârte în jurul semnalelor electrice. Acestea sunt transformate în biţi , biții în nu-
mere iar numerele în caractere. Pentru a putea fi cuprinse într-o terminologie comună bi-
ții,numerele şi caracterele împreună au fost denumite generic date.

Aceste date pentru a putea fi utilizate de un calculator trebuie să poată fi stocate pe hard,
preluate pe magistrale, adică pe benzi de fire, prelucrate de procesor şi reţinute temporar
în memoria RAM.

În funcţie de proprietăţile lor care proprietăţi le definesc şi rolul dar şi încadrarea adică mo-
dul de stocare, preluare, prelucrare, datele sunt de mai multe tipuri.

Prima clasificare este dată de natura datelor:

• date primitive sau simple


• date complexe sau compuse cu sau din datele simple

Datele native ca şi datele complexe sunt de mai multe tipuri.

Tipul de bază , al datelor cu ajutorul cărora se programează un computer este aşa cum era
de aşteptat dat fiind faptul că numerele provin din conversia din baza 2 în baza 10 tipul în-
treg.

Memoria şi hardul unui calculator îi pot privi ca fiind formate din nişte căsuţe poştale din
scara blocului fiecare având numărul ei de ordine şi dimensiune proprie. Unitatea de mă-
sură pentru locaţie şi dimensiune fiind Octetul sau Byte-ul în engleză. Dar şi unităţi mai mici
ca bit.

Pentru a specifica adresa unei locaţii din astea de memorie sau de pe hard se foloseşte ex-
presia: data cutare se găseşte la locaţia 0x000 unde numărul ăsta este un număr în baza 16
adică hexazecimal. Sistemul hexazecimal este utilizat în notarea adreselor de memorie atât
RAM cât şi de pe disk.

Dacă vreau să mă refer la o dată din interiorul unei căsuţe de memorie nu la toată căsuţa
atunci se foloseşte expresia data cutare se găseşte la segmentul 0x000 şi offset-ul 16, şi în-
seamnă că data respectivă este la bitul 0x000 deplasat cu 16 spre dreapta adică 0x000 <<
16.

Pot privi deci memorarea datelor ca ceva pus într=o cutie postală care poate să fie de di-
mensiune cât e cutia sau mai mic şi atunci trebuie să intri în interiorul cutiei ca să ajungi la
el.

© Bitulică 2020
Povestea lui Bitulică

Tipurile primitive adică simple folosite în programarea unui calculator sunt:

Tipul ÎNTREG care este tipul de bază iar cea mai lungă dată de acest tip se memorează pe
atâţia biţi pe câți are procesorul, astfel orice procesor procesează la un tick adică o bătaie
unul şi numai un singur număr întreg.

Prin urmare dacă am procesor pe 16 biţi tipul întreg se va memora pe 2 bytes dacă am pro-
cesor pe 32 de biţi pe 4 bytes iar dacă am procesor pe 64 de biţi pe 8 bytes.

Cuvintele cheie care definesc tipul întreg în limbajele de programare oricare ar fi ele sunt
două şi alternează în funcţie de limbaj

• INTEGER
• INT

Aşa cum ştiu mulţimea numerelor întregi are domeniul de valori de la -infinit la +infinit deci
un număr întreg are un semn în fata - sau + .

Dată fiind limitarea de număr de biţi ce îi poate procesa procesorul la un moment dat în in-
formatică domeniul de valori al numerelor întregi este redus.

Astfel dacă am procesor pe 16 de biţi o variabilă de tip întreg poate lua valori de la -32768
până la 32768 adică de la -2 la "cel mai mare număr întreg care se poate scrie pe 15 biţi
adică 1111111111111111 până la valoare lui cu +. Un bit este rezervat pentru semn.

Date fiind spusele de mai sus variaţiile tipului întreg sunt în funcţie de dacă are sau nu are
semn sunt următoarele:

• signed int care este echivalent cu "int" simplu


• unsigned int care este echivalent cu expresia matematică modul din număr adică
numărul fără semn.

TIPUL CARACTER care se memorează pe 1 byte adică 8 biţi pentru standardul ASCii şi deci
există în acest standard 256 de caractere adică cel mai mare număr întreg scris pe 1 byte
adică 8 biţi este 255 şi cu 0 fac 256 de caractere.

Cuvântul cheie care descrie tipul caracter este de regulă CHAR dar în anumite limbaje mai
este întâlnit şi CHARACTER.

TIPUL ŞIR DE CARACTERE sau STRiNG , aşa cum îi spune şi numele memorează unul sau
mai multe caractere şi se foloseşte aşa cum îmi dai seama uşor în memorarea cuvintelor, a
expresiilor sau a propoziţiilor.

Memorarea şirurilor de caractere se face dinamic sau static. Dacă se foloseşte o alocare a
memorie statică atunci se decide inițial câte caractere poate avea maxim șirul iar orice de-
păşire în program va trebuie manageriată altfel programul crapă când îţi este lumea mai
dragă şi de aceea nu este recomandată.

© Bitulică 2020
Povestea lui Bitulică

În alocarea dinamică şirurile de caractere se stochează pe exact atâţia bytes câte caractere
are cuvântul.

TIPUL FLOAT Se mai numeşte şi tipul virgulă mobilă pentru că permite memorarea nume-
relor raţionale şi iraţionale deci a numerelor reale.
Se memorează pe dublul numărului de bytes al tipului int.
în unele limbaje tipul float nu există el fiind inclus în tipul double.

TIPUL DOUBLE Se mai numește şi tipul virgulă mobila cu preciziei dublă.


Se memorează pe dublul numărului de bytes ai tipului FLOAT.
în unele limbaje tipul double este definit de cuvântul cheie REAL

Tipurile compuse sau definite de utilizator

TIPUL ENUMERARE Este tipul compus din mai multe tipuri de acelaşi fel.
Se foloseşte pentru a cuprinde într=o singură variabilă de exemplu zilele săptămânii:

TIPUL STRUCTURĂ Este un tip definit de utilizator şi poate cuprinde tipuri de mai multe fe-
luri
Se poate folosi de exemplu pentru a creea un tip de variabilă care să reţină valorile unei în-
registrări dintr-un tabel al unei baze de date.
Cuvântul cheie prin care se face referire la tipul de tip structură se mai numeşte şi înregis-
trare este

STRUCT sau în unele limbaje RECORD


TIPUL union Este un tip definit de utilizator şi poate cuprinde tipuri de mai multe feluri

Se poate folosi de exemplu pentru a creea un tip de variabilă care să reţină valorile unei în-
registrări dintr-un tabel al unei baze de date.

Cuvântul cheie prin care se face referire la tipul de tip structură se mai numeşte şi înregis-
trare este

UNION sau în unele limbaje RECORD

CLASĂ Este tot un tip de data şi stă la baza programării pe obiecte adică OOP.

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să fac operații


C++
Am descoperit variabilele

Pentru a nu ține plăcuța în funcțiune cât timp învăț unele lucruri care nu depind de ea, am
creat un proiect in Visual Studio asemănător, dar pe Windows, în care să învăț și să testez
chestii.

Uneori, când operațiile aritmetice sunt complexe, trebuie să execut operațiile pe rând și să
țin minte rezultatele fiecăreia, ca apoi să fac operații cu ele în continuare.

De exemplu, dacă am de efectuat operația

2x2 + 2:2

fac întâi 2x2 și îmi dă 4 pe care îl țin minte si apoi 2:2, care îmi dă 1 și pe care îl țin minte de
asemenea. Apoi

4+1 fac 5

Pentru ca un PC să țină minte are nevoie de spațiu în memoria RAM, unde să depoziteze va-
lorile pe care le ține minte. Numele acestor spații se numesc variabile. Acestea au un tip,
adică o dimensiune.

Pentru a declara o variabilă numită „a” de tip întreg pot scrie următoarea secvenţă de cod:

int a;
//sau după caz
integer a;

iar dacă vreau să definesc o variabilă „a” de tip întreg, inițializând-o cu 0, pentru că se reco-
mandă definirea oricărei variabile, nu doar declararea ei

int a = 0; // acesta este o definiţie

Pentru a defini o variabilă de tip caracter, inițializând-o cu caracterul 'a', se poate folosi de
exemplu următoarea secvenţă de cod:

char c = "a";

acelaşi lucru este şi dacă scriu :

char c = 97;

© Bitulică 2020
Povestea lui Bitulică

pentru că majoritatea compilatoarelor fac conversia de tip şi transforma codul ASCII al lui
caracterului 'a' care este 97 în caracterul 'a' pentru că văd că tipul variabilei care este iniţia-
lizată cu 97 este char.

Dacă tipul era INT atunci variabilă a rămânea cu valoarea 97.

Pentru definirea unei variabile şir de caractere definită static se poate folosi următoarea ex-
presie

char a[100] = "Ana are mere";

în acest caz se vor rezerva 100 de locaţii în memorie de câte un byte dar se vor ocupa numai
15 adică câte caractere are cuvântul cu care am iniţiat variabila restul nemaiputând fi folo-
site de alte variabile . Acesta este alt neajuns al alocării statice.

Pentru definirea unei variabile şir de caractere alocate dinamic se poate folosi

std::string a = "ana are mere";

în acest caz se va folosi memorie exact atâta cât e nevoie de fiecare dată deci la inițializare
15 bytes apoi dacă îi dau valoarea "Maria" doar 7.

În C/C++ se mai foloseşte expresia

const char *a = "Ana are mere";

pentru defini dinamic un sir de caractere. Adică utilizând pointer către un sir de caractere.

Pentru a defini o variabilă de tip FLOAT se poate folosi expresia

float a = 2,5;

Pentru a defini o variabilă de tip DOUBLE se poate folosi expresia

double a = 2.55;

Pentru a defini o variabilă de tip enumerare se poate folosi expresia

enum zi=(luni, marţi, miercuri, joi, vineri, sâmbătă, duminică);

Pentru a defini o variabilă de tip structura trebuie întâi să creăm tipul. Se poate folosi sec-
venţa de mai jos

struct persoana
{
char nume[20];
int varsta;
};

© Bitulică 2020
Povestea lui Bitulică

persoana pers={"Ion Ionescu",21}; // se defineşte variabilă de tipul definit mai sus.

Pentru a defini o variabilă de tip union trebuie întâi să creăm tipul. Se poate folosi secvenţa
de mai jos

union persoana
{
char gen;
int varsta;
};

persoana pers;
pers.gen = 'm';
pers.varsta = 21;

Pentru a defini și instanția o clasă se folosește de exemplu următoarea secvență

class A
{
public:
std::string nume;
int varsta;
};

A *a = new A(); // daca creem un pointer către obiectul a


A a = A(); // daca creăm obiectul a

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să setez o valoare


C++
Am descoperit definiția

Memoria unui calculator poate fi asemuită şi cu un ogor care așteaptă să fie cultivat și apoi
cules. Un ogor de bytes adică 8 biţi adică un ogor de 0 sau 1. Când nu e cultivat e format
doar din 0 peste tot ca și cum ar fi proaspăt arat.

În funcție de cât de mare e ceea ce cultivăm va trebui să alocăm un spaţiu suficient atât pen-
tru a planta cât și pentru a creşte că dacă pui ceva inițial e mic dar poate creşte și trebuie să
îi asiguri spaţiu.

A cultiva în memorie ceva se traduce prin a scrie. A recolta ceva din memorie se traduce
prin a citi iar a crește ceva în memorie se traduce prin a seta.

Atunci când trebuie să scriem ceva în memorie primul lucru care trebuie făcut este alocarea
spațiului de memorie suficient de mare în funcție de necesități.

După alocare trebuie să notăm adresa de unde începe spațiul alocat Această adresă se nu-
mește ADRESA DE MEMORIE sau SEGMENT. Dimensiunea spațiului alocat se numește
OFFSET adică coada adresei de memorie sau a segmentului. Adică cât de mare e segmentul.
Atunci când notăm adresa de memorie îi dăm și un nume ca să știm să strigăm adică să ne
referim la ea când avem nevoie.

Numele adresei de memorie prin care ne referim la ea și cu ajutorul căreia putem scrie și
citi în și din ea se numește POINTER pentru că point în engleză înseamnă punct , pointer în-
seamnă ceva care indică către un punct, în cazul nostru punctul este locul de unde am alocat
spaţiu de memorie deci adresa de memorie unde se găsește spațiul alocat.

Cu ajutorul pointerului se poate aloca memorie adică crea spaţiu, scrie ceva în spaţiul alocat
adică o valoare sau nimic în cazul când scriem nimic spunem că ștergem ce am scris, iar ni-
micul ăsta este informație vida , a cărei valoare este stabilită de sistemul de operare . De
obicei este caracterul /0 numit NULL, dezaloca spațiul de memorie . Prin dezalocare înțele-
gem ștergerea legături cu acel spaţiu. Practic e din nou al nimănui.

Există spații de memorie alocate automat de program având o anumită dimensiune şi asu-
pra cărora nu avem puterea decât de a scrie sau citi . Numele și dimensiunile acestora le
stabilim noi programatorii. Denumirile acestor spaţii se numesc VARIABILE iar dimensiu-
nile lor precum ce avem voie să scriem se numesc TIPURI.

Asupra unui astfel de spaţiu nu avem drept să îl dezalocăm pentru că nu l-am alocat noi.
Singurul care are drept de dezalocare adică distrugere este programul.

© Bitulică 2020
Povestea lui Bitulică

Variabilele care nu își schimbă valoarea pe durata executării programului sunt prin exce-
lență CONSTANTE. Putem chiar impune unei variabile să nu are drept să își modifice valoa-
rea deci să rămână constanta.

O DECLARAŢIE a unei variabile este atunci când se specifică tipul şi numele variabilei fără
să îi fie specificată şi valoarea inițială. Adică

Tip_variabila nume_variabilă;

De exemplu

int a; // declararea unei variabile de tip număr din mulțimea numerelor întregi

O DEFINIŢIE a unei variabile este atunci când se specifică tipul , numele şi valoarea inițială
a sa într-o singură linie.

int a = 0;

Este indicat că mereu să definim variabilele pentru că altfel compilatorul aloca din burta de
la el ce valori vrea.

Unele limbaje cu cod asistat adică manage code NU PERMIT ca o variabilă să fie declarată
fără să îi fie setată o valoare.

De aceea dacă totuși nu știm la momentul respectiv ce valoare să îi dăm inițial , o declarăm
şi o setam mai jos

int a;
// Alte instrucțiuni
a=0;

Este o paradigmă adică conduită a programării ca valorile inițiale ale variabilelor să fie 0.

Nu 1 nu 5 nu 345 adică nu NUMERE MAGICE pentru că cine citește codul ulterior nu are de
unde să știe ce reprezintă acele numere chiar dacă ele fac programul să meargă corect ca
prin minune că de aia se și numesc aşa.

În funcție de limbaj cuvântul cheie adică KEYWORD pus în fața tipului pentru a specifica că
o variabilă e constanta este CONST sau FINAL , final vine de la valoarea finală , adică ce va-
loare îi dau atunci aia va fi și finală , iar const e prescurtarea de la constant.

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să văd ce am făcut


C++
Am descoperit afișarea pe ecran

Textele pe care le scriu în editor atunci când scriu un program am înţeles că se numesc in-
strucţiuni pentru că sunt ca nişte instrucţiuni pe care i le dau cuiva pe foaie când îl rog să
facă ceva.
De exemplu când îl trimit la magazin să ia pâine, Îi scriu pe foaie să se ducă la magazinul
cutare să intre în raionul cutare să ia pâinea cutare de pe raftul cutare apoi să se ducă la
casă ca să plătească şi apoi să vină să îmi aducă pâinea.
Adică îl instruiesc cum să facă ce vreau eu să facă. Pe baza acestor instrucţiuni el va face ce
vreau eu să facă ulterior nu imediat.
Va face atunci când se va apuca de ce i-am zis să facă. Atunci când ştie deja ce are de făcut şi
îi zic să facă ceva de fapt îi comand.
El deja ştie să execute comanda şi o execută atunci când îi spun eu.
Textele scrise în limbajele compilate sunt instrucţiuni iar în limbajele interpretate sunt
comenzi. Deasemenea tot comenzi sunt şi textele scrise în consola ca de exemplu atunci
când îi comand computerului să execute un program sau altul.
Un computer executa instrucţiunile exact în ordinea îi care sunt scrise. Dacă acestea sunt
scrise unele sub altele le executa de sus în jos în ordine.
Atunci când un program conţine doar astfel de instrucţiuni pe care computerul le executa în
ordinea în care sunt scrise şi fiecare instrucţiune este executată o singură dată se cheamă
programare secvenţial[. Pentru că executa fiecare secvenţă de cod adică instrucţiune în
ordine una câte una.
Instrucțiunea cout este instrucțiune cu care îl învăț să afiseze ceva pe ecran. C vine de la
consola iar OUT de la iesire. Adică această instrucțiune instruiește un PC să afiseze ceva în
consola de iesire.
Semnul << este un separator care separă ceea ce vreau să afisez.
Cuvantul endl vine de la end adică sfârsit și l care este prima litera din cuvantul line care
înseamnă linie. Adică semnifică sfarsitul de linie. Când compilatorul da peste el știe că
trebuie să sară pe linia următoare și să afișeze în continuare acolo.
Unele subprograme deja scrise se găsesc în așa numitele biblioteci care sunt importate în
programul meu ca să pot să folosesc chestii din ele. Una din aceste biblioteci este iostream.
Numele ei vine de la input output stream. Input înseamnă intrare, output înseamnă ieșire
iar stream înseamnă râu. Aici sunt instrucțiunile care conduc datele spre monitor sau le
preiau de la tastatură. Datele când sunt transportate spre dispozitivele de intrare și ieșire
formează râuri de biți adică stream-uri.

© Bitulică 2020
Povestea lui Bitulică

Instrucțiunile din biblioteci sunt grupate pe categorii iar în două categorii diferite pot exista
instrucțiuni cu același nume. De aceea aceste categorii se numesc spații de nume. Unul din
ele este std care se găsește în biblioteca iostream.
#include <iostream>
using namespace std;
int main()
{
cout << "ana" << endl;
cout << "are" << endl;
cout << "mere" << endl;
return 0;
}
programul va lua la rând de sus în jos instrucțiunile şi va afişa
ana
are
mere

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să văd am de unde alege


C++
Am descoperit structura alternativă

Atunci când sunt pus în situația de a prezenta două alternative de execuție ulterioară a pro-
gramului am înțeles că programez folosind STRUCTURI DE CONTROL ALTERNATVE.

Structurile de control alternative permise sunt două:

If - else şi switch – case

Structura instrucțiunii If este:

int a = 0;
If (a == 0)
{
}
else
{
}

Comportamentul programului va fi următorul:

Dacă se îndeplinește condiția a==0 va face ce e inclus între primele acolade; în caz că nu se
îndeplinește condiția, va face ce e inclus între acoladele lui „else”.

În cadrul instrucțiunii „If”, alternativa „else” poate să lipsească:

int a = 0;
If (a == 0)
{
}

În acest caz dacă condiția se îndeplinește programul face ce e inclus între acolade; în caz
contrar trece la următoarea instrucțiune de după „If”.

Acoladele pot lipsi doar dacă se dorește ca blocul ce va fi executat să cuprindă doar o sin-
gură instrucțiune, rolul acoladelor în general este de a crea un bloc de instrucțiuni şi un
scop pentru variabile

{
int a=0;
}
a=2;

© Bitulică 2020
Povestea lui Bitulică

Acestă secvenţa de cod va da eroare, pentru că variabila „a”, fiind definită în scopul delimi-
tat de acolade, se dezalocă la încheierea acoladelor şi nu mai este disponibilă în afara lor.

Variabilele definite în interiorul unui bloc, adică scop, se numesc VARIABILE DE SCOP.

Ca un design pattern adică, calea corectă de a scrie cod, pentru instrucțiunea „If - else”
atunci când avem posibilitatea este să folosesc „return”

int a=0;
If (a==0)
return 0;
return 1;

„Return” este un cuvânt cheie care face ca programul sau subprogramul să se termine și
controlul să fie cedat modului apelant.

Dacă e „return” din programul principal, acesta cedează controlul sistemului de operare.

Dacă e „return” din subprogram, atunci cedează controlul programului din care a fost apelat
subprogramul.

Pot folosi asta doar dacă situația îmi permite, dar în niciun caz nu se voi scrie multe instruc-
țiuni „If - else” imbricat, pentru că este un antipatern design

If (a>0)
{
If (a==1)
b=1;
else
b=2;
}
else
b=3;

pentru că e foarte greu de urmărit codul şi de depanat şi foarte greu de executat pentru
computer, întrucât el trebuie să țină valorile condițiilor pe stivă şi umple stiva în STACK
MEMORY, adică un loc unde se ţin minte numele variabilelor, şi devine greu de extras din
ea, aceste neajunsuri îl fac antipatern arrow design, că seamănă cu o săgeată, dacă se res-
pectă indentarea codului.

© Bitulică 2020
Povestea lui Bitulică

Când am avut de ales între valori clare


C++
Am descoperit structura switch

Am înțeles că atunci când am doar câteva valori clare din care să îi spun să aleagă pot să fo-
losesc alternativa la if-else.

Alternativa la If-else este folosirea lui switch

switch (x)
{
case 1:
{
y=y+1;
break;
}
case 2:
{
y=y+2;
break;
}
default :
{
y=0;;
}
}

Se poate face switch doar după o variabilă sau o valoare de tip : int, char, long, short, sau
enum.

În unele limbaje ca Java începând cu Java 7 este permis şi sir de caractere adică string.
Break face ca după ce se execută instrucțiunile de pe o ramură programul să iasă din switch
şi să treacă la instrucțiunea următoare.

Dacă lipsește se va trece la următoarea ramură din switch şi se va executa instrucțiunea de


pe acea ramură fără a mai evalua cinditia.

Ramură default se execută dacă nu se validează condițiile de pe nici o ramură.

© Bitulică 2020
Povestea lui Bitulică

Când am fost nevoit să repet


C++
Am descoperit structura repetitivă

Cea de a doua categorie de STRUCTURI DE CONTROL, alături de STRUCTURILE ALTERNA-


TIVE, sunt STRUCTURILE REPETITIVE.

Structurile repetitive sunt două.

Una din ele este for, care în forma ei standard se folosește atunci când se cunoaște de la în-
ceput numărul de repetări adică iteraţii

for (int a = 0; a<5; a++)


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

și care va afișa

0
1
2
3
4

Variabila a , este definită de tip int şi iniţializată cu 0 adică valoarea ei inițială este 0 , şi are
ca scop doar scopul instrucțiunii for , adică după acolada închisă nu mai este recunoscută de
program , fiind dezalocata la terminarea instrucțiunii for.

Valoarea variabilei a este testată pentru a vedea dacă îndeplinește condiția a<5 , dacă nu o
îndeplinește instrucțiunea for se încheie.

Dacă se îndeplinește condiția atunci se execută secvențial adică una după alta , în ordinea în
care sunt scrise, instrucțiunile din blocul delimitat de acolade.

După ce se execută ultima instrucțiune din bloc, se execută a++, care incrementează adică
adaugă o unitate la valoarea variabilei a.

Apoi se verifică din nou condiția , şi se repetă punctele descrise mai sus până când condiția
nu mai este îndeplinită.

Instrucțiunea din bloc, afișează valoarea variabilei a, care se modifică, la fiecare repetare, cu
o unitate.

© Bitulică 2020
Povestea lui Bitulică

Prima parte a instrucțiunii for adică definirea variabilei cu care se vor parcurge pașii adică
contorul POATE SĂ LIPSEASCĂ, dar ea trebuie definită mai sus în program , pentru ca astfel
să fie recunoscută

int a = 0;
for (; a<5; a++)
{
printf("%d\n",a);
}

În acest caz variabilă a nu moare la sfârșitul acoladei ce încheie blocul instrucțiunii for, şi
poate fi utilizată mai departe în program.

A treia parte a instrucțiunii for adică incrementarea variabilei contor , în cazul de fată, a++,
POATE ŞI EA SĂ LIPSEASCĂ.

int a=0;
for (; a<5;)
{
printf("%d\n",a);
a++;
}

în acest caz , dacă nu dorim un ciclu infinit , va trebui să avem grijă ca variabilă contor să se
incrementeze în interiorul blocului de instrucțiuni

Condiția din cadrul instrucțiunii for POATE ŞI EA LIPSI , dar dacă lipsește atunci va fi un ci-
clu infinit

int a=0;
for (;;)
{
printf("%d\n",a);
}

Va afişa 0 la infinit

0
0
...
0

Dacă aici aloc memorie într-un for de asta blochezi PC , e un virus micuț.

Rezultatul oricărei condiții este interpretat ca una din valorile tipului boolean adică true
sau false.

De aceea pot scrie în locul condiției direct o valoare de adevăr

© Bitulică 2020
Povestea lui Bitulică

for (int a = 0; true; a++)


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

În acest caz , avem tot ciclu infinit pentru ca , condiția , va fi mereu interpretată ca adevărat

for (int a = 0; false; a++)


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

În acest caz nu se îndeplinește condiția niciodată și nu se va intra niciodată în în blocul in-


strucțiunii for.

Pentru a ieși forțat chiar dacă condiția încă se îndeplinește din ciclul for , se folosește in-
strucțiunea break, pusă în blocul instrucțiunii for.

for (int a = 0; a<5; a++)


{
break;
printf("%d\n",a);
}

În acest caz se va intra în bloc, când a = 0 , pentru că condiția a<5 se îndeplinește dar nu se
va executa instrucțiunea de afișare pentru că atunci când programul întâlnește instrucțiu-
nea break va ieși din ciclul for deci din instrucțiunea for şi va trece la executare următoarei
instrucțiuni de după ea.

Break în engleză înseamnă spărtură, o cale de ieșire.


Pentru a sări un pas din ciclul for se utilizează instrucțiunea continue;

for (int a = 0; a<5; a++)


{
continue;
printf("%d\n",a);
}

Nici în acest caz nu se afișa nimic , pentru ca la întâlnirea instrucțiunii continue se va sări
direct la incrementarea contorului și validarea condiției fără să se mai execute restul in-
strucțiunilor din blocul de instrucțiuni aflate după continue.

Continue în engleză înseamnă continuă și aici are sensul de a continua să incrementeze va-
loarea contor ignorând restul operațiilor din bloc de după el.

Funcția printf este omologul din c a funcției cout din c++ dar funcția printf poate fi folosita
și in c++ pentru că c++ chiar dacă a fost implementat de la zero a mostenit tot ce are c.

© Bitulică 2020
Povestea lui Bitulică

Denumirea de printf vine de la print care înseamnă a tipări în engleză și termenul a fost fo-
losit pentru ca pe ecran caracterele apar ca și cum ar fi tiparite adică au un tipar nu sunt
scrise de mană.

Litera f din denumire aș putea gândi că vine de la file care înseamnă fișier pentru că atât
tastatura cât si monitorul sunt considerate fișiere, fișiere standard de intrare și ieșire, dar
vine de la format adică instrucțiunea printf afișează ceva formatat.

Caracterul \n este caracterul care simbolizează sfârșitul unui rând și se numește EOLN de la
end of line. La întâlnire acestul caracter compilatorul sare cu afișarea pe linia următoare.

Simbolul %d îi spune compilatorului ca trebuie să afișeze un număr întreg. D vine de la de-


cimal care înseamnă număr în baza 10 întreg. Oriunde apare %d în instrucțiunea printf el
este înlocuit cu valoarea variabilelor de după virgulă în ordinea apariției variabilelor de la
stanga la dreapta.

printf("%d %d",x,y);

dacă x este 5 și y 7 atunci primul din stânga %d va fi înlocuit cu valoarea lui x adică 5 iar cel
de al doilea cu valoarea lui y adică 7 și va afișa 5 7 exact așa cu spațiul între ele pentru că
rolul acelei constante string "%d %d" este de a formata afisarea.

Adică de a stabili modul în care vor apărea pe ecran valorile afișate.

© Bitulică 2020
Povestea lui Bitulică

Când nu știam de cate ori o să repet


C++
Am descoperit structura do-while

A doua structură repetitivă este „while”, care se folosește atunci când numărul de repetări
nu este cunoscut dinainte și care are două forme folosite alternativ în funcție de situație.

Prima dintre ele este „while-do”. „While” înseamnă „cât timp”, iar „do” înseamnă „execută”.

int a = 0;
while (a<5)
{
printf("%d\n",a);
a++;
}

Se execută instrucțiunile din bloc, cât timp condiția este îndeplinită.

Dacă condiția nu se îndeplinește niciodată nu se va intra în ciclu, adică în buclă.

Această tehnică se folosește când vreau să beau trei căni de apă și, înainte de a bea, trebuie
să mă asigur că am apă.

O altă formă a instrucțiunii „while” este „do-while”.

int a = 0;
do
{
print("%d\n",a);
a++;
}while(a<0);

în acest caz, condiția se testează la sfârșit și, datorită acestui lucru, blocul de instrucțiuni se
execută cel puțin o dată.

Această tehnică se folosește atunci când merg la magazin și trebuie să caut din magazin în
magazin până găsesc ce caut.

Trebuie să intru în cel puțin un magazin ca să văd dacă găsesc și, doar dacă nu găsesc, să
continui căutarea într-un alt magazin.

Instrucțiunile repetitive se pot folosi şi imbricat, la fel ca instrucțiunile alternative.

© Bitulică 2020
Povestea lui Bitulică

for (int a = 0; a<5; a++)


{
for (int b = 0; b<5; b++)
{
If (a==0)
break;
printf("%d\n",a);
}
}

Instrucțiunile break şi continue sunt permise şi în instrucţiunea „while”, având aceleași


comportament ca şi în „for”.

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să fac operații aritmetice


C++
Am descoperit operatorii aritmetici

Operatorii sunt simboluri formate dintr-un caracter sau două cu ajutorul cărora se pot efec-
tua operații matematice sau logice.
OPERATORI ARITMETICI
+ Efectuează adunarea a două elemente
- efectuează diferență dintre două elemente
* efectuează produsul a două elemente
/ efectuează raportul a două elemente
% efectuează restul împărțirii a două numere
În funcție de tipul operanzilor operatorul + efectuează suma a două elemente sau
concatenare lor. În unele limbaje conversia este implicită adică facută automat de către
compilator în timp ce în altele este explicită. Logica este ca
1+1=2
sau
"1" + "1" = "11"
sau
1 + "1" = "11"
conversie implicită la string pentru că dacă ar fi făcut-o la int ar fi riscat ca string-ul să nu
conțină un număr valid şi rezultatul să nu poată fi efectuat
sau
"1" + 1 = "11" explicația e aceeași ca mai sus
1+1+"1" = "21"
se efectuează operațiile în ordine de la stânga și primul + este între doi întregi deci va da 2
iar al doilea + este între întreg și string şi rezultatul va fi un string
"1" + 1 + 1 = "111"
primul plus este între string şi int şi rezultatul va fi string , al doilea + este între string şi int
şi rezultatul va fi string
/ Poate avea ca rezultat un număr întreg sau un număr real în funcție de tipul în care
preluam rezultatul

© Bitulică 2020
Povestea lui Bitulică

int a = 7/3, a va fi 2 , adică câtul lui 7:3


iar
double a = 10/3 , a va fi 3.33333
Dacă nu se specifică tipul rezultatul va fi real întreg
cout << 10/3;
Va afișa 3
Nu este permisă scăderea între un întreg și un string sau între două string-uri pentru că nu
este definit cum să scazi "ana" - "maria"
char a = 'A' +1 , a va avea valoarea 'B', pentru că se ia codul ascii a lui A şi se adună 1 la el
apoi se transformă noul cod ascii în caracter
% (modulo) calculează restul unui împărţiri
10 % 3 va da 1
Ordinea operațiilor este cea din matematica , adică * şi / au precedenta mai mare faţă de +
şi - , iar între operatorii cu aceeași precedentă operațiile se execută de la stânga la dreapta
în ordinea în care sunt scrise
Parantezele, () , stabilesc o precedentă mai mare dacă apar
(2+2) * 2 face 4*2 adică 8
Pe când 2+2*2 face 2+4 adică 6
Nu exista paranteze pătrate şi acolade, ci doar paranteze rotunde.
Precedenta este dată de relația de incluziune
((2+2)-2) * 2 face (4-2)*2 adică 2*2 adică 4
În c/c++ codul
#include <iostream>
#include <string>
using namespace std;
int main()
{
int a = 1;
const char* b = "2";
string c = "3";

© Bitulică 2020
Povestea lui Bitulică

cout << (a + atoi(b)) << endl;


cout << to_string(a) + b << endl;
cout << a + a << endl;
cout << c+c << endl;
return 0;
}
afișează
3
12
2
33
Libraria string inclusă în program conține funcții pentru procesarea șirurilor de caractere
iar tipul string al variabilei c face parte din ea.
funcția atoi din C este inclusă în libraria iostream și transformă un sir de caractere în număr
dacă poate adică dacă valoarea dintre ghilimele este un număr, iar funcția to_string este
complementara ei din C++ și transformă un șir în număr.
Complementara lui atoi din C este itoa unde i vine de la integer iar a de la alphanumeric în
timp ce to în engleză înseamnă la.

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să fac operații logice


C++
Am descoperit operatorii logici

Operatorii logici sunt operatorii care leagă două condiții și stabilesc valoarea de adevăr a
condiției compusă

Operatorul && care se mai numește și ŞI BOOLEAN produce valoarea true doar dacă am-
bele condiții sunt adevărate

true && false da false


false && true da false
true && true da true
false && false da false

Adică dacă eu zic că Ana are mere ȘI Dana are pere , ce am spus este adevărat doar dacă și
Ana și Dana AU mere respectiv pere. Dacă se dovedește că una nu are ce am spus sau nu
cine am spus are ce am zis că are atunci ce am spus e fals per total.

Operatorul || care se mai numește și SAU BOOLEAN produce valoarea true doar dacă cel pu-
țin o condiție este adevărată

true || false da true


false || true da true
true || true da true
false || false da false

Adică dacă eu zic că Ana are mere SAU Dana are pere , ce am spus este adevărat doar dacă
măcar una dintre Ana sau Dana AU mere respectiv pere. Dacă se dovedește că ambele au ce
am spus sau nici una nu are ce am spus că are atunci ce am spus e fals per total.

Operatorul ^ care se mai numește și SAU EXPLICIT produce valoarea true doar dacă doar o
condiție este adevărată

true ^ false da true


false ^ true da true
true ^ true da false
false ^ false da false

Adică produce un rezultat adevărat doar dacă am de unde alege efectiv că dacă ambele sunt
adevărate sau ambele false nu am de ales că nu sunt valori diferite. E ca și cum cineva mi-ar
zice să aleg dintre mere și mere și orice aș alege tot mere mănânc.

Operatorul ! care se mai numește și NEGAŢIE inversează valoarea de adevăr a unei condiții.

© Bitulică 2020
Povestea lui Bitulică

!true da false
!false da true

Adică dacă eu zic că Ana are mere și este adevărat și apoi pun un NU în față și zic NU Ana
are mere , ce am spus ulterior este fals.

Operatorii booleeni sunt operatori cu scurt circuit adică acolo unde este posibil dacă după
aflarea valorii de adevăr al primului membru nu mai este necesară verificarea celui de al
doilea această verificare nu se mai face.

De exemplu daca la o condiție 5==7 && 3==3 primul e fals e clar ca întreaga condiție nu mai
are cum să fie adevărată pentru că pentru a fi adevărată este impetuos necesar ca toți mem-
brii să fie adevărați.

În codul de mai jos

int a = 0;
int b = -1;
int c = 1;

if (a == b && b == c)
cout << "toate trei sunt egale" << endl;
if (a==b || b==c)
cout << "cel putin doua sunt egale" << endl;
if (a==b ^ b==c)
cout << "numai doua sunt egale" << endl;

pentru valorile date nu se afișează nimic pentru că nu se îndeplinește nicio condiție

Pentru

int a = 0;
int b = 0;
int c = 1;

se afișează

cel puțin doua sunt egale


numai doua sunt egale

pentru că se îndeplinesc ultimele două condiții

iar pentru
int a = 0;
int b = 0;
int c = 0;

se afișează

© Bitulică 2020
Povestea lui Bitulică

toate trei sunt egale


cel puțin doua sunt egale

pentru că nu se îndeplinește ultima condiție

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să fac operații pe biți


C++
Am descoperit operatorii la nivel de bit

Operatorii logici sunt operatori care operează la nivel de bit

& SI LOGIC

2&4

00000010 &
00000100
---------------------
00000000

adica 0

Întotdeauna rezultatul e mai mic sau egal decât oricare din operanzi

| SAU LOGIC

2|4

00000010 |
00000100
--------------------
00000110

adică 6

Întotdeauna rezultatul este mai mare sau egal decât oricare dintre operanzi

^ SAU EXCLUSIV XOR

2^4

00000010 ^
00000100
--------------------
00000110

adică 6

© Bitulică 2020
Povestea lui Bitulică

Sau exclusiv ia în considerare doar biții diferiți pe restul îi pune 0 , 0^1 = 1 , 1^0=0, 0^0=0,
1^1=0, de aia îi zice sau exclusiv pentru că practic calculează doar unde e sau cu adevărat ,
doar dacă 0 într-o parte și 1 în altă pune 1, pe restul ii pune 0.

>> DEPLASARE CATRE DREPTA

8>>2

00001000 se deplasează biții lui 8 către dreapta cu 2 biți si se obține


00000010

adică 2

DEPLASARE CATRE STÂNGA

8<<2

00001000 se deplasează biții lui 8 către stânga cu 2 biți se obține


00100000

adică 32

Așezarea biților în teorie se face de la dreapta la stânga. Astfel, bitul cel mai nesemnificativ,
adică bitul setat ultimul, este în teorie cel mai din stânga.

În practică, există două sisteme unul care așează biții de la stînga la dreapta și unul care
așează biții de la dreapta la stânga. Big endian și little endian.

În teorie, bitul cel mai din dreapta are valoarea cea mai mică, adică 2 la puterea 0, iar cel
mai din stânga dintr-un octet, adică dintr-un byte care are 8 biți, are valoarea 2 la puterea a
7-a.

Transformarea unui număr din baza 2 în baza 10 se face adunând valorile rezultate din în-
mulțirea fiecărei cifre din baza 2 a numărului cu baza ridicata la puterea pe care o dă poziția
cifrei în număr.

10101010 în baza 2 este


0x2^0 + 1x2^1 + 0x2^2 + 1x2^3 + 0x2^4 + 1x2^5 + 0x2^6 + 1x2^7
adică 0+2+0+8+0+32+0+128 = 2+8+32+128 = 10+160 = 170

Cel mai mare număr zecimal scris pe 8 biti adică 11111111 este 255
Am înțeles că, atunci când se deplasează biții spre stânga și un bit trece de poziția 0, adică
2^0, bitul se pierde.

00000001 >> 1 = 00000000 = 0

© Bitulică 2020
Povestea lui Bitulică

Dacă un bit este deplasat spre dreapta și iese din cadrul unui byte, adică se duce dincolo de
poziția 8, adică 2^7, atunci el nu se pierde, ci reprezentarea numărului se face pe încă un oc-
tet, adică un byte.

10000000 << 1 = 0000000100000000 = 2^8 = 256

Numărul 256 este reprezentat în memorie pe 2 bytes, adică 16 biți.

Am citit că, dacă vreau să văd dacă un bit e setat, adică are valoarea 1, pot să îmi fac o
mască, adică un număr care are doar acel bit setat și să fac operația de și logic între numă-
rul al cărui bit vreau să văd dacă e setat și acel număr care servește ca mască.

Dacă în casă am 8 întrerupătoare și codez într-un bytes, adică 8 biți, stările de aprins sau
stins ale întrerupătoarelor și vreau să văd dacă întrerupătorul al 3-lea e aprins, atunci fac o
mască în baza 2, așa 00000100, care înseamnă 2^2 în baza 10 adică 4.

Presupunând că starea întrerupătoarelor mele este 10101010 atunci dacă fac

10101010 &
00000100

Obțin

00000000

semn că bitul 3 nu e setat, că dacă ar fi fost setat, aș fi obținut valoarea măștii în baza 10,
adică 4.

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să adaug


C++
Am descoperit operatorii de incrementare

Operatorii de incrementare și decrementare sunt operatorii care adună și scad anumite va-
lori din valoarea actuală a unei variabile.

++ Aduna la un un element o unitate

++1 face 2

dacă este pus în fața unei variabile (++a) îi incrementează valoarea pe loc, dacă e pus după
(a++) îi incrementează valoarea abia la operația următoare.

+= Aduna la un element un anumit număr de elemente

a+=4, dacă a e 1 , va avea valoarea 5

-- idem cu ++ doar că scade


-= idem cu += doar că scade
*= Idem cu += doar că multiplică
\= idem cu += doar că împarte

Operatorii relaționali sunt operatorii care stabilesc relația dintre două elemente. Fie de ega-
litate fie de subordonare.

== stabilește relația de egalitate


!= stabilește relația de inegalitate
< > stabilesc relația de subordonare

Operatorul ternar ?: este operatorul folosit pentru condițiile puse inline adică inserate în
linia instrucțiunii

cout << (a>b)?"a este mai mare":"b este mai mare" << endl;

Daca condiția este adevărată se execută ce este între ? si : iar in ca contrar se execută ce este
după :

În C++ operatorii pot supraîncărcați adică li se pot adăuga funcționalități noi.

De exemplu + este definit by default să adune două numere dar îl pot învăța să adune două
stringuri.

© Bitulică 2020
Povestea lui Bitulică

Sintaxa pentru supraîncărcarea operatorilor este

<tip_returnat> operator <simbol operator> (<tip operand> <variabila transmisa prin refe-
rinta>)
{
return <valoare returnata>;
}

de exemplu dacă vreau să concatenez doua stringuri pot scrie

string operator +(string& s1, string& s2) {


string temp = "";
temp += s1;
temp += s2;

return temp;
}

Am înțeles că prezendența operatorilor trebuie gândită de la interior spre exterior pornind


de la variabilă.

De exemplu dacă am o variabilă a atunci operatorul de lângă ea ca !a are precedența mai


mare ca + din a+b pentru că întâi trebuie calculat a si apoi adunat.

La fel si + din a+b are precedența mai mare ca == din a+b == c+d pentru că întâi trebuie cal-
culat a+b și c+d ca apoi să văd dacă sunt egale.

Prin urmare && are precedența mai mică decât == pentru că întâi trebuie aflată valoarea de
adevăr a fiecărei expresii pentru a vedea ce valoare are o înlănțuire.

© Bitulică 2020
Povestea lui Bitulică

Când am avut erori


C++
Am descoperit excepțiile

O excepție este ceva ce poate apărea ocazional indiferent de datele de intrare , o eroare este
ceva ce apare permanent cât timp datele de intrare nu se schimbă.

Asa cum a spus Einstein este o prostie să faci ceva la fel și să te aștepți la rezultate diferite.
În încercarea de a compila un cod sursă , aplicația compilator, poate întâmpina unele difi-
cultăți legate atât de modul în care este scris codul sursă dar și de modul în care este confi-
gurat mediul de programare sau sistemul de operare pe care se încearcă compilarea.

În încercarea de a rula o aplicație sistemul de operare sau mediul de rulare cum ar fi JRE în
cazul Java sau .NET în cazul C# pot întâmpină dificultăți în a duce la bun sfârșit rularea apli-
cației , dificultăți legate de comportamentul aplicației așa cum a fost specificat de progra-
mator sau de anumite evenimente neprevăzute care au loc în sistemul de operare, mediile
de rulare, sau pe mașina hardware.

În momentul în care apar astfel de probleme , compilatorul, mediul de rulare , sau sistemul
de operare, anunță programul care le-a provocat sau mediul de dezvoltare în cazul compila-
rii.

Dacă se încearcă compilarea textului

Mama are mere

inclus în fișierul Test.cpp

utilizând compilatorul g++ atunci

Dacă compilarea se face din linia de comandă compilatorul va încerca să compileze și va ve-
dea că Mama nu este un cuvânt cheie recunoscut de limbajul C++ și nu va putea continua
compilarea , oprindu-se cu mesajul de ieșire

"Mama" este un identificator necunoscut.

Identificator însemnând orice încearcă să identifice ceva, în cazul nostru compilatorul a în-
cercat să identifice mama printre cuvintele cheie pe care le știe el și nu a reușit pentru că nu
există.

Acest fel de erori , care apar de la momentul când se pornește compilarea până la crearea
unui fișier executabil se numesc ERORI DE COMPILARE.

© Bitulică 2020
Povestea lui Bitulică

Dacă compilarea se face dintr-un mediu de dezvoltare ca Intellij IDEA, Eclipse, Android Stu-
dio, NetBeans , Visual Studio atunci astfel de erori vor apare în consola mediului de dezvol-
tare.

Când se încearcă rularea unei aplicații care încearcă să facă ceva nepermis în sistemul de
operare ca

• scrierea intr-o locație din RAM nealocată sau ocupată de altă valoare ca în cazul ac-
ces violation.
• citirea dintr-o locație nealocata, ca în cazul NULL pointer exception.
• oprirea activității procesorului ca în cazul Intrerupted Exception

atunci sitemul de operare anunță programul care a provocat eroarea iar acesta este liber să
facă ce vrea cu ea.

Programul poate manageria eroarea trimisă de sistemul de operare în timpul rulării numai
dacă codul care a generat eroarea este cuprins între acoladele blocului try care înseamnă a
încerca.

In momentul când un astfel de cod provoacă o eroare de execuție adică de rulare sistemul
de operare îi trimite eroarea în blocul catch , unde programul o poate manageria , afișând
spre exemplu un mesaj uman ca "a apărut o eroare în timpul rulării".

Indiferent dacă codul din blocul try provoacă sau nu o eroare de execuție , se va executa co-
dul din blocul finally.

Logica acestor blocuri este

try
{
}
catch(exceptie e)
{
}
finally
{
}

Blocul catch poate lipsi.

try
{
}
finally
{
}

© Bitulică 2020
Povestea lui Bitulică

În acest caz dacă apare o eroare ea nu este manageriată.


Blocul finally poate lipsi si el

try
{
}
catch(exception e)
{
}

Blocul finally este utilizat doar dacă se dorește execuția unui cod indiferent dacă avem sau
nu eroare la rulare.

exception este tip de data predefinit în limbaje care are câmpuri ca , codul de eroare, sau
textul erorii.

Fiecare tip mai dedicat de excepții are propria lui tip de dată, ca IO Exception, Intrerupted
Exception.

Exception este folosit atunci când nu știm exact ce tip de excepție poate apare.
La runtime adică timpul în care programul rulează pot apărea două mari categorii de excep-
ții.

Excepții de citire / scriere în care intră concretizate în

• Excepții de intrare ieșire IOException când încearcă să citească sau scrie din perife-
rice sau în periferice ca tastatura, mouse, monitor, hard disk.
• NULL pointer exception când încearcă să citească din RAM o locație inexistentă la
momentul încercării.
• Out index of bound exception când încearcă să scrie sau să citească dintr-o locație
nealocata , și apare la vectori pentru ca se încearcă citirea dincolo de zona alocată
pentru vector.

Excepții de întreruperi care apar atunci când se încearcă oprirea activității procesorului fie
pentru a stopa o aplicație fie pentru a lăsa alte aplicații să ruleze.

Aceste excepții apar când sistemul de operare încearcă oprirea unui proces sau repormirea
lui.

C++ este un limbaj flexibil si low level de aceea de cele mai multe ori responsabilitatea tra-
tarii exceptiilor revine programatorului. Blocul finally este implementat diferit în c++ față
de Java sau C#.

© Bitulică 2020
Povestea lui Bitulică

Daca vreau sa impart ceva la zero si vreau sa dau excepție pot face astfel

try
{
int a = 10;;
int b = 0;
int c = 0;
if (b == 0)
throw exception("Nu poti imparti la zero");
else
c = a / b;
}
catch (exception e)
{
cerr << e.what() << '\n';
}

Programul va rula iar în momentul în care va fi îndeplinită condiția b==0 va arunca o excep-
ție (throw înseamnă a arunca) care v-a fi prinsă de blocul catch (cath înseamnă a prinde) și
tratată.

Practic programul încearcă (try) să facă ceva și dacă nu reușește aruncă (throw) o excepție
care este prinsă de blocul (catch) și tratată.

Dacă o excepție nu este prinsă de catch și înăbușită ea este transmisă mai sus sistemului de
operare care oprește execuția programului. Excepțiile se propagă de jos în sus de la cel mai
adânc nivel până la cel mai de deasupra.

Ultimul nivel este interfața sistemului de operare care afișează eroarea.

© Bitulică 2020
Povestea lui Bitulică

Când am dat factor comun


C++
Am descoperit subrutinele

Subprogramele sunt numite aşa pentru că luate individual pot fi însuşi programe dar mai
mici.

Ele intră în componenţa unui program mai mare şi pot fi funcţii şi/sau proceduri.
Subprogramele sunt părţi din program identificate printr-un nume, prin intermediul căruia
vor fi apelate.

Pot scrie subprograme atunci când:

• anumite instrucţiuni dintr-un program apar în mai multe locuri;


• vreau să împart problema în subprograme.

Subprogramele pot fi:

• funcție - returnează întotdeauna o singură valoare;


• proceduri- pot returna zero, una sau mai multe valori;

Funcţiile şi procedurile pot fi standard adică existente deja în biblioteci şi definite de utili-
zator.

Funcţiile sunt foarte asemănătoare procedurilor, singura diferenţa fiind faptul că funcţiile
pot întoarce un rezultat şi primesc cel puţin un parametru la intrare transformându-l.

Sintaxa unui suprogram este

tip_returnat nume_funcţie (tip_parametru1 nume_parametru1,tip_parametru2 nume_para-


metru2,...și așa mai departe )
{
}

Partea de sus se numește SEMNĂTURA FUNCŢIEI

Iar partea dintre acolade CORPUL FUNCŢIEI

O procedură arata tot că o funcție decât da diferă în funcționalitate.

O procedură are sintaxă la fel că o funcție doar că nu are parametrii de intrare nici para-
metri de ieșire , doar folosește referințe de variabile definite în exteriorul ei. Procedura e un
process.

Lista de parametri la suprograme este opţională.

© Bitulică 2020
Povestea lui Bitulică

Variabilele declarate în interiorul unui subprogram se numesc variabile LOCALE iar varia-
bilele declarate în programul principal având că scop tot programul se numesc variabile
GLOBALE.

Variabilele sistemului de operare se numesc variabile de sistem sau în sens mai larg varia-
bile de mediu , că sunt variabile ale mediului în care rulează un program.

Variabilele globale şi locale pot avea acelaşi nume, dar nu se recomandă, pentru că acest lu-
cru poate duce la probleme în program.

Am înțeles că nici un compilator din lume nu îmi va arăta erorile de programare ci doar de
sintaxa şi lexic , iar unele mai inteligente şi greşelile elementare de programare pentru că
atunci când vorbesc cineva mă poate corecta că nu mă exprim corect dar în nici un caz nu
îmi va spune să zic că "am avut ochelari cu rama subţire" când tu zic "am avut ochelari cu
rama groasă" pentru că nu are de unde să ştie CE VREAU să spun. El corectează doar CUM
spun. Așa face și un compilator.

Dacă vreau să fac o funcție care calculează suma a două numere și apoi să o apelez adică să
o folosesc pentru a calcula concret suma a două valori pot scrie

using namespace std;


long suma(int a, int b)
{
return a + b;
}
int main() {
int x = 1;
int y = 2;
cout << "a+b=" << suma(x,y) << endl;
return 0;
}

Atunci când se apelează funcția suma(x,y) și x=1 iar y=2 se apelează cu valorile variabilelor
x și y adică apelul este de forma suma(2,3) și am înțeles că acest mod de apelare se numește
apel prin valoare.

Parametrii funcției adică a și b primesc la apel în ordine valorile 1 și respectiv 2 astfel încât
a = 1 si b = 2. Practic la apelul funcției se crează două variabile locale a și b care primesc va-
lorile cu care funcția este apelată și care se dezaloca la finalizarea apelului funcției. Adică
după ce programul a terminat de executat funcția.

Cuvântul cheie return întoarce rezultatul către modul apelant dacă suprogramul produce
un rezultat. În cazul meu întoarce rezultatul 1+2 adică 3 către instrucțiunea cout iar in-
strucțiunea cout îl afișează.

Am ales tipul long ca tip de return pentru că atunci când adun ceva din două cutii care pot fi
pline îmi trebuie o cutie mai mare ca să fiu sigur că încape ce am adunat din cele două cutii.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie de rapiditate


C++
Am descoperit pointerii

Limbajele permit trei tipuri de variabile

• variabile
• pointeri
• referinte

Variabilele primitive sunt nume ale locațiilor de memorie. Referințele sunt variabilele care
referă către o variabilă primitivă deci indirect către o locație de memorie iar pointerii sunt
referințe direct către o locație de memorie cu putere de alocare și dezalocare a memoriei.

Variabilele se notează

int a;

referintele se noteaza

int &a;

pointerii se notează

int *a;

Referința este o VARIABILA care referă spre o adresă iar semnul & pus în fața unei variabile
înseamnă adresa ei.

Pointerul este o ADRESĂ iar semnul * pus în fața unei adrese înseamnă valoarea de la acea
adresă.

Funcțiile permit doua moduri de a li se transmite parametrii

• prin valoare adică în interiorul funcției se crează o copie a parametrului , deci o vari-
abila locală care preia valoarea parametrului si care moare când funcția se termină
și
• prin referință adică în interiorul funcției se lucrează cu referința parametrului tran-
smis și deci orice modificare în funcție asupra parametrului are efect după ce se ter-
mina funcția, parametrul transmis fiind declarat în afara funcției.

Variabilele primitive sunt transmise atât prin valoare cât ți prin referință.

int x = 0;
change(x);

© Bitulică 2020
Povestea lui Bitulică

x este o variabilă primitivă transmisă prin valoare iar dacă funcția este implementată așa

int change(int i)
{
i=i+1;
return i;
}

În interiorul funcției va fi declarată de compilator o variabilă locală adică i care va primi va-
loarea lui x si se va incrementa apoi se va dezaloca. Deci după ce se termina funcția valoarea
lui x rămâne aceeași care a fost înainte de începerea funcției.

Dacă vreau ca valoarea lui x să se schimbe după apelul funcției am două variante.

Ori fac asa

int x = 0;
x = change(x);

adică preiau în x rezultatul funcției

ori fac așa

int x = 0;
change(x);

adică transmit în funcție referința către x dar ca să fac așa este nevoie să schimb semnătura
funcției așa

void change(int& i)
{
i=i+1;
}

Dacă x este pointer adică secvența de cod e scrisă așa

int* x = new int(0);


change(*x);

atunci x se modifică după apel pentru că x este deja referință și prin urmare apelul funcției
este făcut prin referință. Un pointer este o referință cu puteri mai mari.

Dacă x este pointer și vreau să-l trimit în funcție prin valoare atunci pot scrie tot așa

int* x = new int(0);


change(*x);

dar definiția funcției trebuie să fie așa

© Bitulică 2020
Povestea lui Bitulică

void change(int i)
{
i=i+1;
}

Pentru a aloca memorie se poate folosi operatorul new sau funcția malloc() astfel

char* a = new char[10];

sau

char* a = (char*)malloc(10*sizeof(char)+1);

Prin instrucțiunile de mai sus am alocat 10 locații de memorie de dimensiunea tipului char
adică un bytes (8 biți). Zona de alocare este continua adică locațiile sunt una lângă alta.

sizeof este un operator cuvânt cheie care returnează dimensiunea unui tip de dată.

Am adăugat 1 la cele 10 spații de memorie pentru că orice sir de caractere trebuie să aibă
un hotar.

Adică un caracter care îi spune sistemului de operare că acolo se termină șirul. Caracterul
este \0; Și unii îl numesc end of line dar și null.

Dezalocarea memorie se poate face fie prin cuvântul cheie delete fie prin funcția free();
malloc() și free() sunt specifice limbajului C iar new și delete sunt specifice lui C++ dar pri-
mele se pot folosi fără probleme în C++.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie


C++
Am alocat memorie

Alocarea memoriei trebuie făcută inteligent. Altfel rămân fără.


Am înțeles că memoria unui calculator este ca nişte căsuţe poştale din scara unui bloc unde
sunt stocate anumite date . Aceste date poţi fi atât de mari încât să umple căsuţa sau mai
mici.
A aloca memorie înseamnă a rezervă una sau mai multe astfel de căsuţe pentru a pune
ulterior în ele valori ale variabilelor.
Memoria poate fi alocată STATIC sau DINAMIC.
A aloca STATIC memorie este echivalentul cu a face rezervare la un hotel pentru 10
persoane pentru o perioadă de 10 zile. Dacă ulterior 3 persoane nu mai pot ajunge camerele
rezervate lor pe perioada pe care au fost rezervate nu mai pot fi ocupate de nimeni care
vine între timp şi atunci patronul hotelului iese prost în afacere pentru că poate cineva vine
imediat după ce unii au renunţat. Este astfel posibil să refuze mulţi clienţi pentru că el are
toate camerele ocupate adică rezervate pe hârtie, dar în realitate să nu fie aşa şi camerele
alea să fie goale.
De aceea alocarea STATICĂ a memorie nu este prea EFICIENTĂ şi trebuie pe cât posibil mai
ales în aplicațiile mari şi complexe evitată.
Un exemplu de alocare statică este alocarea unui vector de numere sau a unei matrici de
numere cu număr maxim de elemente stabilite dinainte.
int a[100];
sau
int a[100][100];
Se rezervă în memorie în primul caz 100 de locaţii a câte 4 octeţi şi în al doilea caz 100x100
= 1000 de locaţii a câte 4 octeţi.
Eu poate am de memorat doar o tablă de şah maxim la un moment dat deci 8x8 şi deci
restul căsuţelor rămân libere cât tine scopul variabilei "a". Scopul poate fi chiar până se
termină programul. Scopul este domeniul de viaţă al unei variabile.
A aloca DINAMIC este ca şi cu cabina de probă într-un magazin de haine, unde cabină este
ocupată atât timp cât e cineva în ea după care este eliberată şi oricine altcineva o poate
ocupa.
Mă gândesc ce s-ar întâmpla dacă cabina de probă ar fi alocată static. Cred că n-ar mai
cumpăra nimeni că nu ar putea proba.

© Bitulică 2020
Povestea lui Bitulică

Pentru a aloca dinamic memorie pentru o variabilă se folosesc diferite funcţii în limbajele
de nivel scăzut că C++ sau anumite expresii care fac alocarea dinamică automată.
De exemplu în C++ pentru a aloca dinamic un tablou de 100 numere întregi se poate folosi
funcţie MALLOC aşa
int *a = (int)malloc(100 * sizeof(int));
apoi când scriu
free(a);
după ce nu mai am treabă cu variabila şi dezaloc variabila cele 100 de locaţii nu mai sunt
rezervate şi le poate lua oricine.
Dacă vreau să mă refer la prima locație rezervată de variabila a și să setez în ea valoarea 1
pot să o fac simplu aşa:
a[0] = 1;
Alocarea STATICĂ şi DINAMICĂ a memoriei să foloseşte cu precădere la construcția de liste
cu variabile adică colecții de valori pentru că nu prea are relevanta dacă aloc static sau
dinamic o variabilă simplă , tot acelaşi lucru e, dar capătă relevanta când am de alocat o listă
de variabile.
Aceste liste sunt
1. VECTORUL
Un vector este un tablou cu o singură dimensiune şi de aceea se mai numeşte şi SIR.
Exemplu de vector este înşiruirea de numere 1,10,3,7,9,15.
Pentru a aloca static şi apoi popula un astfel de vector se poate scrie:
int[10] a;
a[0] = 1;
a[1] = 10;
a[2] = 3;
a[3] = 7;
a[4] = 9;
Pentru a aloca memorie dinamic pentru un astfel de vector static şi poate scrie aşa:
int *a = malloc(100 * sizeof(int));
a[0] = 1;
a[1] = 10;

© Bitulică 2020
Povestea lui Bitulică

a[2] = 3;
a[3] = 7;
a[4] = 9;
2. MATRICEA
Este un tablou bidimensional şi de aceea se numeşte şi matrice de la matrix în engleză.
Termenul e împrumutat din matematică.
Exemplu de matrice este
1,2,4
2,4,5
2,1,3
pentru a aloca static şi apoi popula o astfel de matrice se poate scrie:
int[10][10] a;
a[0][0] = 1;
a[0][1] = 2;
a[0][2] = 3;
a[1][0] = 2;
a[1][1] = 4;
a[1][2] = 5;
Pentru a aloca dinamic memorie pentru un astfel de matrice statică şi poate scrie aşa
int **a = (int**)malloc(3 * sizeof(int*));
a[0] = (int*)malloc(10 * sizeof(int));
a[0][0] = 1;
a[0][1] = 2;
a[0][2] = 3;
a[1] = (int*)malloc(3 * sizeof(int));
a[1][0] = 2;
a[1][1] = 4;
a[1][2] = 5;
a[2] = (int*)malloc(3 * sizeof(int));

© Bitulică 2020
Povestea lui Bitulică

a[1][0] = 2;
a[1][1] = 1;
a[1][2] = 3;
sau
int **a = new int*[3];
a[0] = new int[3];
a[0][0] = 1;
a[0][1] = 2;
a[0][2] = 3;
a[1] = new int[3];
a[1][0] = 2;
a[1][1] = 4;
a[1][2] = 5;
a[2] = new int[3];
a[1][0] = 2;
a[1][1] = 1;
a[1][2] = 3
Dacă vreau să afisez elementele unei matrici pot face așa
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
iar dacă vreau să afisez elementele unui vector pot face așa

© Bitulică 2020
Povestea lui Bitulică

for (int i = 0; i < 3; i++)


{
cout << a[i] << endl;
}
Matricea este un vector de vectori. Adică a** este un vector de vectori și deci a[0] este un
vector iar a[0][0] este o variabilă.
3. TABLOU MULTIDIMENSIONAL
Cazurile de mai sus sunt de fapt cazuri particulare ale unui tablou multidimensional de
formă a[x][y][z][k][]...[]
Cel mai cunoscut tablou mulţi dimensional este tabloul în trei dimensiuni (3D sau CUB) iar
cea mai cunoscută aplicabilitate a sa este pentru a memora coordonatele din spaţiul real
tridimensional.
Mai există un spaţiu tot real în 4D dar a patra dimensiune este timpul şi se numeşte spaţiul
Minkowski de la numele celui care l-a descoperit. O deplasare în acest spaţiu este deplasare
spatio-temporară.
LISTE
Modelele de liste de mai sus pot fi dinamice prin modul de a aloca memoria dar nu sunt
dinamice ele însuşi.
Degeaba aloc dinamic memorie pentru listă dacă nu pot scoate un element din ea , iar după
ce îl scot să scurtez şi lista deci şi memoria alocată sau degeaba aloc memorie dinamic
pentru listă dacă nu pot adăuga un element în ea pe o poziţie anume din listă.
Listele cu adevărat dinamice permit aşadar să adaug un element fie la începutul ei fie la
sfârşit fie undeva ]ntre dou[ poziţii în interiorul ei.
La fel şi când vreau să scot un element din listă o pot face atât de la început cât şi de la
sfârşit cât şi de oriunde din lista iar după ce îl scot lista şi memoria alocată pentru ea se
scurtează.
Listele cu adevărat dinamice sunt de două feluri după modul în care sunt înlănţuite.
A fi înlănţuite înseamnă că orice element din listă are informaţii despre vecinii săi.
- liste simplu înlănţuite
când orice element din listă are informaţii despre cine este un singur vecin de-al său adică
ăla din faţa lui.
E ca şi cum aș sta la coadă şi ai şti cine este în faţa mea dar nu şi cine este în spate iar cel din
spate ştie cine este în faţa lui şi tot aşa.
- liste dublu înlănţuite

© Bitulică 2020
Povestea lui Bitulică

când orice element din listă are informații despre cine este atât în faţa lui cât şi în spatele
lui. E ca şi cum aș sta pe scaun în metrou pe laterală şi aș vedea vecinii amândoi.
Diferenţa dintre cele două construcții de lista este esenţială pentru că în cazul listei dublu
înlănţuită ea poate fi parcursă din ambele sensuri pe când cea simplu înlănţuită numai
dintr-un sens.
Dacă caut pe cineva la coadă la pâine şi fiecare ştie cine e ăla din faţa lui, şi vin dinspre
ghişeu, trebuie să ocolesc toată coadă ca să o iau de la ultimul să îl întreb cine e ăla din faţă
şi tot aşa până găsesc persoana.
Dar dacă ar fi cunoscut şi pe ăla din spate puteam să nu mai ocolesc coada şi să întreb direct
de al ghişeu.
Cele două cazuri particulare ale unei liste simplu sau dublu înlănţuite sunt:

• coadă (queue în engleză)


• stivă (stack în engleză)

• gramada (heap în engleză)


COADA (FILO First Input Last Output)
Este acea listă în care intrările se fac pe la un capăt şi ieşirile pe la altul. Exact ca o coadă de
la magazin. Că de aia îi zice coadă.
În informatică este folosită aproape peste tot. De exemplu un server am înțeles că îmi pune
cererile într-o COADĂ şi le va executa în ordinea în care au venit.
STIVA (LIFO Last Input First Output)
este acea listă în care atât intrările cât şi ieşirile se fac la acelaşi capăt. Exact ca atunci când
spăl vasele şi le aşez să se usuce unele peste altele. Când vreau să iau apoi o farfurie să pun
ciorba de legume în ea o iau pe cea de sus adică ultima pe care am pus-o pentru că doar nu
o să risc să le sparg luând-o pe cea de jos.
În informatică stiva se aplică de exemplu în apelul imbricat al funcțiilor unele din altele.
Return cedează controlul funcției care a apelat funcția în care se află el.
-
--
- - - asta este ultimul nivel al stivei
--
-
Mai jos am încercat să fac creare şi parcurgere a unei liste SIMPLU înlănţuita și am scris și
comentarii pe cod comentarii

© Bitulică 2020
Povestea lui Bitulică

Am înțeles că e bine să scriu comentarii pe cod ca să îl pot înțelege ulterior eu și alții chiar
dacă un cod bine scris se comentează singur. Adică nu are nevoie de explicații suplimentare.
#include<iostream>
using namespace std;
// se defineşte o structură cu un câmp în care pui informaţia şi cu unul care ţine informaţia
despre nodul din faţa lui
struct nod
{
int info; // tine informaţia propriuzisă
nod* next; // tine informaţia despre nodul din faţa lui
};
nod* p, * u; // accesează primul respectiv ultimul nod
int n; //numărul de noduri
void creare_lista() //funcţia de creare şi adăugare a unui nou element
{
nod* c;
if (!p) //dacă lista este vida (p==0) se aloca primul nod
{
p = new nod;
cout << "valoare primului nod: ";
cin >> p->info;
u = p; //la creare primul şi ultimul nod vor fi identici
}
else //altfel se adăugă un nou element la sfârşit
{
c = new nod; //se aloca un nou nod
cout << "informatia utila: ";
cin >> c->info; //se completează câmpul informaţie utilă
u->next = c; //se adăugă după ultimul nod
u = c; //se stabileşte noul nod c ca fiind ultimul

© Bitulică 2020
Povestea lui Bitulică

}
u->next = NULL; //câmpul adresa următoare a ultimului nod este NULL
}
void afisare_lista() //funcţia de afişare parcurge elementele cu afişare
{
nod* c;
c = p; //se porneşte de la primul nod din listă
while (c) //cât timp c reţine o adresă nenula
{
cout << c->info << " ";//se afiseza câmpul informaţie utilă
c = c->next;
} //se avansează la următoarea adresă, la următorul nod
cout << endl;
}
void main()
{
int b;
cout << "n= ";
cin >> n;
for (int i = 1; i <= n; i++)
creare_lista();
cout << endl;
afisare_lista();
}
Mai jos am făcut și un exemplu de creare şi parcurgere a unei lista DUBLU înlănţuite
#include<iostream>
using namespace std;
struct Nod
{

© Bitulică 2020
Povestea lui Bitulică

int info;
Nod* next, * back;
};
Nod* prim, * ultim;
void creare_lista()
{
Nod* c;
c = new Nod;
cout << "info ";
cin >> c->info;
if (!prim)
{
prim = c;
prim->next = 0;
prim->back = 0;
ultim = prim;
}
else
{
ultim->next = c;
c->back = ultim;
ultim = c;
ultim->next = 0;
}
}
void listare_stânga_dreapta()
{
Nod* c;
c = prim;

© Bitulică 2020
Povestea lui Bitulică

while (c)
{
cout << c->info << " ";
c = c->next;
}
}
void listare_dreapta_stânga()
{
Nod* c;
c = ultim;
while (c)
{
cout << c->info << " ";
c = c->back;
}
}
void main()
{
int n, i;
cout << "Cate elemente va avea lista? ";
cin >> n;
for (i = 1; i <= n; i++)
creare_lista();
cout << endl << "Elementele listei de la stânga la dreapta sunt: " << endl;
listare_stânga_dreapta();
cout << endl << "Elementele listei de la dreapta la stânga sunt: " << endl;
listare_dreapta_stânga();
}

© Bitulică 2020
Povestea lui Bitulică

#include<iostream.h>
struct Nod
{
int info;
Nod *next,*back;
};
Nod *prim, *ultim;
void creare_listă()
{
Nod *c;
c=new Nod;
cout<<"info ";
cin>>c->info;
if(!prim)
{
prim=c;
prim->next=0;
prim->back=0;
ultim=prim;
}
else
{
ultim->next=c;
c->back=ultim;
ultim=c;
ultim->next=0;
}
}
void listare_stânga_dreapta()

© Bitulică 2020
Povestea lui Bitulică

{
Nod *c;
c=prim;
while(c)
{
cout<<c->info<<" ";
c=c->next;}
}
void listare_dreapta_stânga()
{
Nod *c;
c=ultim;
while(c)
{
cout<<c->info<<" ";
c=c->back;}
}
void main()
{
int n,i;
cout<<"câte elemente va avea listă?";
cin>>n;
for(i=1;i<=n;i++)
creare_listă();
cout<<endl<<"Elementele listei de la stânga la dreapta sunt:"<<endl;
listare_stânga_dreapta();
cout<<endl<<"Elementele listei de la dreapta la stânga sunt:"<<endl;
listare_dreapta_stânga();
}

© Bitulică 2020
Povestea lui Bitulică

Lista poate cuprinde elemente de tipuri diferite în timp ce un vector cuprinde elemente de
același tip. De exemplu lista de cumpărături cuprinde mai multe tipuri de obiecte. Vectorii
în general mai ales cei alocați static au zona de memorie continua ceea ce îi face mai ușor de
accesat.
a[4] este adresa lui a[0] + 4 * dimensiunea tipului alocat
de exemplu daca adresa lui a[0] este 0x0001 și vectorul conține elemente de tipul int atunci
adresa lui a[4] este
0x0001 + 4 * sizeof(int) adică 4 deci adresa este 0x0016
asta pentru că dacă p este un pointer atunci p+1 nu este 2 ci este p+sizeof(de tipul
pointerului) adică adcă
int* p;
p+1 este p + sizeof(int);
deci noua adresă este adresa veche a lui p + atătea locații de memorie cu cat se adună p;
Dacă eu știu adresa unde stă Ion și știu că Gheorghe stă la 4 adrese mai încolo, nu înseamnă
că Gheorghe stă la 5 case mai încolo căci e posibil ca unii să aibă 2 case la o adresă.
Și listele și vectorii sunt colecții de date.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie de hartă


C++
Am descoperit graful

Un graf este o structură în care elementele sunt legate între ele.


Elementele unui graf se numesc vârfuri sau noduri iar legăturile dintre ele se numesc
muchii.
Dacă mă uit pe harta rutieră observ că oraşele sunt legate între ele prin drumuri şi că
drumurile şi oraşele formează împreună un graf.
Ordinul unui graf care îi dă mărimea şi complexitatea este numărul de noduri legate sau nu
ale grafului. Un graf poate să aibă 0 norduri , 1 nod sau oricâte de multe noduri.
Dacă are 0 noduri tot graf e dar fără niciun nod , din acelaşi motiv pentru care un vector sau
o listă fără niciun nod este tot o listă dar care nu are nimic în ea. Graful cu un nod sau
niciunul se numeşte graf vid.
Două vârfuri ale unui graf pot fi legate printr-o muchie sau nu iar totalitatea vârfurilor şi
muchiilor care duc dintr-un vârf în alt vârf se numeşte drum în graf. Ca şi un drum de la San
francisco la New York pe harta rutieră.
Drumurile pot fi cu sens unic sau nu iar dacă sunt cu sens unic atunci graful se numeşte
orientat. Adică din A pot să ajung în B dar din B nu pot ajunge în A oricare ar fi A şi B două
noduri vecine legate printr-o muchie.
Dacă oricare două noduri din graf sunt legate printr-o muchie atunci graful este conex în
caz contrar graful este neconex. Adică nu toate nodurile sunt conectate. Conex vine de la
conexiune.
Un nod care nu este conectat cu nici un alt nod este un nod izolat ca un oraş care nu are
drumuri către altul.
Arborele este un copac. Copacul este format din rădăcină, tulpină care este cea mai groasă
creangă şi frunze. Din tulpină se ramifica alte crengi mai subţiri iar din ele altele şi mai
subţiri. Pot spune că creanga mai groasă din care se ramifica altele mai subţiri este
părintele acelor crengi care se ramifica din ea şi nu greşesc căci din ea iau naştere.
Termenul de graf a fost preluat şi în informatică pentru a organiza datele iar arborele este
un caz particular de graf.
Vectorii se folosesc atunci când datele pot fi aşezate cel mai bine în linie, matricile când
datele pot fi aşezate cel mai bine în grilă, la fel şi cubul doar că grila este şi înaltă nu numai
lungă şi lată.

© Bitulică 2020
Povestea lui Bitulică

Graful se foloseşte atunci când datele nu pot fi ţintuite într-un tipar şi sunt raspundite
aleatoriu pe o suprafaţă sau în spaţiu iar între ele există relaţii de legătură pe picior de
egalitate. Adică nu e nici una superioară ierarhic alteia.
Arborele se foloseşte atunci când datele pot fi ordonate ierarhic ca într-o organigramă la o
firmă sau ca într-un arbore genealogic.
Cel mai de sus element al arborelui care nu are alt element deasupra lui se numeşte
rădăcina arborelui iar cele mai de jos noduri care nu au alte noduri sub ele se numesc
frunzele arborelui.
Arborele informatic creşte de sus în jos invers faţă de cel din natură iar un caz particular al
lui este arborele binar în care oricare nod are cel mult 2 subnoduri adică copii.
Graful şi arborele pot fi reprezentate prin liste simplu şi dublu înlănţuite dar şi vectori de
muchii sau matrici adiacente.
Dacă vreau să folosesc reprezentarea prin vector de muchii pot scrie
#include <iostream>
using namespace std;
// numarul maxim de noduri posibile
const int MAXIM = 10;
// structura unei muchii
struct Muchie {
// nodurile intre care este muchia exemplu 3 si 7
int x, y;
// cosntructorul structurii adica cel care construieste o structura dupa model
// this este self pointer la structura adica indica catre fiecare structura creata dupa model
Muchie(int x = 0, int y = 0) {
this->x = x;
this->y = y;
}
};
int n; // numărul de muchii
Muchie muchii[MAXIM]; // lista de muchii
// functie care cauta o muchie in graf

© Bitulică 2020
Povestea lui Bitulică

int cauta(Muchie muchie) {


// parcurg toate muchiile
for (int i = 0; i < n; i++)
// daca o muchie este intre aceleasi puncte
if (muchii[i].x == muchie.x && muchii[i].y == muchie.y)
// returnez numarul de ordine al muchiei
return i;
// daca nu am gasit niciuna returnez -1 semn ca nu am gasit nici un numar de ordine care
incep de la 0 in sus
return -1;
}
// functia care sterge o muchie din graf
void sterge(Muchie muchie) {
// parcurg toate muchiile
for (int i = 0; i < n; i++)
// daca ma gansit muchia pe care urmeaza sa o sterg
if (muchii[i].x == muchie.x && muchii[i].y == muchie.y) {
// atunci o adaug la sfarsitul listei ca e o lista statica si nu pot sa o scot efectiv

// pentru ca nu am scos-o reduc numarul de muchii ca sa nu o mai prind cand mai


parcurg lista
n--;
return;
}
}
// functie care adauga o muchie in graf
void adauga(Muchie muchie) {
// incrementez numarul de muchii si in acea locatie punc noua muchie
muchii[n++] = muchie;
}

© Bitulică 2020
Povestea lui Bitulică

// functie care afiseaza vecinii unui nod


void vecini(int nod) {
// parcurg lista de muchii
for (int i = 0; i < n; i++)
// daca o muchie este trasata din nodul cautat
if (muchii[i].x == nod)
//ii afisez celalalt capat caci este unul din vecinii nodului cautat
cout << muchii[i].y << ' ';
// sar la linia urmatoare ca sa afisez mai departe
cout << '\n';
}
int main() {
// adaug muchia din punctul 5 in punctul 1
adauga(Muchie(5, 1));
// adaug muchia din punctul 5 in punctul 2
adauga(Muchie(5, 2));
// adaug muchia din punctul 5 in punctul 4
adauga(Muchie(5, 4));
// adaug muchia din punctul 5 in punctul 3
adauga(Muchie(5, 3));
// sterg muchia din punctul 5 in punctul 3
sterge(Muchie(5, 3));
// caut muchia din punctul 5 in punctul 2
cout << cauta(Muchie(5, 2)) << '\n';
// caut muchia din punctul 2 in punctul 5
cout << cauta(Muchie(2, 5)) << '\n';
// afisez vecinii punctului 5
vecini(5);
return 0;

© Bitulică 2020
Povestea lui Bitulică

}
Iar dacă vreau să folosesc matricea adiacentă pentru reprezentare pot scrie
#include <iostream>
using namespace std;
// numarul maxim de noduri posibile
const int MAXIM = 10;
// structura unei muchii
struct Muchie {
// nodurile intre care este muchia exemplu 3 si 7
int x, y;
// cosntructorul structurii adica cel care construieste o structura dupa model
// this este self pointer la structura adica indica catre fiecare structura creata dupa model
Muchie(int x = 0, int y = 0) {
this->x = x;
this->y = y;
}
};
int n; // numărul de muchii
bool muchii[MAXIM][MAXIM]; // matricea adiacenta
// functie care cauta o muchie in graf
bool cauta(Muchie muchie) {
// returneaza true daca exista muchie intre coornonatele matricei
return muchii[muchie.x][muchie.y];
}
// functia care sterge o muchie din graf
void sterge(Muchie muchie) {
// seteaza ca nu exista muchie intre coordonatele matricei si intr-o directie si invers ca nu e
graf orientat
muchii[muchie.x][muchie.y] = muchii[muchie.y][muchie.x] = false;

© Bitulică 2020
Povestea lui Bitulică

}
// functie care adauga o muchie in graf
void adauga(Muchie muchie) {
// setez ca exista muchie intre coordonatee matricei si intr-o directie si invers
muchii[muchie.x][muchie.y] = muchii[muchie.y][muchie.x] = true;
}
// functie care afiseaza vecinii unui nod
void vecini(int nod) {
// parcurg matricea adiacenta pe o dimensiune
for (int j = 1; j <= n; j++)
// daca gasesc ca exista muchie dusa din nod in oricare directie
if (muchii[nod][j])
// afisez capatul celalat al ei
cout << j << ' ';
cout << '\n';
}
int main() {
// adaug muchia din punctul 5 in punctul 1
adauga(Muchie(5, 1));
// adaug muchia din punctul 5 in punctul 2
adauga(Muchie(5, 2));
// adaug muchia din punctul 5 in punctul 4
adauga(Muchie(5, 4));
// adaug muchia din punctul 5 in punctul 3
adauga(Muchie(5, 3));
// sterg muchia din punctul 5 in punctul 3
sterge(Muchie(5, 3));
// caut muchia din punctul 5 in punctul 2
cout << cauta(Muchie(5, 2)) << '\n';

© Bitulică 2020
Povestea lui Bitulică

// caut muchia din punctul 2 in punctul 5


cout << cauta(Muchie(2, 5)) << '\n';
// afisez vecinii punctului 5
vecini(5);
return 0;
}
Cea mi cunoscută utilizare a graful sunt aplicațiile GPS.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie de recurenta


C++
Am descoperit recursivitatea

Recursiv înseamnă referire la sine însuși ceea ce poate avea ca implicație repetiția la infinit.
In informatica recursivitatea este o metoda prin care o funcție se apelează pe ea însăși din
interiorul propriului corp

Test()
{
Test();
}

Dacă las așa programul intra în ciclu infinit și nu se mai termina niciodată.
De aceea condiția esențială în recursivitate sau recurență cum i se mai spune la recursivi-
tate este condiția de oprire a recursivității.

Test()
{
If (ceva se împlinește)
return;
Test();
}

În momentul În care condiția e adevărată funcția cedează controlul funcției apelante adică
tot ei dar pe un nivel mai sus până când cedează controlul programului principal.

Cam așa se schițează grafic recursivitatea


-
-
-
- condiție îndeplinită
- ies pe nivel superior
- ies pe nivel si mai sus
- ies in programul principal

Funcțiile se țin pe o stivă adică lista in care ieșirile și intrările sunt la același capăt numita
Stiva de funcții și dacă recursiunea este foarte lunga se umple stiva de aceea în producție
recursivitate este evitată și transformată în iterație pentru a evita problemele legate de
stack overflow.

Am înțeles că se folosește recursivitatea atunci când trebuie să navighez prin nodurile unei
structuri arborescente pornind de la rădăcină fie pentru a căuta ceva fie pentru a afișa in-
formația din noduri.

© Bitulică 2020
Povestea lui Bitulică

De exemplu sistemul de operare atunci când caut o informație folosește căutarea recursivă
în foldere.

Codul pentru calcul sumei primelor numere naturale scris recursiv este

// functie recursiva pentru calculul sumei


int suma (int n)
{
// conditia de oprire a recursivitatii este ca daca nu exista niciun numar de adunat
if(n==0)
// suma e zero
return 0;
// daca exista numere
else
// suma este suma numerelor prcedente + numarul curent
return suma (n-1) + n;
}

int main()
{
// declar varibila n
int n;
// introduc de la tastatura valoarea pentru variabila n
cin>>n;
// apelez functia suma cu n si afisez rezultatul intors
// se va apela in interior recursiv cu n-1 pana cand n este zero
// apoi cand se intoarce din adanc spre suprafata aduna mereu numarul cu care a fost
apelata cand a fost aruncata in adancime

cout<<suma(n);
return 0;
}

E ca și cum aș merge printr-un apartament nedecomandat și când ajung la ultima camera și


vreau să plec afară trebuie să trec iar prin fiecare cameră pe unde am venit.

Pentru crearea algoritmilor care rezolvă diferite probleme care apar dezvoltatorii limbaju-
lui C++ au creat biblioteci cu funcții usuale predefinite.

Cateva dintre ele care se găsesc în librăriile cstdlib si cmath sunt

abs cstdlib int abs(int x)


Valoarea absolută a argumentului, |x|, număr întreg

abs, fabs cmath double abs(double x), double fabs(double x)


Valoarea absolută a argumentului, |x|, număr real

© Bitulică 2020
Povestea lui Bitulică

sqrt cmath double sqrt(double x) Rădăcina pătrată a argumentului, x−−√

pow cmath double pow(double x, double y) Ridicarea la putere, xy

sin cmath double sin(double x) Funcția trigonometrică sinus, sinx

cos cmath double cos(double x) Funcția trigonometrică cosinus,cosx

tan cmath double tan(double x) Funcția trigonometrică tangentă,tanx

floor cmath double floor(double x) Cel mai mare întreg mai mic sau egal cu x

ceil cmath double ceil(double x) Cel mai mic întreg mai mare sau egal cu x

© Bitulică 2020
Povestea lui Bitulică

Când am făcut probleme cu sume


ALG
Am descoperit algoritmii de sumă

Am înţeles ca algoritmul de calcul al sumei elementelor unui vector este folosit des în indus-
tria tehnologiei informaţiei începând cu calculul punctelor obţinute de un gamer până la
calculul tranzacţiilor bancare aşa că am încercat să îl implementez şi eu.

Am înțeles că indiferent ce reprezintă elementele adunate, bani sau puncte, ele sunt ab-
stractizate în numere puse separat în locații de memorie si pentru asta am definit un vector
de 5 elemente de tip int pe care l-am denumit sugestiv vector în care am pus numere la în-
tâmplare.

int vector[5] = {12,7,3,9,1};

Am citit că atunci când calculez suma elementelor dintr-un vector e ca şi cum aş colecta
ceva din camerele de pe unul din palierele unui hotel.

Fiecare cameră este numerotata de la zero la câte sunt iar în interiorul camerelor este ceea
ce colectez.

Pentru a putea colecta am nevoie de un recipient în care să pun ce colectez suficient de


mare încât să nu mă trezesc că nu mai am unde să pun.

Așa că am definit variabila suma de tip long ca să fie suficient de încăpătoare şi am intiali-
zat-o cu 0 semn că nu am nimic în ea momentan dar şi pentru că zero este elementul neutru
la adunare şi orice număr adunat cu el da fix acel număr.

long suma = 0;

Ca să iau ce am de luat din fiecare cameră trebuie să trec prin dreptul fiecăreia şi să deschid
uşa. Am observat că distanţa dintre camere este aceeaşi şi că dacă fac un pas mai mare
ajung de la o cameră la alta. Văd că pe uşa fiecărei camere este un număr şi mă voi folosi de
el ca să ştiu la ce cameră sunt şi câte mai am până termin tot palierul.

Pentru asta am implementat un for în care indexul porneşte de la zero la fel ca şi numerele
de pe uşile camerelor şi i-am spus că atât timp cât indexul acesta nu ajunge la 5 să nu îmi
zică să mă opresc ci să mă lase să tot fac câte un pas să trec de la cameră la alta.

for (int i = 0; i < 5; i++)

pe măsura ce ajung în dreptul fiecărei camere deschid uşa iau ce este acolo şi pun în sac.

© Bitulică 2020
Povestea lui Bitulică

Pentru a face asta am scris

suma += vector[i];

unde i este indexul camerei adică numărul scris pe uşa fiecărei camere, vector este palierul
cu toate camerele iar vector[i] este conţinutul fiecărei camere.

După ce for-ul nu m-a mai lăsat să continui m-am uitat în sac şi am văzut ce am adunat. Iar
ce am adunat am arătat la camera de supraveghere să vadă şi angajaţii de la securitatea ho-
telului că nu am luat decât ce trebuia să iau.

Pentru asta am scris

cout << suma << endl;

Am înţeles că de fiecare dată când am de parcurs un şir va trebui să folosesc structuri repe-
titive şi să merg pe la fiecare element al şirului şi să fac ce am de făcut cu fiecare în parte.

© Bitulică 2020
Povestea lui Bitulică

Când am făcut probleme cu extremități


ALG
Am descoperit algoritmii de maxim

Înainte să îmi explice algoritmul de determinare a valorii maxime dintr-un şir de numere
Katy fata mea cea mare care este angajată ca Full Stack Software Developer la compania Ri-
verbites din Silicon Valley m-a trimis prin oraş aici la noi să îi spun care clădire e cea mai
înaltă. Vorba vine aici la noi ca noi stăm într-o vale şi până la San Francisco e un tren dar eu
am fost cu maşina şi m-am plimbat prin oraş.

Katy mi-a spus la câte clădiri să mă uit adică cele care sunt mai înalte ca să nu bat drumul
degeaba prin oraş. Nu ştiu de unde a aflat cred că după Google Map sau o fi citit pe undeva.
Am luat-o de la margine şi am văzut prima clădire care dacă nu mai văzusem nici una am zis
că ea e cea mai înaltă.

Apoi am mai mers şi am văzut alta care nu era aşa de înaltă ca cea pe care o văzusem şi pe
care am ţinut-o minte aşa că nu am băgat-o în seamă şi am mers mai departe unde am văzut
un zgârie nori care clar era mai înalt decât clădirea pe care o văzusem eu aşa că de acum ea
a fost cea mai înaltă clădire pe care o văzusem şi pe care am şi ţinut-o minte ca să i-o spun
lui Katy că mă gândeam că nu mai găsesc alta mai înaltă ca ea.

Am mai văzut şi altele dar se pare că am avut dreptate şi nu a mai fost alta mai înaltă din
câte am străbătut. Am văzut şi Golden Gate dar ăla nu e clădire e pod.

Când m-am întors şi am vorbit cu Katy mi-a spus că exact cum am făcut eu trebuie să învăţ
şi calculatorul să facă pentru că nici el nu este suficient de sus încât să vadă toate datele că
să fotografieze peisajul lor şi să arate cu degetul : uite aia e cea mai mare.

Așa că m-am pus pe gânduri şi am zis că ar fi bine să aranjez datele într-un vector căci fie
ele ce or fi înălţimile lor sunt nişte numere care au o valoare mai mare sau mai mică. Prin
urmare am scris un vector în care am notat înălţimile clădirilor. Sunt vreo 5 că doar nu mă
punea pe mine Katy să le iau la rând pe toate din oraş. M-a trimis la câteva.

Am făcut vectorul de mai jos

int vector[5] = {1,7,12,9,3};

Apoi m-am gândit cum am ţinut eu minte clădirea cea mai înaltă şi m-am gândit că undeva
în capul meu trebuie să fie un lăcaş unde să fi ţinut minte înălţimea fiecărei clădirii care pe
moment mi s-a părut a fi cea mai înaltă şi am declarat o variabila de tip int că am înţeles că
cei care au construit clădirile s-au străduit să nu le dea cu virgulă.

int maxim = 0;

© Bitulică 2020
Povestea lui Bitulică

Drumul şi popasurile pe care le-am făcut la fiecare dintre clădiri pentru a le admira că era
frumoase rău dar şi pentru a le măsura din priviri ochiometric l-am codificat într-un for
care se plimba pe la fiecare căsuţă a vectorului ajutat de un contor de paşi care pleacă de la
indexul 0 al primului element al vectorului şi se opreşte la ultimul index adică 4 pentru că în
intervalul închis [0,4] sunt 5 elemente. Închis adică și cu extremitățile incluse.

for (int i = 0; i < 5; i++)

Am înţeles că indexul unui şir memorat de un computer începe de la 0 pentru a fi uşor de


detectat adresa unde se găseşte fiecare element al său pentru ca programul să poată ajunge
la acea adresă şi să facă ceva cu acea valoare.

Dacă adresa unde se găseşte primul element este 0x0000 atunci al 3-a element adică vec-
tor[2] este

0x0000 + 2*sizeof(int) adică 0x0000 + 2*4 adică 0x0008

Dacă ar fi început de la 1 ar fi trebuit să mai adune ceva la acesta expresie şi ar fi fost o ope-
raţie în plus.

Adresa de unde începe un vector este însuşi vectorul pentru că vectorul este pointer către
primul element al său.

La fiecare clădire stăteam şi mă întrebam dacă aceea este mai mare decât cea pe care o ţi-
neam eu minte. Şi cum am făcut eu aşa l-am învăţat și pe calculator să facă.

if (vector[i] > maxim)

Dacă vedeam că cea la care mă uit este mai mare decât cea pe care ţineam minte că era cea
mai înaltă atunci o uitam pe aceea şi o ţineam minte pe asta.

maxim = vector[i];

După ce am terminat de plimbat şi uitat pe la toate clădirile m-am dus la Katy şi i-am spus
care clădire mi-a rămas în minte că este cea mai înaltă din San francisco.

cout << maxim << endl;

Am înţeles că de fiecare dată când am de determinat dintr-un şir o anumită valoare e bine
să folosesc o variabilă în care să reţin la fiecare pas ce mă interesează.

© Bitulică 2020
Povestea lui Bitulică

Când am făcut probleme cu cautări


ALG
Am descoperit algoritmii de cautare

Când a auzit că vreau să îmi explice algoritmul de căutare a unei valori într-un vector Katy
m-a trimis iar în oraş dar de data asta cu un bileţel pe care era scris numărul unei clădiri.
Trebuia să găsesc acea clădire dintre cele 5 pe care le măsurasem înainte cu privirea să văd
care este cea mai înaltă.

Am mers. Nu credeam că o să o găsesc.

Mi s-a părut logic să încep cu prima clădire care mi-a ieşit în cale adică cea care era cea mai
aproape de mine şi când m-am uitat ce număr e am văzut că nu era ăla de îl aveam scris pe
foaie aşa că am continuat să merg la următoarea şi apoi la următoare până când până la
urmă am dat de clădirea care avea numărul identic cu aveam eu scris pe foaie.

După ce am găsit-o m-am întors fără să mai merg şi la celelalte din cele 5 pentru că aflasem
ce voiam eu să aflu şi nu mai avea rost să bat drumul degeaba chiar dacă e frumos în San
Francisco. Am reţinut că am găsit-o şi gata.

Când m-am întors la Katy m-a întrebat dacă am găsit-o Iar eu mi-am amintit că am găsit-o şi
am zis că da.

Atunci ea mi-a zis că exact cum am făcut eu să o găsesc aşa să învăţ şi computerul să caute.
Am aşezat numerele clădirilor într-un vector.

Fiind numere de clădiri vectorul este de numere întregi nenegative adică pozitive pentru că
nu am văzut până acum clădirea cu numărul -1.

Numere de ordine adică indexii indentifică ceva ce există. Numerele negative indentifică
ceva ce nu există.

unsigned int vector[5] = {1,7,12,9,3};

I-am dat şi bileţelul computerului şi i-am scris pe el numărul 7

unsigned int valoare_cautata = 7;

Apoi i-am spus să nu fie optimist şi mai bine să fie pesimist să pună răul înainte ca să nu fie
dezamăgit. E mai bine să fie bucuros dacă va găsi şi să rămână indiferent dacă nu va găsi de-
cât să fie optimist şi să fie trist apoi.

bool exista = false;

© Bitulică 2020
Povestea lui Bitulică

I-am spus să parcurgă fiecare clădire cuantificată printr-un număr pus într-o locaţie a vec-
torului.

for (int i = 0; i < 5; i++)

Şi dacă vreun număr de clădire se va potrivi cu ce i-am scris pe bileţel

if (vector[i] == valoare_cautata)
{

Atunci să ţină mine că a găsit

exista = true;

Şi să nu mai caute în continuare că nu are rost

break;
}

Când vine înapoi la mine să îşi amintească dacă a găsit sau nu

if (există)

Şi dacă a găsit să îmi spună că acea clădire există

cout << "Există" << endl;

Iar în caz contrar

Else

Să îmi spună că acea clădire nu există

cout << "Nu există" << endl;

Am citit că atunci când am de validat ceva cum am validat în cazul de faţă dacă am găsit
ceva sau nu, e bine să am o variabilă booleana adică de aia cu două valori posibile true sau
false pe care să o setez dacă am validat pozitiv sau negativ ce am avut de validat.

Practic acea variabilă îmi extrage esenţialul şi mi-l aduce.

© Bitulică 2020
Povestea lui Bitulică

Când am făcut probleme cu sortări


ALG
Am descoperit algoritmii de sortare

Katy este o fata foarte isteaţă şi ca să înţeleg algoritmul de sortare prin interschimbare nu-
mit bubble-sort pentru că cică bulele mele din bere aşa ies la suprafaţă exact cum se aran-
jează numerele în procesul de sortare ne-a propus să facem o poză de familie.

Fotograful ca să iasă poza bine adică să ne vedem toţi ne-a pus să schimbăm locurile între
noi şi cei mai scunzi să treacă în fata iar cei mai înalți în spate.

Nu ne-a aranjat el aşa că a trebui să ne aranjăm noi să vedem care e mai scund care e mai
înalt şi să ne schimbăm între noi.

Eu m-am uitat că Lisa era în spatele meu şi am lăsat-o să treacă în fata iar în faţa ei era tata
care e mai înalt ca ea dar mai scund ca mine aşa că tata a lăsat-o să treacă de asemenea în
faţa lui.

Fotograful a trecut aşa cu privirea de la distanţă printre noi şi a văzut că nu mai e nici unul
care nu se vede în poza adică suntem toţi ordonaţi doi câte doi astfel încât cel din față e me-
reu mai scund decât cel din spate. Nu aveam scări ca dacă aveam scări nu mai treceam prin
toate astea.

Apoi Katy mi-a zis ca aşa cum am văzut că ne-am poziţionat la poza aşa să învăţ şi compute-
rul să aranjeze un şir de valori în ordine crescătoare şi că pot să mă gândesc că aceste valori
sunt înălţimile noastre.

Aşa că am luat un vector de 5 numere întregi şi am pus nişte numere în el.

int vector[5] = {1,7,12,9,3};

Apoi am definit fotograful care se uită şi vede dacă mai e vreunul înalt în faţa unuia mai
scund.

bool este_sortat = true;

De fiecare dată când fotograful a văzut că mai e cineva poziţionat anapoda astfel încât să ob-
tureze vederea altuia ne-a pus să ne mai schimbăm între noi

do
{

Iniţial fotograful când arunca o privire spre noi era optimist că se vedea după zâmbet şi cre-
dea că în sfârşit o să poată să facă poza şi că nu mai e nimeni pus greşit.

© Bitulică 2020
Povestea lui Bitulică

este_sortat = true;

Apoi ne lua la rând

for (int i = 0; i < 4; i++)

dacă vedea că cel de jos e mai înalt decât cel de sus

if (vector[i] > vector[i + 1])


{

Ne punea să ne schimbăm între noi dar ca să ne schimbăm trebuia să treacă unul în lateral
iar celalat să se pună pe poziţia lui şi apoi cel din lateral să treacă pe poziţia celuilalt că doar
nu ne încălecam pe acolo.

int unealta = vector[i];


vector[i] = vector[i + 1];
vector[i + 1] = unealtă;

Dacă am făceam asta fotograful ştia că nu suntem aranjaţi şi că trebuie să se mai uite cel
puţin o dată peste toţi să vadă dacă suntem puşi bine.

este_sortat = false;
}

Făcea asta cât timp mai exista cineva mai înalt pus în faţa unuia mai scund.

} while (!este_sortat);

Când toţi am fost aranjaţi corespunzător astfel încât cel mai înalt să fie în spatele celui mai
scund fotograful a făcut poza.

for (int i = 0; i < 5; i++)


cout << vector[i] << " ";

Am înţeles că de fiecare dată când trebuie să verific o stare a unui ansamblu de elemente
îmi trebuie o variabilă care să îmi spună starea şi care să se seteze intr-un fel sau altul în
urma analizei de stare.

Şi am mai citit că de fiecare dată când am de interschimbat două valori am nevoie de o vari-
abila temporară ca şi cum aş schimba apa din două găleţi când am nevoie de o a treia gă-
leată pentru că altfel nu am cum.

Pentru numere există şi o metodă de interschimbare fără variabilă intermediară şi este va-
labilă doar pentru numere.
a = a+b
b = a-b
a = a-b

© Bitulică 2020
Povestea lui Bitulică

Când am făcut probleme de eficiență


ALG
Am descoperit metoda greedy

Când ne-am mutat din România în Statele Unite, a trebuit să luăm fiecare cu noi lucruri per-
sonale. Nu am luat mobila sau chestii de astea pentru că aici am primit din partea firmei o
casă complet mobilată şi utilată.

Am avut inclus în pachetul de relocare şi biletul de avion care includea şi un anumit număr
de kilograme de bagaje. Nu mai ştiu câte.

Am împărţit numărul de kilograme la 4 adică eu, Lisa, Katy şi Evy şi am început să ne facem
fiecare bagajul. Doar noi am plecat prima dată apoi au venit și părinții.

După ce mi-am făcut un troler plin care avea fix atâtea kilograme cât aveam voie să iau mi-
au mai rămas nişte lucruri de care nu voiam să mă despart aşa că am mai făcut un rucsac
dar de data asta am încercat să bag în el cât mai multe lucruri în aceeaşi greutate. Că se plă-
teau kilogramele în plus nu numărul de lucruri.

Peste timp când i-am zis lui Katy să îmi explice şi mie cum e cu metoda Greedy m-a pus să
îmi amintesc cum am făcut să îmi pun atunci lucrurile în rucsac astfel încât să iau cât mai
multe lucruri în acelaşi număr de kilograme.

I-am spus că e simplu şi că le-am cântărit apoi le-am aşezat pe pat de la stânga la dreapta în
ordinea crescătoare a greutăţii lor. Apoi le-am băgat pe rând în rucsac de la cel mai uşor la
cel mai greu cântărind mereu rucsacul să văd dacă depăşeşte greutatea maximă pentru care
vreau să plătesc în plus.

Katy mi-a zis că fix aşa trebuie să învăţ şi computerul să gandesca şi că dacă gândeşte aşa se
cheamă că rezolva acestă problemă folosind metoda Greedy.

După ce am vorbit cu Katy m-am apucat să învăţ computerul să gândească ca mine.

Am definit un vector cu greutăţile obiectelor

int obiecte[5] = {1,7,12,9,3};

Am definit greutatea maximă

int greutate_maximă = 10;

Am definit instrumentul care îmi va spune când obiectele vor fi sortate

bool este_sortat = true;

© Bitulică 2020
Povestea lui Bitulică

Am declarat rucsacul dar nu l-am şi iniţializat adică nu l-am definit pentru că am vrut să văd
dacă e adevărat că compilatorul îl iniţializează cu ce vrea el.

int rucsac[5];

Am creat o buclă din care va ieşi doar când obiectele sunt sortate

do
{

i-am zis să plece de la ideea optimistă că nu va mai găsi nici un obiect nesortat

este_sortat = true;

Am luat obiectele la rând

for (int i = 0; i < 4; i++)

I-am spus că dacă mai găseşte vreunul mai greu pus în faţa unuia mai uşor

if (obiecte[i] > obiecte[i + 1])


{

Să le interschimbe punând unul jos apoi celalat în locul primul pe pat şi cel de jos în locul
unde era pe pat cel de-al doilea iar dacă a făcut asta să îi fie clar că va mai trebui să verifice
o dată dacă sunt sortate.

int unealta = obiecte[i];


obiecte[i] = obiecte[i + 1];
obiecte[i + 1] = unealtă;
este_sortat = false;
}

I-am zis că ce a făcut până acum să facă cât timp a găsit că ceva este nesortat

} while (!este_sortat);

Apoi i-am zis să ia obiectele sortate la rând

for (int i = 0; i < 5; i++)

Şi dacă greutatea rucsacului nu a depăşit cât vrea el să fie

if (greutate_maximă > obiecte[i])


{

Să bage obiectele în rucsac

© Bitulică 2020
Povestea lui Bitulică

rucsac[i] = obiecte[i];

Şi să ţină minte ce greutate mai poate băga

greutate_maximă -= rucsac[i];
}

Iar când nu mai poate băga nici un obiect căci ar depăşi greutatea pe care vrea să o aibă ruc-
sacul

Else

Să nu mai bage

break;

În final m-am uitat în rucsac. Ar mai fi fost locuri libere ca volum dar ce mai aveam de băgat
era prea greu şi nu am mai băgat.

for (int i = 0; i < 5; i++)


cout << rucsac[i] << " ";

Am întrebat-o pe Katy dacă doar problema asta se poate rezolva cu aceea metoda şi mi-a
spus că nu. A zis că oricând fac un algoritm în care ceva trebuie să respecte un anumit nu-
măr de condiţii ca să fie adăugat undeva de fiecare dată folosesc metoda Greedy.

Greedy înseamnă lacom. Adică vrea să ia cât mai multe cu bani puțini.

© Bitulică 2020
Povestea lui Bitulică

Când am căutat toate soluțiile posibile


ALG
Am descoperit metoda backtracking

Când am ajuns prima dată în America după ce am ajuns în casa pusă la dispoziţie de compa-
nie a trebuit să ne desfacem bagajele şi să ne instalăm.

Eu aveam un rucsac şi un troler iar trolerul meu este din acela cu cifru. Şi îl uitasem.

Cum nimeni nu îl mai ştia a trebuit să mă descurc şi să îl ghicesc că nu voiam să tai trolerul.

Norocul meu a fost că trolerul avea un cifru format din doar trei cifre iar rotiţele acelea pe
care le învârteam ca să potrivesc cifrele aveau doar 3 cifre pe ele. Adică aveam de aflat un
număr din 6 posibile şi le-am luat la rând. Ce era să fac?

Mi-am amintit întâmplarea asta când Katy mi-a explicat metoda Backtraking într-una din
sălile de relaxare a companiei Riverbites la care lucrăm şi m-a pus să învăţ calculatorul să
facă şi el cum am făcut eu.

I-am zis să declare un şir de maxim 10 numere pe care l-am numit cifru. Apoi i-am zis că nu-
mărul maxim de numere din care să găsească toate soluţiile posibile pentru cifru să fie 3
adică exact ca la mine la troler.

Am pus şi o variabilă care să îmi spună câte soluţii posibile a găsit computerul.

int cifru[10], numere=3, număr_de_soluţii = 0;

Ca să afişez fiecare soluţie găsită de el să o văd şi eu am făcut o funcţie care se numeşte cum
altfel decât Afişare în care afişez fiecare element potrivit în prealabil în cifru luând căsuţele
cifrului la rând.

Am pus în funcţia asta ca după ce afişează soluţia să incrementeze şi numărul de soluţii gă-
site că dacă o afişează înseamnă că a găsit o soluţie

void Afişare()
{
int i;
for (i = 1; i <= numere; i++)
cout << cifru[i] << " ";
cout << endl;
număr_de_soluţii++;
}

Ca să văd dacă atunci când învârt de rotita cifrului şi este o cifră sus ea este şi bună de pus
în combinaţia pe care o construiesc am făcut o funcţie pe care am numit-o Valid adică să îmi

© Bitulică 2020
Povestea lui Bitulică

returneze 1 dacă numărul este validat ca să îl pun în soluţia pe care o construiesc şi 0 dacă
nu e bun de pus în soluţie.

Pun un număr în soluţie doar dacă el nu a mai fost pus niciodată în aceeaşi combinaţie în
cifru. Că nu are rost să încerc două combinaţii la fel că e clar că dacă una e bună e şi cealaltă
sau dacă una nu e bună nu e bună nici cealată.

int Valid(int k)
{
int i;
for (i = 1; i <= k - 1; i++)
if (cifru[k] == cifru[i]) return 0;
return 1;
}

Când am stabilit şi când e valid un element şi când o soluţie e completă m-am apucat să în-
vârt de rotiţele alea până am făcut basici la degete. Noroc că sunt numere puţine.

Am luat numerele de la primul la ultimul şi le-am adăugat în cifru. Dacă numărul era valid şi
ajunsesem la final adică de exemplu dacă îl puneam pe 3 din 3 numere şi le pusesem şi pe
celelalte atunci ziceam că am o soluţie posibilă.

Posibil nu înseamnă că şi merge dar eu le încercam pe toate.

Dacă era valid dar nu ajunsesem la numărul de cifre pe care le permite cifrul atunci mai bă-
gam una şi încă una până îi dădeam de cap.

Katy mi-a zis că aşa cum am făcut eu se numeşte recursiv. Adică cică metoda asta este me-
toda Backtraking dar implementată recursiv pentru că făceam acelaşi lucru dar cu alte date.

Adică se procedează la fel dar la un alt nivel cum zice BUG Mafia.

void Backtracking(int k)
{
int i;
for (i = 1; i <= numere; i++)
{
cifru[k] = i;
if (Valid(k))
if (k == numere)
Afişare();
else
Backtracking(k + 1);
}
}

În programul principal am apelat funcţia recursivă începând cu 1 că 1 era prima cifră de pe


rotiţele cifrului. Am pus să afişeze şi numărul de soluţii ca să văd cât am muncit.

© Bitulică 2020
Povestea lui Bitulică

int main()
{
Backtracking(1);
cout << endl << "Număr soluţii: " << număr_de_soluţii;
return 0;
}

Katy zice că de fiecare dată când trebuie să aflu toate soluţiile posibile al o problemă să folo-
sesc metoda asta dar doar dacă nu găsesc alta mai rapidă că cică e o metodă lentă dar une-
ori nu există altă mai rapidă.

Backtraking înseamnă retrogradare și metodei îi zice așa că atunci când i se înfundă drumul
o ia înapoi pe nivele până ajunge într-unul de unde poate merge din nou înainte.

De exemplu dacă merg cu masina dintr-un oraș în altul si greșesc drumul sau se înfundă o
iau înapoi până pot să merg iar înainte.

Această metoda am înțeles că se foloște și la determinarea tuturor posibilităților de a


ajunge dintr-un punct în altul și deci e folosită de aplicațiile GPS.

© Bitulică 2020
Povestea lui Bitulică

Când am căutat acum în carul cu fân


ALG
Am descoperit metoda divide et impera

Când a fost ziua mea Katy a vrut să prindă doi iepuri dintr-o lovitură și m-a dus la un maga-
zin de pantofi să îmi facă un cadou.

Pantofii erau aranjați frumos pe standuri dar și pe mărimi. La stanga erau cei de copii și la
dreapta cei de baschetbalisti.

M-a pus să îmi aleg unii apoi să caut mărimea. Numerele nu erau la vedere așa că trebuia să
scot pantofii din cutie și să mă uit pe talpă să văd ce mărime sunt și să compar cu cât port
eu.

Nu i-am luat la rând că ar fi durat prea mult așa că încercam să nimeresc mijlocul intervalul
care mai rămânea să văd dacă am noroc. Adică dacă nimeream numărul 34 și eu purtam 43
mă duceam în dreapta cam pe la mijloc să văd dacă acolo e ce caut.

Am găsit pînă la urmă, i-am probat i-am luat iar Katy m-a întrebat dacă acum știu cum să
implementez folosind metoda divide et impera.

Am stat și m-am gândit și se pare că fix cum am căutat eu mărimea pantofilor așa trebuie
să-l învăț și pe computer să caute o valoare dacă vreau să folosesc metoda asta care în cazul
ăsta se mai numește și căutare binară.

Ei, și uite așa Katy a prins doi iepuri. Mi-a luat și pantofi noi și m-a ajutat să îmi și explic
cum pot folosi metoda pe care o foloseau romanii. Divide et impera e în latină și înseamnă
împarte și stăpânește.

Am încercat să implementez și să împart o problema mai mare în probleme mai mici pe


care să le rezolv pe rând și astfel prin rezolvarea lor să rezolv problema mare.
Am definit un vector cu valorile ordonate crescător căci dacă nu sunt ordonate crescător nu
pot aplica pe el căutarea binară.

Am mai declarat și o variabilă în care voi pune valoarea căutată.


int v[7] = {1,2,3,4,5,6,7}, valoare_cautata;

Apoi am definit funcția care caută efectiv în șir și care se apelează recursiv și returnează
dacă am găsit valoarea căutată sau nu.

void caut(int inferior, int superior)


{

Mă poziționez pe mijlocul intervalului dat ca parametru de intrare în funcție

© Bitulică 2020
Povestea lui Bitulică

int jumatate = (inferior + superior) / 2;

Dacă valoarea căutată este valoarea de la mijlocul intervalului

if (valoare_cautata == v[jumatate])

Returnez că am găsit

cout << "gasit, indice = " << jumatate;

Altfel

Else

Dacă valoarea din mijloc nu este valoarea căutată atunci mă întreb dacă limita inferioară a
intervalului este mai mică decât cea superioară că dacă nu este înseamnă că nu mai am un
interval valid

if (inferior < superior)

Dacă am un interval valid și valoarea căutată este mai mică decăt cea din mijlocul intervalu-
lui

if (valoare_cautata < v[jumatate])

Mă duc să caut în jumătatea inferioară a intervalului

caut(inferior, jumatate - 1);

Dacă nu mă duc să caut să caut în jumătatea superioară a intervalului

else caut(jumatate + 1, superior);

Dacă nu mai am un interval valid și nici nu am găsit valoarea căutată înseamnă că ea nu


există în sir

else cout << "nu a fost gasit.";


}

În metoda principală

int main()
{

Setez valoarea căutată

valoare_cautata = 1;

© Bitulică 2020
Povestea lui Bitulică

Și caut valoarea inițial în tot intervalul

caut(0, 6);

return 0;
}

Am înțeles că această metoda se poate aplica și atunci când am două procesoare sau mai
multe și programez în paralel.

Un subprocess care se execută pe un procesor caută într-un interval, alt subproces care ru-
lează pe alt procesor în alt interval iar la final pot să văd dacă au găsit ceva. Subprocesele
căutând în paralel timpul de execuție se reduce și astfel programul se execută mai rapid.

© Bitulică 2020
Povestea lui Bitulică

Când m-am întrebat ce și cum


ALG
Am descoperit antrenamentul

Am învăţat noţiuni metode concepte dar toate ca toate când e să rezolv o problemă cum
fac? Asta am întrebat-o pe Katy şi mi-a zis că nu îmi poate arăta nimeni cum să fac decât
dacă mă ajută să rezolv fiecare problemă căci problemele se schimbă.
Mi-a zis că tot ce mă poate învăţa cineva este la ce să mă gândesc.
Acum mă întreb şi eu. Ăla care s-a gândit prima dată de unde a ştiut la ce să se gândească?
Cred că s-a gândit la tot pănă a aflat la ce trebuia. Mă gândesc că dacă știu bine cum
funcționează un PC îmi vin mai repede ideile.
Mi-a zis Katy că de exemplu dacă am nişte valori cu care lucrez fac un vector şi le pun în el
apoi le parcurg şi fac ceva cu ele. Dar ce fac? Păi depinde ce trebuie să rezolv.
Dar cică întotdeauna trebuie să mă gândesc cum aş face eu ca om şi să transpun situaţiile în
realitate ca să le rezolv cel puţin până capăt experinta şi reuşesc să le rezolv şi fără să le mai
transpun.
Am făcut cu Katy o problemă de pe https://www.codingame.com/home
Adică asta https://www.codingame.com/training/easy/temperatures
Problema zice să aflu care este cea mai apropiată temperatură de zero grade din nişte
temperaturi care îmi sunt date şi ale căror valori nu pot depăşi nişte limite. Temperaturile
sunt şi cu plus şi cu minus adică şi pozitive şi negative şi o temperatură de 1 grad este la fel
de depărtată de 0 ca şi cea de -1 grad. Problema zice că dacă sunt două la fel de apropiate să
o aleg pe cea pozitivă.
Katy mi-a mai zis că sunt şi alte platforme de unde pot să exersez cum ar fi
https://www.testdome.com/ sau https://try.codility.com/
sau
https://www.geeksforgeeks.org/...
unde pot găsi probleme date la interviuri de firme ca Google, Microsoft sau Facebook.
Am rezolvat problema cu Katy am scris comentarii pe cod şi a ieşit cam aşa
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

© Bitulică 2020
Povestea lui Bitulică

using namespace std;


/*
Esenţa problemei indiferent de povestea în care este învăluită este calculul abaterii minime
E ca şi cum aş merge pe o stradă beat şi dau din sunt în şanţ şi când mă uit pe urmele lăsate
vreau să văd în ce punct am ţinut cel mai bine drumul drept.
Trebuie să indic şi direcţia în care am deviat cel mai mult dar dacă am deviat la fel de puţin
în două direcţii spun valoarea deviaţiei în modul
*/
// funcţia main adică programul principal
int main()
{
// va reţine numărul de termeperaturi de analizat
int n;
// se introduce numărul de termepraturi
cin >> n; cin.ignore();
// minimul trebuie să fie iniţial cel mai mare posibil adică prima temperatură cu +
nepermisa
int min = 5526;
// rezultatul afişat
int result = 0;
// parcurg temperaturile
for (int i = 0; i < n; i++) {
// va reţine fiecare temperatură introdusă
int t;
// se introduce fiecare temperatură
cin >> t; cin.ignore();
// dacă temperatura introdusă nu este din plaja acceptată
if (t<=-273 && t>=5526)
// resultatul afişat va fi zero
result = 0;

© Bitulică 2020
Povestea lui Bitulică

// dacă valoarea absolută adică în modul adică fără semn a temperaturii este mai mică ca
mininul găsit până acum
else if (abs(t)<min)
{
// minimul devine acea valoare în modul găsită ca fiind mai mică de cât toate parcurse
de până acum
min = abs(t);
// rezultatul va fi valoarea reală a temperaturii adică chiar şi cu minus
result = t;
}
// dacă am o valoare egală în modul cu minimul de până acum
else if (abs(t)==min)
{
// rezultatul afişat va fi valoarea pozitivă a temperaturii pentru a prinde cazul când una e
cu - şi alta e cu plus dar în modul sunt egale
result = abs(t);
}
}
// se afişează rezultatul
cout << result << endl;
}
Cred că m-am descurcat bine și o să mai fac probleme de pe platformele online ca să
exersez. Caci am înțeles că repetiția e mama învățării.
Katy a zis ca e bine să scriu mereu comentarii pe cod ca să îl înțeleg și eu și alții și a mai zis
că un comentariu e o explicație și că știu că am înțeles abia atunci când pot explica.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie de o varibilă globală


ALG
Am descoperit elementele statice

Un lucru este static dacă el nu se mişca ci sta locului. Catalogarea unui lucru ca imobil tine
de perioada de timp pe care se face analiza acelui lucru.
De exemplu o maşină poate sta în parcare de seară până dimineaţa şi pe perioada asta ea
este statică dar ziua se deplasează şi atunci pe o perioadă de 24 de ore ea nu mai poate fi
catalogată ca fiind statică.
Din punct de vedere fizic un lucru este static sau nu în funcţie de sistemul de referinţă din
care este privit. De exemplu stelele lui Copernic sunt stele fixe şi orice obiect privit prin
prisma lor se mişcă.
Adică sistemul format de aceste stele este un sistem de referinţă neinerţial adică cel în care
nu este valabil principiul inerţiei pe când toate celelalte sisteme sunt sisteme inerţiale.
În sistemele inerţiale un obiect poate fi static văzut din interiorul sistemului dar mobil
văzut din afara sistemului.
Un obiect care se mişca este considerat un obiect dinamic.
Dinamicitate înseamnă mişcare având şi sensul mai larg de a nu fi stabil. Ca de exemplu
când apare şi dispare.
Acest sens larg a fost preluat de tehnologia informaţiei pentru elementele care sunt create
şi distruse.
Toate elementele unui program sunt create şi distruse la un moment dat, Se nasc cel mai
devreme la începutul programului şi dispar cel mai târziu la terminarea lui.
Sistemul de referinţă neinerţial în cazul programului este însuşi scopul programului adică
perioada dintre momentul lansării în execuţie şi momentul finalizării execuţiei ceea ce
înseamnă că variabilele care au durata de viaţă egală cu a programului sunt considerate
variabile statice în timp ce cele care apar şi dispar pe parcursul programului sunt
considerate variabile dinamice sau de scop. Cu sensul că scopul lor de viaţă e mai mic decât
cel al programului.
Variabilele care au ca scop întregul program se mai numesc şi variabile globale pentru că
ele sunt văzute de toate subrutinele.
Deci accesul la ele este permis de oriunde din program.
Elementele definite local în funcţii sau în blocuri delimitate de acolade sau de cuvinte cheie
corespunzătoare cum ar fi begin şi end în Pascal sau SQL sunt considerate elemente
dinamice pentru că se crează la executia subrutinei sau a blocului şi dispar la terminarea
blocului sau a subrutinei.

© Bitulică 2020
Povestea lui Bitulică

Variabilele fie că sunt globale sau locale se definesc la fel.


int a = 0;
Şi am înţeles că dacă vreau ca o variabilă definită local să devină globală trebuie să îi
specific compilatorului că vreau să fie statică punând cuvântul cheie static în fata definiţiei.
static int a = 0;
La întâlnirea acestui cuvânt cheie compilatorul ştie că la finalul rutinei sau blocului nu
trebuie să mai dezaloce variabila ci să o lase să aibă durata de viaţa cât tine programul.
Dar o variabilă globală şi una statică sunt două variabile globale şi atunci m-am întrebat
care este diferenţa între a fi global şi a fi static global.
Am aflat că static se referă şi la a nu putea fugi spre alte module.
Adică o variabilă statică este legată de modulul în care este definită şi nu poate fi utilizată
într-un modul extern în care este inclus modulul în care este definită.
O variabilă globală care nu este declarată ca statică într-un modul poate fi accesată din alt
modul care îl include pe acesta folosind cuvântul cheie extern
extern int a = 0;
iar modul poate fi inclus cu directiva preprocesor #include

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie organizare


OOP
Am descoperit modelul OOP

Pe lângă tipurile de date primitive , limbajele de programare permit programatorilor să își


definească propriile tipuri de date.
Unele din aceste tipuri de date definite de utilizator în limbajele care permit programarea
orientata obiect adică OOP se numesc CLASE.
Clasele sunt urmaşele tipului STRUCT adică structura, care este tot un tip de dată definit de
utilizator şi poate cuprinde mai multe date de tip primitiv organizate sub formă de
structură.
Un tip structura în C/C++ arată astfel
struct exemplu
{
int a;
char ch;
};
Clasele se deosebesc de structuri prin faptul că permit definirea de metode în interiorul lor
iar o variabilă de tip clasă este un pointer fără partea de derefernțiere către adresa din RAM
unde este stocată variabila şi se numește obiect.
Pot să mă gândesc că o clasă este ca un cerc desenat pe o hârtie iar un obiect este un inel
creat după modelul acelui cerc. Clasa este modelul adică ceva abstract pe care nu pot pune
mâna iar obiectul este concretizarea lui într-un obiect palpabil. Adică pe care îl pot simți
prin pipăit. Pot pune mâna pe el.
Pentru a defini o clasă se folosește cuvântul cheie CLASS care este urmat de numele clasei şi
de corpul clasei inclus între acolade.
În corpul clasei se pot defini date care se numesc atribute şi funcții care se numesc metode.
class A
{
};
Pentru a crea o variabilă care să aibă ca tip o clasă se respectă regula de la datele primitive
doar că se numește INSTANŢIERE.
Pot spune deci că un OBIECT este INSTANŢA unui CLASE.

© Bitulică 2020
Povestea lui Bitulică

O instanță a unui obiect este creată de o metodă specială a clasei care se numește
CONSTRUCTOR și care construiește obiectul, alocând memorie pentru el , şi iniţializează
atributele sale cu valorile implicite sau alese de programator. Un constructor returnează un
obiect și nimic alceva.
Dacă constructorul lipsește compilatorul creează automat un constructor implicit care aloca
memorie şi iniţializează atributele cu valorile implicite.
Pentru a instanția o clasă se poate folosi cuvântul cheie new așa cum fac și când creez un
pointer dacă vreau să creez un pointer către un obiect.
class A{}
A a = new A();
sau
A a = A();
class A este declarația clasei
{} este corpul clasei sau implementarea
operatorul NEW specifică că s-a creat un pointer către o nouă instanța a clasei și returnează
adresa către ea.
A() este constructorul clasei care va aloca memorie şi v-a inițializa atributele cu valorile
implicite ale tipurilor lor.
În C++ structura claselor se defineste în fișierele cu extensia .h adică fișierele header iar
implementarea ei se scrie în fișierele cu extensia .cpp.
Daca vreau sa definesc clasa Animal cu atributul nume si metoda merge avand ca
parametru de intrare numărul de picioare atunci creez fișierul
animal.h
în care scriu
#pragma once
#include <iostream>
using namespace std;
class Animal
{
public:
Animal(const char*);
char* nume;

© Bitulică 2020
Povestea lui Bitulică

void merge(int);
~Animal();
};
iar daca vreau să implementez clasa Animal creez fișierul
animal.cpp
În care scriu
#pragma warning(disable:4996)
#include "animal.h"
Animal::Animal(const char* nume)
{
int size = strlen(nume)+1;
this->nume = new char[size];
strcpy(this->nume,nume);
this->nume[strlen(this->nume)] = '\0';
}
void Animal::merge(int numar_de_picioare)
{
cout << this->nume << " merge in " << numar_de_picioare << " picioare";
}
Animal::~Animal()
{
delete[] this->nume;
}
Daca Animal() este constructorul clasei care aloca memorie pentru atributul this->nume
atunci ~Animal() este destructorul clasei care dezaloca memoria alocata pentru atributul
this->nume atunci cand obiectul este distrus.
Atunci cand vreau sa distrug o cutie logic este să distrug întâi fiecare obiect din încăpere
apoi încăperea însăși.
delete se foloște cand se distruge o variabilă primitivă iar delete[] când se distruge un
vector. În cazul meu nume este un sir de caractere deci un vector.

© Bitulică 2020
Povestea lui Bitulică

This este un self pointer și referă către fiecărei instanțe a clasei pornind din interiorul ei. O
expresie de tipul this.nume unde numes este atribut al clasei e ca și cum eu m-aș referi la
gura mea sau la nasul meu sau la mana mea sau la piciorul meu.
#pragma este directiva de precompilare care ii da compilatorului niște informații înainte să
înceapă compilarea. În cazul meu #pragma warning(disable:4996) îi spune compilatorului
să nu mai tină cont de faptul că unele funcții sunt vechi față de versiunea curentă a
compilatorului C++ și am folosit-o pentru funcția strcpy. El ar fi vrut să folosesc strcpy_s dar
nu am vrut. #progma once îi spune compilatorului ca sursa curentă să fie inclusă doar o
singură dată într-o compilare. Adică să nu se creeze dependinte circulare. A include pe B si
B pe A este o dependință circulară care face ca A și B să fie incluse de două ori într-o singura
compilare.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie de intimitate


OOP
Am aflat modificatorii de acces

Modelul OOP încearcă să creeze modelul virtual al lumii reale unde clasele sunt entitățile
iar obiectele sunt concretizarea lor.

Un obiect poate fi privit ca un bulgare de plastilină care poate fi modelată în fel și chip și
deci poate lua diferite forme. Poate fi un iepuraș o căsuță sau o mașinuță.
Un obiect orice formă ar lua are niște atribute ale căror valori dau proprietățile obiectului
iar totalitatea proprietăților dau stare obiectului. Atributele pot fi privite ca suport pentru
proprietăți.

De exemplu o casă are atributele lungime lățime și înălțime. Dacă aceste valori sunt mari
pot spune că casa este mare. Deci totalitatea valorilor atributelor adică proprietățile unui
obiect creionează caracterizarea obiectului adică starea lui. Dacă unul din atributele unui
om este avuția atunci valoarea ei da starea omului. De exemplu bunăstarea.
Atributele unei clase sunt variabile declarate în interiorul unei clase , în afara corpului me-
todelor.

Aceste variabile pot avea că tip atât tipurile primitive cât și clase , atât dintre cele definite
deja în librării cât și cele definite de utilizator în program.
O clasă poate moșteni o alta clasă. Asta înseamnă că un obiect care este instanța unei clase
poate mosteni un alt obiect.

A moșteni ceva înseamnă a dobândi lucruri care îi aparțin. În cazul claselor lucrurile care le
aparțin sunt atribute sau metode.

class A : public B
{
};

Pentru a controla modul în care atributele sunt moștenite a fost nevoie de crearea unor
atribute ale atributelor cu rol în stabilirea accesului la ele numite MODIFICATORI DE AC-
CES.

Modificatorii de acces sunt cuvinte cheie care preced definiția sau declarația atributului.

Modificatorul private

Privat înseamnă personal care nu este disponibil decât persoanei de care aparține.

class A
{
private:

© Bitulică 2020
Povestea lui Bitulică

int a = 0;
};

Variabila a va putea fi accesată doar în interiorul clasei A , fiind un atribut privat al clasei.

Modificatorul protected

Protected înseamnă protejat. Noi oamenii suntem protejați de către apropiații noștri. Cei
mai apropiați de noi sunt familia. Familia unui individ înseamnă ramura de descendență a
arborelui genealogic începând de la el. Acest aspect a fost preluat și în OOP și implementat
prin modificatorul protected

class A
{
protected:
int a = 0;
};

Variabila a va putea fi accesată în clasa A și în toate subclasele adică clasele care descind din
A. Este protejată sa nu poată fi accesată din exteriorul descendenților clasei A.

Modificatorul public

Public înseamnă că este accesibil de către toată lumea. Este ca o informație făcută publică.
class A
{
public:
int a = 0;
};

Variabilă a va putea fi accesată din orice clasă, fiind atribut public

Dacă nu este specificat un modificator de acces compilatorul va considera că variabila are


modificatorul de acces private şi variabila va putea fi accesată doar din interiorul clasei A.

În momentul în care se crează o instanță a clasei adică un obiect atributele se clonează şi se


crează câte un set de atribute pentru fiecare obiect născut.

Aceste atribute se numesc ATRIBUTE DE INSTANŢĂ.

Atributele de instanța își pierd proprietățile adică valorile atunci când instanța moare.

Dacă se dorește ca un atribut să nu fie clonat şi să își păstreze valoarea oricare instanțe s-ar
naște și ar murii atunci va trebui să fie precedat de cuvântul cheie STATIC.

Aceste atribute se numesc ATRIBUTE STATICE.

© Bitulică 2020
Povestea lui Bitulică

class A
{
public:
static int a = 0;
};

Pentru a accesa un atribut de instanța al unui clase trebuie mai întâi să creez obiectul şi
abia apoi pot accesa atributul.

A obj = A();
obj.a = 5;

Obiectul nu e pointer și prin urmare operatorul de apartenență este . adică punct. La poin-
teri este -> adică săgeată semn că punctează către ceva adică arată sau direcționează către
ceva.

Operatorii . și -> sunt operatori de apartenență și stabilesc o relație de subordonare.


obj.a înseamnă a al lui obj. Cum ar fi Ana,Maria adică Maria a Anei.

Atributele statice aparțin clasei în timp ce cele de instanță aparțin obiectului. Care este in-
stanța unei clase.

Prin urmare pentru a accesa un atribut static al unei clase nu am nevoie de o instanță a cla-
sei.

A::a = 5;

Operatorul :: este operatorul de rezoluție și stabilește tot o relație de apartenență. De data


această este o apartenență la model și deci nu se poate spune că este o relație de subordo-
nare că este o relație între ceva abstract și ceva concret.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie mostenire


OOP
Am aflat supraîncarcarea și suprascrierea

Dacă totalitatea proprietăţile unui obiect îi dau starea, totalitatea metodelor unui obiect dau
comportamentul obiectului.

O metodă este o funcţie sau o procedură şi este modalitatea obiectului de a face ceva.
Diferenţa dintre o funcţie şi o metodă este doar conceptuală şi constă în faptul că o metodă
aparţine cuiva. Este metoda acelui cineva de a face un lucru.

Metodele au și ele ca şi obiectele modificatori de acces care le stabilesc vizibilitatea.


Aceștia sunt : private, protected și public şi au același efect ca şi la atribute.
O metodă returnează o valoare care are un anumit tip de dată.

Pentru a nu returna nici o valoare tipul de data returnat de metoda trebuie să fie void.
O metodă poate avea parametrii de intrare , care sunt variabile având un anumit tip de dată
sau poate să nu aibă nici un parametru.

Dacă are parametrii de intrare şi parametrul de ieșire ea prin excelenţă este o funcție pen-
tru că transformă niște valori în altele la fel cum funcțiile din matematica transformă valo-
rile din domeniu de definiție în cele din domeniu de valori

double sinus(double x);

Dacă nu are parametrii de intrare și nici de ieșire ea este prin excelenţă o procedură pentru
că realizează un proces.

void scrie();

Spunem că o metodă este DECLARATĂ dacă în clasă respectivă există doar semnătura me-
todei.

double sinus (double);

Pot fi doar declarate numai metodele abstracte , adică metodele virtuale , adică acele me-
tode care , pot fi implementate sau nu , după dorința sau necesitate, în clasele descendente.

O metodă este DEFINITĂ dacă i se specifică şi semnătura și corpul.

© Bitulică 2020
Povestea lui Bitulică

void scrie()
{
cout << ("Test");
}

Metodele unei clase , ca şi atributele, pot fi moștenite de clasele care descind din clasă în
care sunt definite.

Dacă într-o clasă descendentă din class în care este definită, o metodă are același nume ,
același tip returnat, şi aceeași parametrii şi ca tip și număr, atunci metoda din clasa descen-
dentă o SUPRASCRIE pe cea din clasa din care descinde

class A
{
public:
int suma(int a, int b)
{
return a+b;
}
}
class B : public A
{
int suma(int a, int b)
{
int s = a+b;
return s;
}
}

Dacă într-o clasă descendentă din clasă în care este definită, o metodă are același nume , dar
nu are același tip returnat, sau/și nu are aceeași parametrii şi că tip și număr, atunci me-
toda din clasa descendentă o SUPRAÎNCARCA pe cea din clasa din care descinde

class A
{
int suma(int a, int b)
{
return a+b;
}
}
class B : public A
{
int suma(int a, int b, int c)
{
int s = a+b+c;
return s;
}
}

© Bitulică 2020
Povestea lui Bitulică

Obiectul clasei descendente va avea două metode cu același nume dar semnături diferite.

B b = new B();

b.suma(5,7);
b.suma(5,6,7);

Constructorul unei clase nu poate fi moștenit. Pentru că clasa copil nu are ce face cu el fi-
indcă el știe DOAR să construiască clasa părinte. Prin urmare un constructor nu poate fi su-
prascris căci suprascrierea are rost doar la metodele moștenite dar poate si supraîncărcat
în clasa lui. Adică clasa lui să aibă două forme de constructor. De exemplu unul fără parame-
trii și unul cu parametri.

Am încercat să fac un mic exemplu ca să înțeleg și în fișierul header am scris

class A
{
public:
void afiseaza();
long calculeaza(int,int);
};
class B : public A
{
public:
void afiseaza(char*);
long calculeaza(int,int);
};

iar în fișierul unde am implementat clasele adică în cel cu extensia .cpp am scris

void A::afiseaza()
{
cout << "text" << endl;
}
long A::calculeaza(int a, int b)
{
return a + b;
}
void B::afiseaza(char* text)
{
cout << text << endl;
}
long B::calculeaza(int a, int b)
{
return a - b;
}

© Bitulică 2020
Povestea lui Bitulică

Am înțeles că suprascriu o metodă atunci când obiectul care o moștenește nu are ce să facă
cu ea așa cum e. De exemplu dacă cineva moștenește o casă care nu îi place o fărâmă și își
face alta.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie să lucrez generic


OOP
Am descoperit tipurile template

M-a pus Katy să scriu un program care calculează suma a două numere şi a zis că să am grijă
că numerele nu sunt numai naturale.

Sunt şi întregi cu semn sunt şi raţionale sau iraţionale adică de alea cu virgulă şi că să fac
ceva care să meargă pentru toate.

Eu m-am gândit că aş putea face o metodă care să calculeze suma a două numere naturale şi
că aş putea să o suprancarc să calculeze şi suma pentru celelalte tipuri de numere.
Adică să am o metodă pentru numerele naturale una pentru cele întregi una pentru cele
raţionale şi una pentru cele iraţionale.

Katy a zis că aşa cum vreau eu să fac muncesc prea mult şi că aş putea să fac una pentru nu-
merele întregi care să acopere şi numerele naturale că fac parte din aceeaşi mulţime şi să
mai fac una pentru numerele reale căci şi numerele raţionale şi cele iraţionale sunt tot nu-
mere reale adică de alea care pot avea zecimale. De alea cu virgulă.

Când mă apucam să fac Katy m-a tras de mânecă şi mi-a zis că dacă îi spun unde am ascuns
clătitele îmi spune un secret care îmi va uşura munca.

I-am spus că oricum mâncasem destule dar le-am ascuns că zicea să nu le mai vadă că în-
cearcă să ţină o cură de slăbire. Mie nu mi se pare că ar avea nevoie dar eu ştiu ce modă mai
e acum?

Mi-a spus că pentru a nu mai scrie o grămadă de cod pentru a acoperii toate tipurile pe care
le pot avea valorile programatorii care au dezvoltat limbajele de programare s-au gândit să
inventeze noțiunea de TEMPLATE.

Zic: adică cum? Zice păi nu ţi-ar plăcea să scrii o singură metodă care să poate să preia toate
tipurile de valori, Zic: ba da. Zice: ei, vezi, pentru asta există noţiunea de template.

Template în limba engleză am înţeles că înseamnă şablon dar că se referă mai mult la com-
portament decât la stare.

Adică un obiect fie el ce-o fi: masa, casa, maşina, se naşte după un model care este clasa lui.
Dar modul în care se comportă adică cum şi pe unde merge şi ce face se poate standardiza
în sabloane adică template.

De exemplu eu în fiecare zi mă duc să iau pâine. Dacă cineva face un template din asta orice
om poate respecta acest template şi poate merge să ia pâine în acelaşi mod în care merg eu.
Modul rămâne acelaşi doar omul se schimbă.

© Bitulică 2020
Povestea lui Bitulică

Am înţeles că în felul ăsta au gândit şi cei care au implementat metodele template.

Asta insemana ca în loc să fac

int suma(int int);


double suma(double, doble)

Adică să supraîncarc în aceeaşi clasă o metodă

Pot să scriu

template <typename T>


T suma(T x, T y)
{
return x +y;
}

Iar în metoda principală pot scrie

int main()
{
cout << suma<int>(3, 7) << endl;
cout << suma<double>(3.0, 7.0) << endl;
return 0;
}

Am stat şi m-am gândit şi am întrebat-o apoi pe Katy de ce mai folosesc supraîncărcarea


dacă există noţiunea de template şi mi-a spus că cică supraîncărcarea în aceste condiţii are
rost pentru clasele moştenite.

Adică în aceeaşi clasă pot să folosesc template în loc sa supraîncarc o metoda dar când clasă
este moştenită în clasa derivată trebuie să supraîncarc metoda dacă mai vreau ceva în plus.
În C++ se poate scrie și cod liber care nu este inclus într-o clasă cum este de exemplu me-
toda main unde deasemenea pot sa mă folosesc de template.

Noţiunea de template este valabilă şi pentru datele definite de utilizator adică cele care nu
sunt primitive.

template <class T> unde T poate fi orice tip de data definit de utilizator inclusiv clasă sau
array.

template <class T>


void bubbleSort(T a[], int n)
{
for (int i = 0; i < n - 1; i++)
for (int j = n - 1; i < j; j--)
if (a[j] < a[j - 1])
swap(a[j], a[j - 1]);

© Bitulică 2020
Povestea lui Bitulică

}
int main()
{
int a[5] = {10, 50, 30, 40, 20};
int n = sizeof(a) / sizeof(a[0]);
bubbleSort<int>(a, 5);
cout << " Sirul sortat : ";
for (int i = 0; i < n; i++)
cout << a[i] << " ";
cout << endl;
return 0;
}

Sau

template <typename T>


class Array
{
private:
T *ptr;
int size;
public:
Array(T arr[], int s);
void prinţ();
};

Introducerea noţiunii de template deschide o uşă către utilizarea datelor generice şi către
implementarea generică în care se abstractizează cât de mult posibil orice noţiune concretă.

Avantajul este cuprinderea unui număr cât mai mare de situaţii cu un efort fizic minim
adică să scriu puțin cod, dar cu un efort de maxim de analiză.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie de protecție


OOP
Am descoperit încapsularea

Încapsularea datelor înseamnă ascunderea lor de către programatorul care le-a creat faţă
de programatorul care le utilizează evitând astfel utilizarea lor eronată de către acesta din
urmă.

Aşa cum îi zice şi numele încapsularea vine de la a băga cineva ceva într-o capsulă pentru ca
altcineva să utilizeze capsula fără să îl intereseze ce e în ea având încredere în cel ce e creat-
o.

Cei care fac ampicilina ştiu ce substanţe chimice au pus în ea şi cum au făcut acolo reacţiile
între ele şi au băgat toate aceste elemente chimice şi reacţiile dintre ele într-o capsulă. Aia
jumate roşie jumate galbenă, iar doctorul când cineva e răcit zice doar ia ampicilina şi el ia
pastila. Astfel se reduc la zero riscurile de a greşi doza substanţelor și de a greşi reacţiile
chimice dintre substanțe.

Oare ce s-ar întâmpla dacă doctorul ar zice să iei 0,200 g de sare să o amesteci cu 0.200 de g
de amoniac la temperatura de 200 grade C şi să pui şi nişte apă care se creeze nu știu ce
reacţie între ele şi apoi să bei conținutul. Riscul să greşeşti ar fi mare. Aşa iei capsula şi ai
rezolvat.

Să zicem că telefonul meu deştept nu ar avea carcasa şi butoane şi eu ca să umblu cu el ar


trebui să închid şi să deschid circuite integrate pe acolo. Riscul să îl stric e mai mare. Aşa că
i-au pus carcasă adică l-au ÎNCAPSULAT şi au pus şi nişte butoane pe care să le folosesc
când vreau să fac ceva cu el. Iar ce e în spatele butonului nu e treaba mea. E treaba celor
care l-au creat.

Mă gândesc cum ar fi să pun la dispoziţia unui programator o clasă care să conţină nişte me-
tode pentru a putea implementa în site-ul lui web posibilitate de a plăti cu cardul ceva.
Şi mă gândesc cum ar fi ca în clasă să am un câmp:

string serie_card = NULL;

care este seria pe care utilizatorul o introduce ca fiind seria cardului său.

Dacă i-aș lăsa lui posibilitatea să îl vadă acest câmp fără să îl încapsulez ar putea pune acolo
ce vrea chiar şi string-ul "fara serie" şi când ar trimite la bancă seria i-ar da eroare.

Aşa că eu îl încapsulez şi nu îl las să bage ce îl taie pe el capul pentru că în funcţia care îl in-
capuleaza pun nişte condiţii şi deci fac "din faşă" managementul erorilor.

© Bitulică 2020
Povestea lui Bitulică

Am înțeles că încapsularea presupune un lucru mare şi lat care implică altele două:
Să ascund datele de utilizator
care implică

• să îi dau posibilitatea printr-o funcţie de tip "get" (get înseamnă a lua) să preia da-
tele ascunse. Deci să îi pun ceva la dispoziție să poate lua datele din campulă.
• să îi dau posibilitatea printr-o funcţie să tip "set" (set înseamnă a stabili) să seteze
datele ascunse. Deci să îi pun ceva la dispoziție să poată băga datele în capsulă.

Pentru a încapsula câmpul "serie_card"

Mai întâi pun câmpul cu modificatorul de acces "private" pentru a nu avea nimeni acces la el
decât clasa sa.

class A
{
private:
string _serie_card;
};

Variabilele private de regulă se denumesc cu "_" (underline) în faţă. Este o convenţie să


poată fi deosebite în cod.

Apoi îi creez funcţiile get şi set pentru preluare şi setare a câmpului.

Funcţiilor trebuie să le pun modificatorul de acces public

class A
{
private:
string _serie_card;
public:
string getSerie_card();
};

string A::getSerie_card()
{
return this->_serie_card;
}

adică atunci când în program altcineva are nevoie de seria cardului apelez funcţia asta şi îi
va returna valoarea câmpului _serie_card indiferent cât e el la un moment dat.

Apoi creez metoda pentru set care obligatoriu trebuie să primească un parametru cu ajuto-
rul căruia să poată fi setat atributul privat.

© Bitulică 2020
Povestea lui Bitulică

class A
{
private:
string _serie_card;
public:
string getSerie_card();
void setSerie_card(string);
};

string A::getSerie_card()
{
return this->_serie_card;
}

void A::setSerie_card(string serie_card)


{
this->_serie_card = serie_card;
}

adică atunci când cineva vrea să seteze seria cardului apelează funcţia asta şi câmpul _se-
rie_card se va seta cu valoare pe care o are parametru funcţiei.

În program când vreau setez valoare lui _serie_card dacă să zicem am obiectul card fac aşa

card.setSerie_card("23234234234");

și dacă vreau să iau valoarea și s-o afisez fac aşa

cout << card.getSerie_card() << endl;

Aşa cum am făcut eu funcţiile astea nu e neapărată nevoie de încapsularea că practic nu fac
nimic în ele dar de exemplu în funcţia care setează valoarea seriei pot să pun nişte condiții
de validare.

void A::setSerie_card(string serie_card)


{
if (serie_card=="")
cout << "Trebuie introdusa o serie valida!" << endl;
else
this->_serie_card = serie_card;
}

Ca să înțeleg Katy mi-a dat un măr din care am mușcat și a zis să îi dau și la pisică să mă-
nânce și ea. Eu ca să nu muște pisica din mărul meu am luat un cuțit i-am tăiat și i-am dat.

Adică am creat o metodă ca să îi dau și pisicii fără să muște direct din mărul meu.

© Bitulică 2020
Povestea lui Bitulică

Când am nu am știut de ce am nevoie


OOP
Am descoperit virtualizarea

Astăzi am fost cu familia într-un parc natural. Erau multe animale printre care păsări şi oa-
meni că doar n-om fi plante.

Pentru că erau oameni mulţi care le priveau sau se jucau cu ele animalele erau foarte bucu-
roase şi se mişcau de colo colo. Unele prin aer altele mergând pe pament iar altele târându-
se.

Katy m-a întrebat cum aş face dacă ar fi să implementez teoria evoluţionistă a lui Darwin. I-
am spus că aş pune clasa Vietate ca şi clasa de bază din care aş deriva clasa Planta şi din ea
alte clase până la EuglenaVerde (care face trecerea de la plante la animale) din care aș de-
riva clasa Animal iar din fiecare dintre aceste clase aş deriva alte subclase astfel încât să
merg dinspre abstract spre concret.

Nu există o specie anume pe care să o cheme Animal nici o specie anume pe care să o cheme
Maimuţa dar există o specie anume pe care o cheamă Cimpanzeu.

Clasele Animal şi Maimuţă în cazul ăsta nu ar putea fi concretizate în indivizi care să fie nu-
mai Animal sau Maimuţa fără să fie şi altceva mai concret ca Cimpanzeu, Gibon sau Urangu-
tan.

Fata mea m-a întrebat apoi cum aş implementa partea locomotorie adică mişcarea în
această arborescență de clase care reprezintă teoria evoluţionistă şi i-am spus că aş face o
funcţie merge() în clasa de bază pe care aş mosteni-o în toate clasele care derivă din ea şi la
nevoie aş suprascrie-o în fiecare clasă dacă este nevoie.

Căci fiecare animal fie el mamifer pasăre sau nevertebrat merge în felul lui. Până şi plantele
se mişca doar că doar se leagănă nu pleacă din loc.

Katy a zis că am început să mă prind de nişte chestii şi că gândesc foarte bine cu infor-
maţiile pe care le am dar m-a întrebat ce fac cu metoda merge() în clasele ca Plantă sau Ani-
mal sau Maimuţă unde nu pot să o folosesc că nu am pe ce fiindcă nu există un individ care
să se numească Maimuţă.

I-am spus că nu ştiu şi mi-a zis că pentru asta a fost introdusă în programare noţiunea de
virtual.

A zis că virtual înseamnă ca şi cum ar fi real dar nu este încă. Însă ar putea fi. Şi că să citesc
despre metodele virtuale şi clasele abstracte.

© Bitulică 2020
Povestea lui Bitulică

Am citit ce era să fac dacă nu a vrut să îmi spună ce sunt alea şi am înţeles că o metodă vir-
tuală este o metodă definită în clasa de bază care poate fi suprascrisă sau nu după necesităţi
în clasele care derivă din clasa de bază.

Scria acolo că există două tipuri de metode virtuale. Metode virtuale normale şi metode vir-
tuale pure şi că astea din urmă nu au corp.

Acum mă gândesc că dacă nu au corp clasele din care fac parte nu pot fi instantiate. Căci
dacă eu am doar declarată metoda suma(int,int) şi fac un obiect căruia îi spun să calculeze
suma obiect.suma(x,y) el cum calculează? Că nu i-am spus cum să facă.

Practic aceste clase care conţin metode virtuale pure devin clase abstracte pentru că ele nu
se pot concretiza adică nu pot naşte obiecte.

Pentru a declara o metodă virtuală pură am văzut că trebuie să scriu aşa

class A
{
public:
virtual suma(int,int)=0;
};

Metoda trebuie să fie neapărat publică (public) sau protejată (protected) pentru că ea tre-
buie suprascrisă iar ca să poată fi suprascrisa trebuie să fie moştenită şi ca să fie moştenită
trebuie ca clasă care moşteneşte clasă ei să aibă acces la ea.

Zero de după metoda specifică compilatorului că faptul că metoda nu are implementare nu


este o neatenţie a programatorului ci că programatorul chiar a vrut ca acesta metodă să nu
aibă implementare fiindcă a vrut să o facă virtuală pură. Altfel ar da eroare la compilare pe
motiv că metoda nu este implementată.

class Baza
{
public:
virtual void funcţie() = 0;
};

class Derivata: public Baza


{
public:
void functie() { cout << "funcţia a fost apelata "; }
};
int main(void)
{
Derivată d;
d.functie();
return 0;
}

© Bitulică 2020
Povestea lui Bitulică

Dacă nu implementam funcţia în clasa derivată ea moştenea funcţia aşa virtuală cum era în
clasa de bază şi devenea şi ea clasa abstractă că ar fi avut o metodă virtuală. Căci orice clasă
care are o metodă virtuală pură devine clasa abstractă.

Rolul claselor abstracte este să fie la baza unor ramuri de descendență pentru a prelua me-
todele și atributele comune tuturor descendenților astfel încât acolo unde este posibil să nu
se mai piardă timp cu rescrierea lor și să se evite astfel redundanța în cod.

Una e când fac o modificare să modific într-un singur lor și alta e să modific în mai multe lo-
curi. Șansele se nu modific pește tot cresc cu cât numărul de modificări e mai mare. Chestia
asta am înțeles că mă ajută și la depanare adică debug pentru că știu exact unde să mă uit
dacă ceva nu merge cum trebuie și mă uit doar într-un singur loc.

Metodele virtuale normale sunt metodele virtuale care au corp şi pot fi suprascrise în cla-
sele derivate. Dacă o clasă are o metodă virtuală normală ea poate naşte obiecte.

class Baza
{
public:
virtual void tipareste()
{
cout << "Tiparesc metoda din clasa de baza" << endl;
}
};

class Derivata : public Baza {


public:
void tipareste()
{
cout << "Tiparesc metoda din clasa derivata" << endl;
}
};

int main()
{
Baza* b;
Derivat d;
b = &d;
b->tipareste();
return 0;
}

Am scris cele două clase şi mă gândeam că exact aşa funcţionează şi o metodă normală su-
prascrisa dar când i-am spus lui Katy a zis că nu e chiar aşa şi că dacă vreau să mă conving
să mai scriu o metodă normală în ambele clase.

© Bitulică 2020
Povestea lui Bitulică

class Baza {
public:
virtual void tipareste()
{
cout << "Tiparesc metoda din clasa de baza" << endl;
}
void afiseaza()
{
cout << "Afisez metoda din clasa de baza" << endl;
}
};

class Derivata : public Baza {


public:
void tipareste()
{
cout << "Tiparesc metoda din clasa derivata" << endl;
}

void afiseaza()
{
cout << "Afisez metoda din clasa derivata" << endl;
}
};

int main()
{
Baza* b;
Derivata d;
b = &d;
b->tipareste();
b->afiseaza();
return 0;
}

Am scris am rulat şi am văzut că tipăreşte metoda din clasa derivată dar afişează metoda
din clasa de bază şi am înţeles de la Katy că se întâmplă aşa pentru că metodele virtuale îşi
stabilesc forma finală în timpul rulării iar metodele clasice în timpul compilării.

Cu alte cuvinte pointerul b este al clasei de BAZĂ şi în timpul rulării primeşte adresa unui
obiect al clasei DERIVATE şi punctează către el.

Chiar dacă un obiect sau pointer către un obiect de un anumit tip primeşte adresa unui obi-
ect de alt tip el rămâne tot de tipul care a fost.

Prin urmare forma metodelor clasice pe care le are este forma din clasa sa şi este stabilită la
compilare.

© Bitulică 2020
Povestea lui Bitulică

Nu acelaşi lucru se întâmplă cu forma metodelor virtuale care este stabilită la rulare şi
atunci când un obiect preia adresa unui alt obiect el preia şi forma metodelor virtuale pre-
zentă în clasa acelui obiect.

Forma metodelor virtuale este stabilită la runtime. Asta e diferenţa între o metodă clasică
suprascrisa şi una virtuală. Forma celor clasice este stabilită la compilare.

Am înţeles că metodele virtuale nu pot fi metode statice. Asta pentru că elementele statice
aparţin clasei și forma lor este stabilită în timpul compilării.

© Bitulică 2020
Povestea lui Bitulică

Când am am avut nevoie de schimbare


OOP
Am descoperit polimorfismul

Polimorfism înseamnă capacitatea unor entităţi de a lua forme diferite. Vine de la poli care
înseamnă mai multe şi morf care înseamnă formă.

De aici vine şi a metamorfoza care înseamnă a se transforma în altceva decât e.


Un om poate avea stări si comportamente diferite în situații diferite. Într-un mediu se simte
și se comportă într-un fel în altul se simte și se comportă în alt fel.

În informatică polimorfismul se reflectă asupra obiectelor și este unul dintre cele mai im-
portante principii ale OOP apărând sub două mari feluri

Polimorfism la COMPILARE care se mai numește și polimorfism PARAMETRIC pentru că


constantă în supra încărcarea unei funcții sau a unui operator. Teoretic si practic se poate si
suprascrie o funcție sau un operator dar în cadrul unui astfel de polimorfism este ca și cum
aș scrie ceva și aș adăuga ceva peste adică ca și cum aș ascunde ce am scris anterior.

De aceea în acest caz suprascrierea se numește HIDDING adică ascundere.

class A
{
public:
void functie(int x)
{
cout << "Valoarea lui x este " << x << endl;
}
void func(double x)
{
cout << "Valoarea lui x este " << x << endl;
}
void func(int x, int y)
{
cout << "Valoarea lui x si y este " << x << ", " << y << endl;
}
};
int main()
{
A obiect;
obiect.functie(7);
obiect.functie(9.132);
obiect.functie(85,64);
return 0;
}

© Bitulică 2020
Povestea lui Bitulică

Deci funcția functie se comporta diferit în trei situații diferite.

În C++ pe lângă funcții se pot supraîncărca și operatorii.

class Complex
{
private:
int real, imag;
public:
Complex(int r = 0, int i =0)
{
real = r;
imag = i;
}
Complex operator + (Complex const &obj)
{
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
return res;
}
void scrie()
{
cout << real << " + i" << imag << endl;
}
};
int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2;
c3.print();
return 0;
}

Metodele au același nume dar prima afişează ceva a doua altceva şi a treia altceva în timp ce
operatorul calculează adică se comportă diferit pentru operanzi de tipuri diferite.

Acest concep în programarea pe obiecte se numeşte OVERLOADING adică SUPRAÎNCĂR-


CARE şi este util programatorilor pentru că nu sunt nevoiţi să redenumească metoda.

Dacă nu aș fi avut această posibilitate scriam

string metoda1 (string nume, string prenume, unsigned int varsta);


string metoda2 (string nume, string prenume);
string metoda3 (string nume);

Deci ar fi trebuit să fac mai multe metode şi mă puteam încurca în ele şi mai e şi inestetic.

© Bitulică 2020
Povestea lui Bitulică

Polimorfismul DE MOŞTENIRE când am aceeași metodă în clase diferite care deschind una
din alta și practic metoda din clasa de bază se anulează.

class A
{
public:
void afiseaza(string nume, string prenume)
{
cout << prenume << " " << nume << endl;
}
};
class B : public A
{
public:
void afiseaza(string nume, string prenume)
{
cout << nume << " " << prenume << endl;
}
};

dacă instantiez un obiect al clasei B

B b = B();

şi apelez metoda afiseaza() voi avea posibilitatea să o apelezi numai în formă din clasa B
pentru că metoda din clasa A a fost SUPRASCRISA de metoda din clasa B

b.afiseaza("Popescu","Maria");

Dacă instantiez un obiect al clasei A

A a = A();

atunci pot să apelez metoda din clasa A

a.afiseaza ("Popescu","Maria");

Dacă fac așa

A *a;
B b;
a = &b;

și pun cuvantul cheie virtual în fața metodei din clasa A atunci

a.afişează ("Popescu","Maria");

va apela metoda din clasa B

© Bitulică 2020
Povestea lui Bitulică

Fenomenul descris mai sus se numeşte şi OVERRIDDEN adică SUPRASCRIERE și se reali-


zează doar la RUNTIME.

Polimorfismul este întâlnit și cand se face typecast între obiecte. Adică conversie de timp.
Conversiile de tip sunt fie implicite fie explicite.

char a = 97 este o conversie implicită

int a = (double)97.00 este o conversie explicită

Pentru ca între două tipuri să se poată face conversie trebuie ca cele două tipuri să aibă
ceva în comun.

Dacă clasa B descinde din A și C descinde tot din A atunci între B și C se poate face typecast.
Altfel nu este posibil.

Lucrul acesta se întâmplă pentru că prin conversie se adaugă sau se taie ceva din tipul care
se convertește.

Dacă am o masă și o fac pat adaug la ea saltea. Dacă am un pat și îl fac masă dau jos salteaua
de pe el. O masă și un pat au un cadru comun. Blatul și picioarele. Din scaun nu merge să fac
ușă. Că nu au nimic în comun.

Conversia de la un tip mai larg la unul mai strâmt se face cu pierdere de informație. Dacă
cineva se mută dintr-o casă mai mare în una mai mică nu îi va încăpea toată mobila. Dacă
cineva se mută dintr-o casă mai mică în una mai mare vor fi initial camere nemobilate. De
aceea conversia de la mare la mic este întotdeauna explicită pentru că compilatorul nu îți
asumă pierderile.

Excepție fac tipurile primitive unde la o conversie de la mare la mic se calculeaza modulo
dintre valoarea care depășește cardinalitatea tipului și dimensiunea tipului.

char a = 256 rezulta a = 1 adica 256%255 asta daca a este codat cu UTF-8 că dacă e codat
UTF-16 adică e memorat pe 16 biți adică 2 octeți rezultatul este tot 256 pentru nu mai de-
pășește cardinalitatea tipului.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie să am ceva doar al meu


OOP
Am descoperit constructorul de copiere

Când a fost ziua recunoștinței am primit de la doi vecini de-ai noştri câteva bunătăţi pe care
fiecare le-a făcut acasă pentru familia lui.

Unul dintre vecini a venit cu un platou plin cu prăjituri şi a zis să iau prăjiturile să le pun pe
un platou de-al meu şi să îi dau platoul înapoi că este din cristal şi este moştenire de familie.

Am luat prăjiturile le-am pus pe un platou, am spălat platoul lui şi i l-am înapoiat că doar nu
era să i-l dau aşa nespălat.

După un timp a mai venit un alt vecin de data asta cu eclere multe puse pe un platou de
unică folosită pe care evident că nu l-a mai vrut înapoi dar a zis că a venit să mâncăm amân-
doi din el. Practic mi-a dat și mie să mănânc din mâncarea lui

Până să vină la mine eclerele şi platoul erau doar ale lui după au fost și ale mele. Înainte pu-
tea să le mănânce el acum nu mai poate dacă le mănânc eu înainte.

După ce a plecat şi al doilea vecin am mai rămas puțin la masa din bucătărie cu Lisa iar după
am mers să mai învăţ câte ceva.

Când eu stăteam la calculator Katy trăgea cu ochiul să vadă ce fac şi când a văzut că vreau să
fac o atribuire între două obiecte mi-a zis că dacă vreau să înţeleg ce fac acolo să fiu atent ce
au făcut cei doi vecini?

Zic păi ce să facă? Ne-au adus bunătăţi. Zice: da dar ia gândeşte-te cum? ZIc: ce cum? Zice:
gândeşte-te cum au adus.

Am stat şi m-am gândit şi într-adevăr cu unul am mâncat împreună iar cu altul separat. Se-
parat dar din aceeași mâncare. Zic: asta e diferenţa? Zice: exact.

Păi cum? Am întrebat-o.

ZIce păi fii atent. Când primul ţi-a adus platoul cu prăjituri practic el nu ţi l-a dat. Te-a pus
să copiezi ce avea pe el pe un platou nou. Adică să pui mâncarea lui pe platoul nostru. Deci
practic ai făcut un nou platoul cu conţinutul pe care îl avea el.

După ce mi-a spus asta Katy mi-a zis că eu practic am construit un nou platou cu conţinutul
altui platou şi că în informatică acest lucru se practică când se crează un nou obiect cu
conţinutul altuia deja existent şi că acest lucru îl face constructorul dar că acest tip de con-
structor se numeşte CONSTRUCTOR DE COPIERE.

© Bitulică 2020
Povestea lui Bitulică

Constructorul de copiere poate fi creat explicit de către programator dar dacă programato-
rul nu îl crează el este creat implicit de către compilator. Indiferent de către cine a fost creat
constructorul de copiere se activează atunci când un obiect existent este atribuit unui obi-
ect nou creat.

Dacă nu vreau ca obiectul clasei să poată fi copiat pot să fac constructorul de copiere privat.
Practic constructorul de copiere CLONEAZA un obiect.

Clonarea nu este același lucru cu atribuirea pentru că la atribuirea a două obiecte se atri-
buie adresa de memorie a celui din dreapta celui din stânga. Astfel că cel din stânga va avea
aceeași adresa cu cel din dreapta.

Ca să înţeleg am scris codul de mai jos

class String
{
private:
char *s;
int size;
public:
String(const char *str = NULL);
~String() { delete [] s; }
String(const String&);

void print()
{
cout << s << endl;
}

void change(const char *);


};

String::String(const char *str)


{
size = strlen(str);
s = new char[size+1];
strcpy(s, str);
}

void String::change(const char *str)


{
delete [] s;
size = strlen(str);
s = new char[size+1];
strcpy(s, str);
}

© Bitulică 2020
Povestea lui Bitulică

String::String(const String& old_str)


{
size = old_str.size;
s = new char[size+1];
strcpy(s, old_str.s);
}

int main()
{
String str1("Bitulica");
String str2 = str1;
str1.prinţ();
str2.prinţ();
str2.change("Povestea lui Bitulica");
str1.prinţ();
str2.prinţ();
return 0;
}

În cod am copiat obiectul str1 în obiectul str2 şi când am schimbat valoarea lui str2 nu s-a
schimbat şi valoarea lui str1 pentru că constructorul de copiere crează un nou obiect şi îi dă
valoarea obiectului deja creat.

String str2 = str1;

adică str2 a fost creat şi a primit valoarea lui str1.

Dacă nu aveam constructorul de copiere atunci str2 primea REFERINŢA adică adresa lui
str1 şi dacă ulterior schimbăm valoarea lui str1 sau a lui str2 se schimbau ambele pentru că
punctau către aceeaşi adresă.

Constructorul de copiere se activează atunci când un obiect este trimis undeva prin valoa-
rea. Fie că e vorba de o atribuire fie că e vorba de trimitere ca parametru într-o funcţie. Din
acest motiv argumentul constructorului de copiere trebuie să fie o referinţă pentru că altfel
s-ar apela la infinit constructorul de copiere.

Argumentul unui constructor de copiere poate fi constant daca vreau ca acest obiect sa nu
poată fi modificat din greșeală. Prin urmare dacă pun argumentul constant și cineva în-
cearcă să modifice obiectul programul va da eroare.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie de prieteni


OOP
Am descoperit elementele prietene

Când am ajuns în SUA nu cunoşteam pe nimeni. Între timp mi-am făcut câţiva prieteni.
Am înţeles că şi în informatică există noţiunea de prieten. Prietenia în informatică este ca şi
la noi oamenii. O prietenie între indivizi. În OOP indivizii sunt obiectele.

Dacă oamenii îşi aleg prietenii obiectele nu îşi pot alege singure cu cine să se împriete-
nească ci sunt prietene pentru că modelele după care au fost făcute sunt prietene. Cu alte
cuvinte în informatică există noţiunea de clase prietene si obiectele sunt prietene dinainte
de a se fi născut pentru că așa au fost concepute modelele lor.

Doi prieteni îşi împărtăşesc secretele şi îşi împart lucrurile private. Conceptul a fost preluat
de OOP şi o clasă prietenă cu altă are acces la membrii privaţi ai acesteia.

Prietenia între două clase nu este neapărat bidirecțională cum nici între doi oamenii nu
este. Dacă clasa A este prietenă cu clasa B atunci clasa B are acces la atributele şi metodele
private ale clasei A dar asta nu înseamnă că şi clasa A are acces la membrii privaţi ai clasei
B.

Dacă un om se împrieteneşte cu altul şi îi împărtășește un secret asta nu înseamnă că şi ce-


lalat îi va împărtăşi secretul său. Îl împărtăşeşte doar dacă vrea. Acelaşi lucru se întâmplă şi
în OOP cu clasele care sunt prietene.

Pot să îi spun clasei A să fie prietenă cu clasa B dar şi clasei B să fie prietenă cu clasa A. Însă
dacă îi spun doar clasei A să fie prietenă cu clasa B asta nu înseamnă că automat şi clasa B
va fi prietena cu A. Prin urmare prietenia între clase nu este reflexiva.

Ca şi la oameni prietenia în OOP nu se moşteneşte. Dacă părintele cuiva are un prieten asta
nu înseamnă că şi copilul lui este prieten cu acea persoană. Deci dacă clasa A este prietenă
cu B şi C moşteneşte pe A asta nu înseamnă că şi C este prietenă cu B.

Că tot a venit vorba am înţeles că prietenia între clase nu este nici tranzitivă. Ca şi la oameni
dacă un om este prieten cu alt om şi acel om cu un altul ăsta nu înseamnă că primul este pri-
eten cu al treilea.

Deci dacă clasa A este prietenă cu clasa B şi B cu C , A şi C nu sunt clase prietene.

Vorbeam despre asta cu Katy şi am făcut împreună câteva exemple ca să mă lămuresc

© Bitulică 2020
Povestea lui Bitulică

class A
{
private:
int a;
public:
A() { a = 0; }
friend class B; // clasa prietenă
};
class B
{
private:
int b;
public:
void showA(A& x)
{
std::cout << "A::a=" << x.a;
}
};
int main()
{
A a;
B b;
b.showA(a);
return 0;
}

Aici clasa B este prietenă cu clasa A şi deci şi obiectul b cu obiectul a şi prin urmare obiectul
b are acces la elementele private ale clasei A așa că în funcţia showA din clasa B m-a lăsat să
acceses obiectul privat al clasei A.

Prietenia dintre clase ca şi la oameni poate fi parţială sau totală. Dacă o clasă este prietenă
cu o alta atunci prietenia e totală dar de exemplu dacă doar o funcţie dintr-o clasă este prie-
tenă cu o altă clasă atunci prietenia dintre cele două clase este parţială şi am înţeles că se
spune că acea funcţie este o funcţie prietenă.

O funcţie prietenă cu o clasă este o funcţie care are acces la elementele private ale acelei
clase.

class B;
class A
{
public:
void showB(B&);
};
class B
{
private:
int b;

© Bitulică 2020
Povestea lui Bitulică

public:
B() { b = 0; }
friend void A::showB(B& x); // functie prietena
};
void A::showB(B& x)
{
std::cout << "B::b = " << x.b;
}
int main()
{
A a;
B x;
a.showB(x);
return 0;
}

Aici DOAR funcţia showB este prietena cu clasa B şi prin urmare doar în corpul ei este per-
mis accesul la elementele private ale clasei B

O funcţie prietenă cu o clasă poate fi membră a unei clase dar şi funcţie globală.

class A
{
int a;
public:
A() { a = 0; }
friend void showA(A&);
};
void showA(A& x)
{
std::cout << "A::a=" << x.a;
}
int main()
{
A a;
showA(a);
return 0;
}

Aici funcţia showA nu aparţine niciunei clase căci nu am pus operatorul de rezoluţie în sem-
nătura ei care ar fi legat-o de o clasă.

Un prieten nu respectă protocolul pe care îl respectă un străin când intră în casa prietenului
său şi în acelaşi timp un prieten este mai privilegiat că o rudă.

Ideile inovaţiile şi invenţiile au la bază o nevoie. Nevoia pentru care a fost creat conceptul
de clase şi funcţii prietene este acela de a accelera procesele ignorând validările din meto-
dele care încapsulează elementele private şi de a acorda privilegii sporite în mod selectiv.

© Bitulică 2020
Povestea lui Bitulică

Dacă atributul private este prea restrictiv pentru un membru şi public este prea permisiv
atunci soluţia OOP este protected.

Dar cum prin protected se dă acces la toată ramură de descendenta atunci dacă nu vreau să
aibă toţi acces folosesc conceptul de friend class sau friend function după necesităţi. Dacă
vreau ca toată clasa să aibă acces la elementele private folosesc friend class iar dacă vreau
ca doar anumite metode să aibă acces la ele folosesc friend function.

Am înțeles că în proiectarea unei structurii a unei aplicații nu trebuie abuzat de această po-
sibilitate pentru că se sfidează puterea încapsulării. Dacă noi oamenii nu am avea senzori de
temperatura sau gust pe buze si pe limbă atunci ne-am arde cu mâncarea sau am vomita
pentru că am mânca ceva stricat pe care nu l-am refuza ci ar ajunge în stomac.

Dar avem și acești senzori sunt metodele noastre de încapsulare. Dacă ar fi alimente prie-
tene cu stomacul nostru ne-ar putea face rău căci ele nu ar mai trece prin filtru senzorilor.

Cu cât aceste alimente privilegiate ar fi mai multe cu atât șansele să simțim în stomac ceva
care arde sau este stricat cresc.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie de mai mult


OOP
Am descoperit moștenirea multiplă

Eu semăn şi cu mama şi cu tata şi nu îmi pot da seama cu care dintre ei semăn mai mult.
Mama şi tata seamănă fiecare cu tatăl lui şi cu mama lui şi este posibil ca şi eu să semăn cu
bunicii mei atât din partea tatălui cât şi ai mamei.

Acest lucru se întâmplă pentru că genele se transmit. Genele în genetică sunt ca membrii
claselor în programarea orientată obiect. Atât atribute cât şi metode.

Noi oamenii moştenim de la ambii părinţi câte ceva în mod selectiv. Acest lucru a inspirat şi
dezvoltatorii limbajul C++ unde este permis ca o clasă să moştenească mai multe clase tot
selectiv dar nu pe alese. Spun că nu pe alese pentru că nu o clasă care moşteneşte alege ce
anume să moştenească ci doar de la cine să moştenească.

Dacă clasa A moşteneşte elementele publice şi protejate ale claselor B şi C

class A: public B, public C


{
}

atunci ea moşteneşte toţi membrii cu aceşti modificatori de acces de la cele două clase fără
să aibă posibilitatea să-i selecteze individual.

Dacă mama are ochii albaştri şi tata verzi moştenim doar una dintre cele două culori pentru
ochi. Prin urmare chiar dacă nu le alegem noi modul de transmitere a genelor este selectiv
la nivel de rol. În informatică moştenirea nu este selectivă la nivel de rol.

Dacă clasa B şi C au un atribut comun moştenit de la o altă clasă comună atunci clasa A va
moşteni de două ori acelaşi atribut care poate creea o situaţie ambigua.

Am înţeles că acesta problemă este cunoscută ca problema rombului (diamond problem)


pentru ca schema în care sunt așezate cele patru clase este un romb. Problema poate fi re-
zolvată dacă cele două clase care moştenesc o clasă comună vor fi moștenite doar virtual.

class Persoană
{
public:
Persoană()
{
cout << "Chem persoană" << endl;
}
Persoană(int x)
{

© Bitulică 2020
Povestea lui Bitulică

cout << "Chem persoană" << endl;


}
};

class Bărbat : virtual public Persoană


{
public:
Bărbat(int x) :Persoana(x)
{
cout << "Chem bărbatul" << endl;
}
};

class Femeie : virtual public Persoană {


public:
Femeie(int x) :Persoana(x)
{
cout << "Chem femeia" << endl;
}
};

class Copil : public Femeie, public Bărbat


{
public:
Copil(int x) :Femeie(x), Bărbat(x), Persoană(x)
{
cout << "Chem copilul" << endl;
}
};

int main()
{
Copil copil(10);
return 0;
}

Când un obiect este construit constructorul clasei sale ştie exact cum să îl construiască.

Dacă clasa obiectului construit moşteneşte o altă clasă atunci constructorul său trebuie să
cheme constructorul clasei pe care o moşteneşte pentru că obiectul care se construieşte are
şi elemente de la clasa moştenită şi constructorul clasei curente nu ştie de ele.

Un constructor care construieşte acoperişul o face după ce constructorul care face pereţii a
terminat iar acela care a făcut pereţii adică zidurile s-a apucat de treabă abia după ce cel
care a făcut fundaţia a terminat-o de turnat. Se întâmplă asta pentru că nu poţi ridica zidu-
rile dacă nu ai fundaţia turnată şi nici pune acoperișul dacă nu ai zidurile ridicate.

© Bitulică 2020
Povestea lui Bitulică

În cazul moştenirii multiple constructorii claselor se apelează în ordinea în care sunt scrise
clasele moștenite.

Dacă scriu

class A : public B, public C


{
}

atunci când apelez constructorul lui A se va apela întâi constructorul lui B şi apoi construc-
torul lui C. La apelarea destructorului clasei A, destructorii claselor B și C se vor apela în or-
dine inversă în care s-au apelat constructorii. Adică dacă fărâm o casă încep invers față de
cum am construit-o.

Moştenirea multiplă şi virtualizarea se pot folosi pentru conceptul de interfaţă.


Conceptul de interfaţă este folosit atunci când vreau să ascund codul din spatele ei. Adică
modul în care este implementată.

Un aparat de radio are o interfaţă cu butoane ca utilizatorul să îl poată folosi fără să ştie
electronică. Un translator poate fi considerat o interfaţă între un vorbitor de limba engleză
şi unul de limba chineză. Deci o interfaţă este un paravan între două medii distincte cu rol
în a le face să se înţeleagă.

Conceptul de interfaţă mai este folosit şi atunci când un tip de dată generic poate fi concre-
tizat în mai multe moduri. De exemplu un om este fie bărbat fie femeie. Şi bărbatul şi femeia
sunt oameni dar sunt construiţi diferit.

Un calendar poate fi conceput diferit. De exemplu tot calendar este şi calendarul Gregorian,
Julian sau Mayaş. O formă geometrică poate fi triungi, pătrat sau dreptunghi.

Pentru a implementa conceptul de interfaţă trebuie să apelez la conceptul de virtualizare şi


la polimorfism.

class Shape
{
public:
virtual int getArea() = 0;
void setWidth(int w)
{
width = w;
}
void setHeight(int h)
{
height = h;
}
protected:
int width;
int height;

© Bitulică 2020
Povestea lui Bitulică

};
class Rectangle : public Shape
{
public:
int getArea()
{
return (width * height);
}
};

class Triangle : public Shape


{
public:
int getArea()
{
return (width * height) / 2;
}
};

int main(void)
{
Rectangle Rect;
Triangle Tri;
Rect.setWidth(5);
Rect.setHeight(7);
cout << "Aria dreptunghiului: " << Rect.getArea() << endl;
Tri.setWidth(5);
Tri.setHeight(7);
cout << "Aria triunghiului: " << Tri.getArea() << endl;
return 0;
}

Fie că am un obiect triunghi sau dreptunghi apelez aceleaşi metode pentru a seta dimensiu-
nile şi pentru a afla aria. Astfel că pentru programatorul care foloseşte aceste clase imple-
mentarea din spatele acestor metode este ascunsă.

Fie că am un televizor Samsung Sony sau LG tot pe acelaşi buton din interfaţa apas ca să le
aprind.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie de ceva pe moment


OOP
Am descoperit elementele anonime

Aproape de unde locuim există un loc care colectează lucruri donate de oameni pentru cei
care au mai mare nevoie de ele şi Lisa a propus să donăm şi noi câteva lucruri.

Toţi adică eu Katy Lisa şi Evy am făcut un pachet cu lucrurile pe care am hotărât să le do-
năm.

Firma care colectează pachetele donate recomandă ca pe cutie să fie trecut şi un nume su-
gestiv şi o mică descriere a ceea ce conţine acel pachet pentru a le fi mai uşor când le sor-
tează.

Noi am donat diverse lucruri care nu se încadrează într-o categorie anume. Practic am
strâns la un loc lucruri diverse şi nu am ştiut cum să denumim mulţimea lor ca întreg. Prin
urmare am pus numele Anonymous şi sub el am scris o descriere care cuprinde categoriile
în care se încadrează lucrurile oferite cadou.

Katy era tare bucuroasă când mă vedea că mă tot gândesc cum să denumim pachetul şi când
am întrebat-o ce are de e aşa zâmbăreaţă a zis că se bucură pentru că acum o să înţeleg mai
bine de ce dezvoltatorii C++ au introdus în limbaj noţiunea de clase anonime.

Am întrebat-o de ce şi a zis că practic obiectele născute pe modelul claselor ăstora sunt ca


pachetul pe care l-am făcut noi şi sunt folosite atunci când se vrea agregarea mai multor
atribute din clase diferite într-un obiect spre a-i fi oferit cuva care are nevoie de datele pe
care le conţine.

A zis că e ca şi cum mi-ar cere cineva un raport sub formă de tabel în care trebuie să com-
pletez date pe care le iau din diferite alte tabele care tabele conţin date doar despre un anu-
mit tip de obiecte. Adică tabele tip nomenclator.

Eu la firma Riverbites lucrez pe vânzări că aşa m-au pus când au angajat-o pe Katy. Ne-au
dat şi nouă job-uri pentru că erau incluse în pachetul de relocare şi am înţeles că de exem-
plu dacă cineva îmi cere să îi dau preţul cantitatea şi firma producătoare pentru o maşină, o
casă şi un teren mă duc şi mă uit în tabelele mele cu maşini , cu case, şi cu terenuri, extrag
informaţiile de acolo şi le agreg în tabelul nou pe care i-l dau cui mi l-a cerut.

După ce am dus pachetul la centrul de colectare am venit acasă şi am făcut cu Katy un exem-
plu că să înţeleg ce e cu clasele astea anonime.

class
{
int i;
public:

© Bitulică 2020
Povestea lui Bitulică

void setData(int i)
{
this->i = i;
}
void prinţ()
{
cout << "Valoarea lui i este : " << this->i << endl;
}
} obj1;

int main()
{
obj1.setData(10);
obj1.prinţ();
return 0;
}

Clasele anonime nu au nume ca de asta le zice aşa şi sunt utilizate pentru agregarea datelor.
Agregare înseamnă strângerea lucrurilor din diferite părţi şi punerea lor la un loc. Cand o
mulțime este eterogenă este greu să îi dai un nume. Așa că numele ei rămâne necunoscut.

Se pot naşte obiecte din clasele anonime iar domeniul lor de vizibilitatea este întreg progra-
mul. Practic sunt obiecte globale.

Dacă vreau să le reduc sfera de vizibilitate pot să folosesc cuvântul cheie typedef în fata cu-
vântului cheie class şi practic obiectul clasei îl fac tip de data pe care ulterior pot să îl folo-
sesc pentru a creea obiecte în diferite scopuri astfel încât să le limitez vizibilitatea. Typedef
este cuvântul cheie folosit pentru a defini un tip de dată.

typedef class
{
int i;
public:
void setData(int i)
{
this->i = i;
}
void prinţ()
{
cout << "Valoarea lui i este :" << this->i << endl;
}
} myClass;

int main()
{
{
myClass obj1;
obj1.setData(10);

© Bitulică 2020
Povestea lui Bitulică

obj1.prinţ();
}

myClass obj2;
obj2.setData(20);
obj2.prinţ();
return 0;
}

Tipul de data definit este myClass. Obiectul obj1 are ca scop de unde se deschide paranteza
acoladă în interiorul funcţiei main şi până unde se închide.

Obiectul obj2 are ca scop întreaga funcţie main deci întregul program.

© Bitulică 2020
Povestea lui Bitulică

Când am avut vrut să scriu mai puțin


OOP
Am descoperit expresiile lambdas

Am fost în vacanţă într-un loc superb pe malul râului Coyote Creek ce trece pe lângă o pă-
dure şi acolo a trebuit să ne facem singuri o barcă.
E mult spus barcă. Am făcut o plută din lemn cu care să mergem pe apă pe care seară am
pus-o la uscat am dezmembrat-o şi cu lemnele am făcut un foc de tabără.
Dacă aveam o barcă cu noi fie ea şi de aia gonflabilă era bine deşi nu cred că cea gonflabilă
era cea mai indicată căci prin apă mai erau şi crengi ascuţite sau stufăriși şi se putea înţepa,
Dar dacă am fi avut evident că nu o puneam pe foc ci o păstrăm ca să o mai folosim şi
altădată.
Au fost şi Katy şi Evy cu noi şi Katy m-a întrebat dacă ştiu că în C++ pot să fac şi funcţii
inline. ZIc cum adică inline? Zice adică să le creezi să le foloseşti şi să le ştergi când nu mai ai
nevoie de ele.
Am zis că nu ştiam că se poate aşa ceva şi a zis că aceste funcţii se numesc funcţii
Anonymous că dacă nu le mai folosesc a doua oară nu trebuie să aibă nume că nu e nevoie
să strig la ele.
Vorbeam cu Katy şi mă gândeam că noi oamenii păstrăm lucruri şi implicit le dăm un nume
doar dacă le folosim de mai multe ori. Noi sau altcineva. Dar dacă facem ceva pe moment că
avem nevoie , nu mai are rost să le numim cumva sau să le păstrăm.
Nu am luat laptop cu mine în vacanţă şi doar când am ajuns acasă am stat cu Katy şi am
testat că eram curios să văd la ce sunt bune şi cum se folosesc aceste funcţii.
Am înţeles de la Katy că se mai numesc şi expresii Lambdas care provin din matematică şi
care au la baza abstractizarea funcţiilor.
Alegerea denumirii vine de la litera grecească lambda care a fost la rândul ei aleasa pe
principiul "ăla bala portocala". Adică la nimereală.
Sintaxa unei expresii lambdas este
[ variabile externe utlizate ] (parametrii) -> tipul returnat
{
definiţia funcţiei
}
Funcţiile lambdas sunt funcţii care se crează temporar se folosesc şi se şterg la fel ca
variabilele locale.

© Bitulică 2020
Povestea lui Bitulică

Ca o variabilă din program să poată fi accesată din corpul unei funcții lambdas este nevoie
ca ea să fie trimisă prin referinţă sau prin valoare în funcţie şi scrisă între parantezele
pătrate.
Variabile externe adică cele dintre parantezele pătrate sunt variabile din program şi se
deosebesc de parametrii funcţiei care sunt înlocuiţi cu valori la apel şi care în sintaxa se
scriu între paranteze rotunde. Corpul funcţiei este între paranteze acolade.
Dacă vreau să afişez elementele unui vector pot scrie aşa
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct print
{
void operator()(int element)
{
cout << element << endl;
}
};
int main(void)
{
std::vector<int> v = { 1, 2, 3, 4, 5 };
std::for_each(v.begin(), v.end(), print());
return 0;
}
Dacă scriu ăsta folosind funcţii lambda pot scrie aşa
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(void)

© Bitulică 2020
Povestea lui Bitulică

{
std::vector<int> v = { 1, 2, 3, 4, 5 };
std::for_each(v.begin(), v.end(), [](int element) { cout << element << endl; });
return 0;
}
Dacă aveam nevoie de o variabilă din program o scriam între parantezele pătrate.
de exemplu dacă am nevoie de i ca să îl afisez
[&i] ( ) { std::cout << i; }
Ce am scris mai sus este echivalent cu
struct anonymous
{
int &m_i;
anonymous(int &i) : m_i(i) {}
inline auto operator()() const
{
std::cout << i;
}
};
Adică aşa scrie compilatorul desfăşurat expresia lambdas pe care am scris-o mai sus.
Simbolurile pentru captura variabilelor din program în expresiile lambda sunt
[ ] ( ) { } nu capturez nimic
[=] ( ) { } capturez tot prin valoare
[&] ( ) { } capturez tot prin referinţă
[x] ( ) { } capturez o anumită variabilă prin valoare
[&x] ( ) { } capturez o anumită variabilă prin referinţă
[&, x] ( ) { } capturez o anumită valoare prin valoare şi restul variabilelor din program prin
referinţă
[=, &x] ( ) { } capturez o anumită valoare prin referinţă şi restul variabilelor din program
prin valoare
Expresiile lambdas pot fi şi generice

© Bitulică 2020
Povestea lui Bitulică

const auto l = [](auto a, auto b, auto c) {};


este echivalent cu
struct anonymous
{
template <class T0, class T1, class T2>
auto operator()(T0 a, T1 b, T2 c) const
{
}
};
adică aşa se scrie desfăşurat expresia lambda generică de mai sus.
Expresiile lambdas pot fi mutabile
[]() mutable {}
care este echivalent cu
struct anonymous
{
auto operator()()
{
}
};
Am înțeles că ceva este mutabil dacă poate fi mutat si imutabil daca nu poate fi mutat. In
informatică referințele sunt indicatoare către o locație de memorie.
Dacă unei referințe i se poate schimba locația spre care indică atunci acea referință este
mutabilă. Dacă nu e imutabilă.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie de rapiditate


Am descoperit paralelismul
PARALEL

Când eram în România aveam obiceiul să mă duc pe stadion şi să alerg. Am noroc că şi aici
în Silicon Valley unde locuim este un stadion aproape de noi şi pot merge să mai dau o tură
două trei de pistă căci este din acela cu pistă de atletism.
Ne place la toţi că au prins şi fetele gustul alergărilor ușoare care dau tonus bun şi îl
întreţin.
Într-o zi când eram doar eu cu fata mea cea mare Katy era un concurs ad-hoc de alergat pe
distanţă de 100 m. Noi nu am participat. Doar am stat şi ne-am uitat. Vorba vine ne-am uitat
căci Katy zicea: vezi, fiecare aleargă pe culoarul lui. Eu ziceam: păi ce ai vrea să între unul
peste altul?
Până la urmă am aflat de ce tot zicea Katy că aleargă fiecare pe culoarul lui. Voia să înţeleg
cum e cu firele de execuţie care în engleză se numesc threads-uri.
Cică un process adică un program poate fi divizat dacă vrea programatorul în mai multe
procese. Dar nu în sensul în care ştiam eu de când am învăţat subprogramele.
Subprogramele sunt părţi din program pe când subprocesele sunt culoarele de execuție ale
subprogramelor.
E ca şi cum aş avea o funie împletită pe care merge o bilă şi aş despleti-o în sfori mai subţiri
pe care merg bile mai subțiri.
De exemplu dacă vreau să calculez pe 2+2:2 pot sparge în două subprograme programul.
Unul care calculează pe 2:2 şi altul care calculează pe 2+1 ca apoi să adun rezultatele date
de cele două subprograme în programul principal.
Dacă vreau să calculez aceeaşi expresie folosind firele de execuţie pot să fac unul pe care să
ruleze primul subprogram şi altul pe care să ruleze al doilea subprogram. Firele rulează în
paralel şi după ce aşteptă să termine amândouă pot să adun rezultatele în programul
principal.
Tehnologia mulţi threads permite rularea în acelaşi timp a mai multor aplicaţii în sistemul
de operare.
Primii care au încercat să facă asta au fost cei de la Microsoft în Windows însă la acel
moment computerele aveau un singur procesor aşa că programatorii simulau execuţia în
paralel pentru că ea nu putea fi reală. Ca o execuţie în paralel să fie reală trebuie ca un
computer să aibă cel puţin două procesoare.
O execuţie secvenţială dar alternativă a instrucţiunilor a două programe dă senzaţia că
programele se execută în paralel.

© Bitulică 2020
Povestea lui Bitulică

Dacă aprind şi sting alternativ două becuri suficient de repede am senzaţia că sunt ambele
aprinse. Sau ambele stinse.
Astăzi execuţia în paralel este reală pentru că computerele au mai multe procesoare.
De modul în care se execută aceste procese în paralel se ocupă sistemul de operare. El face
managementul threads-urilor. Programatorul poate doar să le lanseze, să le oprească, să le
spună să aştepte una după alta, să le adoarmă şi să le facă să comunice unul cu altul.
Programatorul nu are control asupra modului şi ordinii în care se execută firele de execuţie.
Limbajul C++ nu este un limbaj cross platformă adică acelaşi program nu rulează şi pe
Windows şi pe Linux şi pe Mac şi are nevoie de modificări. Una dintre chestiile care îl fac
neportabil este dacă foloseşte fire de execuţie pentru că managementul lor este în sarcina
sistemului de operare şi deci depind de sistemul de operare.
Katy mi-a zis că aşa cum alergau oamenii aceia pe culoare separate aşa rulează şi firele de
execuţie într-un computer. Au memorie partajată şi procesor separat. Memoria partajată
este doar pentru variabilele interne ale firului de execuţie.
Un fir de execuţie este un obiect la care se poate ataşa ceva ce poate fi executat şi care în
engleză se numeşte callable sau runnable Adică ceva ce poate fi apelat sau rulat. Acel ceva
poate fi o metodă, un obiect, sau chiar o expresie lambda. Când termină de executat şi
ultima înregistrare din ce are de executat thread-ul dispare.
Am făcut un exemplu că să înţeleg mai bine despre ce este vorba
#include <iostream>
#include <thread>
using namespace std;
void foo(int Z)
{
for (int i = 0; i < Z; i++)
{
cout << "variabilă\n";
}
}
class thread_obj
{
public:
void operator()(int x)

© Bitulică 2020
Povestea lui Bitulică

{
for (int i = 0; i < x; i++)
cout << "Funcţie\n";
}
};
int main()
{
thread th1(foo, 3);
thread th2(thread_obj(), 3);
auto f = [](int x)
{
for (int i = 0; i < x; i++)
cout << "Lambdas\n";
};
thread th3(f, 3);
th1.join();
th2.join();
th3.join();
return 0;
}
Am făcut trei obiecte de tip thread adică trei fire de execuţie.
Pe primul am lansat metoda foo, pe al doilea am lansat un obiect şi pe al treilea am lansat o
expresie lambda.
La finalul programului am aşteptat ca fiecare din aceste trei fire de execuţie să finalizeze ce
a avut de executat pentru că nu toate rulează sincron. Fiecare are altceva de făcut și unul
poate termina mai repede sau mai târziu decât altul.
Dacă aş fi oprit programul fără să aștepte unele după altele nu se opreau forţat cele care nu
se încheiaseră pentru că desi conceptual un program principal pentru sistemul de operare
este un process părinte pentru firele de execuţie lansate din interiorul lui ele sunt procese
separate si nu se opresc cand programul principal se oprește.

© Bitulică 2020
Povestea lui Bitulică

Dacă programul principal se termină nu se termină forţat firele de execuţie lansate de el


care nu s-au terminat încă. Sunt ca niște rachete lansate dintr-un avion. Dacă avionul este
doborât rachetele lansate își continuă traiectoria.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie de comunicare inter proces


Am descoperit pointerii la funcții
PARALEL

M-am gândit că atunci când pun un lucru pe un raft şi notez sau ţin minte unde l-am pus în-
seamnă că am ţinut minte sau am notat adresa unde se găseşte acel lucru.
Dacă obiectul este o ciocolată atunci el seamănă cu o dată primitivă sau cu un obiect şi
înseamnă că hârtia pe care am notat adresa este un pointer către obiect sau respectiv spre
data primitivă.
Pe raft pot să pun şi un robot de bucătărie sau doar o maşină de tocat carne sau o
ascuţitoare care ascute creioane adică ceva cu care se poate executa un process.
La fel ca şi în cazul ciocolatei pot să notez locul adică adresă unde am pus acel mecanism de
făcut chestii. Aceste maşinării care pot executa un process seamănă cu funcţiile.
Când mi-am dat seama de asta am întrebat-o pe Katy dacă nu cumva funcţiile sunt şi ele
stocate undeva în memorie şi dacă nu cumva pot afla şi folosi adresa de memorie unde se
află.
A zis că nici asta nu le-a scăpat celor care au inventat limbajele de programare şi că într-
adevăr şi funcţiile sunt stocate undeva în memorie la o anumită adresa şi că numele lor este
de fapt numele acelei locaţii unde sunt puse. Ca şi în cazul variabilelor primitive.
Mi-a mai zis că la fel ca şi în cazul variabilelor pot afla şi adresa funcţiilor şi le pot accesa
folosind-o.
Am aflat că în limbajul C pointerii către o funcţie se numesc pointeri la funcţie şi reprezintă
adresa unde este stocată funcţia. Adică adresa de unde începe rutina respectivă,
Un pointer la o funcţie se declară aşa:
tip_returnat (*nume_pointer)(... declaraţii parametri ...);
Am implementat o funcţie f1 şi un pointer spre funcţie numit f1_ptr, după care am încercat
să văd dacă pot să apelez funcţia folosind pointerul
#include <stdio.h>
void f1(int a)
{
printf("%d\n",a);
}

© Bitulică 2020
Povestea lui Bitulică

void main(void)
{
void (*f1_ptr)(int);
f1_ptr=f1;
(*f1_ptr)(4);
}
În cazul tablourilor care sunt pointeri către primul element al lor dacă vreau să atribui un
tablou la un pointer pot să atribui direct. Adică dacă f1 era un tablou scriam aşa:
f1_ptr=f1;
Am citit că pointerii la funcţie sunt folosiţi în implementarea evenimentelor. Un eveniment
este ceva se produce în sistem.
Fie că este cauzat de un utilizator fie de o altceva evenimentul reprezintă întreruperi pe
procesor care sunt apoi evaluate de sistemul de operare şi în funcţie de rezultat este activat
un pointer către o funcţie care este delegată să facă ceva corespunzător în funcţie de tipul
evenimentul produs.
De exemplu când dau click pe un buton sistemul de operare percepe evenimentul prin
întreruperea produsă de acesta pe procesor şi deleagă o funcţie să facă ce trebuie să se
întâmple când cineva a apăsat pe acel buton.
Componentele unui eveniment sunt listenerul adică acel modul care trage cu urechea să
vadă dacă se întâmplă ceva şi care tehnic este cel care tratează întreruperile pe procesor
care se declanşează atunci când se întâmplă ceva, handlerul adică pointerul la funcţie care
se activează când listerul decide cine trebuie să trateze acel eveniment şi delegate-ul care
este funcţia spre care punctează pointerul la funcţie şi care execută ceva corespunzător în
funcţie de tipul evenimentului şi de dorinţa programatorului.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie de folosire în comun


Am descoperit transferul asincron
PARALEL

Într-o zi ne-am apucat să facem curăţenie prin casă. Eu Lisa Katy şi Evy. Ne-am împărţit sar-
cinile astfel încât fiecare să facă curățenie în câte o cameră la un moment dat. Deci practic
fiecare era cu treaba lui şi fiecare făcea curăţenie în camera care i-a revenit astfel încât nu
ne călcăm pe bătături unul pe altul.
Noi avem un aspirator din acela care se plimba singur prin casă şi face curăţenie regulat
când crede el că e ceva de strâns dar acum când ne-am apucat am folosit aspiratorul cu
aburi pentru a curăţa şi canapelele şi ce mai era de curăţat.
Avem un aspirator din acela circular care se plimba singur şi unul din acela cu jet de abur.
Cum fiecare făcea curăţenie în camera lui plimbam aspiratorul acela cu jet de la unul la
altul. Făceam eu ceva apoi i-l dădeam lui Evy. Făcea Evy ceva apoi îl dădea Lisei. Făcea Lisa
ceva îl dădea lui Katy. Apoi iar îl primeam eu şi tot aşa până am terminat.
Deşi obosită Katy a zis că i-a venit o idee. Eu eram ochi şi urechi şi îmi ziceam să nu cumva
să îi fi venit vreo idee să mai facem pe undeva curăţenie că obosisem. Dar nu. I-a venit o
idee să îmi explice că ce am făcut noi cu aspiratorul pot să fac şi între firele de execuţie.
Adică să plimb o resursă între ele. O valoare a unei variabile sau un obiect depinde ce vreau.
Aşa că am mers în dormitorul meu unde am computerul. Acolo fusese camera lui Katy unde
a făcut curăţenie şi probabil ştergând computerul de praf i-a venit ideea asta că numai la
programare se gândeşte sau poate se gândeşte doar cum să mă înveţe pe mine.
Oricum ar fi eu sunt bucuros aşa că m-am aşezat cuminte la computer şi am scris codul de
mai jos să mă conving şi eu de ce zice Katy.
#include <iostream>
#include <future>
#include <thread>
using namespace std;
void func(std::promise<int> result_promise) noexcept
{
result_promise.set_value(42);
}
int main()
{

© Bitulică 2020
Povestea lui Bitulică

std::promise<int> result_promise;
std::future<int> result_future = result_promise.get_future();
std::thread t{ func, std::move(result_promise) };
int result = result_future.get();
t.join();
cout << result << endl;
return 0;
}
Am inclus librăria iostream ca să pot să folosesc funcţiile standard apoi am mai inclus
librăria thread ca să pot să folosesc funcţiile şi tipurile de date pentru fire de execuţie şi am
inclus şi librăria future ca să pot să promit date firelor de execuţie şi să mă pot şi tine de
promisiune iar acestea să le obţină în viitor.
Am făcut o funcţie care primeşte ca argument o dată de tip promise. Promise înseamnă
promisă. Adică o valoare pe care o promit cuiva că i-o voi da. A promite înseamnă că nu i-o
dau pe loc ci că o să i-o dau în viitor. Cu alte cuvinte livrarea datei se face asincron. Sincron
înseamnă că eu fac ceva şi cineva stă după mine până termin. Dacă dau ceva sincron cineva
stă cu mâna întinsă până i-o dau. Dacă dau o dată asincron acel cineva îşi vede de treabă şi
când o să am data o să îl trag eu de mânecă ca să întindă mâna să i-o dau.
În cadrul funcţie am setat dată promisă cu valoarea 42. Adică vreau să pun funcția pe un
thread ca un fir de execuţie să promită altui fir de execuţie că o să îi dea valoarea 42.
În funcţia main adică funcţia principală a programului pe care o execută sistemul de
operare când este lansat programul în execuţie am declarat o variabilă de tip promise. Tipul
promise este în librăria future în spaţiul de nume standard din acea librărie adică std. De
aceea am scris std::promise
Am declarat o variabilă de tip future std::future<int> result_future şi i-am spus că acolo va fi
locul unde o să pun dată atunci când o să o livrez. Deci i-am atribuit valoarea promisă
asincron adică o va primi în viitor atribuindu-i result_promise.get_future(); Future
înseamnă viitor.
Apoi am creat un thread pe care am asignat funcţia definită anterior în cadrul căreia se va
face livrarea şi o funcţie de callback numită std::move care va ști când se va efectua livrarea
și care va prelua livrarea.
std::thread t{ funcţie, std::move(result_promise) };
Adică acest thread va avea la el valoarea 42 pe care o va livra cuiva.
Callback vine de la call care înseamnă a chema și back care înseamnă înapoi. Adică cineva
care te strigă să vii înapoi să iei ceva pe care l-ai lăsat să fie prelucrat. Katy zice că e ca la
service. Duc un produs și mă anunță ei când să mă duc să-l iau.

© Bitulică 2020
Povestea lui Bitulică

În final i-am zis programului principal care este şi el tot un thread la origine să ia valoarea
42 de la thread-ul lansat anterior.
int result = result_future.get();
Pe care după ce am asteptat să se termine thread-ul
t.join();
am afişat-o să văd şi eu dacă a luat-o sau nu.
cout << result << endl;
Puteam să văd asta şi folosind instrumentele de debug din Visual Studio. Puteam să dau
click pe bara din stânga ferestrei de editare şi să pun un punct roşu care semnifică un
breakpoint. Un breakpoint aşa cum îi spune şi numele este un punct unde programul ia o
pauză. Break înseamnă spărtură în ceva care are şi sensul de pauză şi point înseamnă punct.
Dacă apăsam F5 ca să rulez, programul s-ar fi oprit în punctul acela şi dacă aveam grijă ca
până la acel punct să fi executat linia unde se preia valoare în programul principal puteam
să ţin mouse-ul pe variabila result şi să văd ce valoare are. Sau puteam să o selectez şi să
dau click dreapta şi să mă duc la quick watch sau la add watch şi să văd ce valoare are. Am
citit că add watch adună variabile pe care le adaug și îmi arată valorile tuturor într-o
fereastră.
După ce programul se opreşte într-un breakpoint pot să apăs F10 dacă vreau să treacă din
instrucţiune în instrucţiune pe nivelul pe care sunt sau să apăs F11 ca să intre în interiorul
funcţiilor şi deci să treacă pe un nivel mai jos unde pot să apăs din nou F10 dacă vreau să
merg din instrucţiune în instrucţiune pe acest nivel.

© Bitulică 2020
Povestea lui Bitulică

Când am folosit în comun


Am descoperit semaforizarea
PARALEL

Când mergeam cu maşina prin oraş întorcându-mă de la birou şi fiind cu Katy în maşină,
înainte de o intersecţie nesemaforizată a apărut ca din senin din stânga o altă maşină şi am
frânat brusc.
Katy a zis că ar trebui un semafor pus acolo că e vizibilitatea redusă şi nu vezi prea departe
nici în stânga nici în dreapta şi singura soluţie e să mergi încet ca să poți să opreşti dacă
apare ceva din cele două direcţii.
Eu i-am spus că într-o intersecţie că asta regulă care se aplică este prioritatea de dreapta
dar ea insista că e nevoie de un semafor şi mi-a explicat că acea intersecţie este o zonă
critică pentru că acolo se pot întâmpla accidente şi că orice zonă critică trebuie
semaforizată atunci când prin ea pot trece două mașini simultan fără să le oprească nimeni.
A zis că ştie ea de la informatică. O ști că la școala de șoferi nu a vrut să se ducă.
I-am zis că dacă tot a adus vorba să îmi spună şi mie cum e cu zonele astea critice în
informatică şi a zis că atunci când două fire de execuţie trebuie să execute acelaşi cod al
cărui rezultat s-ar altera dacă ar trece în acelaşi timp două threads-uri prin el sau ar putea
genera blocaje în sensul că nu mai poate continua niciun fir de execuţie se numeşte zona
critică.
A mai zis că pentru a evita accidentele aceste zone critice se semaforizează adică se pune un
semafor împrejurul lor ca prin ele să treacă doar un singur fir de execuţie la un moment dat
sau măcar să limiteze numărul de fire de execuţie care trec prin ele.
Mi-a spus că atunci când trece doar un singur thread prin acea zonă se mai spune că zona
este sincronizată şi că sincronizatul ăsta este un caz particular de semafor.
Pentru a sincroniza două fire de execuţie Katy zice că am nevoie de un concept care se
numeşte mutex şi care este ca un semafor de circulaţie în două culori. Mutex-ul este o
variabilă care poate lua două stări blocat sau deblocat pe care threadurile îl urmăresc.
Mutex-ul este setat înainte şi după zona critică.
std::mutex mtx;
void funcţie()
{
mtx.lock();
// aici e codul din zona critică
mtx.unlock();
}

© Bitulică 2020
Povestea lui Bitulică

Dacă acest cod este executat de două fire de execuţie în acelaşi tip primul va bloca mutex-ul
iar al doilea va vedea că e blocat şi va sta blocat până când mutex-ul se deblochează. Mutex-
ul se deblochează în momentul când primul thread a terminat de executat zona critică şi a
ajuns la mtx.unlock() adică a pus din nou semaforul pe verde.
Chiar dacă logică e bună în principiu acest cod poate provoca blocaje şi nu este recomandat
să fie folosit în forma asta.
Dacă un thread dă eroare în secţiunea critică mtx.unlock() nu se mai execută şi semaforul
va rămâne pe roşu. Astfel nici un alt thread nu va mai continua.
Pentru a corecta acest neajuns şi a evita blocarea pot să fac aşa
std :: mutex mtx;
void funcţie ()
{
std :: lock_guard < std :: mutex > lck {mtx};
// ce am de executat
}
În acest caz dacă dă eroare se va debloca automat semaforul pentru că erorile se propagă de
jos în sus şi programul va ieşi din funcţie ceea ce face ca lck să își piardă scopul şi mutex-ul
să revină la vechea stare.
Dacă un fir de execuţie are nevoie de mai mult de un semafor adică un mutex atunci trebuie
să fiu atent când le deblochez să le deblochez în aceasi ordine că altfel cauzez un blocaj dacă
firele se intercalează.
De exemplu programul ăsta cauzează un blocaj
#include <iostream>
#include <chrono>
#include <mutex>
#include <thread>
struct CriticalData
{
std::mutex mut;
};
void deadLock(CriticalData& a, CriticalData& b)
{

© Bitulică 2020
Povestea lui Bitulică

std::lock_guard<std::mutex>guard1(a.mut);
std::cout << "Thread: " << std::this_thread::get_id() << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1));
std::lock_guard<std::mutex>guard2(b.mut);
std::cout << "Thread: " << std::this_thread::get_id() << std::endl;
// ce am de făcut
}
int main()
{
std::cout << std::endl;
CriticalData c1;
CriticalData c2;
std::thread t1([&]{deadLock(c1, c2);});
std::thread t2([&]{deadLock(c2, c1);});
t1.join();
t2.join();
std::cout << std::endl;
}
Blocajul e dat de secvența
std::thread t1([&]{deadLock(c1, c2);});
std::thread t2([&]{deadLock(c2, c1);});
Pentru că cele două threads-uri închid şi deschis cele două mutex-uri în ordine diferită.
Dacă primul îl Închide pe c2 al doilea îl găseşte închis şi stă la semafor până i se lungesc
urechile.
Cea mai usoară metodă de rezolvare este blocarea de tip atomic a celor două mutex-uri.
void deadLock(CriticalData& a, CriticalData& b)
{
std::unique_lock < std::mutex > guard1(a.mut, std::defer_lock);
std::unique_lock < std::mutex > guard2(b.mut, std::defer_lock);
std::lock(guard1, guard2);

© Bitulică 2020
Povestea lui Bitulică

// ce am de făcut
}
O operaţie atomică este o operaţie care nu poate fi divizată la niciun nivel în mai multe
operații. Când eu zic că aprind atomic 2 becuri ele se aprins simultan.
Cum Newton a zis că nu se pot sincroniza ceasurile şi Einstein a zis că viteza luminii e cea
mai mare din univers înseamnă că o operaţie atomică nu se poate realiza fără ca cele două
operaţii să fie sincronizate artificial.
Raţionamentul e bun dar e valabil doar pentru computerele cu un singur procesor. Dacă
cele două operaţii se execută pe procesoare diferite atunci sincronizare naturală este
posibilă.
Ultimul cod de mai sus este valabil pentru implementarea 11 a C++ adică C++11. În C++17
pot să fac aşa
void deadLock(CriticalData& a, CriticalData& b)
{
std::scoped_lock(a.mut, b.mut);
// ce am de făcut
}
Deadlock înseamnă impas şi termenul se foloseşte atunci când două fire de execuţie rulează
în paralel şi se blochează unul pe altul.
Zonele critice se formează atunci când două fire de execuţie folosesc o resursă comună. De
aceea programarea paralelă este şi concurenta pentru că firele de execuție au nevoie de
resurse comune pentru a duce la îndeplinire ce au de făcut.
De exemplu când vor să citească sau să scrie ceva pe disc.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie să păstrez


Am descoperit persistența
PERSIST

Lumea virtuală încearcă să fie o proiecție a lumii reale.


Asta pentru că omul a sperat mereu încă de când l-a inventat ca un PC să poată gândi și
comporta ca un om.
Astfel a încercat să îl conceapă după cum e făcut omul . Fiecare componentă a unui PC este
gândită să semene în funcții cu organele umane și fiecare chestie cu care lucrează PC-ul are
un corespondent în lumea reală. Camerele web sunt ochii, microfoanele urechile, boxele
gura, monitorul fața, unitatea centrală creierul.
Așa cum știu foaia din lumea reală este egală cu fișier din lumea virtuală. Dosar (mai multe
foi) din lumea reală este egal cu Director (Folder) în lumea virtuală.
În document are în lumea reală un antet și un corp (cap, trunchi)
În antet se scriu informații care ajută la interpretarea a ce este scris în document precum și
date de arhivare pentru documentul respectiv că să știu la ce folosește ca data emiterii.
Pe acest principiu a fost construit și un fișier în lumea virtuală.
Are un antet care se numește Header (header file) şi un corp care conține datele din fișier
(text sau biţi) în funcție de tipul fișierului (fișier text sau fișier binar). Un exemplu de fișier
text este Ana.txt iar un exemplu de fișier binar este Ana.exe
Datele cu care lucrează un program se pierd atunci când computerul este scos din priză şi
atunci dacă vreau să le păstrez trebuie să le stochez pe un dispozitiv care nu necesită
alimentare cu curent pentru a le putea păstra. Unul dintre aceste dispozitive este hardiscul.
Sau discul dur.
A pune datele din memoria RAM pe hard înseamnă că persist aceste date. Persistent
înseamnă ceva ce rămâne multă vreme neschimbat.
E ca şi cum aş face borcane cu murături pentru iarnă din legume proaspete pe care le pun în
cămară.
Ca şi în cazul murăturile datele persistente pe hardisc pot fi atât puse cât şi luate de acolo
înapoi în RAM atunci când este nevoie de ele.
Un fişier este un bloc delimitat de date pe un anumit dispozitiv. În sens larg şi monitorul şi
tastatura sunt considerate fişiere. Fişiere standard de ieşire şi respectiv intrare. În sens mai
restrâns un fişier este un bloc de date delimitat de un delimitator care se numeşte EOF de la
End Of File adică sfârşit de fişier. Datele sunt stocate pe hardisk organizate în fişiere. Mai
multe fişiere pot fi organizate în foldere.
Am văzut că pentru a citi date de la tastatură în C++ pot să folosesc funcţia cin sau scanf

© Bitulică 2020
Povestea lui Bitulică

cin >> a;
scanf("%d",a);
Iar pentru a scrie date pe monitor pot să folosesc funcţiile cout sau printf
cout << a;
printf("%d",a);
Dacă cout vine de la console out cin vine de la console in. Dacă printf vine de la formated
print scanf vine de la formated scan. A scana are sensul de a explora pas cu pas.
Dacă dispozitivele unde scriu şi citesc datele nu mai sunt dispozitivele standard de intrare
şi ieșire ci un fişiere atunci pot să folosesc librăria fstream.
#include <iostream>
#include <fstream>
using namespace std;
int main ()
{
ofstream myfile ("exemplu.txt");
if (myfile.îs_open())
{
myfile << "Aceasta este o linie.\n";
myfile << "Aceasta este alta linie.\n";
myfile.close();
}
else cout << "Nu se poate deschide fişierul";
return 0;
}
În acest cod am importat librăria fstream care conţine funcţii pentru lucru cu fişiere şi am
folosit din ea tipul ofstream.
Stream înseamnă date care circulă dintr-un loc în altul. Dacă datele sunt la origine biţi când
spun că circulă datele înseamnă că circulă biții. Sunt biţi care curg şi formează râuri de biţi.
Stream în engleză înseamnă ceva care curge sau rău. Litera f din ofstream vine de la file care
înseamnă fişier iar o vine de la output. Cu acest tip de obiect se scriu date în fişier deci se
scot afară din memoria RAM.

© Bitulică 2020
Povestea lui Bitulică

După ce am pus datele în fişier la păstrare adică le-am salvat pentru a nu se fi pierdut când
scoteam PC-ul din priză pot să le readuc în memoria RAM citindu-le din fişier
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main ()
{
string line;
ifstream myfile ("exemplu.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n';
}
myfile.close();
}
else cout << "Nu se poate deschide fişierul";
return 0;
}
În cele două coduri sursă metoda is_open() verifică dacă fişierul se poate deschide pentru a
scrie sau citi din el. Un fişier se poate deschide în mai multe moduri. Pentru citire sau
pentru scriere.
Modul pentru scriere cuprinde mai multe sub moduri ca scrierea prin ştergere şi rescriere a
informaţiei sau scrierea prin adăugare de informaţii la informaţiile existente.
De exemplu puteam să scriu aşa
#include <stdio.h>
int main ()
{

© Bitulică 2020
Povestea lui Bitulică

FILE * pFile;
pFile = fopen ("myfile.txt","w");
if (pFile!=NULL)
{
fputs ("fopen example",pFile);
fclose (pFile);
}
return 0;
}
Litera w vine de la write şi înseamnă că am deschis fişierul în modul de scriere.
• r read

• w write

• a append
• r+ read/update

• w+ write/update

• a+ append update
Fişierele pot fi text sau binare iar cele binare pot fi cu tip sau fără.
La cele cu tip informaţia este de tip structură iar structurile sunt ca nişte rânduri într-un
tabel în timp ce la cele fără tip informaţia este un singur bloc de biţi.
Din categoria acestora din urmă fac parte fişierele imagine şi filmele.

© Bitulică 2020
Povestea lui Bitulică

Când ce am avut de păstrat au fost poze


Am descoperit fișierul binar
PERSIST

Fişierele binare au în interiorul lor un bloc de biţi care a fost scris în prealabil. Acest bloc
poate reprezenta de exemplu o imagine.
O imagine de tip bitmap (.bmp) este un bloc de biţi care reprezintă nişte numere. Aceste
numere sunt caracteristicile unui punct pe ecran. Poziţia pe axa x poziţia pe axa y şi
culoarea.
Culoarea la rândul ei poate fi reprezentată în codul RGB adică Red Green Blue care sunt tot
nişte numere. De exemplu culoarea alb este reprezentată de numerele 255 255 255. Fiecare
nuanţă de culoare este una din culorile PROTV-ului sunt culorile fundamentale în definirea
culorilor în mediul digital.
Orice culoare pe un ecran este formată din combinarea lui roşu verde şi albastru. Fiecare
nuanţă de culoare poate fi reprezentată pe 8 biţi ceea ce înseamnă că o culoare este
reprezentată pe 3*8=24 de biţi
Dacă vreau să scriu un număr întreg într-un fișier binar pot să fac aşa
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int my_int = 10;
ofstream OutFile;
OutFile.open("exemplu.bin", ios::out | ios::binary);
OutFile.write((char*)&my_int, sizeof(int));
OutFile.close();
return 0;
}
iar dacă vreau să citesc un bloc de biţi dintr-un fişier binar pot să fac aşa
#include <iostream>
#include <fstream>

© Bitulică 2020
Povestea lui Bitulică

using namespace std;


int main()
{
streampos size;
char* memblock;
ifstream file("exemplu.bin", ios::in | ios::binary | ios::ate);
if (file.is_open())
{
size = file.tellg();
memblock = new char[size];
file.seekg(0, ios::beg);
file.read(memblock, size);
file.close();
cout << "Am copiat conţinutul fişierului în memoria RAM";
delete[] memblock;
}
else cout << "Nu am putut deschide fişierul";
return 0;
}
Metoda seekg poziţionează cursorul de citire (cum ar fi acul de pickup) la o anumită poziţie
în fişier pentru a se începe citirea biţilor începând cu acea poziţie.
ios::în înseamnă că fişierul este deschis în modul citire în vine de la faptul că datele intră în
stream ca să fie duse undeva
ios::binary înseamnă că datele sunt biţi deci stream-ul va lua câte un bit nu un octet adică
un caracter dacă encodarea este UTF-8 ceea ce înseamnă caractere codate pe 8 biti adică un
octet.
ios::ate înseamnă că în momentul când este deschis fişierul capul de citire sare la ultimul bit
din fişier. Adică se deschide fişierul în regim de adăugare de informaţie adică append
Funcţia tellg() returnează dimensiunea în biţi a fişierului.

© Bitulică 2020
Povestea lui Bitulică

Variabila memblock este un buffer adică o variabilă temporară care reţine informaţia citită
din fişier. Este nevoie de un buffer atunci când două dispozitive nu rulează la aceeași viteza
adică frecvenţa în cazul componentelor hardware.
Procesorul , memoria RAM şi hardisk-ul nu lucrează la aceeași frecventă şi dacă nu ar exista
acest buffer s-ar pierde date.
E ca şi cum un om ar fi suit pe casă să pună ţigle şi unul i-ar da ţiglele de jos.
Cel care le da de jos le da mai repede decât poate să le monteze cel de pe casă şi atunci cel
care i le da le pune undeva într-o grămadă pe casa de unde cel care le montează le ia pe
măsură ce le termină de montat pe cele pe care le-a luat deja.

© Bitulică 2020
Povestea lui Bitulică

Când ce am avut de păstrat tabele de date


Am descoperit fișierul cu tip
PERSIST

Eu deocamdată aici în SUA lucrez pe vânzări la compania Riverbites şi am nevoie de liste cu


clienţi actuali sau potenţiali. Listele mi le fac în tabele în care pe fiecare rând trec numărul
de ordine al clientului numele şi numărul de telefon. Adică practic am o listă de contacte ale
clienţilor potenţiali şi actuali.
Lisa lucrează în cadrul departamentului de resurse umane şi are şi ea un astfel de tabel cu
angajaţii companiei dar şi cu potenţialii angajaţi adică cei care sunt în proces de recrutare
sau cu cei pe care îi urmăreşte să îi recruteze.
Evy că e la şcoală are şi ea un orar în care sunt trecute materiile dar şi colegii că aici în
Statele Unite sistemul de învățământ de la liceu presupune să îţi alegi cursurile şi are colegi
diferiţi la cursuri diferite şi nu îi ştie pe toţi pe dinafară.
Katy mi-a zis că aş putea să fac şi eu un nomenclator în C++ şi să grupez informaţiile despre
anumite lucruri iar aceste grupuri de informaţie să le pun într-un fişier folosind tipul
structură care se mai numeşte şi tipul înregistrare tocmai din acest motiv. Anume că aceste
grupări de informaţie sunt puse în fişier ca nişte melodii pe o placă de pickup sau pe o
bandă de magnetofon sau pe un CD sau DVD sau BlueRay şi cine vrea să asculte o
înregistrare poate derula sau sari până la acea înregistrare.
Nomenclator înseamnă un tabel în care există informații despre o singură entitate.
Informațiile despre acea entitate cuprind doar informații legate de atributele care îi
definesc integritatea structurală. De exemplu nomenclatorul de cărți cuprinde : Titlu,
autorul, număr pagini și așa mai departe. Fără a conține informații despre a cui e cartea sau
unde e pusă căci dacă o carte e obiect pierdut în spațiu tot carte e.
Deci această informație nu îi afectează integritatea structurală. Dar dacă o carte nu are
autor fie el și necunoscut nu mai este o carte căci o carte trebuie sa fi fost scrisă de cineva că
doar nu s-a scris singura.
Am făcut cu Katy un mic exemplu că să înţeleg şi cum era şi Evy pe lângă noi şi zicea că se
gândeşte cum o să fie la facultate am introdus în cod noţiunea de student
#include<iostream>
#include<fstream>
using namespace std;
struct Student
{
int roll_no;

© Bitulică 2020
Povestea lui Bitulică

string name;
};
int main()
{
ofstream wf("student.dat", ios::out | ios::binary);
if (!wf)
{
cout << "Nu am putut deschide fisierul!" << endl;
return 1;
}
Student wstu[3];
wstu[0].roll_no = 1;
wstu[0].name = "Lisa";
wstu[1].roll_no = 2;
wstu[1].name = "Katy";
wstu[2].roll_no = 3;
wstu[2].name = "Evy";
for (int i = 0; i < 3; i++)
wf.write((char*)&wstu[i], sizeof(Student));
wf.close();
if (!wf.good())
{
cout << "A aparut o eroare in timp ce scriam in fisier" << endl;
return 1;
}
ifstream rf("student.dat", ios::out | ios::binary);
if (!rf)
{
cout << "Nu am putut deschide fisierul" << endl;

© Bitulică 2020
Povestea lui Bitulică

return 1;
}
Student rstu[3];
for (int i = 0; i < 3; i++)
rf.read((char*)&rstu[i], sizeof(Student));
rf.close();
if (!rf.good())
{
cout << "Error occurred at reading time!" << endl;
return 1;
}
cout << "Studentii din fisier sunt:" << endl << endl;
for (int i = 0; i < 3; i++)
{
cout << "Numar matricol: " << wstu[i].roll_no << endl;
cout << "Nume: " << wstu[i].name << endl;
cout << endl;
}
return 0;
}
Practic am creat structuri separate pentru fiecare student și le-am scris în fișier.
Apoi am luat structurile din fișier le-am pus în memoria RAM și de acolo le-am afișat.

© Bitulică 2020
Povestea lui Bitulică

Când ce am avut nevoie să transport


Am descoperit serializarea
FORMAT

Un vecin de aici şi-a mai cumpărat o casă în altă zonă pentru unul dintre copii lui. A cumpă-
rat şi mobila dar copilul a vrut neapărat să aibă acolo patul în care doarme de când era mic.
Patul e mare şi nu intră pe uşile casei aşa că a trebuit demontat. L-am ajutat şi eu să îl
demonteze, să scoată afară piesele demontate şi să le urce în maşina firmei de mutări.
Am fost şi la noua casă şi l-am ajutat să dea jos piesele din maşină, să le transporte în casa şi
să monteze patul în camera unde ne-a spus fiul sau că îl vrea.
Când am ajuns acasă i-am povestit şi lui Katy toată chestia şi ea mi-a zis că adică am
serializat şi am deserializat patul. ZIc: a? ce să fac? ZIce: aşa se zice în IT la ce ai făcut tu.
Nu mai auzisem niciodată cuvintele astea aşa că am pus-o să îmi explice.
A zis că în sens larg a serializa înseamnă a pregăti ceva pentru trecerea dintr-un mediu în
altul astfel încât să fie în acord cu metoda de transport.
Trecerea se face folosind o poartă sau un tunel de trecere.
Mi-a spus că dacă vreau să trec un bagaj imens de un gard peste care îmi e imposibil să îl
arunc și singura opțiune este o poartă îngustă pe care nu pot băga bagajul întreg trebuie să
îl descompun şi să bag pe poarta bucăți din el.
Operațiunea de descompunere a bagajului este o operație de serializare.
Îl pregătesc să poată trece pe poartă și deci să respecte condițiile porţii. Cât e poarta de
îngustă atât de mari fac și eu bucățile de bagaj. Dacă poarta este un tunel şi are sine , pun la
fiecare bucată de bagaj roţi.
Deci respectând condițiile porţii pregătesc fiecare părticică din bagaj și trimit bagajul
bucată cu bucată dincolo de gard.
Dincolo bagajul îl recompun și îl fac la loc respectând condițiile de acolo. Dacă acolo e un
elefant îl recompun să se muleze pe spinarea lui , nu ca până la gard unde trebuia să îl pot
lua în spinare.
Operația executată dincolo de gard cică se numește deserializare
În informatica a serializa înseamnă a transforma informația prezentă într-un obiect, adică
atributele și valorile lor în biţi, pentru că aceștia să fie transformați în semnale electrice și
trimise pe fir la distanţă sau transformate în unde electromagnetice şi trimise prin aer dacă
trimiterea se face prin wireless unde undele electromagnetice sunt unde radio.
Acolo, la distanţă, semnalele electrice sau undele radio sunt transformate în biţi și biții din
nou în obiect.

© Bitulică 2020
Povestea lui Bitulică

A transforma în biţi este similar la nivel logic cu a transforma în string adică text pentru că
caracterele sunt nişte octeţi adică 8 biţi adică bytes.
De exemplu dacă am clasa OM cu atribute nume și vârstă , omul având proprietățile că îl
cheamă Ion și are 37 de ani, pot serializa ăsta folosind un protocol definit de mine și care
zice că între atribut și proprietate pun : (două puncte) și între două atribute pun ; (punct şi
virgulă). Adică aşa nume:Ion;vârstă:37
Trimit asta la distanţa iar acolo aplic algoritmul invers și parsând textul după ; (punct şi
virgulă) și apoi : (două puncte) obțin un obiect cu două atribute Nume și vârstă care au
valorile Ion și 37.
Am încercat să fac o clasă cu metode atât de serializare cât si de deserializare ca să văd dacă
îmi iese și mi-a ieșit codul de mai jos
#include <iostream>
#include <string>
using namespace std;
class A
{
public:
string a;
int b;
char c;
string serialize();
A deserialize(string);
};
string A::serialize()
{
string retval;
retval += a;
retval += "|";
retval += to_string(b);
retval += "|";
retval += c;

© Bitulică 2020
Povestea lui Bitulică

return retval;
}
A A::deserialize(string text)
{
A retval = A();
int index = 0;
string temp = "";
for (int i = 0; i < text.length(); i++)
{
if (text[i] == '|')
{
if (index == 0)
retval.a = temp;
else if (index == 1)
retval.b = atoi(temp.c_str());
temp = "";
index++;
}
else
temp += text[i];
}
retval.c = temp[0];
return retval;
}
int main()
{
A a_object = A();
a_object.a = "test";
a_object.b = 1;

© Bitulică 2020
Povestea lui Bitulică

a_object.c = 'A';
string a_object_serializat = a_object.serialize();
cout << "Obiectul serializat " << a_object_serializat << endl;
A b_object = b_object.deserialize(a_object_serializat);
cout << "b_object.a " << b_object.a << endl;
cout << "b_object.b " << b_object.b << endl;
cout << "b_object.c " << b_object.c << endl;
return 0;
}
Metoda prin care se serializează un obiect trebuie să fie cunoscută de cel care va deserializa
obiectul pentru ca să știe cum să facă algoritmul. În codul astă eu am si serializat și tot eu
am și deserializat obiectul și de asta am știut cum să fac dar dacă trimiteam obiectul pe
rețea altcuiva fără să știe ordinea în care am pus valorile atributelor și ce separator am
folosit nu ar fi știut să facă algoritmul de parsare a textului pentru a deseriliza obiectul.
Putea doar să încerce să îl decodifice. Poate până la urmă reușea dar nu i-ar fi fost ușor.
Pentru a nu exista problema asta între cel care scrie algoritmul de serializare și cel care
scrie algoritmul de deserilizare modelele de serializare au fost standardizate în mai multe
modele dintre care cele mai utilizate sunt XML și JSON.
Am înțeles că atunci când trimit o poză de pe Facebook pe Instagram sau invers imaginea
este serializată de aplicația sursă și deserilizată de aplicația destinație.

© Bitulică 2020
Povestea lui Bitulică

Când ce am avut nevoie să cifrez


Am descoperit codarea
FORMAT

În camera lui Katy există un dulap cu uşi din acelea pătrate şi multe, unde şi-a băgat diferite
tipuri de haine. Într-un compartiment are cămăşi, în altul bluze în altul șosete şi în felul ăsta
şi-a aranjat toate tipurile de îmbrăcăminte.
Eu ştiam asta dar nu ştiam că pe uşi a lipit şi numere iar când am întrebat-o ce e cu ele acolo
a zis că aşa găseşte mai repede ce caută fiindcă ştie cărui tip de îmbrăcăminte îi corespunde
fiecare număr şi că de exemplu pălăriile sunt ultimul număr că pe ele le ia ultimele.
Mie mi s-a părut interesantă chestia asta şi a zis că ce a făcut ea se numeşte encodare şi că
se întâlneşte des în tehnologia informaţiei.
A zis că cel mai clar se vede la caractere unde fiecare simbol are ataşat un număr iar întreg
codul se numeşte codul ASCII.
A stat lângă mine ca să înţeleg şi eu cum stă treaba cu encodarea şi am făcut un exemplu
#include <iostream>
#include <strâng>
using namespace std;
int main()
{
string a = "ana are mere";
cout << a << endl;
string a_encodat = "";
for (int i = 0; i < a.length(); i++)
{
string temp = to_string((int)a[i]);
for (int k = temp.length(); k < 3; k++)
temp = "0" + temp;
a_encodat += temp;
}
cout << a_encodat << endl;

© Bitulică 2020
Povestea lui Bitulică

a = "";
for (int i = 0; i < a_encodat.length(); i+=3)
{
string temp = "";
for (int k = i; k < i + 3; k++)
temp += a_encodat[k];
a += atoi(temp.c_str());
}
cout << a << endl;
return 0;
}
Am transformat fiecare caracter al textului într-un şir de numere în care fiecare trei cifre
reprezintă codul ASCII al caracterului.
Dacă codul caracterului are mai puţin de 3 cifre am completat cu zerouri în faţă ca să pot să
decodez că altfel nu aş fi ştiut care cod are 1, care are 2, şi care are 3 cifre.
Când am decodat înapoi am parcurs şirul encodat şi am luat câte trei cifre pe care ştiind că
reprezintă codul ASCII al unui caracter le-am transformat în caractere.
Eu am făcut un algoritm propriu de encodare pe care nu îl ştie nimeni ci doar eu. Aşa că
dacă trimiteam mesajul encodat cuiva ar fi trebuit să îi spun şi care este algoritmul de
encodare ca să îl poată înțelege.
Pentru a se putea trimite mesaje codate între două persoane care nu se cunosc sau între
două aplicaţii dezvoltate de programatori diferiţi care nu au vorbit niciodată encodarea a
fost standardizata pentru diferite tipuri de mesaje.
Există sisteme de encodare că alfabetul morse, codarea seturilor de caractere în UTF-8 sau
UTF-16 sau codarea mesajelor de tip SMS pe 7 biţi.

© Bitulică 2020
Povestea lui Bitulică

Când ce am avut nevoie să ascund


Am descoperit criptarea
FORMAT

După ce am văzut dulapul din camera ei şi am înţeles de ce arată aşa Katy mi-a arătat un bi-
let de la un băiat care ea zice că o place şi îi lipeşte bilete pe birou.
Când m-am uitat pe el nu am înţeles nimic şi Katy a început să râdă şi a zis că dacă vreau să
înţeleg ce scrie îmi trebuie o cheie. M-am uitat nedumerit al ea şi văzându-mă a zis că
mesajul ăla e criptat şi că e încuiat cu o cheie.
Zic adică cum? Zice că băiatul ăla adăugă la codul ASCII al fiecărui caracter codul ASCII al
caracterului corespunzător din parolă adică din cheie.
Tot nedumerit am rămas şi am întrebat ce face dacă cheia e mai mică decât textul iar Katy
mi-a zis că reia caracterele din cheie de la primul dacă se termină. Adică dacă cheia este
"ion" şi textul este "ana are gem" adună codul ASCII al lui i cu al lui a, al lui o cu al lui n, al lui
n cu al lui a şi apoi adună codul ASCII al lui i cu al lui space adică spaţiul ăla dintre "ana" şi
"are" şi continuă.
Am făcut împreună un astfel de algoritm nu înainte să îmi spună de ce criptează băiatul ăla
mesajele. A zis că pentru ca să nu vadă alţii colegi ce îi transmite.
#include <iostream>
#include <strâng>
using namespace std;
int main()
{
string cheie = "bitulica";
string a = "ana are mere";
cout << a << endl;
string a_encodat = "";
int index = 0;
for (int i = 0; i < a.length(); i++)
{
if (index > cheie.length() - 1)
index = 0;

© Bitulică 2020
Povestea lui Bitulică

string temp = to_string((int)a[i] + (int)cheie[index++]);


for (int k = temp.length(); k < 3; k++)
temp = "0" + temp;
a_encodat += temp;
}
cout << a_encodat << endl;
a = "";
index = 0;
for (int i = 0; i < a_encodat.length(); i+=3)
{
string temp = "";
for (int k = i; k < i + 3; k++)
temp += a_encodat[k];
if (index > cheie.length() - 1)
index = 0;
a += atoi(temp.c_str()) - (int)cheie[index++];
}
cout << a << endl;
getchar();
return 0;
}
Am setat o parolă, am scris un mesaj, şi am codat mesajul folosind parola astfel încât codul
ASCII al fiecărui caracter al mesajului să fie adunat cu caracterul corespunzător ca poziţie
din parolă.
Dacă parola e mai scurtă ca mesajul reiau caracterele din parolă de la primul la ultimul până
când se termină mesajul.
După ce am criptat mesajul am aplicat algoritmul invers folosind din nou parola şi am
readus mesajul la forma inițială.
Am înţeles că acesta practică este folosită la criptarea datelor dintr-un fişier sau la criptarea
unei parole a unui utilizator prezentă pe un server pentru a nu putea fi decriptată de
administratorii serverului respectiv.

© Bitulică 2020
Povestea lui Bitulică

Katy mi-a zis că există algoritmi standard de criptare foarte puternici şi că criptarea se
poate face fie prin trecerea codului ASCII printr-o funcţie cum am făcut eu, fie prin
interschimbarea caracterelor între ele fie prin interschimbarea biţilor fiecărui caracter
între ei. Mi-a zis că cei mai cunoscuţi algoritmi de criptare sunt cel al lui Caesar care
trimitea Cleopatrei mesaje criptate, criptarea în md5, criptarea cu SHA în cele trei forme ale
sale şi că criptarea se poate face atât reversibil cât şi ireversibil şi că cheile cu care se
criptează pot fi atât publice cât şi private.
Criptarea ireversibilă poartă denumirea de criptare HASH în care textul criptat nu se mai
poate aduce la forma inițială întrucât criptarea se face cu pierdere de informaţie. E ca şi
cum aş vărsa trei cutii de vopsea de culori diferite într-o găleată şi aş încerca să pun din nou
vopseaua în cutii astfel încât fiecare culoare să fie în cutia ei.
Un alt exemplu este când o orchestră este înregistrată pe bandă şi sunetele instrumentelor
sunt suprapuse. O încercare de a separa apoi fiecare instrument în parte este imposibil
pentru că frecvenţa la care cântă de exemplu un saxofon este identică cu cea la care cânta
un acordeon. Diferă timbrul dar timbrul am înţeles că nu poate fi cuantificat.

© Bitulică 2020
Povestea lui Bitulică

Când ce am avut nevoie de spațiu


Am descoperit comprimarea
FORMAT

Într-o zi Evy faţa noastră cea mică i-a spus lui Katy faţa noastră cea mare că nu mai are loc
în dulap să-şi pună lucrurile şi că o roagă să o lase să şi le pună în dulapul ei.
Katy i-a cumpărat un aparat de vidat şi nişte saci şi a reuşit să îi facă loc în dulap eliminând
aerul din haine.
Înainte să videze hainele Katy a întrebat-o pe Evy care haine nu le poartă aşa des. Şi pe
acelea le-a vidat.
Eu eram bucuros că se ajută între ele şi că lucrează în armonie şi Katy mi-a zis că ce a făcut
ea se numeşte ca a arhivat hainele vechi reducându-le dimensiunea. Adică le-a comprimat şi
le-a pus în dulap mai în spate iar când va fi nevoie de ele le va aduce în starea lor naturală.
Mi-a zis că şi datele dintr-un computer pot fi comprimate în arhive pentru a reduce spaţiul
pe disk sau în memoria RAM şi că ele oricând pot fi readuse la starea iniţială de înainte de
arhivare prin decompresare.
Ca să mă conving am mers şi am încercat să compresez o imagine făcută din caractere şi
pusă într-un vector de texte.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string image[7] = {"aaaaaiiaaaaaa",
"aaaiiiiiiaaaa",
"aaaaaiiaaaaaa",
"aaaaaiiaaaaaa",
"aaaaaiiaaaaaa",
"aaaiiiiiiaaaa",
"aaaaaiiaaaaaa"};
int size = 0;
for (int i = 0; i < 7; i++)

© Bitulică 2020
Povestea lui Bitulică

for (int j = 0; j < image[i].length(); j++)


size++;
cout << "Imaginea iniţială" << endl << endl;
for (int i = 0; i < 7; i++)
cout << image[i] << endl;
cout << endl << "Dimensiunea iniţială este: " << size << " bytes" << endl << endl;
for (int i = 0; i < 7; i++)
{
string temp = "";
char last_char = image[i][0];
int count = 0;
for (int j = 0; j < image[i].length(); j++)
{
if (image[i][j] != last_char || j == image[i].length()-1)
{
if (j == image[i].length() - 1)
count++;
temp += to_string(count);
temp += last_char;
last_char = image[i][j];
count = 0;
}
count++;
}
image[i] = temp;
}
size = 0;
for (int i = 0; i < 7; i++)
for (int j = 0; j < image[i].length(); j++)

© Bitulică 2020
Povestea lui Bitulică

size++;
cout << "Imaginea arhivata" << endl << endl;
for (int i = 0; i < 7; i++)
cout << image[i] << endl;
cout << endl << "Dimensiunea după arhivare este: " << size << " bytes" << endl << endl;
for (int i = 0; i < 7; i++)
{
string temp = "";
for (int j = 0; j < image[i].length()-1;j+=2)
{
int count = image[i][j]-48;
char ch = image[i][j + 1];
for (int k = 0; k < count; k++)
temp += ch;
}
image[i] = temp;
}
size = 0;
for (int i = 0; i < 7; i++)
for (int j = 0; j < image[i].length(); j++)
size++;
cout << "Imaginea dezarhivata" << endl << endl;
for (int i = 0; i < 7; i++)
cout << image[i] << endl;
cout << endl << "Dimensiunea după dezarhivare este: " << size << " bytes" << endl;
return 0;
}
Am parcurs imaginea şi unde am detectat mai multe caractere de acelaşi fel unul lângă altul
am înlocuit tot şirul lor cu numărul de caractere detectat şi cu caracterul găsit în acea zonă.

© Bitulică 2020
Povestea lui Bitulică

Astfel imaginea s-a redus semnificativ. Dacă ea ar fi fost aaaabbaaaa atunci aş fi pus 4a2b4a.
Prin înlocuirea datelor redundate se reduce dimensiunea expresiei. Ca la matematică
a+a+a+a+a = 5a
Există algoritmi de compresie cu pierderi de informaţiei numiţi lossy şi care sunt folosiţi
acolo unde beneficiarul compresiei este un organ uman că urechea sau ochiul şi care poate
înţelege ce ascultă sau ce vede şi fără acele date care se pierd prin compresie si exista
algoritmi de compresie fără pierdere de informație care se numesc lossless.
De exemplu dacă o imagine este puţin neclară ochiul înţelege ce vede. La fel şi dacă sunetul
este puţin distorsionat.
Există mulţi algoritmi de compresie consacraţi. De exemplu fişierele zip folosesc
algoritmului Lempel-Ziv-Renau.
Cele mai bune metode de compresie folosesc modelele probabilistice, în care predicţiile
sunt dublate de un algoritm numit codarea aritmetică - inventat de Jorma Rissanen.
Codarea aritmetică este folosită în compresia fişierelor de tip DjVu.
Lempel-Ziv este o metodă de compresie fără pierderi. O variantă a acestei metode, numită
Deflate, optimizează compresia şi este folosită pentru formatele pkzip, gzip şi png.
Codarea Huffman este astăzi folosită ca metodă complementară pentru alte metode de
compresie. De exemplu algoritmul PKZIP, imaginile JPEG ori formatul audio mp3 folosesc
codarea Huffman.

© Bitulică 2020
Povestea lui Bitulică

Când am avut mult de muncă


Am aflat de instrumentele algoritmice
STL

În spatele casei am o curte și acolo m-am gândit că ar fi bine să avem un foișor și cum îmi
place să fac mișcare și îmi place să construiesc am zis să îl fac singur.

Când Katy m-a văzut că băteam cuie a zâmbit și a plecat iar peste un timp a revenit cu o cutie
pe care tot zâmbind mi-a dat-o și mi-a spus că ea crede câ îmi va fi de folos. Desfăcând cutia
am văzut că în ea era un ciocan pneumatic așa că am început să îl folosesc și mi-am dat
seama că fata mea Katy avea dreptate și că folosind-ul, efortul depus pentru a bate cuie se re-
duce.

Katy a venit din nou la mine, tot zâmbind, și mi-a zis că instrumente precum ciocanul pneu-
matic există și în tehnologia informației și că programatorii le-au construit pentru a le ușura
munca. Mi-a mai spus că fiecare limbaj are definite astfel de instrumente cu ajutorul cărora
programatorii care dezvoltă în limbajul respectiv își ușurează munca și astfel se pot gândi mai
liberi la algoritmul pe care îl au de implementat.

Am înțeles că atunci când tot ce ai de făcut este să bați cuie și vrei să înveți să bați cuie este
bine să le bați folosind un ciocan clasic dar în momentul în care ce ai de făcut este un lucru
mai complex care implică în anumite operații bătutul de cuie este bine să folosești ciocanul
pneumatic adică un instrument care te ajută să bați cuie fără să mai pierzi timpul să bați cu-
iele respective și mai ales fără a face risipă de efort pentru a bate acele cuie.

Katy a zis că în limbajul C++ aceste instrumente se găsesc în mai multe librării care sunt cu-
noscute laolaltă sub denumirea de STL adică standard template library.

© Bitulică 2020
Povestea lui Bitulică

După ce am făcut la foișor ce îmi propusesem pentru ziua respectivă am mers cu Katy să îmi
explice mai în detaliu despre aceste librării standard și am folosit împreună funcția creată
special pentru sortarea unui șir și care se găsește în cadrul librăriilor standard. Această func-
ție se numește sort()

Sintaxa ei este

sort(startaddress, endaddress)

Unde

startaddress este adresa primului element al vectorului

endaddress: este adresa unultimului element al zonei continue pe care se doreste sortarea

Am facut următorul program

#include <algorithm>

#include <iostream>

using namespace std;

void show(int a[], int array_size)

© Bitulică 2020
Povestea lui Bitulică

for (int i = 0; i < array_size; ++i)

cout << a[i] << " ";

int main()

int a[] = { 1, 5, 8, 9, 6, 7, 3, 4, 2, 0 };

int asize = sizeof(a) / sizeof(a[0]); // dimensiunea vectorului este greutatea intregului vector
impartita la greutatea unui singur element pentru ca toate elementele au aceeasi greutate

cout << "Vectorul inaite sa fie sortat : \n";

show(a, asize); // afisez vectorul

sort(a, a + asize); // sortez vectorul

cout << "\n\nVectorul dupa sortare :\n";

show(a, asize); // afisez vectorul sortat

© Bitulică 2020
Povestea lui Bitulică

return 0;

Acestă funcție face parte din cadrul bibiotecii algoritm din care mai fac parte funcții precum

reverse() care inversează elementele vectorului, *max_element() si *min_element() care retur-


nează elementul maxim și minim din vector, accumulate() care calculează suma elementelor
vectorului, binary_search() care implementează algoritmul de căutare binară între elementele
vectorului și returnează printr-o valoare de adevăr dacă a gasit sau nu elementul căutat,
all_of() care filtrează elementele unui array în funcție de o condiție, any_of() care verifică dacă
vreun element al unui array satisface o anumită condiție, none_of() care verifică dacă nici un
element al unui vector nu satisface o anumită condiție, copy_n() care copiaza n poziții dintr-
un array in alt array sau iota() care asignează o valoare unei zone finite dintr-un array.

© Bitulică 2020
Povestea lui Bitulică

Când a fost mai anevoios să construiesc unele


Am aflat de instrumentele container
STL

Într-o zi aveam nevoie de niște cutii și pentru că aveam niște scândură am zis să le fac eu, mai
ales că aveam și niște colțare din acelea de fier care se folosesc la construcția cutiilor.

Am făcut o cutie și îmi mi-a dat seama că scopul meu nu este acela de a construi cutiile ci
acela de a folosi niște cutii pentru a aranja lucrurile din garaj, așa că am zis că este mai bine să
comand niște cutii deja făcute în care să îmi pun lucrurile pentru că, să fac și cutiile și să și
aranjez lucrurile în ele ar dura mai mult timp, timp în care aș putea să fac altceva.

Evident că am luat această decizie pentru că știam că am de unde să comand niște cutii pen-
tru că dacă nu aș fi avut de unde o comand nu aș fi avut altă alternativă decât să le fac eu.

Am comandat cutii. Au sosit și am constatat că sunt și frumoase și bine făcute și rezistente și


per asamblu sunt mai bune decât cele pe care le aș fi făcut eu, asta pe lângă efortul pe care l-
aș fi depus ca să le fac.

Fata mea cea mare roia pe lângă mine și mi-a zis că exact așa se întâmplă și informatică și că
programatorii preferă să folosească funcții implementate în limbaj pentru a scuti timpul alo-
cat pentru a implementa dar și pentru că aceste funcții sunt implementate și testate de unii
dintre cei mai buni programatori și ele au fost optimizate de a lungul timpului de mai mulți
programatori astfel încât forma lor este cea mai bună formă posibilă până la momentul ac-
tual.

Când m-a văzut că învăț la informatică Katy mi-a zis să îmi arăte care sunt cutiile în tehnologia
Informației și mi-a zis ca acestea se numesc containere pentru că ele conțin alte elemente
cum ar fi valori numerice și deci în ele ca și în niște cutii se pot pune lucruri.

© Bitulică 2020
Povestea lui Bitulică

Am făcut împreună un program prin care să înțeleg aceste aspecte și care să mă familiarizeze
cu noțiunea de container.

#include <iostream>

#include <vector>

using namespace std;

int main()

vector<int> g1;

for (int i = 1; i <= 5; i++)

g1.push_back(i);

cout << "Afiseaza de la inceput la sfarsit: ";

for (auto i = g1.begin(); i != g1.end(); ++i)

cout << *i << " ";

© Bitulică 2020
Povestea lui Bitulică

cout << "\nAfiseaza de la prima valoare constanta pana la ultima valoare constanta: ";

for (auto i = g1.cbegin(); i != g1.cend(); ++i)

cout << *i << " ";

cout << "\nAfiseaza de la prima valoare a vectorului inversat pana la ultima valoare a vecto-
rului inversat: ";

for (auto ir = g1.rbegin(); ir != g1.rend(); ++ir)

cout << *ir << " ";

cout << "\nAfiseaza de la prima valoare constanta a vectorului inversat pana la ultima va-
loare constanta a vectorului inversat: ";

for (auto ir = g1.crbegin(); ir != g1.crend(); ++ir)

cout << *ir << " ";

return 0;

© Bitulică 2020
Povestea lui Bitulică

Pentru manipularea vectorului existe implementate functii ca

▪ begin() – returnează indicele primul element din vector


▪ end() – returnează indicele ultimului element din vector
▪ rbegin() – returnează indicele primului element din vectorul inversat
▪ rend() – returnează ultimul element din vectorul inversat
▪ cbegin() – returnează primul indice constant din vector
▪ cend() – returnează ultimul indice constant din vector
▪ crbegin() – returnează primul indice constant din vectorul inversat
▪ crend() – returnează ultimul indice constant din vectorul inversat
▪ size() – returnează numărul de elemente al vectorului
▪ max_size() – returnează numarul maxim de elemente al vectorului
▪ capacity() – returnează memoria ocupată de vector
▪ resize(n) – redimensionează vectorul astfel încât să aibă n locații
▪ empty() – spune dacă vectorul este gol
▪ shrink_to_fit() – reduce capacitate să fie conformă cu dimensiunea și distruge tot
ce nu se încadrează.
▪ reserve() – Solicită alocarea memorie astfel încât să încapă toate elementele vec-
torului
▪ assign() – asignează o nouă valoare unui element înlocuind-o pe cea veche
▪ push_back() – pune o noua valoare după ultima valoare a vectorului
▪ pop_back() – inlatură ultimul element din vector.
▪ insert() – inserează un element iniatea unui element de la o pozitie specificată
▪ erase() – inlatura un element de la o pozitie specificat-o sau o serie de elemente.
▪ swap() – este folosită când se dorește interschimbarea valorilor a doi vectori.
▪ clear() – inlatură toate elementele vectorului
▪ emplace() – extinde vectorul prin inserarea unui element la o anumitp poziție
▪ emplace_back() – extinde vectorul prin adaugarea unui nou element dupa ultimul
element din vector

© Bitulică 2020
Povestea lui Bitulică

Am înțeles că este diferentă între a sterge un element și a-l înlătura. Când sterg suprascriu va-
loarea lui dar elementul însuși rămăne acolo unde era și deci numărul de elemente al vectoru-
lui nu se schimbă. Dacă înlătur un element atunci dezaloc memoria alocată pentru acel ele-
ment și scot elementul din vector refăcând legaturile între elementele vecine cu el. În acest
caz numărul de elemente al vectorului scade cu o unitate.

© Bitulică 2020
Povestea lui Bitulică

Când a fost nevoie sa deplasez ceva


Am descoperit iteratorii
STL

Când am avut nevoie să mut mobila căci am vrut să reamenajez o cameră la început am tran-
sportat mobila dintr o parte în altă cameră așa cum am putut. O mutam câțiva centimetri mai
încolo apoi mai odihneam apoi iar mutam câțiva centimetri apoi iar odihneam până când a
venit Lisa și împreună am comandat o platformă din aceea pe rotile pe care se urcă diferite
corpuri și se transportă.

Practic acea platformă m-a ajutat să mut mult mai repede mobila pentru că având roți și coe-
ficientul de frecare la alunecare pentru roată este minim, efortul depus de mine a fost dease-
menea redus la minim.

După ce am rearanjat camera fata mea cea mare Katy a spus că astfel de platforme care usu-
rează munca programatorilor când vine vorba de mișcarea în interiorul unor structuri de date
există și în informatică și poartă numele de iterator.

A itera înseamnă a repeta pași și atunci când cineva repetă pași merge adică se deplasează.

Am făcut împreună cu ea un exemplu cu ajutorul căruia să mă obișnuiesc cu noțiunea de ite-


rator.

#include<iostream>

#include<iterator> // pentru iteratori

#include<vector> // pentru vectori

© Bitulică 2020
Povestea lui Bitulică

using namespace std;

int main()

vector<int> ar = { 1, 2, 3, 4, 5 };

vector<int>::iterator ptr = ar.begin(); // itaratorul porneste de la inceputul vectorului

advance(ptr, 3); // ii spun iteratorului sa avanseze 3 pozitii

cout << "Afisez elementul de pe pozitia curenta a iteratorului : ";

cout << *ptr << " ";

return 0;

Pe lângă această funcție iteratorii mai au si funcțiile prev() si next() care avansează de la ele-
mentul curent către elementul din spatele lui (previeus) respectiv cel din fața elementului cu-
rent (next). Iteratorii fac parte din categoria mecanismelor care ajută structurile repetitive.

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să fac mai multe operații odată


Am descoperit cum lucrează functorii
STL

Am un vecin care se ocupă cu lucrări agricole. Are o fermă și are și utilaje. Într-o zi de primă-
vară ne-a invitat pe la el pe la fermă și am mers să vedem cum se seamănă porumbul.

Totul era utiliat și am observat că semănătoarea cand punea câte un cuib facea mai multe lu-
cruri de o dată. Facea o gaură, apoi punea bobul de porumb apoi astupa la loc.

Am fost și eu și Katy și Evi și Lisa. Ne-a invitat pe toți Katy a zis ca așa ceva pot sa fac și in ca-
drul unei structuri repetitive la fiecare pas al ei. A zis ca aceste mecanisme se numeste func-
tori.

Când am ajuns acasă am facut un program sub indrumarea ei ca să înțeleg cum stă treaba cu
aceste mecanisme.

#include <iostream>

#include <algorithm>

using namespace std;

int increment(int x) { return (x+1); } // functie in care pot sa fac mai multe lucruri

int main()

© Bitulică 2020
Povestea lui Bitulică

int arr[] = {1, 2, 3, 4, 5};

int n = sizeof(arr)/sizeof(arr[0]);

transform(arr, arr+n, arr, increment); // la fiecare pas al vectorului apelez functia care
aduna o unitate la elementul gasit acolo

for (int i=0; i<n; i++)

cout << arr[i] <<" ";

return 0;

Functor înseamnă o expresie care influențează altă expresie, adică este cel care efectuează
operații asupra unei expresii și poate fi privit ca un operator care operează asupra expresiei.

În cazul meu functorul transform transformă un vector cu ajutorul functiei increment care
modifică valorile vectorului întâlnite la fiecare pas.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie de lucruri simple dar utile


Am descoperit instrumentele utilitare
STL

Am fost într-o zi cu fata mea cea mare la un magazin unde erau tot felul de chestii interesante
adică erau mici gadget-uri care făceau te miri ce dar care erau, și nu a fost doar părerea mea,
ci și a lui Katy, foarte utile.

Am luat și eu de acolo un inel care monitorizează parametrii corporali și reține datele undeva.
L-am luat pentru Lisa. Acel undeva Katy a spus că se numește Cloud și că este ca un nor pen-
tru că toată lumea oriunde ar fi are acces la el. Ba mai mult decât atât el ca și norul este o
agregare de elemente disponibile oricând și oricui.

Norul este format din firicele de praf și apă pe care le adună de pe întreg Pământul adică le
agrega și din ele produce ploaia pe care ne-o dă nouă.

Kati a mai spus că așa face și acest sistem și că el practic adună informațiile din mai multe lo-
curi aflate în locații diferite pe mapamond și face ca noi să avem acces la ele adică să ne fie
disponibile oricând și oriunde.

A mai zis că așa cum în acest magazin pot găsi gadge-uri adică lucruri mici dar utile așa și în
informatică limbajele de programare au librării ce conțin funcții utile.

Am mers acasă și i-am dat Lisei inelul. S-a bucurat. Apoi am mers cu Katy și am făcut un exem-
plu ca să înțeleg care sunt aceste funcții utile prezente în biblioteca template standard a lim-
bajului C++.

#include <iostream>

© Bitulică 2020
Povestea lui Bitulică

#include <utility>

using namespace std;

int main()

pair<int, char> PAIR1;

PAIR1.first = 100;

PAIR1.second = 'G';

cout << PAIR1.first << " ";

cout << PAIR1.second << endl;

return 0;

© Bitulică 2020
Povestea lui Bitulică

Pair înseamnă pereche și aici cuplează două valori care nu se vor despărțite. Se poate folosi
de exemplu la cuplarea coordonatelor carteziene din plan. Pair poate fi initializat cu
make_pair() iar daca nu este initializat prima valoare este intitializata implicit.

Instrumentul Pair are o serie de functii cum ar fi swap() care interschimba valorile a doua vari-
abile de tip Pair și care se poate folosi asa pair1.swap(pair2).

Va valoare de tip Pair poate fi atribuită către două variabile folosind funcția tie() așa tie(a, b) =
pair1, unde a si b sunt două variabile de tip întreg.

Instrumentul Pair poate fi util și cand se doreste pastrarea unei liste de elemente în format
cheie valoare. De exemplu numele unor persoane care asteaptă să obțină ceva și numarul lor
de ordine.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie să comunic


Am descoperit protocoalele
PROTOCOL

Am un vecin cu care mai ies pe afară seara şi care locuieşte chiar lângă mine. De la geamul
meu de la bucătărie se vede geamul lui de la camera de zi. Pentru ca să nu deranjăm pe
nimeni când hotărâm să mai ieşim pe la poarta am stabilit că dacă ne dăm trei flash-uri din
lanterna şi celalat poate să vină să răspundă cu două flash-uri iar dacă nu poate să răspundă
cu unul singur. Într-o seară am dat trei flash-uri dar nu am primit răspuns aşa că m-am culcat.

Nu este un secret ce facem noi pentru că atât la bucătărie la mine cât şi în camera lui de zi
poate intra oricine în timp ce ne facem semnale aşa că familiele noastre ştiu de mica noastră
tehnică de comunicare.

Katy zice că ce facem noi se numeşte protocol de comunicare şi că este folosit şi la


comunicare între două maşini adică doau computere. A zis că nu e diferenţa aşa mare între ce
facem noi şi ce fac computerele mai ales că acum conexiunile sunt pe fibră optică. Deci şi ele
folosesc lumina. Dar a zis că ele comunica prin mesaje scrise şi că trebuie să înţeleagă ce
citesc. Motiv pentru care folosesc un anumit format pentru mesaje dinainte stabilit şi
cunoscut de ambele părţi.

Aşadar protocolul de comunicaţie constă în modalitatea în care se face schimbul de mesaje


modalitatea care cuprinde ordinea şi momentulele de timp în care sunt tranmsise dar şi în
formatarea mesajelor pentru că mesajele trebuie să fie înţelese de ambele părţi.

Un computer este format atât din componente hardware cât şi din componente software. Din
acest motiv mesajul transmis între ele va trece atât prin componentele fizice cât şi prin
componentele logice. Componenta hardware responsabilă cu trimiterea mesajelor între
computere este placă de reţea.

Nivelele prin care trece un mesaj conform modelului ISO/OSI sunt

- nivelul fizic
- nivel de legături de date
- nivelul de reţea
- nivelul de transport
- nivelul de sesiune
- nivelul de prezentare
- nivelul de aplicaţie

În cadrul nivelului fizic datele sunt transmise prin fir (wired) sau prin aer (wireless) şi deci pot
fi transmise atât analogic cât şi digital. Datorită rezistei întâmpinate în fir sa în aer semnalul

© Bitulică 2020
Povestea lui Bitulică

trebuie retransmis din loc în loc şi se face cu ajutorul amplificatoarelor de semnal. Semnalul
trebuie să fie partajat astfel încât să poată ajunge la cât mai mulţi utilizatori şi prin urmare
sunt necesare dispozitive că hub-uri sau swich-uri. La nivel fizic trebuie rezolvată problema
aşa numitului zgomot de semnal adică a impurităţilor prezente pe fir sau prin aer care bruiasa
semnalul.

În cadrul nivelul legături de date semanalele fizice adică impulsurile sunt grupate în pachete
şi pregătite pentru a trece la nivelul reţea. Tot aici se stabilesc priorităţile canalelor în cazul
comunicării mulţi canal dar şi tipul de comunicare. Adică dacă comunicarea se face orientată
conexiune sau fără. În cadrul comunicării orientată conexiune întâi trebuie să se stabilească o
conexiune şi abia apoi se poate comunica. E ca şi cum inati trebuie să te asiguri că cineva este
atent la ce zici şi abia apoi vorbeşti cu el. În cadrul trasnmisiiilor neorietate către conexiune e
ca şi cum ai vorbi cu cineva chiar dacă el nu te ascultă şi nu e atent la tine. Dar tu vorbeşti fără
să te intereseze asta. Îi spui ce ai de spus. Putintile sau podurile între canalelel de comunicare
se fac tot la acest nivel. Acesta este nivelul de legătură între nivelele fizice şi cele logice.

În cadrul nivelului reţea se preiau pachetele de la sursă şi se transfera la destinaţie. Adică


semnalele se transformă în biţi şi se transfera în funcţie de tipul de comunicare. Dacă este
orientată către conexiune sau nu.

În cadrul nivelul de transport există un mecanism de verificare a comunicării între expeditor şi


destinatar. Aici se stabileşte când un utilizator încearcă să se conecteze şi se stabileşte o
conexiune în cadrul căreia se trimit şi se primesc date între destinatar şi expeditor.

În cadrul nivelului sesiune se stabileşte o sesiune de comunicare între expeditor şi destinatar


care presupune autentificarea şi sincronizarea conversaţiilor pe o o durată stabilită.

Nivelul de prezentare se ocupă de modul în care sunt prezentate datele că de exemplu


prezentarea lor în format ascii codificat sub formă de utf-8.

Nivelul de aplicaţie stabileşte modul în care sunt folosite datele că de exemplu tranfer de
fişiere, poştă electronică sau rularea aplicaţiilor de la distanţă.

© Bitulică 2020
Povestea lui Bitulică

Când a trebuit să aleg unul din ele


Am aflat diferențele între TCP și UDP
PROTOCOL

Katy mi-a zis că TCP și UDP sunt două protocoale fundamentale pentru comunicațiile pe in-
ternet, pentru că sunt localizate în stratul de transport al modelului TCP / IP , care este primul
strat în care originea și destinația comunică direct, deoarece straturile inferioare adică cel de
rețea și cel de legaături de date nu îndeplinesc această funcție.

Protocolul TCP adică protocolul de control al transmisiei este unul dintre protocoalele funda-
mentale de pe Internet care permite aplicațiilor să comunice cu garanții, indiferent de stratu-
rile inferioare ale modelului TCP / IP. Acest lucru înseamnă că routerele adică stratul de rețea
din modelul TCP / IP trebuie să trimită doar segmentele care sunt unitatea de măsură în TCP,
fără să se îngrijoreze dacă aceste date vor ajunge sau nu corect. TCP acceptă protocoale cu
mai multe straturi de aplicație , cum ar fi HTTP adică web, HTTPS adică web securizat, POP3
adică poștă de intrare și SMTP adică poștă de ieșire, precum și versiunile lor sigure folosind
TLS. TCP este de asemenea utilizat în protocoale importante precum FTP, FTPES și SFTP pen-
tru a transfera fișiere de la o sursă la o destinație și chiar protocolul SSH pentru a gestiona cal-
culatoarele local și de la distanță în siguranță folosește protocolul TCP.

Deoarece TCP servește un număr mare de protocoale de nivel de aplicație, acesta este esen-
țial ca datele adică segmentele să ajungă la destinatar corect , fără erori și, în ordine. Dacă în
transmiterea segmentelor, acestea sunt corupte sau pierdute, automat TCP începe retransmi-
sia , fără intervenția stratului de aplicație. În acest fel, se garantează că datele ajung la desti-
natar fără erori, deoarece acest protocol este responsabil pentru rezolvarea oricărui tip de
problemă.

MSS adică dimensiunea maximă a segmentului este dimensiunea maximă în octeți pe care
TCP o poate primi într-un singur segment, este similară cu MTU, dar MSS este la nivelul stratu-
lui de transport. Pentru a obține cele mai bune performanțe, MSS trebuie să fie suficient de
mic pentru a evita fragmentarea pachetelor de date. În mod normal, MSS este anunțat pe fie-
care parte a canalului de comunicare, prin antetul TCP în sine. În mod normal, dimensiunea
MSS este cea a lui MTU și este de 1500 octeți minus antetul TCP care are o lungime variabilă
de cel puțin 20 de octeți minus antetul IP care are o lungime variabilă de cel puțin 20 de oc-
teți. Deci MSS = MTU 1,500 octeți - 20 octeți Antet TCP - Antet IP de 20 octeți

TCP are un mecanism complex de control al erorilor , o tehnică de fereastră glisantă este utili-
zată astfel încât toate segmentele să ajungă corect. Această caracteristică utilizează diferite
metode pentru a detecta posibile erori care apar:

▪ checksum
▪ Numerotarea tuturor segmentelor pentru a controla corect

© Bitulică 2020
Povestea lui Bitulică

▪ Confirmări selective ACK, deși permite, să se “acumuleze” segmente, astfel încât cu un


singur ACK să se poata confirma mai multe.
▪ Temporizatoare: adică dacă trece mult timp, TCP retransmite automat segmentul care
a fost „pierdut”.
▪ Segmentele duplicate sunt aruncate: în cazul în care ajunge un segment duplicat
deoarece unul a durat mai mult decât normal și a fost retrimis atunci îl șterge.

Desigur, dacă TCP detectează o eroare, va începe retransmiterea automat, fără ca stratul de
aplicație să fie nevoit să facă nimic.

O altă caracteristică foarte importantă a informațiilor care călătoresc de la o origine la o desti-


nație este aceea că datele ajung în ordine , adică în aceeași ordine în care au fost emise, întru-
cât protocolul IP este un protocol cu cel mai bun efort, face tot posibilul, astfel încât pache-
tele să ajungă în ordine și să fie corecte, dar nu este fiabil, deoarece nu garantează nimic . TCP
are o fereastră glisantă pe expeditor și receptor, astfel încât, dacă primim un segment care nu
este în ordine, acesta va „automat aștepta” până când va sosi segmentul care lipsește, sau
altfel, va solicita o retransmisie numai a segmentului care lipsește. . Cu fiecare segment primit
de receptor, va fi trimis un ACK indicând expeditorului că totul ajunge corect, însă, în realitate,
implementările TCP permit trimiterii unui ACK pentru a confirma recepția mai multor seg-
mente simultan, cu obiectivul de a nu satura rețeaua cu atâtea confirmări.

Protocolul TCP permite Controlul debitului , adică este capabil să atenueze saturația posibilă
a rețelei sau a gazdei la distanță. În cazul în care un dispozitiv transmite la o viteză de
500Mbps, iar dispozitivul de destinație poate primi informații doar la 100Mbps, protocolul TCP
este adaptat dinamic. În acest fel, protocolul TCP va încerca întotdeauna să maximizeze lăți-
mea de bandă disponibilă între sursă și destinație. Funcționarea acestei ferestre glisante este
complexă, dar practic funcționează prin faptul că receptorul are o fereastră TCP disponibilă
cu un număr de octeți care poate fi stocat într-un tampon adică buffer. Expeditorul poate tri-
mite date până când această cantitate este completată. Pentru ca expeditorul să poată tri-
mite mai multe date, este necesar ca receptorul să trimită un ACK care să indice că totul este
corect și că procedează la „încărcarea” acestuia în stratul de aplicație.

TCP are și el controlul congestiei , acest lucru ne permite să nu pierdem pachetele de pe Inter-
net, deoarece există congestii pe routere. Dacă routerul nu este capabil să proceseze sau să
redirecționeze pachetele la rata în care le primește, routerul însuși le va arunca și pachetele
vor fi pierdute, deoarece bufferul său va fi completat cu alceva. Nu trebuie să confundăm con-
trolul debitului cu controlul congestiei. Fereastra de congestie care este complementară cu
fereastra de recepție este utilizată pentru a gestiona controlul congestiei în TCP. În situații de
non-congestionare, avantajul congestiei este același cu fereastra de recepție, adică dacă
apare congestia, dimensiunea avantajului de congestie este redusă, iar dacă aceasta dispare,
crește. Numărul maxim de octeți pe care expeditorul îl poate trimite este minimul ambelor
dimensiuni ale ferestrei adică dacă fereastra de congestionare este de 1500 de octeți, iar fe-
reastra de recepție este de 2000 de octeți, atunci sunt trimise 1500 de octeți, cel mai mic.

© Bitulică 2020
Povestea lui Bitulică

Pentru a evita congestia și pentru a putea strânge lățimea de bandă maximă disponibilă între
origine și destinație, există un total de trei faze. Prima dată începe faza pornire lentă care este
responsabilă de creșterea exponențială a ferestrei de congestionare deci nu se poate consi-
dera cu adevărat început lent, apoi congestia de evitare faza care este responsabilă de crește-
rea liniară a ferestrei de congestie și, în sfârșit, faza constantă unde fereastra de recepție este
aceeași cu fereastra de congestionare.

TCP are în prezent algoritmi diferiți pentru a gestiona eficient congestia, primii au fost TCP Ta-
hoe și Reno, deși avem și alți, cum ar fi TCP Vegas, dar, de-a lungul anilor, cu noile rețele de
date TCP / IP, au apărut alți algoritmi care sunt mai eficienți. De exemplu, este TCP BRR care
îmi permite să trimit informații cât mai repede posibil, deoarece este mult mai eficient decât
protocolul TCP original adică are o viteză mai mare. Există, de asemenea, TCP Cubic, care este
controlul congestiei utilizat de Linux și sisteme de operare Unix.

În cele din urmă, o altă caracteristică interesantă a TCP este că permite date multiplex , astfel
încât să se poată primi informații de la diferite gazde simultan. De asemenea, permite Full-Du-
plex, deoarece poate trimite și primi date simultan prin același canal de comunicare.

Principala caracteristică a protocolului TCP este că acesta este un protocol orientat pe conexi-
une , pentru a stabili o conexiune între client și server, este absolut necesar să se stabilească o
conexiune anterioară cu respectivul server.

Această conexiune anterioară se numește “Strângere de mână cu 3 căi” , și constă practic în


faptul că clientul adică cel care inițiază conexiunea trimite un mesaj SYN către server adică cel
care primește conexiunea. Ulterior, serverul va trimite un mesaj de tip SYN-ACK, indicând că
poate începe să trimită informații, în cele din urmă, clientul trimite un ACK indicând că a pri-
mit-o corect și că toate informațiile dintre client și server sunt deja trimise. mod bidirecțional.
Un detaliu foarte important al TCP este acela că generează numere de ordine pe fiecare parte,
ajutând la faptul că nu pot fi stabilite conexiuni false între ele, deși dacă atacatorul este „la
mijloc”, atunci ar putea fi făcut Spoofing sau ceva similar, dar nu prin Internet.

Una dintre vulnerabilitățile TCP constă în trimiterea unui număr mare de segmente TCP SYN,
cu scopul de a „satura” conexiunile cu receptor. Unele soluții posibile pentru atenuarea aces-
tui atac de refuz de serviciu sunt:

▪ Limitarea numărului de conexiuni, fie global, fie conexiuni IP.


▪ Acceptarea numai conexiunilor la adresele IP de încredere.
▪ Întârzierea alocării resurselor folosind „cookie-uri” așa numitele Cookie SYN.

La închiderea conexiunii , cel care dorește să încheie conexiunea trimite un mesaj FIN, iar
gazda care îl primește va trimite un mesaj ACK împreună cu un alt mesaj FIN, astfel încât cel
care a inițiat terminarea conexiunii îi trimite un ultim ACK și conexiunea deschisă se închide.
Un detaliu important este faptul că se poate creea o conexiune „pe jumătate deschisă”, dacă
o gazdă încheie conexiunea, iar cealaltă nu, partea care a încheiat conexiunea nu va putea tri-
mite mai multe date, dar cea care nu a închis, poate continua să trimită informații.

© Bitulică 2020
Povestea lui Bitulică

Antetul TCP adaugă la mesaje cel puțin 20 octeți în fiecare segment, deoarece este un câmp
„opțional”. În acest antet TCP se găsețte portul sursă și portul de destinație al conexiunii
adică soclul. Se mai găsește și numărul de secvență, numărul ACK și diferitele FLAG-uri TCP
precum SYN, ACK, RST, FIN, URG și altele. În acest antet există și o parte foarte importantă
pentru funcționarea ferestrei glisante și vom avea un câmp de 16 biți care indică dimensiunea
ferestrei de recepție.

Portul sursă și portul destinație sunt esențiale pentru buna funcționare a TCP. TCP folosește
aceste numere de port pentru a identifica o priză, adică o aplicație care emite date sau pri-
mește date. Porturile TCP variază de la 0 la 65535, dar sunt trei tipuri diferite de porturi:

▪ Porturi cunoscute : de la 0 la 1023. Aceste porturi sunt rezervate de IANA pentru anu-
mite aplicații, cum ar fi serverul HTTP, FTP, SSH și multe alte porturi cunoscute.
▪ Porturi înregistrate : De la 1024 la 49151. Aceste porturi sunt rezervate aplicațiilor spe-
cifice, cum ar fi sistemele de gestionare a bazelor de date, BitTorrent și multe alte apli-
cații.
▪ Porturi private : de la 49152 la 65535. Aceste porturi nu sunt rezervate de nicio aplica-
ție și se pot utiliza în mod liber fără a afecta niciun alt protocol.

Protocol UDP adică User Datagram Protocol este unul dintre protocoalele fundamentale de
pe internet și permite aplicațiilor să comunice cu garanții, indiferent de straturile inferioare
ale modelului TCP / IP. Aceasta înseamnă că routerele adică stratul de rețea în modelul TCP /
IP trebuie să trimită doar datagramele adică unitatea de măsură în UDP. UDP acceptă mai
multe protocoale de nivel de aplicație, cum ar fi popularul DNS și chiar protocolul DHCP pen-
tru a obține și furniza adresarea IP în mod automat.

Protocolul UDP permite trimiterea de datagrame fără a fi necesară stabilirea unei conexiuni.
Este necesar doar să am o priză deschisă la destinație pentru a accepta datagramele sursei.
UDP este un protocol care nu este conectat, adică nu se întâmplă ca în TCP unde există o fază
de stabilire a conexiunii, aici sunt trimise direct fără „avertizare” în prealabil.

Acest protocol nu oferă niciun tip de control al debitului , adică dacă un dispozitiv este mai
rapid decât altul și trimite informații, este foarte posibil ca informațiile să se piardă, deoarece
acestea se vor pierde la cel mai lent și va trebui să se retransmită informațiilor. Un detaliu im-
portant este faptul că gestionarea de expediere a datagramelor este realizată de stratul de
transport, deoarece UDP este foarte simplu și nu are mecanisme de control pentru redirecțio-
narea datagramelor.

UDP nu oferă, de asemenea niciun tip de control al congestiei. În cazul în care există o conges-
tie în rețea, pachetele ar putea fi pierdute și, desigur, nu va fi responsabil de trimiterea lor, așa
cum se întâmplă cu TCP. Prin urmare, UDP nu are controlul congestiei, controlul fluxului sau
controlul erorilor și s-ar putea spune că UDP este un protocol nesigur. În plus, nu furnizează
ordine în datagramele trimise și nici informații dacă un pachet de date a ajuns corect, deoa-
rece nu există nicio confirmare de livrare sau de primire. Orice tip de garanții pentru transmi-
terea informațiilor trebuie implementate în straturi superioare.

© Bitulică 2020
Povestea lui Bitulică

Acest protocol este utilizat în principal în DHCP și DNS, unde viteza este mai importantă decât
fiabilitatea. UDP este utilizat pe scară largă în sarcinile de control al transmisiilor audio și vi-
deo printr-o rețea. UDP adaugă numai multiplexare și cheksum.

UDP adaugă antetul de 8 octeți în fiecare datagramă. În acest antet UDP se găsesc portul
sursă și portul de destinație al conexiunii adică socket, lungimea datagramei și checkum-ul
datagramei menționate pentru a verifica dacă acesta nu are erori, nici antetul, nici datele da-
tagramei. Portul sursă și portul destinație sunt esențiale pentru buna funcționare a UDP. UDP
folosește aceste numere de port pentru a identifica o priză, adică o aplicație care emite date
sau primește date.

© Bitulică 2020
Povestea lui Bitulică

Când am comunicat fără pretenții


Am creat un server și un client UDP
PROTOCOL

Am înțeles că managementul proceselor dintr-un computer revine în sarcina sistemului


de operare și cum procesele de comunicare sunt tot procese ele depind de cum sunt
implementate în diferitele sisteme de operare. Ştiu că limbajul de programare C++ nu este
cross platformă deci este dependent de sistemul de operare. Prin urmare a trebuit să scriu
cod diferit pentru diferite sisteme de operare pentru a creea aceeași aplicație care să
implementeze un server şi un client care comunică între ele utilizând protocolul UDP
Am început scriind aplicaţia server pentru sistemul de operare Windows

#define _WINSOCK_DEPRECATED_NO_WARNINGS // pentru a functiona cu variante mai vechi


ale functiilor winsock

#include<stdio.h> // biblioteca standard

#include<winsock2.h> // biblioteca windows pentru lucrul cu socket

#pragma comment(lib,"ws2_32.lib") // libraria Winsock

#define BUFLEN 512 // lungimea maxima a bufferului cu care trimit mesajele

#define PORT 8888 // portul pe care asculta serverul sa vada daca se trimit date

int main()

SOCKET s; // variabila socket

© Bitulică 2020
Povestea lui Bitulică

struct sockaddr_in server, si_other; // structura pe modelul caruia se stocheaza adresa


ip

int slen, recv_len; // dimenisunea structurii pentru adresa ip

char buf[BUFLEN]; // bufferul cu care trimit mesajele

WSADATA wsa; // obiectul care asculta mesajele

slen = sizeof(si_other); // lungimea structurii pe modelul careia se memoreaza adresa

printf("\nSe initailizeaza Socketul...");

if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) // initailizare socket

printf("Nu se poate initializa Soket. Codul erorii este: %d", WSAGetLastError());

exit(EXIT_FAILURE);

printf("Socket initializat.\n"); // daca a ajuns aici socketul este initializat cu succes

if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) // se creaza un socket

printf("Nu am putut crea socketul : %d", WSAGetLastError());

printf("Socket creat.\n"); // daca am ajuns aici socketul a fost creat cu succes

© Bitulică 2020
Povestea lui Bitulică

server.sin_family = AF_INET; // se initializeaza tipul de structura cu cel standard din


win-dows

server.sin_addr.s_addr = INADDR_ANY; // se initilizeaza formatul adresei cu cel stan-


dard

server.sin_port = htons(PORT); // se seteaza portul pe care asculta socketul

if (bind(s, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) // se mon-


teaza socketul creat in lista de socketuri a sistemului de operare

printf("Nu se poate monta socketul : %d", WSAGetLastError());

exit(EXIT_FAILURE);

puts("Socket montat");

while (1) // se asculta pe port sa se observer cand se primesc mesaje

printf("Astept date...");

fflush(stdout); // se asculta pe streamul de iesire

memset(buf, '\0', BUFLEN); // se curata bufferul

if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr*)&si_other, &slen))


== SOCKET_ERROR) // se asteapta primirea datelor . operatia este blocanta

printf("Eroare la receptia datelor : %d", WSAGetLastError());

© Bitulică 2020
Povestea lui Bitulică

exit(EXIT_FAILURE);

printf("Am receptionat pachet de la %s:%d\n", inet_ntoa(si_other.sin_addr),


ntohs(si_other.sin_port));

printf("Continutul mesajului: %s\n", buf);

if (sendto(s, buf, recv_len, 0, (struct sockaddr*)&si_other, slen) == SOCKET_ER-


ROR) // se trimite raspuns catre client

printf("Eroare la trimiterea datelor : %d", WSAGetLastError());

exit(EXIT_FAILURE);

closesocket(s); // se inchide conexiunea

WSACleanup(); // se dezaloca memoria alocata de process

return 0; // se returneaza succes catre sistemul de operare

Am continuat scriind aplicația client pentru sistemul de operare Windows

© Bitulică 2020
Povestea lui Bitulică

#define _WINSOCK_DEPRECATED_NO_WARNINGS // pentru a functiona cu variante mai vechi


ale functiilor winsock

#include<stdio.h> // biblioteca standard

#include<winsock2.h> // biblioteca pentru socket

#include<string>

#pragma comment(lib,"ws2_32.lib") // libraria Winsock

#define SERVER "127.0.0.1" // definesc adresa serverului UDP

#define BUFLEN 512 // definesc lungimea maxima a mesajelor

#define PORT 8888 // definesc portul pe care stiu ca asculta serverul

using namespace std;

int main(void)

struct sockaddr_in si_other; // declar structurile pentru adresa

int s, slen = sizeof(si_other); // declar si definesc cat cantareste structura

char buf[BUFLEN]; // creez bufferul in care voi primi mesaje

char message[BUFLEN]; // definesc variabila in care voi scrie mesajul

WSADATA wsa; // obiectul windows pentru socket

© Bitulică 2020
Povestea lui Bitulică

printf("\nSe initializeaza Winsock...");

if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) // incerc initializarea

printf("Eroare la initializare. Codul de eroare : %d", WSAGetLastError());

exit(EXIT_FAILURE);

printf("Socket initializate.\n"); // daca am ajuns aici socketul este initializat

if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR) // creez un


socket

printf("Eroare la creare socket cu codul de eroare : %d", WSAGetLastError());

exit(EXIT_FAILURE);

memset((char*)&si_other, 0, sizeof(si_other)); // setez structura adresei

si_other.sin_family = AF_INET; // setez tipul de adresa

si_other.sin_port = htons(PORT); // setez portul

si_other.sin_addr.S_un.S_addr = inet_addr(SERVER); //setez adresa serverului

while (1) // incep comunicarea cu serverul

© Bitulică 2020
Povestea lui Bitulică

printf("Introduce un mesaj : ");

gets_s(message);

if (sendto(s, message, strlen(message), 0, (struct sockaddr*)&si_other,


slen) == SOCKET_ERROR) // trimit mesajul

printf("Mesajul nu a putut fi trimis. Cod de eroare : %d", WSAGe-


tLastError());

exit(EXIT_FAILURE);

memset(buf, '\0', BUFLEN); // se curata bufferul

if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr*)&si_other, &slen) ==


SOCKET_ERROR) // se asteapta raspunsul, operatia este blocanda deci apelul este sincron

printf("Eroare la primirea raspunsului. Codul erorii este : %d",


WSAGetLastError());

exit(EXIT_FAILURE);

puts(buf); // afiseaza raspunsul serverului pe ecran

closesocket(s); // se inchide conexiunea

© Bitulică 2020
Povestea lui Bitulică

WSACleanup(); // se dezaloca memoria alocata procesului

return 0; // se returneaza codul de succes catre sistemul de operare

Cele două programe adică cel server şi cel client eu le-am rulat pe acelaşi computer dar
ele pot fi rulate , şi asta este şi scopul unei aplicaţii client-server, pe două sau mai multe
computere dintre care pe unul să ruleze aplicaţia server.

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să fiu ascultat atunci când comunic


Am creat un server și un client TCP
PROTOCOL

Am înțeles că atunci când vreau să comunic cu cineva și acesta să fie atent la mine trebuie să
stabilesc o conexiune cu el. Acest lucru este necesar și cand comunică două sau mai multe
computere cu un server.

Am făcut împreună cu Katy un exemplu de client și unul de server care comunică împreună
folosind protocolul TCP adică înainte de a începe să comunice stabilesc o conexiune.

Am început implementând codul pentru server

#undef UNICODE // se inactiveaza unicode

#define WIN32_LEAN_AND_MEAN // se reduce win32 header file pentru a compila mai rapid

#include <windows.h> // libraria penttru functii windows

#include <winsock2.h> // libraria pentru socket pe windows

#include <ws2tcpip.h> // libraria pentru protocolul tcpip

#include <stdlib.h> // libraria standard cu functii utile

#include <stdio.h> // libraria standard cu functii de intrare si iesire

#pragma comment (lib, "Ws2_32.lib") // se leaga libraria ws2_32 pentru socket tcpip

#define DEFAULT_BUFLEN 512 // se defineste lungimea bufferului

#define DEFAULT_PORT "777" // se stabileste portul pe care se comunica

© Bitulică 2020
Povestea lui Bitulică

int main(void)

WSADATA wsaData; // obiectul pentru socket

int iResult; // rezultatul

SOCKET ListenSocket = INVALID_SOCKET; // socketul server

SOCKET ClientSocket = INVALID_SOCKET; // socketul client

struct addrinfo* result = NULL; // adresa clientului

struct addrinfo hints; // adresa serverului

int iSendResult; // mesjul trimis

char recvbuf[DEFAULT_BUFLEN]; // bufferul in care se primesc mesajele

int recvbuflen = DEFAULT_BUFLEN; // dimensiunea bufferului in care se primesc mesaje

iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); // se initializeaza socketul

if (iResult != 0) {

printf("Eroare la initializare: %d\n", iResult);

return 1;

ZeroMemory(&hints, sizeof(hints)); // se seteaza memoria pentru structura socket

© Bitulică 2020
Povestea lui Bitulică

hints.ai_family = AF_INET; // se seteaza tipul de adresa

hints.ai_socktype = SOCK_STREAM; // se seteaza tipul de socket

hints.ai_protocol = IPPROTO_TCP; // se seteaza protocolul

hints.ai_flags = AI_PASSIVE; // se seteaza tipul de atentie al socketului

iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result); // se seteaza adresa si portul

if (iResult != 0) {

printf("Eroare la setarea adresei si portului: %d\n", iResult);

WSACleanup();

return 1;

ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); // se


creaza un socket

if (ListenSocket == INVALID_SOCKET) {

printf("Eroare la creare socket: %ld\n", WSAGetLastError());

freeaddrinfo(result); // se eibereaza memoria alocata de structura adresei ip si a portului

WSACleanup(); // se dezaloca memoria alocata pentru socket

return 1;

iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen); // se monteaza socke-


tul

if (iResult == SOCKET_ERROR) {

© Bitulică 2020
Povestea lui Bitulică

printf("Eroare la montarea socketului: %d\n", WSAGetLastError());

freeaddrinfo(result); // se elibereaza memoria

closesocket(ListenSocket); // se inchide conexiunea

WSACleanup(); // se eleibereaza memoria alocata pentru socket

return 1;

freeaddrinfo(result); // se elibereaza memoria alocata pentru adresa si port

iResult = listen(ListenSocket, SOMAXCONN); // se asculta pe socket pentru a detecta o in-


cerca-re de conectare

if (iResult == SOCKET_ERROR) {

printf("Eroare la ascultare pe socket: %d\n", WSAGetLastError());

closesocket(ListenSocket);

WSACleanup();

return 1;

ClientSocket = accept(ListenSocket, NULL, NULL); // se accepta o conexiune

if (ClientSocket == INVALID_SOCKET) {

printf("Eroare la acceptarea conexiunii: %d\n", WSAGetLastError());

closesocket(ListenSocket);

WSACleanup();

© Bitulică 2020
Povestea lui Bitulică

return 1;

closesocket(ListenSocket); // se opreste ascultarea adica poate primi doar un singur client


co-nectat

do {

iResult = recv(ClientSocket, recvbuf, recvbuflen, 0); // se primeste un mesaj

if (iResult > 0) {

printf("Am receptionat un numar de bytes de: %d\n", iResult);

iSendResult = send(ClientSocket, recvbuf, iResult, 0); // se trimite un mesaj la clientul


co-nectat

if (iSendResult == SOCKET_ERROR) {

printf("Nu am putut trimite mesajul: %d\n", WSAGetLastError());

closesocket(ClientSocket);

WSACleanup();

return 1;

printf("Am trimis un numar de bytes de: %d\n", iSendResult);

else if (iResult == 0)

© Bitulică 2020
Povestea lui Bitulică

printf("Se inchide conexiunea...\n");

else {

printf("Am receptionat o eroare: %d\n", WSAGetLastError());

closesocket(ClientSocket);

WSACleanup();

return 1;

} while (iResult > 0);

iResult = shutdown(ClientSocket, SD_SEND); // se inchide conexiunea cu clientul conectat

if (iResult == SOCKET_ERROR) {

printf("Eroare la inchidera conexiunii: %d\n", WSAGetLastError());

closesocket(ClientSocket);

WSACleanup();

return 1;

// cleanup

closesocket(ClientSocket); // se inchide socket

WSACleanup(); // se elibereaza memoria folosita de socket

return 0;

© Bitulică 2020
Povestea lui Bitulică

Apoi am scris codul client

#define WIN32_LEAN_AND_MEAN

#include <windows.h>

#include <winsock2.h>

#include <ws2tcpip.h>

#include <stdlib.h>

#include <stdio.h>

#pragma comment (lib, "Ws2_32.lib")

#pragma comment (lib, "Mswsock.lib")

#pragma comment (lib, "AdvApi32.lib")

#define DEFAULT_BUFLEN 512

#define DEFAULT_PORT "777"

int main(int argc, char** argv)

© Bitulică 2020
Povestea lui Bitulică

const char* server_address = "127.0.0.1";

WSADATA wsaData;

SOCKET ConnectSocket = INVALID_SOCKET;

struct addrinfo* result = NULL,

* ptr = NULL,

hints;

const char* sendbuf = "Acesta este un test";

char recvbuf[DEFAULT_BUFLEN];

int iResult;

int recvbuflen = DEFAULT_BUFLEN;

iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);

if (iResult != 0) {

printf("Socketul a pornit cu eroare: %d\n", iResult);

return 1;

ZeroMemory(&hints, sizeof(hints));

hints.ai_family = AF_UNSPEC;

hints.ai_socktype = SOCK_STREAM;

hints.ai_protocol = IPPROTO_TCP;

© Bitulică 2020
Povestea lui Bitulică

iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);

if (iResult != 0) {

printf("Nu se pot obtine datele de conectare: %d\n", iResult);

WSACleanup();

return 1;

for (ptr = result; ptr != NULL; ptr = ptr->ai_next) { // se incearca conextarea la server

ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,

ptr->ai_protocol);

if (ConnectSocket == INVALID_SOCKET) {

printf("Nu se poate crea un socket client: %ld\n", WSAGetLastError());

WSACleanup();

return 1;

iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);

if (iResult == SOCKET_ERROR) {

closesocket(ConnectSocket);

ConnectSocket = INVALID_SOCKET;

continue;

© Bitulică 2020
Povestea lui Bitulică

break;

freeaddrinfo(result);

if (ConnectSocket == INVALID_SOCKET) {

printf("Nu se poate realiza conexiunea cu serverul!\n");

WSACleanup();

return 1;

iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0); // se trimite mesajul

if (iResult == SOCKET_ERROR) {

printf("Eroare la trimiterea mesajului: %d\n", WSAGetLastError());

closesocket(ConnectSocket);

WSACleanup();

return 1;

printf("Am trimis un numar de bytes de: %ld\n", iResult);

iResult = shutdown(ConnectSocket, SD_SEND); // se inchide conexiunea cu serverul

© Bitulică 2020
Povestea lui Bitulică

if (iResult == SOCKET_ERROR) {

printf("Eroare la inchiderea conexiunii : % d\n", WSAGetLastError());

closesocket(ConnectSocket);

WSACleanup();

return 1;

do {

iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0); // se primeste un mesaj

if (iResult > 0)

printf("Am primit un numar de bytes de: %d\n", iResult);

else if (iResult == 0)

printf("Conexiune inchisa\n");

else

printf("Nu am putut receptiona mesajul: %d\n", WSAGetLastError());

} while (iResult > 0);

closesocket(ConnectSocket); // se inchide socket

WSACleanup(); // se elibereaza memoria

return 0;

© Bitulică 2020
Povestea lui Bitulică

Socket în limba engleză înseamnă sosetă. Soseta este ceva în care se bagă talpa piciorului
deci este un suport pentru talpă. în tehnologia informației sensul este acelasi și este utilizat
atât în hardware cât și în software. În socket se pune procesorul deci este un suport pentru
procesor iar aici este un suport pentru comunicare.

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să comunic cu mai mulți deodată


Am creat un server socket multithreads
PROTOCOL

Katy mi-a zis că, ca să fie util un server socket trebuie să poată comunica cu mai multi clienți
simultan. Ca să poată face asta, aplicația server trebuie să poată comunica cu fiecare pe cate
un fir de execuție separat.

Am făcut împreună cu Katy un exemplu de aplicție server multithreads pentru a înțelege mai
bine cum stau lucrurile.

#define _CRT_SECURE_NO_WARNINGS

#define WIN32_LEAN_AND_MEAN

#include <windows.h>

#include <stdlib.h>

#include <stdio.h>

#include <winsock2.h>

#pragma comment(lib,"WS2_32")

DWORD WINAPI receive_cmds(LPVOID lpParam)

printf("Am creat un fir de executie\r\n");

SOCKET current_client = (SOCKET)lpParam;

char buf[100];

© Bitulică 2020
Povestea lui Bitulică

char sendData[100];

int res;

while (true)

res = recv(current_client, buf, sizeof(buf), 0); // recv cmds

Sleep(10);

if (res == 0)

MessageBox(0, (LPCWSTR)"error", (LPCWSTR)"error", MB_OK);

closesocket(current_client);

ExitThread(0);

if (strstr(buf, "Salut"))

printf("\nAm fost salutat");

strcpy(sendData, "Salut. Bine te-am gasit.\n");

Sleep(10);

send(current_client, sendData, sizeof(sendData), 0);

© Bitulică 2020
Povestea lui Bitulică

else if (strstr(buf, "La revedere."))

printf("\nMi s-a zis la revedere.\n");

strcpy(sendData, "La revedere\n");

Sleep(10);

send(current_client, sendData, sizeof(sendData), 0);

closesocket(current_client);

ExitThread(0);

else

strcpy(sendData, "Comanda invalida\n");

Sleep(10);

send(current_client, sendData, sizeof(sendData), 0);

strcpy(sendData, "");

strcpy(buf, "");

© Bitulică 2020
Povestea lui Bitulică

int main()

printf("A pornit serverul multi fir de executie a lui Bitulica\r\n");

SOCKET sock;

DWORD thread;

WSADATA wsaData;

sockaddr_in server;

int ret = WSAStartup(0x101, &wsaData);

if (ret != 0)

return 0;

server.sin_family = AF_INET;

server.sin_addr.s_addr = INADDR_ANY;

server.sin_port = htons(123);

© Bitulică 2020
Povestea lui Bitulică

sock = socket(AF_INET, SOCK_STREAM, 0);

if (sock == INVALID_SOCKET)

return 0;

if (bind(sock, (sockaddr*)&server, sizeof(server)) != 0)

return 0;

if (listen(sock, 5) != 0)

return 0;

SOCKET client;

sockaddr_in from;

int fromlen = sizeof(from);

© Bitulică 2020
Povestea lui Bitulică

while (true)

client = accept(sock, (struct sockaddr*)&from, &fromlen);

printf("S-a conectat un client nou\r\n");

CreateThread(NULL, 0, receive_cmds, (LPVOID)client, 0, &thread);

closesocket(sock);

WSACleanup();

return 0;

Am înțeles că în acest mod clienții vorbesc pe culoare separate cu serverul și astfel este satis-
facută probrietatea unui server de a putea servi mai multi clienți.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie de protocoalele standard


Am învățat cum să fac să le folosesc
PROTOCOL

Katy mi-a spus că dacă tot am făcut o aplicație server socket care să permită comunicarea cu
mai mulți clienți simultan adică o aplicație server socket multithreads ar putea să îmi explice
acum, cum și cu ce ar trebui să răspund ca aplicația mea să folosească protocoalele standard
de comunicare.

Am înțeles că pentru ca o aplicație să folosească un protocol standard trebuie să folosească


un model de schimb de mesaje stabilit de acest protocol standard dar și să folosească același
format al mesajelor stabilit de protocol.

Dacă în aplicația mea vreau să folosesc protocolul HTTP și astfel aplicația să poată răspunde
unei accesări din browser atunci ea va primi de la aplicația client un mesaj de forma

GET /hello.htm HTTP/1.1

User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)

Host: www.tutorialspoint.com

Accept-Language: en-us

Accept-Encoding: gzip, deflate

Connection: Keep-Alive

Și va trebui să răspundă clientului cu un mesaj de forma

HTTP/1.1 200 OK

© Bitulică 2020
Povestea lui Bitulică

Date: Mon, 27 Jul 2009 12:28:53 GMT

Server: Apache/2.2.14 (Win32)

Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT

Content-Length: 88

Content-Type: text/html

Connection: Closed

<html>

<body>

<h1>Hello, World!</h1>

</body>

</html>

Unde pe prima linie a mesajului de interogare este specificată metoda de interogare folosită,
formatul așteptat și protocolul folosit. Pe a doua linie este specificat agentul web folosit adică
tipul de browser iar pe a treia linie este specificat sistemul de operare.

Pe a patra linie este trecută gazda de la care se așteaptă răspunsul iar pe a cincea linie este
trecută limba în care se face interogarea.

Pe a șasea linie este trecut formatul de encodare în care este codat răspunsul iar pe a șaptea
linie este trecut faptul că conexiunea trebuie să rămână activă după trimiterea interogări și
până la primirea răspunsului adică interogarea este o interogare sincronă.

În cadrul răspunsului pe prima linie este trecut protocolul în baza căruia este formulat răs-
punsul precum și codul și mesajul de eroare cu care vine acest răspuns. Pentru succes Codul
este 200 iar răspunsul este OK.

© Bitulică 2020
Povestea lui Bitulică

Pe a doua linie este specificată data la care s-a primit răspunsul iar pe a treia linie este specifi-
cată aplicația web care a trimis răspunsul precum și sistemul de operare peste care aceasta
funcționează.

Pe a patra linie este specificată cea mai recentă dată la care aplicația a fost actualizată. Toate
aceste date calendaristice sunt în format GMT.

Pe a cincea linie din răspuns este trecută lungimea corpului răspunsului iar pe a șasea linie
este trecut tipul răspunsului adică formatul în care răspunsul va fi livrat.

Pe a șaptea linie este specificat că conexiunea va fi închisă în urmă trimiteri răspunsului iar de
la linia a opta încolo începe corpul răspunsului care în cadrul unei aplicații web este un cod
HTML.

Fata mea cea mare Katy mi-a mai zis că dacă vreau să trimit un mesaj de răspuns atunci când
cineva îmi apelează aplicația direct folosind protocolul IRC pot să îi răspund așa

001 RPL_WELCOME

"Bine ai venit pe internet

<Bitulică>!<bit.bitulica>@<localhost>"

Și am făcut împreună o aplicație care folosește protocolul IRC

#define _CRT_SECURE_NO_WARNINGS

#define WIN32_LEAN_AND_MEAN

#define _WINSOCK_DEPRECATED_NO_WARNINGS

© Bitulică 2020
Povestea lui Bitulică

#include <windows.h>

#include <winsock2.h>

#include <iostream>

#include <string>

#include <algorithm>

#pragma comment(lib,"WS2_32")

void replaceStr(std::string& str, const std::string& oldStr, const std::string& newStr)

std::string::size_type index = 0;

do

index = str.find(oldStr, index);

if (index == std::string::npos)

return;

str.replace(index, oldStr.length(), newStr);

index += newStr.length();

} while (true);

© Bitulică 2020
Povestea lui Bitulică

std::string quote(const std::string& s)

std::string result = s;

replaceStr(result, "\x10", "\x10""\x10");

replaceStr(result, "\0", "\x10""0");

replaceStr(result, "\n", "\x10""n");

replaceStr(result, "\r", "\x10""r");

return result;

std::string unquote(const std::string& s)

std::string result = s;

std::string::size_type len = result.length();

std::string::size_type index = 0;

while (index < len)

index = result.find("\x10", index);

if (index = std::string::npos)

break;

result.erase(index, 1);

--len;

© Bitulică 2020
Povestea lui Bitulică

if (index >= len)

break;

switch (result[index])

case '0':

result[index] = '\0';

break;

case 'n':

result[index] = '\n';

break;

case 'r':

result[index] = '\r';

break;

++index;

return result;

© Bitulică 2020
Povestea lui Bitulică

std::string fetch(std::string& s, const std::string& delim)

std::string result;

std::string::size_type pos = s.find(delim);

if (pos == std::string::npos)

result = s;

s = "";

else

result = s.substr(0, pos);

s.erase(0, pos + delim.length());

return result;

bool sendStr(SOCKET sock, const std::string& s)

const char* ptr = s.c_str();

int len = s.length();

while (len > 0)

© Bitulică 2020
Povestea lui Bitulică

int ret = send(sock, ptr, len, 0);

if (ret == SOCKET_ERROR)

std::cout << "Eroare de trimitere: " << WSAGetLastError() << std::endl;

return false;

ptr += ret;

len -= ret;

return true;

bool sendCmd(SOCKET sock, const std::string& cmd)

std::cout << "În curs de trimitere: " << cmd << std::endl;

return sendStr(sock, quote(cmd)) && sendStr(sock, "\r\n");

int main()

int exitCode = -1;

© Bitulică 2020
Povestea lui Bitulică

WSADATA wsa;

int ret = WSAStartup(MAKEWORD(2, 0), &wsa);

if (ret != 0)

std::cout << "Eroare de initializare socket: " << ret << std::endl;

return exitCode;

SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (sock == INVALID_SOCKET)

std::cout << "socket() error: " << WSAGetLastError() << std::endl;

return exitCode;

SOCKADDR_IN addr = { 0 };

addr.sin_family = AF_INET;

addr.sin_addr.s_addr = inet_addr("127.0.0.1");

addr.sin_port = htons(777);

if (connect(sock, (SOCKADDR*)&addr, sizeof(addr)) != 0)

© Bitulică 2020
Povestea lui Bitulică

std::cout << "Eroare de conectare: " << WSAGetLastError() << std::endl;

closesocket(sock);

std::cout << "Aplicatie conectata" << std::endl;

std::string oauth = "";

std::string nick = "Bitulica";

std::string user = "bit.bitlica";

std::string channel = "Test";

sendCmd(sock,"PASS " + oauth);

sendCmd(sock,"NICK " + nick);

sendCmd(sock,"USER " + user);

sendCmd(sock,"JOIN " + channel);

char buf[1024];

std::string LineBuffer;

std::string::size_type StartIdx = 0;

do

int ret = recv(sock, buf, sizeof(buf), 0);

© Bitulică 2020
Povestea lui Bitulică

if (ret == SOCKET_ERROR)

std::cout << "Eroare la primire raspuns: " << WSAGetLastError() << std::endl;

closesocket(sock);

if (ret == 0)

std::cout << "Server deconectat" << std::endl;

break;

LineBuffer.append(buf, ret);

do

std::string::size_type pos = LineBuffer.find('\n', StartIdx);

if (pos == std::string::npos)

break;

std::string::size_type len = pos;

if ((pos > 0) && (LineBuffer[pos - 1] == '\r'))

--len;

© Bitulică 2020
Povestea lui Bitulică

std::string msg = unquote(LineBuffer.substr(0, len));

LineBuffer.erase(0, pos + 1);

StartIdx = 0;

std::string senderNick;

std::string senderHost;

if (!msg.empty() && (msg[0] == ':'))

std::string tmp = fetch(msg, " ");

tmp.erase(0, 1); // remove ':'

senderNick = fetch(tmp, "!");

senderHost = tmp;

std::cout << "Raspuns primit: " << msg << std::endl;

if (msg == "PING")

sendCmd(sock,"PONG");

} while (true);

} while (true);

© Bitulică 2020
Povestea lui Bitulică

exitCode = 0;

return exitCode;

Am înțeles că protocolul FTP cu care pot să uploadez un fișier pe un server nu este un protocol
care are header și că trimiterea fișierului pe server se face linie cu linie.

La fel este și în cazul protocolului IMAP și POP3 protocoale specifice trimiterii și primirii de
mesaje tip email adică poștă electronică.

Am mai citit că dacă vreau să fac o aplicație care trimite și primește SMS trebuie să respect
protocolul SMTP și trebuie să trimit un mesaj de forma

+CMGL: 0,"REC READ","1011161051159710897116",,"16/10/29,10:36:09+00"


06440642062F002006270633062A064706440643062A0020064306440020062706440648062D06
2F0627062A0020062706440645062C06270646064A

Unde formatul în care este codat mesajul este codat la rândul lui în codul ascii

1011161051159710897116 =

© Bitulică 2020
Povestea lui Bitulică

101 = &65 = e

116 = &74 = t

105 = &69 = i

115 = &73 = s

97 = &61 = a

108 = &6C = l

97 = &61 = a

116 = &74 = t

Iar ce este în hexazecimal este corpul mesajului adică textul codat în hexazecimal.

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să testez protocoalele standard


Am învățat cum să fac să le testez
PROTOCOL

Am aflat că aceste protocoale standard sunt deja implementate și că ele pot fi folosite în apli-
cațiile pe care le dezvolt.

Am citit de exemplu ca Protocolul HTTP funcționează pe portul implicit 80 și că dacă vreau să


verific dacă un site funcționează pot să folosesc aplicația telnet care implementează protoco-
lul cu același nume și să verific dacă mă pot conecta pe mașina pe care rulează site-ul și pe
portul 80.

telnet google.com 80

Adresa unui site web este formată din protocolul de comunicație urmat de DNS adică de nu-
mele domeniului sau al serverului care este de fapt numele dat IP-iului serverului respectiv
apoi în continuare este portul pe care aplicația ascultă să vadă dacă cineva dorește să comu-
nice cu ea.

https://bitulica.ro:80

Un site poate să ruleze pe orice port dar portul implicit este 80 și prin urmare dacă acesta lip-
sește el este înlocuit automat cu 80.

https://bitulica.ro

© Bitulică 2020
Povestea lui Bitulică

Am înțeles că este recomandat ca portul intern al mașinii pe care rulează siteul să nu fie portul
implicit pentru că cei care scanează site-uri pentru a le afla vulnerabilității și ulterior a decide
dacă să le atace sau nu, știu că porturi implicit este 80 și pe el lansează atacul.

Portul extern este portul pe care îl vede cineva din afara rețelei Interne portul intern este cel
pe care îl vede cineva din interiorul rețelei Interne.

Aceste porturi pot fi setate pe router atunci când se utilizează aplicația de forward port a rute-
rul. Dacă eu pe PC am setat portul 777 pe care rulează aplicația server atunci degeaba atacă
cineva portul 80 că nu va avea acces.

Portul implicit al protocolului FTP este 21 iar portul implicit al protocolului SMTP este 25. Așa
cum îmi dau seama acestei porturi sunt porturi pe care protocoalele le folosesc pentru comu-
nicare și cum protocoalele au și variante securizate înseamnă că aceste variante securizate au
și ele porturile lor specifice.

Protocolul https folosește portul 443 iar protocolul securizat cu SSl pentru imap folosește
portul 465 sau 993.

Pentru a verifica dacă o mașină adică un computer conectat la rețea este vizibil în acea rețea
de la un alt computer atunci de la computerul dinspre care se privește se poate da comanda
PING către celălalt computer.

ping 127.0.0.1

IP-ul 127.0.0.1 este ip-ul local al fiecărei mașini iar numele său adică DNS este localhost

ping localhost

© Bitulică 2020
Povestea lui Bitulică

Pentru a putea să mă conectez remote de la o mașină pe altă mașină am înțeles că am nevoie


să folosesc protocolul ssh

Protocolul ssh folosește implicit portul 22 și varianta pentru remote desktop connection este
protocolul rdp.

Am citit că pot crea și o rețea virtuala privată adică o rețea la nivel logic peste rețeaua fizică
folosind aplicația OpenVPN care crează o rețea tip VPN adică o rețea virtuală privată.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie de managementul datelor


SGBD
Am descoperit sistemul de gestiune

Noi avem trei mașini. Eu am una Katy are una și Lisa încă una Evi nu are că e încă mică în curte
avem un garaj în care intră o singură mașină așa că pe celelalte două le ducem la o parcare
supraetajata pentru că acolo sunt în siguranță nu le ninge și nu le plouă și nici nu se pune pra-
ful pe ele

parcarea este una de ultimă generație în care la o simplă apăsare de buton după ce am ales
numărul locației mi se aduce mașina și pot pleca cu ea

Practic acea parcare este un sistem specializat pentru parcarea mașinilor având mult mai
multe facilități decât ar avea cineva individual în curte sau în fața casei sau a blocului

De fiecare dată când merg cu mașina lui Katy ea îmi aduce aminte că așa cum această parcare
este un instrument specializat pentru parcarea mașinilor așa și în informatică există instru-
mente specializate pentru parcarea datelor adică pentru persistarea lor în vederea păstrării
pentru un timp îndelungat

Zice că a pune datele în fișier local este ca și cum aș avea parcare în fața casei iar a ține datele
într-un sistem specializat așa cum sunt sistemele de gestiune a bazelor de date este ca și cum
aș avea mașina parcată într-o parcare specializată

Am înțeles că există mai multe sisteme de gestiune ale bazelor de date și că dezvoltatorii de
aplicații le folosesc în funcție de necesități unele dintre cele mai folosite sisteme de gestiune
ale bazelor de date sunt cel dezvoltat de Microsoft și care se numește SQL Server cele dezvol-
tate de Oracle Și care se numesc MySQL si Oracle Pe lângă acestea mai există și alte sisteme
de gestiune cum ar fi Mongo MariaDB sau Orient DB

© Bitulică 2020
Povestea lui Bitulică

Există trei categorii de sisteme de gestiune unele SQL și altele NOSQL dar și sisteme de gesti-
une hibrid Sistemele de gestiune SQL sunt sistemele de gestiune în care datele sunt stocate
pe hard-disk iar sistemele NOSQL sunt sistemele în care datele sunt stocate în memoria RAM
Evident că în cadrul sistemelor hibrid datele sunt stocate atât în memoria RAM cât și pe
harddisk un exemplu de astfel de sistem de gestiune fiind Mongo Microsoft SQL Server este un
sistem de gestiune în care datele sunt stocate pe hard la fel este și MySQL în timp ce Oracle
este un sistem în care datele sunt stocate în memoria RAM

Viteza de execuție este de partea sistemelor de gestiune care își țin datele în memoria RAM
pentru că viteza de acces din memoria RAM este mult mai mare decât viteza de acces de pe
hard disk Dar mașinile care formează sistemul de gestiune al bazelor de date la nivel fizic sunt
mult mai scumpe decât cele în care datele sunt stocate pe hard-disk pentru că memoria RAM
este mult mai scumpă decât hard disk-ul pentru același volum de Stocare

Pentru că aplicațiile se poate trimite date către sistemele de gestiune ale bazelor de date pen-
tru a fi stocate de acesta din urmă este nevoie ca aplicațiile să poată comunica cu sistemele
de gestiune

Pentru că o aplicație să poată comunica cu sistemele de gestiune este nevoie ca între siste-
mele de gestiune și aplicații să existe o Conexiune în baza căruia să fie trimise și primite date
de la aplicație că tre să stăm unde ai gestiona și de la sistemul de gestiune către aplicație

De asemenea Datele care Circulă pe conexiune trebuie să fie manipulate de către cineva astfel
încât el să fie înțelese atât de aplicație cat și de sistemul de gestionare și pentru aceasta este
nevoie de un driver

Când o aplicație încearcă să se conecteze la un sistem de gestiune al bazelor de date ea tri-


mite către sistemul de gestiune cu care se conectează niște date de conectare și odată ce co-
nexiunea fost stabilită aplicația poate trimite și primi date de la sistemul de gestiune

Datele de conectare trimise către sistemul de gestiune conțin un utilizator o parolă și instanța
sistemului de gestiune la care se dorește conectarea.

© Bitulică 2020
Povestea lui Bitulică

Când am avut nevoie de sistemul de gestiune


SGBD
Am descoperit din ce este compus

Un sistem de gestiune a bazelor de date este format din baze de date care la rândul lor sunt
formate din tabele legate între ele prin diferite scheme de legătură

Tabelele conțin o colecție de câmpuri care au un anumit tip și care conțin date care se înca-
drează în acest tip. Tabelele pot fi imaginate ca tabelele de pe hârtie care conțin un cap de ta-
bel niște coloane și niște date corespunzătoare fiecărei valori din capul de tabel așezate pe
fiecare rând.

Din punct de vedere tehnic tabelele seamănă și uneori chiar sunt fișiere de date cu tip în care
tipul este o structură. Tipul structură mai poarte numele și de înregistrare tocmai datorită fap-
tului că acest tip seamănă cu o înregistrare dintr-o tabelă.

Am înțeles că există semnificații diferite între tabel și tabela. Tabelul fiind obiectul informatic
care conține datele iar tabela fiind modul în care aceste date sunt prezentate adică un instru-
ment de prezentare a datelor exact cum există tabela de marcaj de pe stadioane.

Așadar o bază de date este o colecție de tabele legate într-o formă sau alta adică după o
schemă sau alta iar tabelele la rândul lor sunt o colecție de câmpuri populate cu valori.

Am înțeles că o înregistrare dintr-un tabel este reprezentată de un rând, altul decât capul de
tabel din acel tabel.

Pe lângă baze de date scheme și tabele un sistem de gestiune al bazelor de date cuprinde ve-
deri adică view-uri care reprezintă agregarea mai multor date dintr-un tabel sau tabele dife-
rite astfel încât utilizatorul să le perceapă ca fiind într-un singur tabel. Așa cum îi spune și de-
numirea ele reprezintă ceea ce utilizatorul vede și modul în care utilizatorul vede datele.

© Bitulică 2020
Povestea lui Bitulică

O bază de date conține funcții și proceduri stocate care reprezintă scripturi ce execută anu-
mite operații pe baza de date sau pe tabelele din baza de date. Funcțiile pot fi funcții tabelare
sau funcții scalare. Funcțiile tabelare sunt funcțiile al cărui rezultat este un tabel în timp ce
funcțiile scalare sunt funcțiile al cărui rezultat este o mărime scalară O funcție tabelară poate
fi privită și ca funcție vectorială pentru că în fond un tabel reprezintă modificarea în timp a
unei valori exact ca și un vector.

Un sistem de gestiune al bazelor de date mai cuprinde punți între serverele de baze de date
care sunt obiecte cu ajutorul cărora se poate aduce informația de pe un server extern de baze
de date pe server-ul actual pentru a fi procesată.

Sistemul de gestiune al bazelor de date mai cuprinde și declanșatoare adică triggere care se
declanșează la anumite operații pe tabele. Acestea sunt utilizate în principal pentru copierea
de date dintr-un tabel intr-altul atunci când este nevoie de copierea lor la momentul în care
au fost executate anumite operații asupra unei tabele dar sunt utilizate și pentru validarea da-
telor care urmează să fie introduse în tabele.

Un sistem de baze de date permite indexarea datelor din tabel adică aranjarea lor într-o anu-
mită ordine care să permită găsirea datelor mult mai ușor aceste indexuri sunt tabele la rân-
dul lor care sunt atașate unei anumite tabele,

Sistemul de gestiune al bazelor de date permite și replicarea datelor de pe un server pe altul


operație necesară pentru asigurarea consistenței datelor pe două servere diferite de bază de
date.

Un sistem de gestiune al bazelor de date permite inserarea datelor în tabele modificarea date-
lor din tabel ștergerea datelor din tabel și selecția datelor din tabel de asemenea permite ală-
turarea a două sau mai multe tabele astfel încât rezultatul să fie un tabel unitar. Această ope-
rație fiind utilă pentru legarea informației stocate separat adică în tabele separate.

Sistemele de gestiune a bazelor de date pot permite baze de date relaționale adică între tabe-
lele cărora există relații de corespondență dar și baze de date distribuite adică cele ale căror

© Bitulică 2020
Povestea lui Bitulică

tabele se afle pe servere diferite aflate în locații diferite dar pe care utilizatorul le vede ca fiind
pe un singur server exact cum funcționează și sistemul de cloud.

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să pastrez datele


Am descoperit baza de date
SQL SERVER

Acum ceva vreme am făcut în curtea casei un foișor și în acest foișor am un dulap în care îmi
pun diferite chestii de care am nevoie în curte în principal unelte și scule.

Katy zice că așa cum am dulapul cu scule și așa cum sculele sunt aranjate pe rafturi în dulap
așa și datele în tehnologia informației sunt aranjate în sistemele de gestiune ale bazelor de
date.

Practic sistemul de gestiune a bazelor de date este ca un magazioner iar bazele de date ca
niște magazii.

Atunci când vreau să iau ceva din aceste magazii sau să pun ceva în ele trebuie să vorbesc cu
magazionerul pentru că doar el are acces la ele. De asemenea și dacă vreau să arunc ceva din
ce este în magazie sau să repar ceva ce este în magazie tot cu magazionerul trebuie să vor-
besc pentru că el poate face asta având acces la magazie.

Sistemul de gestiune al bazelor de date am înțeles că este ca foișorul meu înainte să am dula-
pul în el și practic când am creat dulapul am făcut o bază de date în foișor și exact așa trebuie
să procedez și cu sistemul de gestiune al bazelor de date și să creez baze de date în el atunci
când am nevoie de o nouă baza de date cum ar veni un nou dulap în foișorul meu că acesta
este plin sau poate vreau să organizez mai bine și să fac un dulap pentru scule de tâmplărie și
altul pentru sculele de grădină.

Pentru a crea o nouă bază de date în sistemul de gestiune al bazelor de date trebuie să mă
conectez la sistemul de gestiune al bazelor de date folosind un user și o parolă sau folosind
credentialele implicite ale sistemului de operare iar apoi să stabilesc o conexiune cu sistemul
de gestiune a bazelor de date prin care să trimit niște comenzi pe care el să le interpreteze și
să creeze diferite chestii cum ar fi de exemplu în cazul de față o bază de date.

© Bitulică 2020
Povestea lui Bitulică

Comanda prin care pot creea în sql server o bază de date este

CREATE DARABASE test;

Create în limba engleză înseamnă a crea iar database înseamnă baza de date prin urmare test
este numele bazei de date pe care vreau să o creez.

Pentru a specifica în același script că imediat după ce a citit această comandă să o și execute
trebuie să scriu comanda

GO

care în limba engleză are sensul de a se duce și a executa.

Dacă vreau să utilizez noua bază de dată creată atunci trebuie să scriu comanda

USE test;

Și apoi ca să o execute imediat ce a citit comanda trebuie să scriu comanda

GO

© Bitulică 2020
Povestea lui Bitulică

De acum în acest script toate comenzile pe care le voi scrie de aici încolo se vor executa pe
bază de date pe care am dorit să o utilizez.

Pentru a executa o comandă într-un statement pe sql server folosind utilitarul SQL Server Ma-
nagement Studio pot să selectez textul comenzii și să apăs tasta funcțională F5.

Dacă nu este nimic selectat atunci la apăsarea tastei funcționale F5 se va executa întreg scrip-
tul scris în statementul curent.

© Bitulică 2020
Povestea lui Bitulică

Când am vrut să stochez date


Am descoperit tipurile de date
SQL SERVER

Dulapul din foișorul meu are mai multe sertare unele sunt mai mici în care îmi pun uneltele
mai mici și altele sunt mai mari în care îmi pun uneltele mai mari.

Ca și dulapul și sistemul de gestiune a bazelor de date lucrează cu câmpuri de diferite di-


mensiuni în care se pot stoca diferite date care au o dimensiune sau alta la fel cum datele
din limbajul de programare C sau C++ au locații de diferite mărimi în care sunt stocate în
memoria RAM.

Tipurile de date întâlnite în limbajul sql server sunt ca și în celelalte limbaje de programare
sau de gestionarea datelor împărțite pe diferite categorii.

Unele tipuri de date sunt concepute pentru a stoca date numerice exacte adică acele date
de o precizie fixă.

bigint

Este tipul de dată care memorează numere întregi de dimensiuni mari și este omologul tipu-
lui long din limbajele C și C++

numeric

Este un tip de dată care memorează numere reale având o anumită precizie adică un anu-
mit număr specificat de zecimale după virgulă

bit

Așa cum îi spune și numele el este tipul de dată care memorează un bit adică ori valoarea 0
ori valoarea 1.

smallint

Acest tip de dată este un tip de dată mai mic decât bigint și chiar mai mic decât int fiind ca
dimensiune un sfert din tipul bigint

decimal

Este tot un tip care memorează numere reale având o anumită precizie specificată adică un
anumit număr de zecimale după virgulă

smallmoney

Acest tip de dată memorează simboluri de monezi dar este ca dimensiune mai mic decât ti-
pul money

© Bitulică 2020
Povestea lui Bitulică

int

Așa cum îi spune și numele și după cum văd seamănă cu omologul său din limbajele C și
C++ acest tip de dată memorează numere întregi adică numere cu semn și este la jumăta-
tea distanței dintre tipul smallint și tipul bigint

tinyint

Este un tip de dată care are ca dimensiune un byte adică poate memora valori doar până la
255 începând de la zero

money

Este tipul de dată specific pentru simbolurile monezilor

float

La fel ca și omologul său din limbajele de programare acest tip memorează numere în vir-
gulă mobilă ceea ce înseamnă că precizia lui este inexactă

real

La fel se întâmplă și cu acest tip de dată el este omologul tipului double din limbajele de pro-
gramare

date

Acest tip de dată permite memorarea datelor calendaristice dar fără partea rezervată timpu-
lui

datetimeoffset

Tipul acesta este un tip care memorează duratele scurse între două momente cu alte cu-
vinte memorează perioadele

datetime2

Acest tip este o variantă îmbunătățită a lui datetime și care memorează date calendaristice
complete adică și împreună cu timpul

smalldatetime

Acest tip memorează tot date calendaristice dar în format scurt

datetime

© Bitulică 2020
Povestea lui Bitulică

Acesta este tipul clasic care memorează date calendaristice împreună cu timpul aparent
până la milisecundă

time

Acest tip permite memorarea datelor care reprezintă timpul adică orele minutele secundele
și milisecundele

char

Acest tip de dată permite memorarea unui singur caracter și este omologul tipului cu același
nume din limbajul de programare

varchar

Acesta este un omologul timpului string din limbajele de programare și permite memorarea
unui număr variabil de caractere ocupând atâta memorie câte caractere sunt introduse în
câmpul al cărui tip este

text

Acesta este un alt mod de a memora texte adică șiruri de caractere

nchar

Acesta este varianta lui char dar pentru memorarea textelor unicode

nvarchar

Acesta este varianta lui varchar dar pentru memorarea textelor unicode

ntext

Aceasta este varianta tipului text dar pentru memorarea textelor unicode

binary

Acest tip permite memorarea datelor în format binar acestea pot fi codate în format hexaze-
cimal

varbinary

Acest tip este omologului varchar dar pentru datele în format binar

image

În câmpurile care au acest tip se pot memora imagini

© Bitulică 2020
Povestea lui Bitulică

cursor

Acest tip este un un iterator și cu ajutorul lui se poate litera un set de rezultate rând cu rând

rowversion

Acest tip de date este folosit pentru indexarea tabelelor adică un câmp care are acest tip
conține un cod binar unic

hierarchyid

Acest tip de date este folosit pentru ierarhizarea datelor

uniqueidentifier

Acesta este un tip de dată care permite memorarea unui identificator unic unicitatea acestui
identificator vine din faptul că el este o colecție de bytes care reprezintă în ordine timpul la
care a fost generat nodul de rețea în care a fost generat și tipul procesorului cu ajutorul că-
ruia a fost generat astfel prin conlucrarea acestor factori un astfel de identificator este unic
la nivel mondial

sql_variant

Dacă un câmp are acest tip de dată atunci în acel câmp se pot stoca diferite tipuri de date
ale sistemului de gestiune e ca și cum o funcție are avea parametrul Void și poate fi apelată
cu orice tip de parametru

xml

Ați tip de dată permite memorarea unui text în format xml adică întru un mod de serializare
standard practic un astfel de câmp poate fi considerat un rând la rândul său

Spatial Geometry Types

Acest tip de date permite memorarea coordonatelor spațiale geometrice adică cu o precizie
mai mică

Spatial Geography Types

Acest tip de date permite memorarea coordonatelor spațiale geografice adică cu o precizie
mai mare și aici pot fi memorate coordonatele GPS ca longitudine latitudine și altitudinea

table

Acest tip de dată poate memora un tabel deci practic câmpul care are acest tip poate fi con-
siderat un tabel la rândul său

© Bitulică 2020
Povestea lui Bitulică

© Bitulică 2020

S-ar putea să vă placă și