pct 5 informatica-intrebari+raspuns(2016)6 vh ghilqhdvf xup wrduhoh 7'$ xul $ duwlfro fx...

51
Probleme pentru examenul de licenţă - INFORMATICĂ Introducere în programarea calculatoarelor / Tehnici de programare (1) 1. Daţi o soluţie recursivă, în limbajul de programare C, pentru Algoritmul lui Euclid de aflare a celui mai mare divizor comun a două numere întregi. Formularea în cuvinte a algoritmului este următoarea: Dacă unul dintre numere este zero, c.m.m.d.c. al lor este celălalt număr. Dacă nici unul dintre numere nu este zero, atunci c.m.m.d.c. nu se modifică dacă se înlocuieşte unul dintre numere cu restul împărţirii sale cu celălalt. 2. Să se scrie o funcţie care inversează conţinutul unui şir de caractere; şirul iniţial va fi returnat ca rezultat al apelului funcţiei. Se vor folosi operaţii cu pointeri. 3. Scrieţi, în C, un program care să creeze un fişier copie a unui fişier dat. SOLUŢII 1. unsigned cmmdc (unsigned m, unsigned n) { if (n==0) return m; else return cmmdc(n, m%n); } 2. char *strrev (char *sir) { char *initial = sir; char *urmator = sir; char temp; while (*sir) sir++; while (urmator < sir) { temp = *(--sir); *sir = *urmator; *urmator++ = temp; } return (initial); } 3.

Upload: others

Post on 25-Feb-2020

9 views

Category:

Documents


0 download

TRANSCRIPT

Probleme pentru examenul de licenţă - INFORMATICĂ

Introducere în programarea calculatoarelor / Tehnici de programare (1) 1. Daţi o soluţie recursivă, în limbajul de programare C, pentru Algoritmul lui Euclid de aflare a

celui mai mare divizor comun a două numere întregi. Formularea în cuvinte a algoritmului este următoarea: Dacă unul dintre numere este zero, c.m.m.d.c. al lor este celălalt număr. Dacă nici unul dintre numere nu este zero, atunci c.m.m.d.c. nu se modifică dacă se înlocuieşte unul dintre numere cu restul împărţirii sale cu celălalt.

2. Să se scrie o funcţie care inversează conţinutul unui şir de caractere; şirul iniţial va fi returnat ca rezultat al apelului funcţiei. Se vor folosi operaţii cu pointeri.

3. Scrieţi, în C, un program care să creeze un fişier copie a unui fişier dat. SOLUŢII

1. unsigned cmmdc (unsigned m, unsigned n) { if (n==0) return m; else return cmmdc(n, m%n); } 2. char *strrev (char *sir) { char *initial = sir; char *urmator = sir; char temp; while (*sir) sir++; while (urmator < sir) { temp = *(--sir); *sir = *urmator; *urmator++ = temp; } return (initial); } 3.

#include <stdio.h> #include <stdlib.h> void main() { int c; char nume_sursa[80], nume_dest[80]; FILE *fs,*fd; printf("Introduceti numele fisierului sursa \n"); fgets(nume_sursa, 80, stdin); printf("Introduceti numele fisierului copie \n"); fgets(nume_dest, 80, stdin); if ((fs=fopen(nume_sursa, "r"))==NULL) { printf("Nu se poate deschide fisierul %s\n", nume_sursa); exit(1); } if ((fd=fopen(nume_dest, "w"))==NULL) { printf("Nu se poate deschide fisierul %s\n", nume_dest); exit(1); } while ((c=getc(fs))!=EOF) putc(c, fd); fclose(fs); fclose(fd); }

Fundamentele calculatoarelor (2) 1. Se considera numerele zecimale X=38 si Y=79. Se cere adunarea acestora in toate combinatiile de semne corespunzatoare reprezentarilor binare de virgula fixa, precum si adunarea fara semn corepunzatoare formatelor zecimale pe 4 biti. 2. Se consideră un format ipotetic de reprezentare a numerelor binare de virgulă flotantă pe 10 biţi partiţionaţi astfel: de la stânga la dreapta: 1 bit de semn, 3 biţi de exponent şi 6 biţi de mantisă. Admiţând că sunt adoptate convenţiile standardului IEEE 754 la formatul dat, să se determine câmpurile de reprezentare tolerate. 3. Admiţând că sunt date două numere binare pe 2 biţi, A=a1a0 si B=b1b0. Se cere sinteza unui dispozitiv de înmulţire combinaţional uzitând de circuitele ŞI-NU cu 2 şi 3 intrări şi circuite inversoare. R: 1. Semn Marime Identic C1 si C2 +38 = 0. 0 1 0 0 1 1 0 + +79 = 0. 1 0 0 1 1 1 1 0. 1 1 1 0 1 0 1 = +117 Semn Marime Complement de 1 (C1) +38 = 0. 0 1 0 0 1 1 0 + 0. 0 1 0 0 1 1 0 + -79 = 1. 1 0 0 1 1 1 1 1. 0 1 1 0 0 0 0 1. 1 1 1 0 1 0 1 = -117 1. 1 0 1 0 1 1 0 Raspuns Gresit (se impune verificare de semn) =-41 in C1 (corect) Complement de 2 (C2) +38 = 0. 0 1 0 0 1 1 0 + -79 = 1. 0 1 1 0 0 0 1 1. 1 0 1 0 1 1 1 =-41 in C2 (corect) Semn Marime Complement de 1 (C1) -38 = 1. 0 1 0 0 1 1 0 + 1. 1 0 1 1 0 0 1 + +79 = 0. 1 0 0 1 1 1 1 0. 1 0 0 1 1 1 1 1. 1 1 1 0 1 0 1 = -117 1 0. 0 1 0 1 0 0 0 +

Raspuns Gresit (se impune verificare de semn) End around carry 1 0. 0 1 0 1 0 0 1 = 41 Complement de 2 (C2) -38 = 1. 1 0 1 1 0 1 0 + +79 = 0. 1 0 0 1 1 1 1 1 0. 0 1 0 1 0 0 1

=-41 in C2 (corect) Semn Marime Complement de 1 (C1) -38 = 1. 0 1 0 0 1 1 0 + 1. 1 0 1 1 0 0 1 + -79 = 1 1 0 0 1 1 1 1 1. 0 1 1 0 0 0 0 1 0. 1 1 1 0 1 0 1 = +117 1 1. 1 0 0 1 0 0 1 + Fals End around carry 1 1. 1 0 0 1 0 1 0 = -117 Complement de 2 (C2) -38 = 1. 1 0 1 1 0 1 0 + -79 = 1. 0 1 1 0 0 0 0 1 1. 1 0 0 1 0 1 1

=-117 in C2 (corect)

1 1 38 = 0011 1000 + 0110 1011 79 = 0111 1001 1010 1100 1011 1 0001 + 1 0001 1 0111 + 0110 0110 0011 0011 1 0001 0111 1 0100 1010 =117 (zecimal) =117 (zecimal)

2. Translatarea convenţiilor standardului IEEE 754 la cazul dat conduce la: Es x 3N 1 2 1.M , unde E0 x 7

7 31 2 3 6

741

1 2

1 1 1 1x 2 1 2 2 2 211 2x 2 11 2

127 1x 32 42

0 322

x 2 1 0 01x 8

3

4

1x 8127x 4

3. Tabel de adevar intrări ieşiri

a1 a0 b1 b0 c3 c2 c1 c0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 1 0 1 1 0 0 0 1 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0

1 0 0 1 0 0 1 0 1 0 1 0 0 1 0 0 1 0 1 1 0 0 1 1 1 1 0 0 0 0 0 0 1 1 0 1 0 0 1 1 1 1 1 0 0 1 1 0 1 1 1 1 1 0 0 1

0123

c 5,7,11,13,15c 6,7,9,11,13,14c 10,14c 15

În urma minimizării rezultă:

0 1 0 1 0 1 0 1 0 0 1 0 1 0 01 1 1 0 1 0 0 1 0 1 0 1 02 1 1 03 1 0 1 0

c a a b b a a b b a b b a a bc a b b a a b a a b a b bc a b bc a a b b

