Thursday, December 31, 2015

Limbajul C++. Implementarea unei functionalitati aritmetice intr-o clasa

Exemplul urmator propus de programmr.com are un singur aspect netrivial: se cere ca initializarea membrilor clasei sa se faca prin metode, si nu prin explicitarea constructorilor.

Clasa student invocata in enunt are trei membri - un string care prezerva numele studentului, un integer pentru matricola si un tablou de intregi pentru notele la cinci materii.

O metoda publica input initializeaza membrii dupa instantierea unui obiect student. O alta metoda publica output afiseaza media notelor.

Enuntul original:

"A class student has three data members: name, roll, marks of 5 subjects and member functions to input name, roll no and marks, and display Percentage. Declare the class student and define the member functions. The program should ask user for name, roll no and marks in 5 subjects, and should display the percentage."

Codul si printscreen-ul:

Limbajul C++. Alte probleme cu siruri de caractere

Doua enunturi fara mari dificultati de pe programmr.com, cu mentiunea ca am folosit pentru initializarea sirurilor de caractere, in locul "batranei" functii gets(char *str) din biblioteca C, metoda getline din clasa std::istream

Aceasta incarca in spatiul indirectat de char * str un numar specificat, n, de caractere inclusiv terminatorul de sir. Adica, daca dorim sa impunem citirea a maxim 50 de caractere, linia corespunzatoare va fi:

cin.getline(str, 51);

Primul enunt cere scrierea unui cod care converteste fiecare caracter al unui sir de caractere in echivalent binar, fiind luate in calcul si eventualele spatii si semne de punctuatie.

O functie de conversie realizeaza 8 impartiri la 2 ale codului ASCII corespunzator fiercarui caracter transmis ca parametru, pentru a initializa bitii care codifica respectivul caracter, stiut fiind ca o variabila de tip char ocupa 8 biti in memorie.

Codul si printscreen-ul:

Wednesday, December 30, 2015

Limbajul C++. Capitalizarea literelor sau o problema stil K & R


Un exemplu de cod care numara cuvintele intr-un sir de caractere este prezentat in cartea scrisa de Kernighan si Ritchie.

Enuntul urmator, "Write a program which takes input string and capitalizes the first character of each word in a string, and does not affect the others"  este de pe site-ul programmr.com, dar cu siguranta poate fi intalnit in multe alte locuri/lucrari.

Rezolvarea problemei se bazeaza pe acelasi mecanism descris in lucrarea lui K & R:

- definirea unui cuvant ca o succesiune de caractere non-space care sunt bordate de spaces. Desigur, pe baza acestei definitii, ,,,#@sg-abcd,, este un cuvant, ceea ce poate parea derutant in raport cu bunul simt. Desigur, asd_g def este, conform aceleiasi definitii, o succesiune de doua cuvinte, asd_g si def.

- declararea si setarea unei variabile inword  care "tine cont" daca la un moment oarecare (la o iteratie oarecare) ne aflam sau nu in interiorul unui cuvant.

Daca s este un sir de caractere introdus de la tastatura, a carui lungime length o vom determina, atunci algoritmul implementat poate fi urmatorul:

Tuesday, December 29, 2015

Limbajul C++. Implementarea unei aplicatii cu clase derivate


Urmatorul enunt reprezinta un assignment aferent uneia dintre lectiile din cadrul cursului "Bazele programarii C++" sustinut la InfoAcademy.

Aceasta prezentare nu are intentia de a compromite procesul didactic, ci de a oferi o perspectiva asupra felului in care sunt prezentate in viata reala cerintele de implementare a unui proiect.

Enuntarea si implementarea cerintelor sunt abordate pas cu pas.

Se lucreaza intr-un spatiu de nume intitulat "Assignment9".

Declaratiile de clase sunt salvate in fisiere header (.h). Definitiile sunt salvate in fisiere sursa (.cpp).

Limbajul C++. Clonarea obiectelor folosind metodele virtuale si constructorul de copiere


Realizarea unei clone a unui obiect presupune crearea unui obiect nou, cu existenta independenta de cel clonat, care ocupa in memorie un spatiu distinct de cel clonat dar care are toate atributele si metodele identice cu ale celui clonat.

Mecanismul urmator foloseste constructorul de copiere si o metoda declarata virtuala, care este supracrisa in clasa derivata. Declararea virtuala este necesara pentru apelul corect al metodelor: metoda Clone va fi cautata intai in clasa derivata, indiferent de scenariu - fie ca variabila are tipul clasei de baza sau cel al clasei derivate.

Stim ca o variabila initializata cu o instanta a clasei derivate are si tipul clasei de baza (invers nu!)