0 1 0 1 0 1 0 1 0 0 1 0 1 0 01 1 1 0 1 0 0 1 0 1 0 1 02 1 1 03 1 0 1 0

c a a b b a a b b a b b a a bc a b b a a b a a b a b bc a b bc a a b b

Structuri de date şi algoritmi (3) 1. Să se definească următoarele TDA-uri: A1-articol : strada(max 19 caractere), nr(int), localitate(max 19 caractere); A2-articol : nume(19 caractere), adresa(A1); Sa se implementeze funcţia care ordonează alfbetic după nume, folosind sortarea prin selectie, un tablou de articole de tip A2 (de dimensiune 10) .Prototipul funcţiei este: void ordonare_selectie(A2 tablou[]); Obs: Se va folosi limbajul de programare C. (15 minute) Rezolvare: #include <string.h> …. #define N 10 typedef struct{ char strada[20]; int numar; char localitate[20]; }A1; typedef struct{ char nume[20]; A1 adresa; }A2; void ordonare_selectie(A2 tablou[]){ A2 aux; int i,j,k; char nume_k[20]; for (i=0;i<N;i++){ k=i; aux=tablou[i]; for(j=i+1;j<N;j++) if(strcmp(aux.nume, tablou[j].nume)>0){ k=j; aux=tablou[j]; } aux=tablou[k]; tablou[k]=tablou[i]; tablou[i]=aux; } } 2. Se consideră tipul de dată abstract listă simplu înlănţuită ordonată, implementată cu ajutorul pointerilor. typedef struct nod{

char nume[10]; struct nod* urm; }nod; Să se implementeze operatorii de: inserarea unui nod în lista simplu înlănţuită nod* adaugare(nod*, nod*); Obs: Se va folosi limbajul de programare C. (15minute) Rezolvare: #include<stdio.h> #include<string.h> …. typedef struct nod{ char nume[10]; struct nod*urm; } nod; nod* adaugare(nod*lista, nod*q){ nod*q1,*q2; for(q1=q2=lista;q1!=NULL&&strcmp(q1->nume,q->nume)<0;q2=q1,q1=q1->urm); if(strcmp(q1->nume,q->nume)==0){ printf("\nNodul a fost introdus in lista"); free(q); return lista; } if(q1==q2){ q->urm=lista; lista=q; } else{ q2->urm=q; q->urm=q1; } return lista; } 3.Fişierul evidenta.txt conţine: NumeProdus Producator Defect NrPieseInlocuite PieseInlocuite NumeProdus-sir de 9caractere Producator-sir de 9 caractere Defect-sir de 9 caractere NrPieseInlocuite -int PieseInlocuite -tablou siruri de caractere, maxim 10 siruri de 9 caractere

Să se definească următoarele TDA-uri: A1-articol cu câmpurile : Prod,TipDefect, NrPieseInloc, PieseInloc; A2- articol cu câmpurile : NumeProd, inf(A1); Să se implementeze funcţia ce caută un produs într-un tablou de articole de tip A2 (de dimensiune 10) folosind tehnica fanionului. .Prototipul funcţiei este: void Tehnica_Fanion(A2 tablou[], char*nume); Obs: Se va folosi limbajul de programare C. (15minute) Rezolvare: #include <string.h> …… #define N 11 typedef struct{ char Prod[10]; char TipDefect[10]; int NrPieseInloc; char PieseInloc[10][10]; }A1; typedef struct{ char NumeProd[10]; A1 Inf; }A2; void Tehnica_Fanion(A2 tablou[], char*nume){ int i=0; int n=strlen(nume); if (n<=9){ strcpy(tablou[N-1].NumeProd, nume); while(strcmp(tablou[i].NumeProd, nume)!=0) i++; if(i<N-1)printf("Produsul cautat se afla pe pozitia %d",i); else printf("Elementul nu a fost gasit"); } else{ printf(“\n Sirul are mai mult de 9 caractere”); exit (1); } }

Arhitectura calculatoarelor (4) 1. Să se reprezinte valoarea -53,125 conform standardului IEEE 754, simplă precizie (32 de biți). Rezolvare Expresia reprezentării IEEE 754

S (1 bit)

E (8 biți) M (23 biți) Convertim numărul 53,125 în binar.

Normalizăm mantisa.

M reprezintă biți aflați după virgulă. Bitul 1 din fața virgulei fiind bitul ascuns. M = 10101001 Exponentul reprezintă valoare puterii lui 2 după normalizare, plus bias-ul (în acest caz 127). E = 5 + 127 = 132 Convertim valoarea 132 în binar.

Bitul de semn este 1 deoarece semnul este minus. Rezultatul este:

S (1 bit)

E (8 biți) M (23 biți) 1 1000 0100 1010 1001 0000 0000 0000 000

2. Să se calculeze valoarea zecimală pentru următorul șablon de biți exprimați conform standardului IEEE 754:

1 1000 0011 1010 1100 0000 0000 0000 000 Rezolvare Expresia reprezentării IEEE 754

S (1 bit)

E (8 biți) M (23 biți) 1 1000 0011 1010 1100 0000 0000 0000 000

Transformăm exponentul din binar în zecimal

Înlocuim valorile în expresia reprezentării standardului IEEE 754

3. Să se scrie o secvență de cod, în limbaj de asamblare, care preia numere de la tastatură și face suma acestora până la introducere valorii 0. Rezultatul se va afișa pe poziția a 7-a a ecranului. Pentru preluare numerelor de la tastatură se va folosi întreruperii INT 08H. Pentru afișarea numerelor se va folosi întreruperea INT 09H. Rezolvare MOV BL, 00H : se inițializează BL cu valoarea 0 LOOP:INT 08H ; se stochează valoarea introdusă de la ;tastatură în registrul AL

ADD BL, AL ; se adună valoarea din AL la valoarea din BL CMP AL, 00H ; se compară conținutul registrului AL cu 0 JNZ LOOP ; dacă flag-ul zero nu este activ atunci se

;sare la LOOP MOV AL, BL ; se mută rezultatul în registrul AL MOV CL, 07H ; se încarcă conținutul lui CL cu valoarea 7 INT 09H ; se va afișa valoarea din registrul AL pe

;poziția 7 (care este stocată în registrul CL)

Sisteme de operare (5) 1: Realizaţi un program în C ce funcţionează pe baza următorului scenariu: Un proces P afişeaza cifre de la 0 la 9. Va începe afişarea cu cifra 0 (cifra va fi afişată în buclă de câte ori e posibil într-o secundă) iar la fiecare secundă va incrementa cifra afişată. Procesul de afişare se va încheia când se ajunge la 10 şi va afişa numărul total de cifre tipărite. Rezolvare: #include<unistd.h> #include<signal.h> #include<sys/wait.h> #include<sys/types.h> void handler(int sig); int number, counter; int main(int argc, char** argv){ number = 0; counter = 0; signal(SIGALRM, &handler); alarm(1); while(number < 10) { printf("%d", number); counter++; } printf("Total:%d", counter); return 0; } void handler(int sig){ number++; alarm(1); } 2: Realizaţi un program C ce funcţionează pe baza următorului scenariu: Un proces părinte P şi un proces fiu F. Procesul P va citi un fişier primit ca şi argument şi îl va trimite printr-un pipe procesului F. F va număra caracterele primite într-un contor pe care îl va afisa în terminal. Rezolvare: #include<stdio.h> #include<string.h> #include<unistd.h> #include<fcntl.h>

int main(int argc, char**argv){ int ppf[2];//pipes int fd;//file descriptor char buffer[2]; pipe(ppf); if(fork()){ //close unused pipe ends close(ppf[0]); //open file fd = open(argv[1], O_RDONLY); if(fd == -1){ perror("File read error"); _exit(1); } int n; while((n = read(fd,buffer, strlen(buffer)+1)) != 0){ write(ppf[1], buffer, n); } close(ppf[1]); int rc; wait(&rc); }else{ //close pipe ends close(ppf[1]); int contor = 0,n; while((n = read(ppf[0],buffer, strlen(buffer)+1)) != 0){ contor += n; } printf("\nContor:%d\n",contor); } return 0; } 3: Realizaţi un program shell script ce va primi ca şi argument un nume de director D şi un cuvânt C. Programul va căuta cuvântul C parcurgând recursiv directorul D iar pentru fiecare fişier întâlnit care conţine cuvântul C va afişa calea relativă a acestuia.

Rezolvare: #!/bin/sh word=$2 lst(){ for i in $1/* do if [ -d $i ] then lst $i elif [ -f $i ] then count=`grep $word $i | wc -l` if [ $count -gt 0 ] then echo $i fi fi done } lst $1

Programare orientată pe obiecte (6) 1. Într-o aplicaţie de conducere de proces se utilizează senzori de tip analogic şi optic. Toţi senzorii trebuie resetaţi şi calibraţi, respectiv periodic citiţi. Citirea presupune şi filtrare folosind valoarea anterioară citită, dar metodele de filtrare sunt diferite pentru senzori de tip diferit. Toate valorile citite sunt întregi. Fiecare operaţie de citire este specifică senzorului respectiv, resetarea este comună tuturor tipurilor de senzori iar calibarea este diferită pentru senzorii analogici şi optici. Senzorii permit şi o operaţie identică de interogare a stării. Senzorii optici mai necesită o operaţie specifică de aducere la zero, alta decât reset, iar senzorii analogici necesită o operaţie specifică de selectare a canalului. Proiectaţi o ierarhie de clase (se cer doar declaraţiile, nu şi implementările) care să modeleze fragmentul corespunzător de realitate, în cadrul aplicaţiei software de conducere de proces. Sugeraţi care vor fi metodele publice şi unde vor fi folosite acele funcţii care nu sunt publice. Comentati fiecare variabilă şi fiecare funcţie membră. R. class senzor{ int status; // starea protected: int val_citita; // valoarea citita (va fi setata de citire) int val_anterioara; // valoarea anterioara va fi transferata din val_citita // in timpul apelului metodei de citire int val_filtrata; // valoarea prelucrata prin filtrare (va fi returnata de get) virtual int filtru()=0; public: virtual void calibrare()=0; // calibrarea este o functie virtuala pura virtual void citire()=0; // citirea este si ea o functie virtuala pura void reset(); // operatia de reset int status(); // returneaza starea int get(); // returneaza valoarea filtrata }; class senzor_analog public: senzor { // clasa specializata pentru senzori analogici int filtru(); // functia de filtrare nu va fi accesata de afara public: void calibrare(); // calibrarea specifica senzorului analogic void citire(); // aici se va apela si filtrul specific void select_canal(int ); // extensie pentru selectia canalului analogic }; class senzor_optic public: senzor { int filtru(); public: void calibrare(); // calibrarea specifica senzorului optic void citire(); // aici se va apela si filtrul specific void zero(); // extensie pentru operatia specifica de aducere la zero };

2. Valorile citite într-un sistem de monitorizare trebuie stocate într-o stivă. Creaţi pentru aceasta o stivă cu alocare dinamică care să funcționeze (incremental) astfel: dacă se atinge dimensiunea curentă a stivei, se alocă memorie pentru ca să poată stoca stiva existentă și încă câteva valori și se copiază stiva în noua zonă de memorie, eliberând apoi vechea zonă. R: class CStack { int *m_p; // stiva propriu-zisa va fi aici int m_nStored; // indicator varf stiva int m_nDepth; // dimensiunea temporara a stivei enum {GROW_BY=5}; // pasul de crestere a stivei public: CStack( ); // constructor virtual ~CStack(); // destructor int IsEmpty() const; // test stiva goala void Push(const int &item); // introducere in stiva int Pop(); // extragere din stiva }; // Constructori CStack::CStack() { m_p=0; m_nStored=0; m_nDepth=0; } CStack::~ CStack() { delete []m_p; } // Operatii int CStack::IsEmpty() const { return m_nStored==0; } void CStack::Push(const int &item) { if(m_nStored==m_nDepth) // stiva alocata s-a terminat {

Int *p=new int[m_nDepth+GROW_BY]; // trebuie una mai mare for (int i = 0; i<m_nDepth; i++) // stiva se replica in cea noua { p[i]=m_p[i]; } m_nDepth+=GROW_BY; // dimensiunea temporara creste delete [ ]m_p; // stiva anterioara este eliberata m_p=p;

} m_p[m_nStored]=item; // introducerea in stiva m_nStored ++; // si avansul indicatorului de varf stiva } int CStack::Pop( ) { m_nStored--; // indicatorul de varf al stivei merge inapoi

return m_p[m_nStored]; // scoaterea din stiva } … CStack stivaMea; // utilizare 3. Prezentaţi declararea clasei/claselor care permit implementarea unei liste înlănţuite, pentru stocarea unor informaţii despre variabile citite de senzori. Acestea cuprind: denumirea variabilei de proces, valoarea sa întreagă şi valoarea sa prelucrată. Valoarea întreagă se setează la citirea de către senzor. Valoarea prelucrată este de tip double, se obţine prin apelarea unei metode de procesare şi trebuie furnizată în exterior prin apelul unei metode. R: (una din solutiile simple) class var_proc{ // un nod stocheaza date specifice unei citiri si valoarea procesata // pentru lista inlantuita static var_proc *cap; // capul listei var_proc *urm; // pointer catre urmatorul element din lista // mai departe, valorile stocate in nod char *denumire; // denumirea int val; // valoarea citita double val_proc; // valoarea prelucrata // metode private double procesare(); // metoda nu trebuie apelata de afara public: var_proc(char* ); // constructor care va apela si functia de citire a senzorului virtual int citire(); // citirea va trebui redefinita la implementarea concreta (in // cadrul unei clase derivate var_proc_concreta double getval(); // aici va fi apelata si procesarea, se va seta val_proc si // valoarea este furnizata apelantului }; var_proc *var_proc::cap=NULL;

Analiza algoritmilor (7) 1. Se cere să se implementeze tipul de date abstract Arbore Binar Ordonat. În acest scop se cere: 1. Să se definească o structură de date care defineşte în manieră recursivă structura

Arbore Binar Ordonat; 2. Să se implementeze pe această structurră, în forma unor funcţii C operatorii Caută, Inserează şi Suprimă definiţi peste TDA Arbore Binar Ordonat; 3. Să se dezvolte operatorul Inordine, care să afişeze cheile unui Arbore Binar Ordonat în inordine.

R1: typedef int T_cheie; typedef void (*T_prelucrare)(T_cheie); void Initializare(T_arbore *A); int ArboreVid(T_arbore A); int Cauta(T_arbore A, T_cheie k); T_arbore Insereaza(T_arbore A, T_cheie k); T_arbore Suprima(T_arbore A, T_cheie k); void Preordine(T_arbore A, T_prelucrare f); void Inordine(T_arbore A, T_prelucrare f); void Postordine(T_arbore A, T_prelucrare f); [1] typedef struct nod T_nod; /* tipul nodurilor */ typedef T_nod *T_arbore; /* tipul arbore binar ordonat */ struct nod { T_cheie ch; /* cheia unica per nod */ T_nod *st; /* pointer subarbore stang */ T_nod *dr; /* pointer subarbore drept */ }; [2] int Cauta(T_arbore p, T_cheie k) { int gasit = 0; while (p) { if (k < p->ch) p = p->st; else if (p->ch < k) p = p->dr; else { gasit = 1; break; } } return gasit; } T_nod* alocaNod(T_cheie k)

{ T_nod *p = malloc(sizeof(T_nod)); p->st = p->dr = NULL; p->ch = k; return p; } T_arbore Insereaza(T_arbore p, T_cheie k) { if (!p) p = alocaNod(k); else if (k < p->ch) p->st = Insereaza(p->st, k); else if (p->ch < k) p->dr = Insereaza(p->dr, k); return p; } T_nod *supred(T_nod **p) { T_nod *q; while (q = *p, q->dr) p = &q->dr; *p = q->st; return q; } T_arbore Suprima(T_arbore p, T_cheie k) { if (!p) return NULL; if (k < p->ch) p->st = Suprima(p->st, k); else if (p->ch < k) p->dr = Suprima(p->dr, k); else { T_nod *q = p; if (!p->st) p = p->dr; else if (!p->dr) p = p->st; else { q = supred(&p->st); p->ch = q->ch; } free(q); } return p; } [3] void Inordine(T_arbore p, T_prelucrare f) { if (!p) return; inordine(p->st);

(*f)(p->ch); inordine(p->dr); } static void afisNod(int k) { printf(“%-8d”, *k); /* maxim de ordinul sutelor de mii */ } int main() { T_arbore rad; Initializare(&rad); /* . . . */ Inordine(rad, &afisNod); return 0; } 2. Se cere să se redacteze o aplicaţie care realizează următoarele activităţi:

1. Defineşte structura de date aferentă unui graf; 2. Implementează operatorii CautăNod, InserNod, SuprimaNod, InserArc, SuprimArc, Crează, Afişează, TraversareInAdancime;

3. Acceptă la intrare un graf precizat prin mulţimea nodurilor şi arcelor sale; 4. Crează graful; 5. Listează nodurile în ordinea parcurgerii lor pe baza căutării în adâncime.

R2: #include <stdio.h> #include <stdlib.h> #define VAR * #define REF & #define BUF while(fgetc(file) != ‘\n’) typedef void (*T_traversare)(char); [1] #define MAX 100 typedef int MatrAdj[MAX][MAX]; typedef struct graf T_graf; struct graf { int contor; /* contorul nodurilor */ char nume[MAX]; /* numele nodurilor (litera) */ MatrAdj madj; /* matricea de adiacenta */ int marc[MAX]; /* tabloul vizitat */ }; [2] void Initializare(T_graf VAR graf) { graf->contor = 0; }

int CautaNod(T_graf *graf, char nume) { int i, n = graf->contor; for (i = 0; i < n; ++i) if (graf->nume[i] == nume) break; return i; } void InserNod(T_graf VAR graf, char nume) { int i = CautaNod(graf, nume), n = graf->contor; if ((i < n || n >= MAX)) return; graf->nume[n] = nume; for (i = 0; i <= n; ++i) { graf->madj[i][n] = 0; graf->madj[n][i] = 0; } ++graf->contor; } void SuprimNod(T_graf VAR graf, char nume) { int i = CautaNod(graf, nume), j, n = graf->contor; if (i == n) return; n = --graf->contor; for (j = 0; j < n; ++j) { graf->madj[i][j] = graf->madj[n][j]; graf->madj[j][i] = graf->madj[j][n]; } } void InserArc(T_graf VAR graf, char nod1, char nod2) { int i = CautaNod(graf, nod1), j = CautaNod(graf, nod2), n = graf->contor; if (i == n || j == n) return; graf->madj[i][j] = 1; } void SuprimArc(T_graf VAR graf, char nod1, char nod2) { int i = CautaNod(graf, nod1), j = CautaNod(graf, nod2), n = graf->contor; if (i == n || j == n) return; graf->madj[i][j] = 0; } void adancime(T_graf g, T_traversare f, int i) { int j, n = g.contor; g.marc[i] = 1; (*f)(g.nume[i]); for (j = 0; j < n; ++j)

if (!g.marc[j] && g.madj[i][j]) adancime(g, f, j); } void TraversareInAdancime(T_graf graf, T_traversare func) { int i, n = graf.contor; for (i = 0; i < n; ++i) graf.marc[i] = 0; for (i = 0; i < n; ++i) if (!graf.marc[i]) adancime(graf, func, i); } void Creaza(FILE* file, T_graf VAR graf) { int i, n; if (file == NULL) return; fscanf(file, “%d”, &n); BUF; for (i = 0; i < n; ++i) { InserNod(graf, fgetc(file)); BUF; } while (!feof(file)) { char nod1, nod2; nod1 = fgetc(file); BUF; nod2 = fgetc(file); BUF; InserArc(graf, nod1, nod2); } } static void afisareNod(char nume) { printf(“%c\n”, nume); } void Afiseaza(T_graf graf) { TraversareInAdancime(graf, &afisareNod); } int main() { T_graf g; char f[] = “?.txt”; Initializare(graf); puts(“Nume fisier text: ”); f[0] = getchar(); Creaza((f[0] == ‘\n’) ? stdin : fopen(f, “rt”), REF g); Afiseaza(g); return 0; }

3. Se consideră o structură graf orientat ponderat. Se cere: 1. Să se descrie o structură de graf orientat ponderat. 2. Să se implementeze procedura care determină lungimile drumurilor minime între toate

perechile de noduri ale grafului. 3. Să se implementeze procedura care determină traseul drumului de lungime minimă între două noduri precizate ala grafului. Indicaţie: În implementare se va utiliza algoritmul FLOYD. R3: [1] #define INF 1000 #define MAX 100 struct graf { int contor; /* numarul de noduri */ float COST[MAX][MAX]; /* matrice costuri arce (lipsa=INF) */ }; [2] float A[MAX][MAX]; /* mattrice lungim drumuri minime */ int Drum[MAX][MAX]; /* reconstituire traseu */ void FLOYD(struct graf *Graf) { int i, j, k, n = Graf->contor; for (i = 0; i < n; ++i) for (j = 0; j < n; ++j) { A[i][j] = Graf->COST[i][j]; Drum[i][j] = 0; } for (i = 0; i < n; ++i) A[i][i] = 0; for (k = 0; k < n; ++k) for (i = 0; i < n; ++i) for (j = 0; j < n; ++j) if (A[i][k] + A[k][j] < A[i][j]) { A[i][j] = A[i][k] + A[k][j]; Drum[i][j] = k; } } [3] void Traseu(int i, int j) { int k = Drum[i][j]; if (k != 0) { Traseu(i, k); printf(“%d\n”, k) Traseu(k, j); } }

Proiectarea microsistemelor digitale (8) 1. Prezentaţi schema pentru o interfaţă serială de tip RS 232 . 2. Prezentaţi schema pentru o interfaţă paralelă de tip CENTRONIX. 3. Prezentaţi schema pentru conectarea a 64 led-uri la o unitate centrală cu microprocesorul 8086. R: 1. Schema este alcătuită din un decodificator de porturi, un circuit specializat 8251 şi un circuit MAX 232 pentru translatarea nivelelor de tensiune din TTL în EIA şi invers. Oricare din ieşirile decodificatorului poate fi folosită pentru selectarea circuitului 8251.

2. Schema este alcătuită din un decodificator de porturi, un circuit specializat 8255 şi porţi pentru amplificarea/separarea liniilor între circuitul specializat şi periferic. Oricare din ieşirile decodificatorului poate fi folosită pentru selectarea circuitului 8251.

3. Schema este alcătuită din un decodificator de porturi, 8 circuite registru, fiecare cu câte 8 ieşiri. La fiecare ieşire de registru se conecteză catodul unui led iar anodul acestuia se leagă prin o rezistenţă la alimentare. Aprinderea/stingerea led-urilor se va comanda prin intermediul informaţiilor înscrise în registre prin intermediul magistralei de date. Pentru ca un led să lumineze ieşirea la care este conectat va trebui să aibă 0 logic iar pentru ca un led să fie stins, ieşirea la care este conectat va trebui să aibă 1 logic.

Fundamente de inginerie software(9) 1. Să se reprezinte o diagramă „use case” ce implementează un sistem web on-line de achiziţii publice care acţionează în următorul fel: - pe site-ul web există conturi de contractori, de prestatori şi un cont special de administrare; - contractorii şi prestatorii se pot înregistra şi pot să-şi modifice doar datele proprii. Contul de administrator este predefinit şi poate administra şi conturile de contractori şi prestatori; - pentru acces utilizatorii se vor autentifica (prin logare); - beneficiarul poate posta un anunţ pentru o lucrare; - contractorii care doresc acea lucrare, îşi postează oferta, care cuprinde preţul propus, termen de timp şi descrierea soluţiei. Ulterior ei pot să îşi modifice oferta; - beneficiarul poate să renunţe la o lucrare (să o şteargă); - în caz că o oferta este acceptată ea intră în execuţie. Prestatorul o va executa iar contractorul o va recepţiona.

R:

Sistem on-line Creare cont

Logare

Administrare conturi

Administrare cont propriu

Lucrare

Ofertă

Execuţie

înregistrare

autentificare

administrare

administrare administrare

postare/ ştergere acceptare

recepţionare

postare/modificare/ştergere executare

Vizitator

Administrator

Contractor

Prestator

autentificare

2. Considerând următorul formular de introducere date, cu validările specificate, specificaţi un set de date eronate pentru a se verifica funcţionarea corecta a sistemului de validare: cod utilizator - intre 6 si 20 caractere, format doar din litere si cifre, trebuie sa fie unic in baza de date parola - intre 4 si 15 caractere, doar litere si cifre e-mail - trebuie sa fie un e-mail scris corect (daca notam cu S setul de caractere permise, trebuie sa avem: S @ S(.S)+, adică după @ trebuie sa fie minim 2 grupe de caractere S, despărţite prin .) nume - trebuie sa conţină doar litere, cu minim 2 caractere pentru un cuvânt si minim 2 cuvinte telefon intern - trebuie sa fie un număr valid de 5 până la 10 cifre, fără prefix internaţional (00), putând cuprinde opţional pentru lizibilitate liniuţe şi puncte.

R: a) 1. Codul sa fie format din mai puţin de 6 caractere 2. Codul sa fie format din mai mult de 20 caractere 4. Codul sa conţină şi alte caractere pe lângă litere si cifre 3. Codul sa fie duplicat b) 1. Parola să fie formată din mai puţin de 4 caractere 2. Parola să fie formată din mai mult de 15 caractere 4. Parola să conţină şi alte caractere pe lângă litere si cifre c) 1. Să conţină si alte caractere pe lângă cele permise 2. Sa nu existe @ 3. După @ urmează un singur S 4. Sa fie @ la început sau la sfârşit 5. După @S sau @S. nu mai urmează nimic d) 1. Numele să conţină şi alte caractere în afara de litere 2. Numele are mai puţin de două caractere 3. Numele este format dintr-un singur cuvânt e) 1. Număr incorect de telefon cu mai puţin de 5 sau mai mult de 10 cifre 2. Să conţină 00 in fata 3. Să conţină alte caractere decât cifre, liniuţe şi puncte