Suprascrierea metodei implica prezervarea aceleiasi semnaturi (nume, argumente, tip de return) dar o implementare diferita in clasa derivata.

Sunday, December 20, 2015

Limbajul C++. Functii. Transfer prin valoare, referinta, adresa


Stim ca la transmiterea prin valoare a argumentelor unei functii, prelucrarea nu se face asupra variabilelor-argument, ci asupra unor copii. Copiile sunt variabile interne blocului functiei, de aceea durata lor de viata este limitata la blocul functiei. Reguli:

1) nu folosim transmisia prin valoare in cazul unor variabile de mari dimensiuni, pentru ca dimensiunea trebuie replicata pentru copiile folosite in corpul functiei;

2) nu folosim transferul prin valoare cand vrem ca variabilele transmise ca argument sa fie modificate.

Pentru cazurile mentionate anterior putem folosi transferul prin referinta (alias al variabilei-argument, permis doar in C++) sau transferul prin adresa (cu pointeri, permis in C/C++). 

Transferul prin adresa este, de fapt, tot un transfer prin valoare.

Tuesday, December 15, 2015

Limbajul C. Sortarea unei liste

Este vorba despre o lista simplu inlantuita (LSI), ale carei noduri servesc drept container pentru valori numerice (numere intregi in cazul de fata). Sigur ca se poate obiecta ca e un efort inutil sa scrii cod pentru a sorta secvente de numere intregi folosind structuri, recte LSI. 

Exista varianta binecunoscuta de sortare folosind vectori sau tablouri monodimensionale drept container.

Totusi, structura fiind un tip de data definit de utilizator, este mai flexibila decat un tablou, fie si prin faptul ca un nod al listei, spre deosebire de elementul unui tablou, poate contine mai mult de o variabila de baza la un moment dat.

Ne putem imagina, de pilda, o LSI care stocheaza in fiecare nod trei intregi corespunzand unei date calendaristice: ziua, luna, anul.

Intr-un astfel de caz, LSI este optiunea naturala, in detrimentul celei cu tablouri.

Sortarea unei astfel de liste ar trebui gandita dupa urmatorul algoritm:

Monday, December 14, 2015

Limbajul C. Un cronometru simplu cu ciclu de intarziere

Aplicatia urmatoare simuleaza un cronometru care afiseaza timpul pana la o valoare (ore, minute, secunde) introdusa de utilizator. 

Valoarea sau, mai exact, conversia acesteia in secunde trebuie sa fie mai mica decat numarul secundelor care echivaleaza 24 de ore (==86400).

O structura cu trei variabile int este folosita pentru a stoca timpul curent. O functie Display afiseaza acest timp, secunda cu secunda, parametrul functiei fiind variabila structura.

In mod uzual se folosesc pointeri la structura pentru a evita copierea intregii structuri in parametrul formal. In cazul de fata, nefiind vorba de o structura foarte 'voluminoasa', s-a optat pentru transferul prin valoare.

Sunday, December 6, 2015

Limbajul C. Implementarea unei stive cu un tablou monodimensional

O stiva este o colectie de elemente de acelasi tip procesata dupa principiul LIFO, last in, first out. Asta inseamna ca procesarea se face intotdeauna la "capatul din dreapta", adica introducerea de element nou, stergerea unui element si citirea elementelor din stiva se realizeaza pornind de la ultimul element adaugat.

Implementarea pe baza unui tablou monodimensional, numit in continuare 'stack', are o anumita valoare didactica dar si limitari, care pot fi depasite prin folosirea unei liste inlantuite, caz ce va fi detaliat intr-o postare ulterioara.

index: 0  stack[0]: neinitializat

Wednesday, December 2, 2015

Limbajul PHP. Ordonarea unui sir numeric cu un algoritm "ineficient"

Codul urmator implementeaza probabil cel mai trivial algoritm de sortare, bazat pe urmatoarele consideratii.

1) Fie cel mai defavorabil caz al unui sir pentru care se doreste ordonarea crescatoare, adica, presupunand ca este vorba de un sir de 4 numere intregi,
$i = array(4, 3, 2, 1);

2) Ne propunem ca pentru $k = 0, $k < 4, pentru fiecare situatie $i[$k] >= $i[$k + 1] sa inversam valorile celor doua elemente, folosind in acest scop variabila intermediara $temp:

$temp = $i[$k]; $i[$k] = $i[$k + 1]; $[k + 1] = $temp;

Monday, November 30, 2015

Limbajul PHP. Functii si tablouri. Aplicatie: eliminarea elementelor dintr-un string pe baza paritatii si afisarea optimizata a rezultatului

Problema urmatoare este enuntata pe site-ul www.programmr.com si face apel la notiunile de functie, string, tablou, instructiuni de decizie si ciclare.