3. Se cere diagrama de clase UML care implementează un sistem de gestiune al angajaţilor dintr-o companie considerând următoarele precizări: - fiecare angajat are un cod personal, nume, adresa, telefon, data angajării si observaţii; - un angajat poate ocupa unul din trei posturi posibile: salariat, şef de echipă sau director de departament; - fiecare angajat are un salariu rezultat printr-o procedură de calcul; - există trei departamente (tipuri de angajaţi): producţie, vânzare şi achiziţii; - angajaţii din producţie mai au în plus şi o calificare specifică; - la vânzare si achiziţii, angajaţii mai trebuie să cunoască o limbă străină şi pot să muncească în alte locaţii, decât la sediul firmei; - la achiziţii, unii angajaţi pot avea şi calificarea de testor pentru a testa lotul achiziţionat. La proiectare se va utiliza conceptul de moştenire şi se va respecta principiul open-close. R: În plus fiecare clasă va mai conţine câte o metodă set, respectiv get pentru fiecare atribut.

Productie - calificare : String

Angajat - codPersonal : int - nume : String - adresa : String - dataAngajare : Date - observatii : String - post + salariu()

AngajatAV - limbaStraina : String - locatie : String

Vanzare Achizitie - calificareTestor : boolean

enum{Salariat, Sef_Echipa, Director}

Securitatea Informației(10)

1. (Structura unei chei pentru criptosistemul RSA în .NET) Fie o cheie de RSA exportată incluzând parametrii privaţi din .NET aşa cum reiese din Figura 1. De asemenea, fie valorile artificiale de dimensiune redusă: modul n=115 şi exponent public e=3. Se cere: a) Pentru cheia RSA din figură indicaţi care dintre valorile D, DP, DQ, Exponent, InverseQ,

Modulus, P şi Q sunt parametrii publici şi privaţi precum şi dimensiunea aproximativă a acestora în biţi.

b) Pentru modulul şi exponentul de dimensiune redusă calculaţi ceilalţi parametrii care se regăsesc în structura unei chei de RSA în .NET. Eplicaţi ce exponent se foloseşte pentru fiecare din cele 4 operaţii: criptare, decriptare, semnare, verificare, atunci când aceste operaţii sunt efectuate modulo n.

Figura 1. Parametrii unei chei RSA în mediul .NET Răspuns:

a) Parametrii publici ai cheii din .NET din figură sunt: - modulul Modulus de 128*8=1024 biţi, - exponentul Exponent care este reprezentat pe 3 bytes aşa cum se observă în structură, adică 24 de biţi dar care poate fi reprezentat pe doar 17 biţi corespunzând valorii 65537. Parametrii privaţi ai cheii din .NET din figură sunt: - Exponentul D folosit la criptare având 128 de bytes adică 1024 biţi, - Exponenţii de decriptare DP şi DQ având 64 de bytes adică 512 biţi, - Inversul multiplicativ al lui Q modulo P adică InverseQ având 64 de bytes adică 512 biţi. - Factorii primi ai modulului P şi Q având fiecare câte 64 de bytes adică 512 biţi.

b) Pentru modulul n=115 factorizarea acestuia este n=5*23 de unde P=5 şi Q=23. Funcţia Euler Phi este 4*22=88 de unde inversul multiplicativ al lui 3 este 59 deoarece 3*59=1 mod 88 şi deci D=59. De aici exponenţii DP şi DQ urmează imediat ca: DP=59 mod 4 =3 şi DQ = 59 mod 22 =15, inversul multiplicativ al lui Q modulo P este 2 deoarece 2*23 = 1 mod 5 şi deci InverseQ=2. Sumarizând: D = 59, DP = 3, DQ = 15, Exponent = 3, InverseQ = 2, Modulus = 115, P = 5, Q = 23.

La criptare şi respectiv verificarea semnăturii digitale se foloseşte exponentul e= 3 iar la decriptare şi respectiv semnare digitală exponentul d = 59 (cu mentiunea ca atunci cand operatia cu cheie privata se efectueaza conform CRT se vor folosi desigur DP exponentii si DQ modulo P si Q).

2. (Structura unei chei pentru algoritmul de semnătură digitală DSA în .NET) Fie o cheie de DSA exportată incluzând parametrii privaţi din .NET aşa cum reiese din Figura 1. De asemenea, fie valorile artificiale de dimensiune redusă: modul P=31, generator G=3 şi Y=17. Se cere: a) Pentru cheia DSA din figură indicaţi care dintre valorile G, P, X şi Y sunt parametrii publici şi

privaţi precum şi dimensiunea aproximativă a acestora în biţi. b) Pentru parametrii de dimensiune redusă calculaţi cheia secretă X. Dacă valoarea Y ar fi parte

a unui schimb de cheie Diffie-Hellman în care a fost primit de la partenerul de comunicare Y’=29, explicaţi care va fi cheia comună de sesiune.

Figura 1. Parametrii unei chei DSA în mediul .NET Răspuns:

a) Parametrii publici ai cheii DSA din .NET din figură sunt: - modulul P de 64*8=512 biţi, - generatorul G de 64*8=512 biţi, - valoarea Y de 64*8=512 biţi. Parametrii privaţi ai cheii din .NET din figură sunt: - Exponentul X aplicat asupra generatorului G modulo P pentru calculul valorii Y având 20 de

bytes adică 160 biţi. Limitarea acestuia la 160 biţi se datorează folosirii funcţiei SHA1 la semnare care are 160 biţi la output.

b) Pentru modulul P=31, generator G=3 şi Y=17 ştim că GXmod P=17 şi prin calcule succesive (deşi nu cea mai eficientă metodă) avem 30mod 31=1, 31mod 31=3, 32mod 31=9, 33mod 31=27, 34mod 31=19, 35mod 31=26, 36mod 31=16, 37mod 31=17, de unde parametrul secret este X=7.

Pentru schimbul de cheie Diffie-Hellman, având Y’=20 trebuie să îl aflăm pe X’ pentru care va trebui să continuăm succesiunea de calcule de mai sus, din fericire după doar 2 paşi avem 38mod 31=20, 39mod 31=29 de unde X’=9. Aceasta înseamnă că avem cheia comună 37*9mod 31 iar cum calculele se efectuează modulo modulo 31 exponenţii pot fi reduşi modulo 30 (vezi Teorema lui Euler) şi deci 37*9mod 31 = 33mod 31=27 aceasta fiind cheia de sesiune Diffie-Hellman.