Enuntul:

"Write a function evens that accepts an integer parameter 'n' and that returns the integer formed by removing the odd digits from 'n'.

If a negative number with even digits other than 0 is passed to the method, the result should also be negative.


Leading zeros in the result should be ignored and if there are no even digits other than 0 in the number, the method should return 0."

Rezolvarea propusa in codul urmator face abstractie de functiile accesibile in manipularea sirurilor se caractere. De pilda, lungimea stringului in care sunt stocate cifrele si eventualul semn al numarului introdus de la tastatura se determina intr-o bucla while si nu cu strlen().

Sunday, November 29, 2015

Limbajul C. Adunarea intregilor lungi. Aspecte netriviale intr-o problema aparent banala.

Puterm reprezenta, in conformitate cu tipurile de baza din limbajul C, numere intregi pozitive de la 0 la 2^32 - 1 sau numere intregi cu semn in domeniul: -2^31, +2^31 - 1.

Intrucat limbajul nu impune restrictii (dar sistemul de operare si compilatorul pot impune restrictii!) asupra dimensiunii tablourilor de intregi (== asupra memoriei alocate static), putem imagina un sistem de citire si afisare a numerelor intergi lungi de o dimensiune convenabila utilizatorului, fiind, de asemenea, posibila si simularea operatiilor aritmetice cu astfel de numere.

Desigur, trebuie tinut cont de mecanismul de transport: daca doua cifre situate pe pozitii corespunzatoare dau, adunate, un rezultat mai mare decat valoarea bazei de reprezentare, in cazul de fata 10, trebuie adunat 1 (== valoarea transportului) la rezultatul adunarii cifrelor de pe urmatoarea pozitie si, de asemenea, verificat iar rezultatul prin comparatie cu baza etc.

Este clasicul algoritm invatat in clasa a 2-aJ

Friday, November 27, 2015

Limbajul C. Pointeri la functii. Un mic reminder al algoritmului GCD (Greatest Common Divisor)

O functie este stocata in memorie la o adresa, exact ca o variabila iar adresa functiei respective se obtine utilizand numele functiei, fara paranteze si parametri formali, exact cum utilizam numele unui tablou pentru a asigna adresa sa unui pointer la tipul elementelor tabloului. 

Faptul ca o functie este stocata (incarcata) de compilator la o anumita adresa permite utilizarea unui pointer la functia respectiva.

Sintaxa declararii unui pointer la functie:

tip_return_functie (* ptrf)( lista_de_parametri_formali_ai_functiei );

Prima pereche de paranteze este necesara intrucat, in absenta acestor paranteze, declaratia respectiva ar fi prototipul unei functii numite ptrf cu lista specificata de parametri si care intoarce un pointer la tip_return_functie.

Wednesday, November 25, 2015

Limbajul C. "Insert a letter in string".

Fara prea multe comentarii (cu exceptia celor din cod :-), inca o problema din cursul de la University College Cork, menita sa fixeze notiuni precum siruri de caractere, tablouri, functii.

1.  Write and test a function that inserts a character anywhere in a string. The function should take the general form: strins(  char *string,  char character,  int position ).

Codul si printscreen-ul executiei:

Monday, November 23, 2015

Limbajul C. Matrice "X si 0". "X si 0" la consola pentru 2 jucatori


1.
 Codul urmator atribuie elementelor unei matrice bi dimensionale 3 x 3 valori de tip char (pentru o afisare corespunzatoare, trebuie introduse caractere alfanumerice, nu white-spaces) preluate de la tastatura sub forma unui sir.


Initial toate elementele matricii au valoarea '\0', neafisabila. Se pot introduce oricate caractere, oricum vor fi incarcate doar primele 9. Daca sunt introduse mai putin de 9 caractere, fie numarul acestora n, sirul de n caractere se va termina cu 'z' pe post de validator.

Codul si printscreen-ul:

Saturday, November 21, 2015

Limbajul C. Exercitii clasice cu siruri de caractere. MyStrcmp si eliminarea asa-numitelor white-spaces

1. Clasicul MyStrcmp

Doua siruri de caractere sunt "egale" daca au exact aceleasi caractere dispuse in aceeasi ordine.

O functie testeaza aceasta "egalitate" si intoarce zero in caz ca se verifica egalitatea.

Daca sir1 < sir2, adica daca verificarea, pentru un caracter oarecare, incepand cu primul, a codurilor ASCII, satisface inegalitatea, functia intoarce -1.

In caz contrar, intoarce +1.

Friday, November 20, 2015

Limbajul C. Mai multe probleme cu tablouri

Urmatoarele enunturi figureaza in cursul predat la University College Cork.