3. (Autentificarea cu parole în sistemul de operare Linux). Fie secvenţa de mai jos din fişierul

criptat de parole aparţinând unei distribuţii de Ubuntu. Se cer următoarele următoarele: a) Cum se numeşte şi unde se găseşte acest fişier în sistemul de operare Ubuntu, respectiv

cum se adaugă un nou utilizator şi o parolă? b) Care este valoarea de salt pentru parola utilizatorului ubuntu şi care este hash-ul acesteia

respectiv cum au fost calculate acesta? c) Explicaţi dacă funcţia de criptare pentru parola userului ubuntu şi alice este acceaşi? d) Care este funcţia cu ajutorul căreia se pot genera programatic parole?

ubuntu:$1$js9ai3VX$iFbR5uTfv3JMmFCladdcn1:16459:0:99999:7::: tom:$6$vIkXOyrz$CMiFB8meMfTANianaS7z5f8yMfplk/TtncZs/7b0es65XZSIyz3kaiSwN/61sBdrPhT9B0RulJ9tWEnE7kpJC/:16470:0:99999:7::: alice:$6$gpOJXcSy$AVrdUKBdSM8NlGmrbexoyetS2LhRgg3qkaTbZdMh4mj.Yps3UxIkrtGDQfEGA.yNDhlIPG3m1hupX3b0I0Vs3.:16470:0:99999:7::: bob:$6$5IPGOooA$J6rZ74NUpCVx9C2mpesKKr0iBjkHNCxz8Io3aPj5W6mwVKKvnhWIbq0H91T9bDcWmDE3/6Ageoa3olcVe2nKY0:16470:0:99999:7:::

Figura 1. Secvenţă dintr-un fişier de parole Linux

Răspuns: a) Este vorba despre fişierul shadow aflat în /etc/shadow iar un n nou user şi o nouă parolă se

pot adăuga cu urmatoare secventa de comenzi fiind necesare privilegii de root:

sudo useradd -m tom sudo passwd tom

b) Valoarea salt pentru utilizatorul ubuntu este

js9ai3VX

iar cea a hashului

iFbR5uTfv3JMmFCladdcn1

fiind obţinută prin aplicarea unei funcţii one-way peste salt şi parola utilizatorului. c) Nu, pentru utilizatorul ubuntu se foloseşte o funcţie bazată pe MD5 iar pentru alice una

bazată pe SHA512, distingem despre care dintre acestea este vorba din valoarile $1$ şi $6$ care arată că este vorba de MD5 respectiv SHA512.

d) Funcţia pentru generare a parolelor este char *crypt(const char *key, const char *salt)

Rețele de calculatoare(11) 1. Se considera adresa ip v4 172.16.0.150 având masca 255.255.255.192. Se cere: a) Adresa rețelei respectiv adresa de broadcast a rețelei din care face parte adresa ip; b) Adresa subrețelei respectiv adresa de broadcast a subrețelei din care face parte adresa ip; c) Numărul de hosturi din subrețeaua din care face parte adresa ip; d) Numărul de subrețele definite de masca adresei ip dată. R: a) Adresa IP definește o rețea de clasa B rezultă că masca rețelei este 255.255.0.0 . Făcând operațiile pe biți vom avea: 10101100.00010000.00000000.10010110 Adresa IP 11111111 .11111111 .00000000.00000000 Mască rețea -------------------------------------------------- 10101100.00010000.00000000.00000000 Adresa rețelei -------------------------------------------------- 10101100.00010000.11111111 .11111111 Adresa de broadcast a rețelei Adresa rețelei este 172.16.0.0 Adresa de broadcast a rețelei este 172.16.255.255 b) Făcând operațiile pe biți vom avea: 10101100.00010000.00000000.10010110 Adresa IP 11111111 .11111111 .11111111 .11000000 Masca subrețea -------------------------------------------------- 10101100.00010000.00000000.10000000 Adresa subrețelei -------------------------------------------------- 10101100.00010000.00000000.10111111 Adresa de broadcast a subrețelei Adresa subrețelei este 172.16.0.128 Adresa de broadcast a subrețelei este 172.16.0.191 c) Numărul de hosturi din subrețea: NH = 26-2 = 62 hosturi d) Numărul de subrețele: NSR = 210-2 = 1022 subrețele 2. Se considera adresa ip v4 192.168.10.125/28. Se cere: a) Adresa rețelei respectiv adresa de broadcast a rețelei definite de perechea adresă ip / mască rețea. b) Numărul de hosturi din rețeaua determinată la punctul a). R:

a) Făcând operațiile pe biți vom avea: 11000000.10101000.00001010.01111101 Adresa IP 11111111 .11111111 .11111111 .11110000 Masca rețea -------------------------------------------------- 11000000.10101000.00001010.01110000 Adresa de rețea -------------------------------------------------- 11000000.10101000.00001010.01111111 Adresa de broadcast a rețelei Adresa rețelei este 192.168.10.112 Adresa de broadcast a rețelei este 192.168.10.127 b) Numărul de hosturi din subrețea: NH = 24-2 = 14

Baze de date(12) Nota: Pentru rezolvarea problemelor propuse se poate folosi şi limbajul SQL sau PL/SQL, dar cu definirea cheilor primare şi externe.

1. Se consideră două fişiere dintr-o bază de date existentă pentru rezervare locuri la avion. Fişierul Curse conţine datele pentru fiecare cursă din orarul de zbor. Fişierul Pasageri conţine datele pentru toţi pasagerii din toate cursele. Toţi pasagerii unei curse vor avea acelaşi cod cursă CodC. Curse CodC Pilot Copilot Avion Oras1 Ora1 Oras2 Ora2 PretR NrLoc

Pasageri CodC CNP NumeP Adresa DataN Tel Pret Să se afişeze informaţiile despre o cursă de avion şi lista pasagerilor din acea cursă folosind comenzi simpe din limbajul XBase. Se recomandă forma de afişare: CodC Oras1 Ora1 Oras2 Ora2 Pilot Copilot TipAv Ro234-0609

Timisoara TSR

8:30 Bucuresti 9:30 Popescu Adam B747 Lista Pasageri CNP Nume Pas Adresa Telefon DataN Pret R. SET TALK OFF CLEAR USE Curse INDEX Icodc IN 1 ALIAS CS USE Pasageri INDEX Icodc, Inume IN 2 ALIAS PS SET RELATION TO Codc INTO PS ACCEPT ’Cod cursa: ’ TO Vcodc SEEK VCodc ? ’CodC Pilot Copilot Avion Oras1 Ora1 Oras2 Ora2 ‘ ? REPL(‘=’,120) ? Codc, Pilot, Copilot, Avion, Oras1, Ora1, Oras2, Ora2 ? ? ‘ LISTA PASAGERI ‘ ?

SELECT PS ? ‘CNP Nume Pasager Adresa Tel DataN Pret ‘ ? ‘ REPL(‘-’,120) DO WHILE Codc=Vcodc ? CNP, NumeP, Adresa, Tel, DataN, Pret SKIP ENDDO 2. Considerăm o bază de date normalizată pentru evidenţă studenţi care cuprinde tabelele: STUD CodS Nume Adresa DataN Bursa Telefon CNP ...... NOTE CodS CodC NOTA Data CURS CodC Titlu NumeProf Folosind comenzi simple Xbase se cere afişarea notelor unui student dat prin nume sub forma: CODS: AC321 Nume: Popescu Bogdan Adresa: Bogdanesi 3 Bursa:150 Situatia notelor Curs Nota Data Nume prof Sisteme de operare 9 23-01-2011 Popovici ..................................... R. USE Stud INDEX Inume, Icods IN 1 ALIAS ST USE Note INDEX Icodsn IN 2 ALIAS NT USE CURS INDEX Icodc IN 3 ALIAS CS SET RELATION Cods INTO Note Select 2 SET RELATION Codc INTO Curs Select 1 ACCEPT ‘ Nume Student: ‘ TO Vnume SEEK Vnume IF EOF() ? ‘Studentul ‘ + Vnume + ‘ Nu exista’ ELSE ? ‘Cods: ‘ + Cods, ‘ Nume: ‘+ Nume, ‘ Adresa: ‘+ Adresa, ‘ Bursa: ‘,Bursa ?

? ‘ Situatia notelor ‘ ? ? ‘ Curs Nota Data Nume Prof ‘ ? ‘ ------------------------------------------------------------------------------------ ‘ Select 2 DO WHILE Cods=Vcods ? CS-->Titlu, Nota, Data, CS-->NumeProf SKIP ENDDO ENDIF 3. Considerăm o bază de date normalizată pentru evidenţă studenţi care cuprinde tabelele: STUD CodS Nume Adresa DataN Bursa Telefon CNP ...... NOTE CodS CodC NOTA Data CURS CodC Titlu NumeProf Folosind comenzile XBase elementare pentru dialog şi SQL pentru căutarea informaţiilor, să se scrie secvenţe de program care realizează funcţiile:

Afişare Cods, Nume student, Bursa, pentru toţi studenţii care au medii mai mari decât o valoare N Afişare pentru un student dat prin Cods toate notele, Titlul cursului pentru fiecare notă şi Nume profesor. Se va ţine cont că rezultatul unei comenzi SQL se obţine într-o zona de lucru din care se poate afişa

direct folosind comanda BROWSE, iar variabilele citite sunt externe precedate de “:”. R. ACCEPT ‘ Media minima: ‘ TO N SELECT ST.Cods,ST.Nume, AVG(NT.Nota) Media FROM Stud ST, Note NT WHERE ST.Cods=NT.Cods GROUP BY ST.Cods,ST.Nume,ST.Bursa, HAVING AVG(NT.Nota)>:N

Browse && - afisare rezultat Wait

ACCEPT ‘ Dati Cod student’ TO Vcods SELECT ST.Cods, ST.Nume,NT.Nota,CS.Titlu,CS.NumeP Profesor FROM Stud ST, Note NT, Curs CS WHERE ST.Cods=:Vcods AND ST.Cods=NT.Cods AND NT.Codc=CS.CODC BROWSE Wait

Proiectarea interfeţelor utilizator şi grafică(13) 1. Analizati din punctul de vedere al uzabilității mesajul de eroare de mai jos: Mesaj de “help” al unui site al unei companii (Midwest Microwave) care apare atunci când utilizatorii doresc să parcurgă catalogul de produse de pe site. Mesajul apare înainte de prezentarea catalogului. Are scopul de a completa câteva lucruri care nu au fost precizate anterior în catalog.

R: Supraîncărcarea utilizatorului cu detalii; nu reiese ce este important şi ce este mai puţin important (-

minus la design minimalist). Aspect dezastruos: fără paragrafe, fără titlu, fără spaţii care să ghideze privirea (- la design estetic) Materialul nu este organizat pe module, astfel încât să fie parcurs ușor şi utilizatorul să aleagă din ceea ce este prezentat ceea ce ştie şi nu ştie deja (- la flexibilitate şi eficienţă). Informaţia prezentată este inutilă şi în afara contextului atât timp cât utilizatorul nu a văzut încă despre ce este vorba (- la suport şi documentare) Fiind o casetă de dialog modală, aceasta va dispărea îndată ce utilizatorul va continua şi va ajunge la catalog, atunci când de fapt va avea nevoie de a-şi aduce aminte de cele scrise în casetă (- la minimizarea încărcării memoriei). Utilizarea termenilor precum modem V.90 (nu vorbeşte în limbajul utilizatorului general). 2. Analizați interfața de mai jos și propuneți o variantă mai bună, conform regulilor de design

cunoscute.

R.: Prea multe culori, fără reguli asociate; Prea multe fonturi, prea mult bold; Nu e nevoie de umbrire în titlu; Bara orizontală nu este necesară în prima zonă de text; butonul Close – care apare ca secundar aici – este mai mare decât butonul Send – cel mai des

folosit.

3. Indicați elementele din proiectarea interfețelor utilizator de tip web care caracterizează o proiectare reuşită. R: Text Fondul nu creează discontinuităţi ale textului Textul este suficient de mare pentru a fi bine citit, dar nu prea mare Ierarhizarea informaţiei este clară Coloane textului sunt mai înguste decât într-o carte pentru a facilita citirea mai uşoară de pe ecran. Navigarea Butoanele de navigare sunt uşor de înţeles şi folosit Navigarea este consistentă în tot web-site-ul Butoanele de navigare conţin o indicaţie pentru a informa utilizatorul unde se găseşte, în ce pagină Daca se folosesc frame-uri, acestea nu sunt obtruzive (stridente, deranjante) Un site mare are un index sau o hartă a site-ului. Links Culorile link-urilor sunt corelate cu culorile paginilor Link-urile sunt subliniate şi astfel sunt imediat vizibile utilizatorului. Grafica Butoanele nu sunt prea mari şi greoaie Fiecare element grafic are asociat un “alt label” (descriere prin text atunci când trecem peste acesta) Fiecare link grafic are un corespondent link text Elementele grafice şi fondurile folosesc culori care nu sunt denaturate de browser Elementele de grafica animată se opresc automat Proiectarea generală Paginile se încarcă rapid Prima pagină şi pagina ’Acasă’ (Home) intră într-un spaţiu de 800x600 pixeli Restul paginilor au un impact vizual imediat în legătură cu relaţia 800x600 Utilizarea corectă a elementelor grafice pentru a “sparge” zone mari de text Fiecare pagină din site arată ca o parte a unui întreg; există elemente repetitive care sunt menţinute în toate paginile.

Medii şi tehnologii de programare(14) 1. Scrieți în C# sau Visual Basic .NET două funcții care să calculeze, pe baza CNP-ului unei persoane, data de naștere și vârsta acesteia. ' Visual Basic Private Function DataNasterii(ByVal sCNP As String) As Date Private Function Varsta(ByVal sCNP As String) As Integer // C# private DateTime DataNasterii(string cnp); private int Varsta(string cnp); Exemplu: DataNasterii(”1900228350001”) va returna 28.02.1990, iar Varsta(”1900228350001”) va returna 24 (dacă anul curent este 2014). SOLUŢIE: ' Visual Basic Private Function DataNasterii(ByVal sCNP As String) As Date Dim an, luna, zi As Integer an = 1900 + Convert.ToInt32(sCNP.Substring(1, 2)) luna = Convert.ToInt32(sCNP.Substring(3, 2)) zi = Convert.ToInt32(sCNP.Substring(5, 2)) Return New Date(an, luna, zi) End Function Private Function Varsta(ByVal sCNP As String) As Integer Return DateDiff(DateInterval.Year, DataNasterii(sCNP), Today) End Function //C# private DateTime DataNasterii(string cnp) { DateTime dn; int an = Convert.ToInt32("19" + cnp.Substring(1, 2)); int luna = Convert.ToInt32(cnp.Substring(3, 2)); int zi = Convert.ToInt32(cnp.Substring(5, 2)); if (DateTime.TryParse(zi + "/" + luna + "/" + an, out dn)) return (dn); return DateTime.MinValue; } private int Varsta(string cnp) { long ticks; long ticks0 = DataNasterii(cnp).Ticks; if (ticks0 > 0) { TimeSpan ts = new TimeSpan(ticks0); ticks = DateTime.Now.Ticks - ticks0; DateTime v = new DateTime(ticks); return v.Year - 1; } return 0; }

2. Secvența de cod de mai jos (Visual Basic sau C#) are ca efect trasarea într-un control PictureBox1 a unei linii între coordonatele (x1,y1) și (x2,y2). Modificați secvența pentru a se desena, în interiorul aceluiași control, un trapez isoscel având baza mare latura inferioară a dreptunghiului format de cele două perechi de coordonate, iar baza mică o treime din latura superioară a aceluiași dreptunghi. Se presupune că x1<x2 și y1<y2. ' Visual Basic Dim myGraph As System.Drawing.Graphics myGraph = PictureBox1.CreateGraphics() myGraph.DrawLine(Pens.Black, x1, y1, x2, y2) // C# System.Drawing.Graphics myGraph; myGraph = pictureBox1.CreateGraphics(); myGraph.DrawLine(Pens.Black, x1, y1, x2, y2);

SOLUŢIE: ' Visual Basic Dim myGraph As System.Drawing.Graphics myGraph = PictureBox1.CreateGraphics() myGraph.DrawLine(Pens.Black, x1, y2, x2, y2) myGraph.DrawLine(Pens.Black, x2, y2, (CInt(x2-(x2- x1)/3)), y1) myGraph.DrawLine(Pens.Black, (CInt(x2-(x2-x1)/3)), y1, (CInt(x1+(x2-x1)/3)), y1) myGraph.DrawLine(Pens.Black, (CInt(x1+(x2-x1)/3)), y1, x1, y2) // C# System.Drawing.Graphics myGraph; myGraph = pictureBox1.CreateGraphics(); myGraph.DrawLine(Pens.Black, x1, y2, x2, y2); myGraph.DrawLine(Pens.Black, x2, y2, (Convert.ToInt32(x2 - (x2 - x1) / 3)), y1); myGraph.DrawLine(Pens.Black, (Convert.ToInt32(x2 - (x2 - x1) / 3)), y1, (Convert.ToInt32(x1 + (x2 - x1) / 3)), y1); myGraph.DrawLine(Pens.Black, (Convert.ToInt32(x1 + (x2 - x1) / 3)), y1, x1, y2);

3. Ce va afișa la ieșire secvența de cod (Visual Basic sau C#) de mai jos? ' Visual Basic Dim i, j As Integer For i = 1 To 5 For j = 5 To 1 Step -1 If (j - i) < 0 Then Continue For Console.Write(j + i) Next Next // C# int i = 0; int j = 0; for (i = 1; i <= 5; i++) { for (j = 5; j >= 1; j += -1) { if ((j - i) < 0) break; Console.Write(j + i); } } SOLUŢIE: ' Visual Basic 6543276548769810 // C# 6543276548769810

Limbaje formale şi tehnici de compilare(15) 1. Se dă gramatica: G1:E → E+ E | E * E | (E) | i

Să se arate că această gramatică este ambiguă. 2. Se consideră definiţia regulată pentru identificatori: identif → litera(litera|cifra)* Să se deseneze diagrama de tranzitii (automatul finit) corespunzătoare, incluzând şi cuvintele cheie şi menţionând procedurile semantice necesare.

3. Se dă gramatica: E → T | E+T T → F | T*F F → (E) | id

Să se elimine recursivitatea de stânga din această gramatică. Răspunsuri 1. Se consideră şirul de intrare:

i + i * i Pentru acest şir există 2 arbori de derivare:

În concluzie, gramatica este ambiguă.

2. Tratarea identificatorilor:

3. Pentru relaţiile recursive, se foloseşte formula: AA AA’

A’A’ În acest fel, mulţimea de şiruri derivate din A nu se schimbă. Se obţine următoarea gramatică transformată:

EE+TT ETE’ E’TE’ TTFF TFT’ T’FT’ F(E)id F(E)id

E

E + E

i E E * i i

E

E * E

i E E + i i

Programare WEB (16) 1. În cadrul unei baze de date cu numele RESURSE_UMANE, stocată pe un server MySQL (localhost, user “root”, fără parolă), se consideră tabela PERSONAL, creată cu comanda SQL următoare: CREATE TABLE personal ( cnp CHAR(13) PRIMARY KEY, nume VARCHAR(20), prenume VARCHAR(20); salar INTEGER); Să se scrie o aplicaţie Web (structurată sub forma a două fişiere script, unul HTML, celălalt PHP) care permite interogarea parametrizată a tabelei după o informaţie din coloana CNP (cod numeric personal) introdusă de la tastatura (prin intermediul unui formular HTML). Parametrul de interogare va fi transmis spre scriptul PHP, acesta realizând interogarea efectivă a tabelei şi afişarea pe o coloană a datelor returnate. Dacă nu se găseşte nici o înregistrare, se va semnala acest lucru printr-un mesaj. Se vor trata eventualele erori/excepţii prin afişarea unor mesaje. Alegerea numelor fişierelor este la latitudinea programatorului. R. (o soluţie posibilă, aceasta nefiind unică): fisier.html <html> <form action="fisier.php" method="POST"> CNP:<input type="text" name="cnp" size="13"><br> <input type="SUBMIT" value="Cauta"> </form> </html> fisier.php <?php $link=mysql_connect("localhost","root","") or die ("Eroare: Conectare esuata la server MySQL"); mysql_select_db("resurse_umane") or die ("Eroare: Nu se poate deschide baza de date"); $cnp=$_POST['cnp']; $query=mysql_query("select * from personal where cnp='$cnp'"); $contor_linii=0; while($row=mysql_fetch_row($query)) { $contor_linii++; //gasit o linie foreach ($row as $value) echo $value." <br>"; } if ($contor_linii==0)

echo "Nu s-a gasit nici o linie!"; mysql_close($link); ?> 2. În cadrul unei baze de date cu numele BAZA, stocată pe un server MySQL (localhost, user “root”, fără parolă), se consideră tabela EVIDENTA, creată cu comanda SQL următoare: CREATE TABLE evidenta(nume CHAR(20), varsta INTEGER, localitate CHAR(20)); Să se scrie un script PHP care permite interogarea tabelei, respectiv afişarea în format tabelat al întregului ei conţinut. Se vor trata eventualele erori/excepţii prin afişarea unor mesaje. Secvenţa de cod PHP se va comenta succint. R. (o soluţie posibilă, aceasta nefiind unică): <?php //conectare la server si selectie baza de date $link=mysql_connect("localhost","root","") or die ("Eroare: Conectare esuata la server MySQL"); mysql_select_db("baza") or die ("Eroare: Nu se poate deschide baza de date"); //interogare tabela $query=mysql_query("select * from evidenta"); //creare antet tabel echo "<table border='1'>"; echo "<tr>"; echo "<th>Nume</th>"; echo "<th>Varsta</th>"; echo "<th>Localitate</th>"; echo "</tr>"; //ciclare dupa numarul de inregistrari/linii gasite si afisarea lor, element cu element while ($row=mysql_fetch_row($query)) { echo "<tr>"; foreach ($row as $value) { echo "<td>$value</td>"; } echo "</tr>"; } echo "</table>"; //inchidere conexiune la baza de date mysql_close($link); ?>

3. În cadrul unei baze de date cu numele MAGAZIN, stocată pe un server MySQL (localhost, user “root”, fără parolă), se consideră tabela PRODUSE, creată cu comanda SQL următoare: CREATE TABLE produse (id INTEGER PRIMARY KEY, nume_produs VARCHAR(20), stoc INTEGER); Să se scrie o aplicaţie Web (structurată sub forma a două fişiere script, unul HTML, celălalt PHP) care permite introducere de la tastatură (prin intermediul unui formular HTML) a datelor privitoare la un produs din tabela bazei de date (id, nume_produs, stoc). Aceşti parametrii se vor transmite către un script PHP, realizând adăugarea efectivă a noului articolului în tabela bazei de date. Reuşita sau nereuşita operaţiei se va semnala prin afişarea unui mesaj corespunzător. Alegerea numele fişierelor este la latitudinea programatorului. R. (o soluţie posibilă, aceasta nefiind unică): fisier.html <html> <form action="fisier.php" method="POST"> Id:<input type="text" name="id" size="5"></p> Nume Produs:<input type="text" name="nume_produs" size="20"><br> Stoc:<input type="text" name="stoc" size="5"><br> <input type="SUBMIT" value="Trimite"> </form> </html> fisier.php <?php $link=mysql_connect("localhost","root","") or die ("Eroare: Conectare esuata la server MySQL"); mysql_select_db("magazin") or die ("Eroare: Nu se poate deschide baza de date"); $id=$_POST['id']; $nume_produs=$_POST['nume_produs']; $stoc=$_POST['stoc']; mysql_query("insert into produse values ($id, '$nume_produs', $stoc)") or die ("Eroare: Nu se poate finaliza operatia"); echo "Informatiile au fost introduse in baza de date"; mysql_close($link); ?>