1. Se cere un program care citeste de la tastatura numere reale dubla precizie intr-un cuantum n specificat de utilizator, le stocheaza intr-un tablou de maximum 100 de elemente, calculeaza suma si media lor. La final se elimina din suma valorile extreme introduse, adica maximul si minimul. Se afiseaza tabloul initial apoi se realizeaza inversarea elementelor stocate in tablou, astfel incat primul devine ultimul etc.


Evident, se vor folosi functii definite de utilizator pentru fiecare sarcina specificata.

Thursday, November 19, 2015

Limbajul C. Tablouri mono si bi dimensionale. Matrici, liniarizare

Tablourile multi-dimensionale (uzual bi si tri dimensionale) sunt tablouri ale caror elemente sunt alte tablouri (mono, respectiv bi dimensionale pentru cazul uzual invocat).

tab[2][3] = {1,2,3,4,5,6}; // tab[1][1] are valoarea 5

Declaratia de sus reprezinta initializarea unei matrici bi dimensionale cu 2 linii si 3 coloane.
Putem liniariza aceasta matrice folosind un tablou mono dimensional de 6 intregi, considerand ca primele trei elemente ale sale formeaza prima linie iar ultimele, cea de-a doua linie.

Wednesday, November 18, 2015

Limbajul C. Numere prime, numere prietene, Fibonacci, listarea valorilor unei functii pe un interval

Toate problemele de mai jos sunt enunturi adaptate sau luate ca atare din cartea scrisa de V.Iorga & colaboratorii, "Programare in C/C++. Culegere de probleme", ISBN 973-568-800-X aparuta in 2003.

Toate enunturile reprezinta probleme de programare procedurala.

1. Descompunerile unui numar par ca suma de numere prime. Problema P2_3. 

Teorie: daca n este un numar par, adica n = 2*k iar k e un intreg oarecare,
atunci o cale ar fi determinarea tuturor numerelor prime pana la n, fie m numarul
acestor numere prime. Scazand din n fiecare dintre cele m numere si verificand daca
rezultatul scaderii este tot numar prim, aflam descompunerile cerute de problema.

Codul si printscreen-ul executiei:

Tuesday, November 17, 2015

Limbajul C. O ecuatie neliniara rezolvata cu metoda bisectiei.


Problema urmatoare reprezinta proiectul de mid-term al cursului predat la University College Cork. Enuntul - sa se rezolve prin metoda bisectiei urmatoarea ecuatie neliniara:

sin(2x/5) - x + 1 = 0.

O prima observatie este ca avem o suma de doua functii continue, deci functia-rezultat este continua.

Ecuatia se poate rescrie sin(2x/5) = x - 1, deci intr-o rezolvare "geometrica" ar trebui determinat punctul de intersectie al dreptei x - 1 cu graficul lui sin(2x/5), conform figurii urmatoare, desenata chinuit, cu pixul:-)

Saturday, November 14, 2015

Limbajul C. Alte doua probleme simple. Conversie la binar si permutari. Simularea citirii numerelor intregi

La un moment dat, oricine codeaza se va lovi de problema permutarilor, fie ele circulare sau nu. Codul de mai jos rezolva doua chestiuni: conversia la binar a unui numar pe pozitiv pe 8 biti si permutarea circulara, de un numar de ori, a celor 8 biti.

Enuntul problemei figureaza in lista exercitiilor de la jumatatea materiei de C procedural predata in cursul de la University College Cork. Rezolvarea propusa este oarecum inaintea materiei, pentru ca foloseste vectori. Desi este posibila rezolvarea fara a apela la vectori (tablouri), a fost aleasa varianta cu tablouri, intre altele si pentru ca in practica o variabila modificata este, in general, stocata pana la finalul executiei codului.

Thursday, November 12, 2015

Limbajul C. O situatie netriviala intr-o problema triviala de calculare a sumei si valorii medii a n numere

Enuntul urmator nu comporta surprize decat la final. Desigur, exista si alte variante de a asigura un input corect de tip double sau macar numeric insa, intrucat 'batrana' functie scanf are, intre altele, si proprietatea ca returneaza numarul campurilor corect citite, a fost preferata solutia de mai jos.

De reamintit ca scanf ignora caracterele white-space (tab, newline, space) si se alimenteaza din buffer (este din categoria "buffered input") la apasarea tastei Enter.

Enuntul original, din cursul predat la Cork University College (Irlanda):

Wednesday, November 11, 2015

Limbajul C. Contorizarea caracterelor

O problema simpla de C procedural din cursul Cork.

Enuntul:

"2. Write a program to keep count of the occurrence of a user specified character in a stream of characters of known length ( e.g. 50 characters ) input from the keyboard. Compare this to the total number of characters input when ignoring all but alphabetic characters."

Codul: