Sari la conținut

King Of Underground

LCS PREMIUM
  • Număr conținut

    25
  • Înregistrat

  • Ultima Vizită

Despre King Of Underground

  • Dată Naștere 04.01.2000

Câmpuri de profil

  • Titlul de membru
    #mostHated.

Configurații server

  • Server & Games
    ESL

Vizitatori Recenți Profil

245 citiri profil

Realizările lui King Of Underground

IRON III

IRON III (3/25)

  • 1 an de LeagueCS

Insigne recente

605

Reputație Comunitate

  1. ** Algoritm de Cautare Binar ** Este un algoritm de cautare utilizat intr-o colectie SORTATA , ne ofera posibilitatea de a miscora timpul de executie (Complexitate Timp mai optim) prin divizarea repetata a intervalelor la jumatate . ** Explicatie ** Sa presupunem ca avem o colectie de 10 numere (SORTATA) : [11 , 22 , 34 , 56 , 65 , 76 , 78 , 84 , 96 , 98] Si dorim sa aflam daca exista numar 78 in colectie si la ce index : APLICAM ALGORITMUL :: --> AFLAM INDEX-UL CARE-I CORESPUNDE NUMARULUI DIN MIJLOCUL INTERVALULUI : (9+0)/2 = 4.5 ==> 5 ==> Verificam daca a[5] = 76 este echivalent cu 78 ==> DIFERIT CONTINUAM ALGORITMUL ; --> CUNOASTEM FAPTUL CA 78 > 76 ASA CA VOM STII CA NUMARUL CAUTAT SE AFLA IN INTERVALUL DIN DREAPTA [76 , 78 , 84 , 96 , 98 ] --> AFLAM INDEXUL CAREI CORESPUNDE NUMARUL DIN MIJLOCUL INTERVALULUI : (5+9)/2 = 14/2 = 7 (indexul din mijloc) ==> Verificam daca a[7] = 84 este echivalent cu 78 ==> DIFERIT CONTINUAM ALGORITMUL ; --> CUNOASTEM FAPTUL CA 84 > 78 ASA CA VOM STII CA NUMARUL CAUTAT SE AFLA IN INTERVALUL DIN STANGA [ 76 , 78 , 84 ] --> AFLAM INDEXUL CAREI CORESPUNDE NUMARUL DIN MIJLOCUL INTERVALULUI : (5+7)/2 = 6 (Indexul din mijloc) ==> verficam daca [a6] = 78 = este echivalent cu 78 ==> AM GASIT ELEMENTU , INTRERUPEM ALGORITMUL CU SUCCES !! ** Interpretare in Cod C ** : #include <stdio.h> #include <stdlib.h> // Pentru malloc & free int main() { int arrayBuffer; printf("Cate numere doresti sa aiba colectia : "); scanf_s("%d", &arrayBuffer); int* a = (int*)malloc(arrayBuffer * sizeof(int)); // ALOCAM UN ARRAY IN FUNCTIE DE CATE NUMERE VREA UTILIZATORUL SA INTRODUCA printf("Insereaza %d numere in sir crescator : \n",arrayBuffer); for (int i = 0; i < arrayBuffer; i++) { printf("colectie[%d] = ",i); scanf_s("%d", &a[i]); // Inseram numerele de la tastatura } int numberToSearch, found = 0, index; do { printf("Insereaza numarul pe care vrei sa l cauti in colectie : "); scanf_s("%d", &numberToSearch); int leftIndex = 0, RightIndex = arrayBuffer - 1; // Aflam Primul Si Ultimul Index // LE AM INITIALIZAT IN AFARA LOOPULUI PENTRU A SI PASTRA VALOAREA LA FIECARE ITERARE !!! do { int mid = (leftIndex + RightIndex) / 2; // Aflam Indexul Din Mijlocul Intervalului if (a[mid] == numberToSearch) // Comparam Cu Mijlocul { // Daca Am gasit numarul index = mid; // Preluam Indexul found = 1; break; } else if(a[mid] < numberToSearch) { // DACA NUMARUL CAUTAT ESTE MAI MARE DECAT MIJLOCUL leftIndex = mid; // Vom Cauta in Continuare de la Mijloc Spre Dreapta } else { // DACA NUMARUL CAUTAT ESTE MAI MIC DECAT MIJLOCUL RightIndex = mid; } } while (leftIndex <= RightIndex); printf("\n"); } while (found == 0); printf("Am gasit elementul %d la pozitia %d", numberToSearch, index); // Eliberam Memoria Ocupata de Array (Sa prevenim Memory Leak) free(a); // Eliberam Colectia in sine a = NULL; // Setam NULL Pointer return 0; } NOTA 1 ** : ALGORITM INEFICIENT IN CAZUL COLECTIILOR DEZORDONATE (NESORTATE) !!! Explicatie : Sa presupunem ca avem o colectie de 10 numere (NESORTAT) : [98 , 33 , 22 , 11 , 65 , 55 , 44 , 78 , 45 , 99] Si dorim sa aflam daca exista numarul 44 in colectie si la ce index : Aplicam Algoritmul : 1. mid = (0+9)/2 = 4.5 a[5] = 55 diferit de 44 ==> 55 > 44 ==> CAUTAM IN INTERVALUL DIN STANGA [98 , 33 , 22 , 11 , 65 , 55] NU L GASIM PE 44 IN ACEST INTERVAL !! ==> ALGORITMUL ESUEAZA NOTA 2 ** : FOARTE BUN DACA AVEM O COLECTIE MARE DE DATE , SCUTINDU NE DE A CAUTAT FIECARE ELEMENT !! (CU CONDITIA DE A FI ORDONAT)
  2. ** Analiza Algoritmilor ** Algoritmii sunt modalitati de identificare si rezolvare a unei sau mai multe probleme . In rezolvarea unei probleme , pot exista mai multe solutii dar unele pot fi mai eficiente sau nu . Eficacitatea unui algoritm este masurata in TIMP SI SPATIU . * TIMPUL CONSTA IN PERIOADA DE EXECUTIE A ALGORITMULUI . CU CAT TINDE SPRE 0 , cu atat este mult mai eficient din acest aspect !! * SPATIUL CONSTA IN RESURSELE ALOCATE IN EXECUTAREA ALGORITMULUI . CU CAT SPATIUL ESTE MAI MIC , CU ATAT ALGORITMUL ESTE MAI EFICIENT !! ** Introducere in Algoritmii de Cautare ** Algoritmii de cautare reprezinta modalitati diferite de rezolvare a problemei privind cautarea unui element sau mai multe , intr-o colectie (array,liste,arbori etc.) . Importanta algoritmilor de cautare : Ne ajuta la cautarea unui produs sau persoana , dupa preferintele noastre , de pe un site de e-commerce sau social media (persoana) ; Ne ajuta in diferite sisteme de recunoastere vocala , faciala etc. ; Ne ajuta sa cautam relevant intr o baza de date ; Ne ajuta la aflarea rutei optime dintr - o retea etc. ** Algoritmul de Cautare Liniar ** Cautarea Liniara reprezinta cea mai usoara modalitate de a descoperi un termen dintr- o colectie . Ea consta in verificarea fiecarui element in parte , de la un cap la celalalt . Explicatie : Definim o colectie de 10 numere . Sa cautam termenul 30 in colectie : [40 , 50 , 35 , 60 , 70 , 78 , 30 , 10 , 5 , 12] Navigam prin colectie si luam la comparatie fiecare numar (de la cifra 40 pana la 30) 40 diferit de 30 ==> mergem la urmatorul 50 diferit de 30 ==> mergem la urmatorul 35 diferit de 30 ==> mergem la urmatorul 60 diferit de 30 ==> mergem la urmatorul 70 diferit de 30 ==> mergem la urmatorul 78 diferit de 30 ==> mergem la urmatorul 30 egal cu 30 ==> TERMEN GASIT , OPRIM ALGORITMUL !!! Interpretare algoritm in C : #include <stdio.h> int main() { int a[10]; printf("Insereaza 10 numere : \n"); for (int i = 0; i < 10; i++) { printf("colectie[%d] = ",i); scanf_s("%d", &a[i]); // Inseram numerele de la tastatura } int numberToSearch, found = 0, index; do { printf("Insereaza numarul pe care vrei sa l cauti in colectie : "); scanf_s("%d", &numberToSearch); for (int i = 0; i < 10; i++) // Navigam prin colectie { if (numberToSearch == a[i]) // Cautam secvential prin toata colectia si comparam cu fiecare individ { // DACA S -A IMPLINIT CONDITIA DE MAI SUS found = 1; // Am gasit elementul index = i; // Salvam indexul break; // Intrerupem bucla !! } } printf("\n"); } while (found == 0); printf("Am gasit elementul %d la pozitia %d", numberToSearch, index); return 0; } NOTA 1 ** : Algoritmul devine mai ineficient cu cat elementul cautat este mai aproape de capat (TIMPUL DE EXECUTIE DEVINE DIN CE IN CE MAI MARE !!) NOTA 2 ** : NU SE RECOMANDA ACEST ALGORITM DE CAUTARE CAND AVEM DE A FACE CU COLECTII DE MARI DIMENSIUNI SAU ORDONATE !!!
  3. ** Constructor cu Argumente (Parametrii) ** Constructorul sau Constructorii cu parametrii sunt metode care ne permit sa avem instante (obiecte) unice in functie de parametrii luati . De asemenea , pot exista si impreuna cu constructorul implicit . Reconstruim clasa de la tutorialul trecut (cu constructorul implicit) + functia de alocare a sirurilor de caractere : void atribuireSirCaractere(char** target, const char* source) { size_t bufferString = strlen(source) + 1; *target = new char [bufferString]; strcpy_s(*target, bufferString, source); } class Utilizator { public : // Punem enumul pe public deoarece trebuie sa l accesam din exterior enum class type { // Tip de Utilizator MEMBER, PREMIUM, MODERATOR, ADMIN }; private: // Sector Privat (Membrii aflati la acest nivel de acces NU pot fi accesati unsigned id; // Numar Natural char* username; // String char* email; // String char* password; // String unsigned nrPosts; // Numar Natural bool isForbidden; // Banat sau NU type userType; // Tip Utilizator public: // Sector Public (Membrii aflati la acest nivel de acces POT FI ACCESATI) Utilizator() { /// Definitie Constructor fara parametrii (argumente) //// Definim Stringurile pe care le dorim sa le atribuim campurilor // Initializam campurile statice id = 0; nrPosts = 0; isForbidden = false; userType = type::MEMBER; // Member by Default // Atribuire Nume de Utilizator atribuireSirCaractere(&username, "Vasile"); // Atribuire Nume atribuireSirCaractere(&email, "vasile79@gmail.com"); // Atribuire Email atribuireSirCaractere(&password, "vasileParola"); } // Definim Getteri const unsigned _getIdUser() { return id; } const char* const _getUsername() { return username; } const char* const _getEmail() { return email; } const char* const _getPassword() { return password; } const unsigned _getNrPosts() { return nrPosts; } const bool _isForbidden() { return isForbidden; } const type _getType() { return userType; } }; NOTA ** : Am adaugat trei campuri noi ("isForbidden","NrPosts" si "TypeUser") sa devina mai interesant ; Acum in clasa respectiva , vom adauga 4 constructori cu paramatrii : Utilizator(unsigned _id,type _userType) { // Constructor care preia ca argument ID-ul si tipul de user ; id = _id; // Atribuim id-ul din argumentul preluat userType = _userType; // Atribuim tipul din argumentul preluat // Restu e implicit isForbidden = false; nrPosts = 0; atribuireSirCaractere(&username, "Vasile"); // Atribuire Nume atribuireSirCaractere(&email, "vasile79@gmail.com"); // Atribuire Email atribuireSirCaractere(&password, "vasileParola"); } Utilizator(unsigned _id, const char* _username,type _userType) // Al doilea Constructor cu id si nume preluat { // Atribuire cu argumente preluate id = _id; atribuireSirCaractere(&username, _username); userType = _userType; // Restu Implicit isForbidden = false; nrPosts = 0; atribuireSirCaractere(&email, "vasile79@gmail.com"); // Atribuire Email atribuireSirCaractere(&password, "vasileParola"); // Atribuire Parola A } Utilizator(unsigned _id, const char* _username , const char* _email , const unsigned _nrPosts) // Al treilea Constructor cu id , nume , email preluat si numar posturi { // Atribuire cu argumente preluate id = _id; atribuireSirCaractere(&username, _username); atribuireSirCaractere(&email, _email); // Atribuire Email nrPosts = _nrPosts; // Atribuire cu argumente default atribuireSirCaractere(&password, "vasileParola"); // Atribuire Parola A userType = type::MEMBER; // Atribuire Tip Utilizator isForbidden = false; } /// Constructor care preia toate argumentele Utilizator(unsigned _id, const char* _username, const char* _email, const char* _password,const unsigned _nrPosts,const bool _isForbidden,type _userType) { // Atribuire cu argumente preluate id = _id; nrPosts = _nrPosts; isForbidden = _isForbidden; userType = _userType; atribuireSirCaractere(&username, _username); // Atribuire Nume Utilizator atribuireSirCaractere(&email, _email); // Atribuire Email atribuireSirCaractere(&password, _password); // Atribuire Parola } NOTA ** : PUTEM FACE CATI CONSTRUCTORI CU PARAMETRII DORIM NOI !! (TOTUSI E RECOMANDAT DOAR CE E STRICT NECESAR) Pentru a putea afisa un enum ca sir de caractere , avem nevoie de un adaptor in interiorul clasei : static const char* typeUser(type userType) // O Folosim la nivel static { switch (userType) { case type::ADMIN: return "Administrator"; break; case type::MODERATOR: return "Moderator"; break; case type::PREMIUM: return "Utilizator Premium"; break; default: return "Utilizator Simplu"; break; } } NOTA ** : L am notat cu "static" deoarece functia nu depinde de campurile instantei !! Vom discuta in tutorialele ce urmeaza despre membrii statici , in detaliu !! Totodata , construim o alta functie in interiorul clasei care sa ne afiseze datele (Cu scopul de a nu repeta cod aiurea ): void toString(){ // Interfata de afisare a fiecarui obiect cout << _getIdUser() << " | " << _getUsername() << " | " << _getEmail() << " | " << _getPassword() << " | " << _isForbidden() << " | " << _getNrPosts() << " | " << typeUser(_getType()) << endl; } Acum , trecem in functia main si instantiem 5 obiecte (1 cu constructor default si 4 cu parametrii ) : int main() { Utilizator vasileEntitate1; // Instantiat cu Constructorul Default (Implicit) // Afisam Campurile : ID | USERNAME | EMAIL | PASSWORD vasileEntitate1.toString(); Utilizator vasileEntitate2(1,Utilizator::type::MEMBER); // Instantiere Prim Constructor vasileEntitate2.toString(); Utilizator ionEntitate(2, "Ion", Utilizator::type::PREMIUM); // Instantiere Al Doilea Constructor ionEntitate.toString(); Utilizator alinEntitate(3, "Alin", "alin21332@gmail.com" ,50); // Instantiere Al Treilea Constructor alinEntitate.toString(); Utilizator georgeEntitate(4, "George", "george21332@gmail.com", "georgeParola" , 80 , false,Utilizator::type::ADMIN); // Instantiere Al Treilea Constructor georgeEntitate.toString(); return 0; } Si primim ca rezultat : 0 | Vasile | vasile79@gmail.com | vasileParola | 0 | 0 | Utilizator Simplu 1 | Vasile | vasile79@gmail.com | vasileParola | 0 | 0 | Utilizator Simplu 2 | Ion | vasile79@gmail.com | vasileParola | 0 | 0 | Utilizator Premium 3 | Alin | alin21332@gmail.com | vasileParola | 0 | 50 | Utilizator Simplu 4 | George | george21332@gmail.com | georgeParola | 0 | 80 | Administrator
  4. ** Importanta Constructori ** Constructorii sunt metode care NU returneaza un tip de date , pot detine parametrii sau nu, si sunt utilizati pentru initializarea si alocarea dinamica a campurilor unei clase . Asemenea , ei poarta numele clasei si se declanseaza la instantierea clasei !!! ** Constructor fara Parametrii ** Constructorul fara Parametrii sau Implicit (Default) este un constructor fara argumente , el se declanseaza daca nu oferim parametrii la instantiere . Construim o functie in afara clasei care ne permite alocarea si atribuirea pentru fiecare sir de caractere : void atribuireSirCaractere(char** target, const char* source) // Luam ca argument sirul de caracter pe care dorim sa l initializam dar si valoarea pe care dorim sa o atribuim // Nota ** : char** pentru ca dorim sa efectuam o modificare a argumentului { size_t bufferString = strlen(source) + 1; // Aflam numarul de caractere pe care l are sursa + 1 bit (pentru caracterul terminal) *target = new char [bufferString]; // Alocam Targetul in functie de "bufferstring" strcpy_s(*target, bufferString, source); /// Atribuim targetul cu sursa } Construim clasa "Utilizator" cu campurile "id , username , emal , password " : class Utilizator { private: // Sector Privat (Membrii aflati la acest nivel de acces NU pot fi accesati) unsigned id; // Numar Natural char* username; // String char* email; // String char* password; // String }; Definim un costructor fara parametrii cu rolul de a atribui acele campuri private : class Utilizator { public: // Sector Public (Membrii aflati la acest nivel de acces POT FI ACCESATI) Utilizator() { /// Definitie Constructor fara parametrii (argumente) // Initializam campurile id = 0; // O initializam cu o valoare default // Atribuire Stringuri de Caractere (Accesam functia de mai sus) /* Astfel ca : username , email , password --> sunt targeturi (transferate prin adresa, continutul acestor pointeri se poate schimba la apelul functiei) Celalalte valori (al doilea parametru al functiei) sunt siruri de caractere constante (transferate prin valoare deoarece ne intereseaza sa atribuim targetul cu aceste valori) !! */ atribuireSirCaractere(&username, "Vasile"); // Atribuire Nume atribuireSirCaractere(&email, "vasile79@gmail.com"); // Atribuire Email atribuireSirCaractere(&password, "vasileParola"); // Atribuire Parola } }; Definim getteri pentru accesa campurile in functia main : // Definim Getteri // Functii Constante deoarece ne intereseaza doar sa citim valorile !!! const unsigned _getIdUser() { return id; } const char* const _getUsername() { return username; } const char* const _getEmail() { return email; } const char* const _getPassword() { return password; } Construim doua entitati de utilizator ("vasileEntitate1" , respectiv "vasileEntitate2") si afisam continutul acestora : int main() { Utilizator vasileEntitate1; // Instantiez + Declansam constructorul fara parametrii // Afisam Campurile : ID | USERNAME | EMAIL | PASSWORD cout << vasileEntitate1._getIdUser() << " | " << vasileEntitate1._getUsername() << " | " << vasileEntitate1._getEmail() << " | " << vasileEntitate1._getPassword() << endl; Utilizator vasileEntitate2; // Instantiem alt obiect dar Declansam acelasi constructor cout << endl; /// VOM AVEA ACELASI REZULTAT cout << vasileEntitate2._getIdUser() << " | " << vasileEntitate2._getUsername() << " | " << vasileEntitate2._getEmail() << " | " << vasileEntitate2._getPassword() << endl; return 0; } NOTA ** : VOM OBSERVA CA AMBELE ENTITATI LA APELUL CONSTRUCTORULUI IMPLICIT , NE FURNIZEAZA ACELEASI DETALII !!
  5. Corect , e o abordare buna atunci cand NU cunoastem dimensiunea acelui array . Practic , impartim numarul total de biti alocat pentru array la numarul alocat pentru fiecare unitate individuala (prima unitate are acelasi spatiu alocat ca al doilea , al treilea etc. Multumesc pentru completare !
  6. ** Tablouri de Dimensiune ** Tablouri de Dimensiune sau "Arrays" sunt tipuri de date compuse care au abilitatea de a stoca una sau mai multe valori . Asemenea putem stoca mai multe tipuri de date . (int , float ,char , pointeri chiar etc.) De exemplu : #include <stdio.h> int main() { int a[3] = { 0,1,2}; // Initializare Array cu 3 elemente for (int i = 0; i < 3; i++) { printf("%d | ", a[i]); // AFISARE CELE TREI ELEMENTE : a[0] , a[1] , a[2] } return 0; } NOTA 1 ** : Indexul primul element din array va fi intotdeauna 0 , cel putin in limbajele comune C/C++ , C# , Java etc. Astfel daca : int a[3] = {1 , 2 , 3} ; printf("%d" , a[1]); // Vom AFISA VALOAREA 2 , NICIDECUM 1 . PENTRU CA CEREM SA ACCESAM AL DOILEA ELEMENT /* a[n] --> n oricare numar natural o fi {1 , 2 , 3 , 4 , 5 , 6 , .... , n } ---> Valori [0 , 1 , 2 , 3 , 4 , 5 , .... , n-1] ---> Index (Incepe de la 0 si se termina la (n-1) ) Defapt Index e un sir de crescator de numere naturale */ NOTA 2 ** : ATENTIE , putem, din neatentie , sa accesam zone de memorie invalide . Astfel ca : #include <stdio.h> int main() { int a[3] = { 0,1,2}; // Initializare Array cu 3 elemente for (int i = 0; i <= 3; i++) { printf("%d | ", a[i]); // VOM AVEA O EROARE LA ACCESAREA LUI a[n] } /* {0 , 1 , 2 } -> valorile lui a [a[0] ,a[1] , a[2]] -> indexurile lui a iar noi incercam prin loop sa accesam a[3] care nu exista !!! */ return 0; } De asemenea , putem modifica valorile corespondete tabloului #include <stdio.h> int main() { int a[3] = { 0,1,2}; // Initializare Array cu 3 elemente for (int i = 0; i < 3; i++) { printf("%d | ", a[i]); // 0 , 1 , 2 } printf("\n"); /// Modificam valorile tabloului for (int j = 5 , i = 0 ; i < 3; (j += 2) , (i++)) // i = 0 , 1 , 2 ; j = 5 , 7 , 9 { a[i] = j; // a[0] = 5 ; a[1] = 7 ; a[2] = 9 } // Printam noul array for (int i = 0; i < 3; i++) { printf("%d | ", a[i]); // 5 , 7 , 9 } return 0; }
  7. ** POINTERI NULI SAU INVALIZI ** * In programare , vor exista situatii cand declaram dinamic o variabila , o folosim iar dupa va trebui sa o eliberam din memorie . In acest context (dupa eliberare) , pointerul respectiv devine INVALID si poate produce o eroare de tip runtime (In timpul rularii programului) daca acesta este accesat accidental . #include <stdio.h> #include <stdlib.h> // Pentru alocare dinamica int main() { int* pointer; pointer = (int*)malloc(sizeof(int)); // Alocam in memorie o variabila de tip intreg // VOM DISCUTA ULTERIOR DESPRE ALOCARE DINAMICA IN DETALIU *pointer = 30; // Atribuim numarul 30 ; printf("%i\n", *pointer); // Afisam 30 OK free(pointer); // Eliberam memoria ==> *pointer devine invalid printf("%i", *pointer); // EROARE ==>> *Pointer DEVINE DAGGLING return 0; } * In astfel de situatii , apelam la pointer nuli . Practic atribuim valoarea "null" acelui pointer !! pointer = NULL; // DUPA ELIBERAREA MEMORIEI SE RECOMANDA sa fie atrebuit cu NULL // SAU CHIAR LA INITIALIZARE NOTA ** : SE RECOMANDA CA POINTERI CARE NU POINTEAZA UN OBIECT VALID LA INCEPUT , SA FIE NOTATI CU NULL !! ** Pointeri Constanti ** * Pointeri constanti sunt pointeri a carora adresa nu se poate modifica dupa initializare . Pot pointa atat valori modificabile (atat variabile cat si constante) . #include <stdio.h> int main() { int a = 100; // Variabila int b = 50; // Constanta (NU SE POATE MODIFICA VALOAREA) int* const c = &a; // Pointer Constant pointeaza o variabila const int* const d = &b; // Pointer Constant pointeaza o constanta // EROARE DACA INCERCAM SA FACEM "c = &b" sau "d = &a" pentru ca nu putem schimba adresa de memorie // A DOUA SITUATIE *c = 30; // E OK (PUTEM SCHIMBA TOTUSI VALOAREA PENTRU CA POINTEAZA O VARIABILA) // *d = 30; /// EROARE NU PUTEM MODIFICA VALOAREA DEOARECE POINTAM O CONSTANTA printf("%d || %d ", *c , *d); // Afisam 30 | 50 return 0; } * Pointeri care pointeaza valori constante NU SI POT MODIFICA VALOARE DAR SPRE DEOSEBIRE DE POINTERI CONSTANTI ISI POT MODIFICA ADRESA DE MEMORIE #include <stdio.h> #include <stdlib.h> // Pentru alocare dinamica int main() { const int a = 50; const int* ptr = &a; printf("%d \n", *ptr); // Afisam 50 (CONSTANTA A) /// *ptr = 100; // NU PUTEM MODIFICA VALOAREA POINTERULUI CARE POINTEAZA O VALOARE CONSTANTA // Totusi spre deosebire de pointeri constanti putem schimba adresa de memorie !!!! // astfel ca const int b = 100; ptr = &b; // E OK , PUTEM SCHIMBA ADRESA DE MEMORIE printf("%d", *ptr); // AFISAM CONSTANTA B (100) return 0; }
  8. ** Introducere in Pointeri ** * Pointeri reprezinta variabile compuse care retin adresa altor variabile . * Ei sunt folositi pentru alocarea dinamica a variabilelor dar si pentru transferul parametrilor (functii) prin referinta . (Daca dorim sa modificam parametrii in subprogram) ; * Este un concept solid gasit doar in C/C++ (si partial in C#) deoarece pot duce la situatii complexe si erori , daca nu sunt gestionati cum trebuie ; ** Operatorul "&" ** * Operatorul '&' , insotit de oricare variabila , ne furnizeaza locatia de memorie a acesteia . * Spre exemplu : #include <stdio.h> int main() { int variabila; // Declaram o variabila de tip intreg printf("%p", &variabila); // Afisam adresa de memorie a acestei variabile return 0; } * Primim ca output locatia de memorie : * NOTA : Prin acest operator , pointerul poate obtine adresa de memorie a variabilei pe care o pointeaza . ** Operatorul '*' ** * Operatorul '*' , insotit de numele variabilei si tipul de date , ne indica o variabila de tip pointer ; int* pointer; // Declaratie variabila de tip pointer (Poate stoca adresa de memorie a altei variabile de tip int ) * Operatorul '*' poate fi interpretat si ca operatorul de referentiere astfel ca putem obtine valoarea adresei pe care o pointeaza : #include <stdio.h> int main() { int variabila = 100 , *variabilePointer; // Declaram o variabila de tip intreg si un pointer de tip intreg variabilePointer = &variabila; // Obtinem adresa de memorie a variabilei (Pointam "variabila") printf("%d", *variabilePointer); // Afisam valoarea variabilei return 0; } * Si obtinem in output valoarea variabilei : * Daca efectuam modificari pe valoarea stocata de variabila Pointeri se va modifica asemenea si valoarea variabilei simple !!! #include <stdio.h> int main() { int variabila = 100 , *variabilePointer; // Declaram o variabila de tip intreg si un pointer de tip intreg variabilePointer = &variabila; // Obtinem adresa de memorie a variabilei *variabilePointer = 50; // Modificam valoarea variabilei POINTER printf("%d", variabila); // Obtinem 50 deoarece pointerul stocheaza adresa de memoriei a variabilei automat se va modifica si valoarea !!! return 0; } ** Dimensiunea in memorie a pointerilor ** * Indiferent de tipul de date pe care l poate stoca , pointerul ocupa in memorie 4 biti (arhitectura x86 - 32 biti) sau 8 biti (arhitectura x64 - 64 biti) #include <stdio.h> int main() { int* ptr1; double* ptr2; char* ptr3; float* ptr4; printf("%zu | %zu | %zu | %zu", sizeof(ptr1), sizeof(ptr2), sizeof(ptr3), sizeof(ptr4)); // Vom Obtine 8 | 8 | 8 | 8 (Arhitectura x64) indiferent de tipul de date pe care l stocheaza return 0; }
  9. ** Introducere in Incapsulare ** Incapsularea reprezinta un alt concept crucial in paradigma orientata pe obiecte care ne permite capacitatea de a restrictiona accesul campurilor unei clase de catre exterior . De exemplu , utilizatorului NU i se permite modificarea sau citirea parolei de catre persoane NEAUTORIZATE (DOAR DE CATRE ADMINISTRATOR SAU UTILIZATORUL RESPECTIV) . ** Nivele de Acces ** In limbajul C++ , exista 3 nivele de acces : "private" --> nu se permite accesul (modificare/citire) din exterior (doar in interiorul clasei) ; "public" --> se permite accesul (modificare/citire) din exterior . "protected" --> similar cu "private" doar ca se permite accesul de catre alte clase derivate . (VOM DISCUTA LA MOMENTU POTRIVIT) De exemplu : #include <iostream> using namespace std; class Utilizator { private: // Sector Privat (Membrii aflati la acest nivel de acces NU pot fi accesati) char username[50]; // Declar Privat public : // Sector Public (Membrii aflati la acest nivel de acces POT FI ACCESATI) char email[50]; // Declar Public protected : // Sector Protejat (Membrii aflati la acest nivel de acces NU POT FII ACCESATI DIN EXTERIOR CU EXCEPTIA MEMBRIILOR CARE APARTIN DE CLASE DERIVATE DIN ACEASTA) char password[50]; // Declar Protected }; int main() { Utilizator vasileEntitate; // Instantiez /// Atribuim valori catre instanta strcpy_s(vasileEntitate.email, "vasileemai@gmail.com"); // OK strcpy_s(vasileEntitate.username, "vasile"); // EROARE MEMBRU INACCESIBIL --> MEMBRU PRIVAT strcpy_s(vasileEntitate.password, "vasileParola"); // EROARE MEMBRU INACCESIBIL --> MEMBRU PROTECTED return 0; } NOTA ** : SE RECOMANDA CA VARIABILELE SA FIE STOCATE PE SECTOR PRIVAT IAR FUNCTIILE (METODELE) PE PUBLIC !!! ** Getteri && Setteri ** Pentru citirea si modificarea campurilor private din exterior , exista conceptul de getteri (pentru citire) & setteri (pentru modificari) . Practic , putem modifica campurile private prin intermediul unor metode publice . De exemplu : #include <iostream> using namespace std; class Utilizator { private: // Sector Privat (Membrii aflati la acest nivel de acces NU pot fi accesati) char username[50]; // Declar Privat char email[50]; // Declar Privat char password[50]; // Declar Privat public : // Sector Public (Membrii aflati la acest nivel de acces POT FI ACCESATI) // Getteri ( Getteri Trebuie sa returneze tipul de date al campului) const char* getUsername() { return username; } const char* getEmailAddress() { return email; } const char* getPassword() { return password; } // Setteri (Setteri NU returneaza nimic doar modifica) void setUsername(const char* _username) { strcpy_s(username, _username); } void setEmail(const char* _email) { strcpy_s(email , _email); } void setPassword (const char* _password) { strcpy_s(password, _password); } }; int main() { Utilizator vasileEntitate; // Instantiez /// Atribuim valori catre instanta prin Setteri vasileEntitate.setUsername("Vasile"); vasileEntitate.setEmail("vasileEmail@gmail.com"); vasileEntitate.setPassword("vasileParola"); // Afisam valorile prin getteri cout << vasileEntitate.getUsername() << endl; cout << vasileEntitate.getEmailAddress() << endl; cout << vasileEntitate.getPassword() << endl; return 0; } Rezultat output : TUTORIAL CONSTRUIT DE CATRE MINE PENTRU UTILIZATORI LEAGUECS !!! PENTRU SUGESTII , RECLAMATII , OBIECTII , va astept cu PM sau jos , in comentarii !!!
  10. Obiective : * Introducere Clase ; * Introducere Obiecte (Instante) ; * Implementare Clasa si Obiect in C++ . ** Clasele ** Clasele reprezinta un concept crucial in paradigma orientata pe obiecte definind atat caracteristicile cat si comportamentele unei entitate . Spre exemplu , o clasa poate fi reprezentat de utilizator la care se descriu informatii precum varsta , nume , email , parola etc. Practic , reprezinta modelul pentru fiecare obiect instantiat in clasa respectiva . O clasa poate avea membrii de tip : --> Variabile (Simple , Pointeri,Tablouri de dimensiune etc.) ; --> Structuri , Clase sau Enumeratii ("Imbracate") ; --> Metode (Functii) ce descriu comportamentele obiectelor ; --> Constructori & Destructori (Pentru atribuire/alocare membrii cu valori si pentru eliminarea valorilor reziduale ) ** De constructori si destructori vom discuta in subiectele ce urmeaza !! Exemplu de Implementare Clasa in C++ : class Utilizator { public: // Recunoscut in afara Clasei // Variabile Simple int id; // Id Utilizator char username[50]; // Nume Utilizator char email[50]; // Email Utilizator char password[50]; // Parola Utilizator // Functii (Metode) const char* afisarenume() { return username; // Afisam numele utilizatorului } const char* afisareemail() // Afisam Email Utilizator { return email; } const int afisareid() // Afisam Id utilizator { return id; } const char* afisareParola() // Afisam Parola Utilizator { return password; } }; ** Obiectele sau Instantele ** Instantele reprezinta exemplarele sau entitatile autonome facute pe baza clasei instantate . De exemplu , clasa utilizatori poate instantia una sau mai multi elevi . Practic , putem avea elevi cu nume sau adresa de mail diferite , cu altfel de comportamente etc. O clasa se poate instantia pe cale statica sau dinamica : int main() { // Alocare Statica Utilizator vasileEntitate; // Initializare Proprietati vasileEntitate.id = 1; strcpy_s(vasileEntitate.username, "Vasile"); strcpy_s(vasileEntitate.email, "vasile323@gmail.com"); strcpy_s(vasileEntitate.password, "VasileParola"); cout << vasileEntitate.afisareid() << endl; cout << vasileEntitate.afisarenume() << endl; cout << vasileEntitate.afisareemail() << endl; cout << vasileEntitate.afisareParola() << endl; /// Alocare Dinamica (Stocata in memorie) Utilizator* ionEntitate = new Utilizator(); // Initializare cu valori ionEntitate->id = 2; strcpy_s(ionEntitate->username, "Ion"); strcpy_s(ionEntitate->email, "ion323@gmail.com"); strcpy_s(ionEntitate->password, "IonParola"); // Afisare Valori pentru ion cout << ionEntitate->afisareid() << endl; cout << ionEntitate->afisarenume() << endl; cout << ionEntitate->afisareemail() << endl; cout << ionEntitate->afisareParola() << endl; // Intotdeauna la Alocarea Dinamica Stergem valorile Reziduale delete ionEntitate; // Stergem Valoare Reziduala ionEntitate = nullptr; // Si o transformam in null pointer !! return 0; } Rezultatul in consola : NOTA** : VOM DISCUTA IN TUTORIALELE CE URMEAZA MAI IN DETALIU DESPRE ALOCAREA DINAMICA A INSTANTELOR !! **MULTUMESC FRUMOS PENTRU ATENTIE , TUTORIAL CONSTRUIT INTEGRAL DE CATRE MINE PENTRU UTILIZATORI LEAGUECS !! **PENTRU NELAMURIRI , SUGESTII , RECLAMATII VA PUTETI ADRESA JOS (IN COMENTARII) SAU PM !!!
      • 1
      • Fortzaaaa
  11. Nume actual: Deja Vu Numele pe care il doriti: ^^King Of Underground^^ Motivul pentru care doriti sa il schimbati: Nu mi mai place Link de la ultima cerere: Link PS : Daca nu sunt acceptate caractere speciale , cer sa ramana fara ele , Multumesc !
  12. Obiective tutorial : Validare Utilizator prin detectia campurilor nule sau goale (1) ; Validare Utilizator prin verificarea campului de "adresa mail" (2) ; Validare Utilizator prin verificarea unicitatii (3) . De ce se fac verificari la nivel de server , asta daca exista si pe partea de interfata ? Aceste verificari ne ofera garantia ca ORICE fel de cerere spre server , sa fie REVERIFICATA asigurandu ne o aplicatie web securizata si robusta . Pentru a valida , respectiva a salva un obiect la nivelul bazei de date , va trebui sa construim pachetul "Service Layer" , la radacina proiectului , unde vom construi o clasa numita "UserService" : Adaugam instanta necesara pentru a efectua operatiuni cu baza de date : package com.example.demo.ServiceLayer; import com.example.demo.Repositories.UserRepos; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service // Adnotam clasa de tip "Service" public class UserService { @Autowired // INSTANTELE ADNOTATE CU "AUTOWIRED" ne ofera posibilitatea de a utiliza instanta fara a fi INITIATA PRIN CONSTRUCTOR !! private UserRepos userRepos; /// Instanta pentru efectuarea operatiunilor la nivel cu baza de date } NOTA 1 * : Implementarea Interfetei "UserRepos" , o avem la tutorialul anterior !! NOTA 2 * : "@Autowired " functioneaza pe acelasi principiu cu "Lombok" , ne scuteste de a initializa instanta !!! Construim o functie "createUser()" care preia ca parametru campurile utilizatorului ..... public class UserService { .... public int createUser(User userData) // Functie User care preia ca parametru date despre utilizator { // } } Mergem in clasa "User" , vom adauga functia "hasEmptyOrNullFields" cu urmatoarea validare : ... public class User{ ..... /// Validare camp nul sau gol public boolean hasEmptyOrNullFields() { // SE VOR VERIFICA CAMPURILE CARE AU INITIALIZARE IN FUNCTIE DE "INPUT" (CELE CU @NonNull) /// Exceptie face "data de nastere" deoarece exista o modalitate aparte pentru validarea acestui camp . return nameUserLeagueCS.isBlank() || emailAddressLeagueCS.isBlank() || passwordLeagueCS.isBlank(); // Daca unu SAU mai multe campuri sunt nule sau goale atunci returnam "TRUE" } } Ne intoarcem in clasa "UserService " si vom valida obiectul in functie de existenta sau nu a campurilor nule sau goale : public int createUser(User userData) // Functie User care preia ca parametru date despre utilizator { // Validare Obiect UserData /// 1. Validare campuri nule sau goale ! if(userData.hasEmptyOrNullFields()) { /// DACA EXISTA VOM RETURNA UN COD DE EROARE -1 return -1; } // DACA NU , VOM MERGE LA URMATOAREA FORMA DE VALIDARE } Pentru validarea adresei de mail , vom construi o expresie "regex" (constituita din caractere) si care decide, pe baza conditiilor impuse de dezvoltator , daca aceea adresa este conforma . public class UserService { .... /* Validare Email bazat pe standardul RFC 5322 NOTA** : Expresiile REGEX se pot folosi la diverse validari (caractere permise , lungime etc.) si se pot personaliza in functie de preferinta dvs . */ final String regexEmail = "^[a-zA-Z0-9_!#$%&'*+/=?`{|}~^.-]+@[a-zA-Z0-9.-]+$"; .... } Si vom vedea prin functia "matches" : /// 2. Validarea adresei de mail if(!Pattern.matches(userData.getEmailAddressLeagueCS(),regexEmail)) { // Daca NU EXISTA COMPATIBILITATE INTRE ADRESA NOASTRA DE MAIL INSERATA SI CONDITIILE IMPUSE DE CATRE REGEX , VOM RETURNA -2 return -2; } In continuare , vom verifica daca exista un utilizator in baza de date care are acelasi nume de utilizator sau adresa de mail (duplicat) : ... public class UserService{ .... /// Introducem o functie care sa ne caute in baza de date orice utilizator care este similar cu cel ce urmeaza sa fie inserat (ASTA DACA EXISTA) private Predicate<User> IsADuplicatedUser = (user) -> userRepos.findAll().stream().anyMatch(userIterator -> userIterator.equals(user)); ..... public int createUser(User userData) { ... if(IsADuplicatedUser.test(userData)) { // DACA EXISTA UN UTILIZATOR CU ACELASI NUME SAU ADRESA DE MAIL , VA TREBUI SA RETURNAM COD DE EROARE -3; return -3; } /// AICI VOM CONTINUA IN URMATORUL TUTORIAL !! } } NOTA 1*** : VOM CONTINUA DATA VIITOARE CU VALIDAREA DATEI DE NASTERE SI CU SALVAREA UTILIZATORULUI IN BAZA DE DATE !! NOTA 2** : PENTRU PROBLEME , RECLAMATII SAU SUGESTII , PM SAU COMENTARIU IN TOPIC !! NOTA 3 **: MULTUMESC PENTRU ATENTIE !! NOTA 4** : SURSA CONSTRUITA SI INSPIRATA DE CATRE MINE !!!
  13. Obiective --> Ce reprezinta si ce utilitate are conceptul de "JPA Repository" ; --> Vom construi o interfata de tip "JPA Repository" pentru clasa "Utilizatori" . Ce reprezinta si ce utilitate are o interfata de tip "JPA Repository" ? Conceptul "JPA Repository" reprezinta o modalitate de a simplifica procesul de a efectua diverse operatiuni asupra bazei de date , astfel ca putem salva , cauta , modifica , sterge etc. inregistrari folosind anumite functii ajutatoare (predefinite sau personalizate) fara a utiliza comenzi SQL "RAW" . /*DE GENU INSERT */ INSERT INTO table_name (column1, column2, column3, ...) VALUES (value1, value2, value3, ...) Prin aceasta modalitate , putem introduce un utilizator folosind comanda : // userRepos instanta de UserRepository (ce extinde JpaRepository<User,Long>) // userData instanta de User (date despre un anumit utilizator ce urmeaza sa fie introdus) userRepos.save(userData) Construire interfata de tip "JpaRepository" pentru clasa "Utilizatori" Vom construi un pachet la radacina proiectului ce il vom numi "Repositories" , adaugand o interfata (NU CLASA) numita "UserRepos" : Iar apoi , vom deriva interfata din "JpaRepository<Clasa Model,Tip Date Cheie Primara Model>" : package com.example.demo.Repositories; import com.example.demo.Model.User; import org.springframework.data.jpa.repository.JpaRepository; public interface UserRepos extends JpaRepository<User,Long> { /// FUNCTII PERSONALIZATE DE IMPLEMENTAT PENTRU OPERATIUNI ULTERIOARE /// USER --> PROVINE DE LA MODELUL PE CARE L AM CREAT LA TUTORIALUL PRECEDENT /// LONG --> ESTE TIPUL DE DATE PE CARE IL ARE CHEIA PRIMARA (ID-UL UTILIZATORULUI) } NOTA 1 * : PENTRU SUGESTII , RECLAMATII & INDICATII AVETI PM SAU COMENTARIU LA TOPIC ; NOTA 2* : TUTORIAL CREATA SI INSPIRATA DE CATRE MINE PENTRU UTILIZATORI LEAGUECS ! NOTA 3 * : PENTRU SUSTINERE SI ALTE TUTORIALE , APESATI BUTONUL DE LIKE !
  14. Obiectivele acoperite in acest tutorial : Construirea unei clase de tip Model luand ca exemplu clasa Utilizatori (pentru proiectul nostru) care sa contina urmatoarele campuri : Cod Unic de Inregistrare (ID) exprimat in Long sau Numar Natural Distinct (Cheie Primara) ; Nume de Utilizator exprimat in String (Sir de caracter) , unic si nenul ; Adresa de Mail exprimat in String (Sir de caracter) , unic si nenul ; Parola exprimata in String (Sir de caracter) si nenul ; (NU E NECESAR SA FIE UNIC) ; Interdictie exprimat in valoare Booleana (True/False) ; Data Nasterii exprimat in LocalDate (Data de Nastere) . Sa incepem Vom avea nevoie de un pachet (numit Model) , respectiv o clasa de tip Model numita "User" , pe care le vom construi la radacina proiectului Adnotam clasa Utilizatori ca "Entitate" (de tip Model) si setam numele tabelei "Utilizatori LeagueCS" : package com.example.demo.Model; import jakarta.persistence.Entity; import jakarta.persistence.Table; @Entity // Clasa de tip Model (ENTITATE SQL) @Table(name = "Utilizatori LeagueCS") // Setam numele tabelei ("Utilizatori LeagueCS") ; public class User { } Adaugam campurile aferentei clasei Utilizatori mentionate la obiective cu caracteristicile lor : ...... public class User { /////// Adaugam Campurile ///// /// ID UTILIZATOR @Id // Cheie Primara (UNIC SI NENULA) @GeneratedValue(strategy = GenerationType.IDENTITY) // GENERARE AUTOMATA ID (DE LA 0 LA N ...) @Column(name = "ID UTILIZATOR") // NUMELE CAMPULUI IN BAZA DE DATE private Long idUserLeagueCS; // CAMPUL DIN MODEL /// NUME UTILIZATOR @NonNull // OBLIGATORIU IN CONSTRUCTIA OBIECTULUI (ADNOTARE LOMBOK) @Column(name="NUME UTILIZATOR" , unique = true , nullable = false) // NUMELE CAMPULUI IN BAZA DE DATE , UNICAT (NU TREBUIE SA EXISTE UTILIZATOR CU ACELASI NUME SAU FARA !! ) @JsonProperty("username") private String nameUserLeagueCS; //// Adresa Mail Utilizator (IDEM) @NonNull @Column(name="ADRESA MAIL",unique = true,nullable = false) @JsonProperty("emailAddess") private String emailAddressLeagueCS; //// Parola Utilizator (IDEM CU EXCEPTIA CA POATE FI GENERAL ) @NonNull @Column(name="PAROLA",nullable = false) @JsonProperty("password") private String passwordLeagueCS; //// Interdictie Utilizator (IDEM DOAR CA E O VALOARE BOOLEANA , PORNESTE CU O VALOARE FALSA IMPLICIT) @Column(name="INTERDICTIE",nullable = false) @JsonProperty("forbidden") @Value("${props.forbidden:false}") // VALOARE DEFAULT "FALSE" care se poate modifica ulterior . private Boolean forbiddenLeagueCS; /// Data de Nastere @NonNull @Column(name="DATA NASTERE",nullable = false) @JsonProperty("bornDate") @JsonFormat(shape= JsonFormat.Shape.STRING,pattern = "dd/MM/yyyy") /// DATA DE NASTERE TREBUIE SA FIE IN FORMATUL "yyyy/MM/dd" // (De exemplu , "11/03/2024" , alte variatii NU sunt acceptate . ) private LocalDate bornDateLeagueCS; } NOTA ** : TEXTELE PRECEDATE DE "//" SUNT CONSIDERATE CA COMENTARII SI SUNT OMISE DE COMPILATOR !!! Adaugam (prin Lombok) constructorii , implicit si cel cu parametrii , cei adnotati (Campurile) cu "NonNull" sunt luati in considerare ca Paramatrii ...... @RequiredArgsConstructor // Constructor cu parametrii (aia adnotati cu "NonNull") ; @NoArgsConstructor // Constructor Implicit (Default fara parametrii) ; public class User { .... } Adaugam "getteri" si "setteri" (prin Lombok) pentru accesul si modificarea campurilor PRIVATE (acces indirect) : ........ @Getter // Adauga getteri pentru toate campurile @Setter // Adauga setteri pentru toate campurile public class User { ....... } Adaugam o functie derivata "toString" pentru afisare obiectului in format "String" (Prin Lombok) : .... @ToString public class User { ..... } Adaugam functiile derivate "hash" & "equal" pentru clasa noastra : ....... public class User { ..... //////////// Functii Derivate @Override // Functie derivata din Clasa Object public int hashCode() // Genereaza un cod unic alocat fiecarui obiect in functie de algoritm { return (int) (idUserLeagueCS * nameUserLeagueCS.hashCode() * emailAddressLeagueCS.hashCode() * passwordLeagueCS.hashCode() *bornDateLeagueCS.hashCode() * forbiddenLeagueCS.hashCode()); // DUPA ACEST ALGORITM DE CALCUL , VA REZULTAT UN COD UNIC PENTRU // FIECARE OBIECT ASOCIAT AL ACESTEI CLASE } @Override public boolean equals(Object otherUserLeagueCS) /// COMPARA FIECARE OBIECT ASOCIAT AL ACESTEI CLASE // NE AJUTA SA AFLAM DACA MAI EXISTA UN UTILIZATOR CU ACELASI NUME & ADRESA DE MAIL { if(this.getClass() != otherUserLeagueCS.getClass()) // OBIECTUL LUAT LA COMPARATIE NU ESTE ASOCIAT CU CLASA NOASTRA { return false; // RETURNAM FALSE } if(this == otherUserLeagueCS) // OBIECTUL IN CAUZA ESTE O CLONA (CAZ IMPOSIBIL ORICUM) { return true; // RETURN TRUE } else{ // DACA AVEM ACELASI NUME SAU ADRESA DE MAIL INTRE UTILIZATORI INSEAMNA CA SUNT ASEMANATORI INTRE EI !! return nameUserLeagueCS.equals(((User) otherUserLeagueCS).nameUserLeagueCS) || emailAddressLeagueCS.equals(((User) otherUserLeagueCS).emailAddressLeagueCS); } } } CODUL FINAL PENTRU MODEL AR TREBUI SA ARATE ASA : package com.example.demo.Model; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.persistence.*; import lombok.*; import org.springframework.beans.factory.annotation.Value; import java.time.LocalDate; @Entity // Clasa de tip Model (ENTITATE SQL) @Table(name = "Utilizatori LeagueCS") // Setam numele tabelei ("Utilizatori LeagueCS") ; @RequiredArgsConstructor // Constructor cu parametrii (aia adnotati cu "NonNull") ; @NoArgsConstructor // Constructor Implicit (Default fara parametrii) ; @Getter @Setter @ToString public class User { /////// Adaugam Campurile ///// /// ID UTILIZATOR @Id // Cheie Primara (UNIC SI NENULA) @GeneratedValue(strategy = GenerationType.IDENTITY) // GENERARE AUTOMATA ID (DE LA 0 LA N ...) @Column(name = "ID UTILIZATOR") // NUMELE CAMPULUI IN BAZA DE DATE private Long idUserLeagueCS; // CAMPUL DIN MODEL /// NUME UTILIZATOR @NonNull // OBLIGATORIU IN CONSTRUCTIA OBIECTULUI (ADNOTARE LOMBOK) @Column(name="NUME UTILIZATOR" , unique = true , nullable = false) // NUMELE CAMPULUI IN BAZA DE DATE , UNICAT (NU TREBUIE SA EXISTE UTILIZATOR CU ACELASI NUME SAU FARA !! ) @JsonProperty("username") private String nameUserLeagueCS; //// Adresa Mail Utilizator (IDEM) @NonNull @Column(name="ADRESA MAIL",unique = true,nullable = false) @JsonProperty("emailAddess") private String emailAddressLeagueCS; //// Parola Utilizator (IDEM CU EXCEPTIA CA POATE FI GENERAL ) @NonNull @Column(name="PAROLA",nullable = false) @JsonProperty("password") private String passwordLeagueCS; //// Interdictie Utilizator (IDEM DOAR CA E O VALOARE BOOLEANA , PORNESTE CU O VALOARE FALSA IMPLICIT) @Column(name="INTERDICTIE",nullable = false) @JsonProperty("forbidden") @Value("${props.forbidden:false}") // VALOARE DEFAULT "FALSE" care se poate modifica ulterior . private Boolean forbiddenLeagueCS; /// Data de Nastere @NonNull @Column(name="DATA NASTERE",nullable = false) @JsonProperty("bornDate") @JsonFormat(shape= JsonFormat.Shape.STRING,pattern = "dd/MM/yyyy") /// DATA DE NASTERE TREBUIE SA FIE IN FORMATUL "yyyy/MM/dd" // (De exemplu , "11/03/2024" , alte variatii NU sunt acceptate . ) private LocalDate bornDateLeagueCS; //////////// Functii Derivate @Override // Functie derivata din Clasa Object public int hashCode() // Genereaza un cod unic alocat fiecarui obiect in functie de algoritm { return (int) (idUserLeagueCS * nameUserLeagueCS.hashCode() * emailAddressLeagueCS.hashCode() * passwordLeagueCS.hashCode() *bornDateLeagueCS.hashCode() * forbiddenLeagueCS.hashCode()); // DUPA ACEST ALGORITM DE CALCUL , VA REZULTAT UN COD UNIC PENTRU // FIECARE OBIECT ASOCIAT AL ACESTEI CLASE } @Override public boolean equals(Object otherUserLeagueCS) /// COMPARA FIECARE OBIECT ASOCIAT AL ACESTEI CLASE // NE AJUTA SA AFLAM DACA MAI EXISTA UN UTILIZATOR CU ACELASI NUME & ADRESA DE MAIL { if(this.getClass() != otherUserLeagueCS.getClass()) // OBIECTUL LUAT LA COMPARATIE NU ESTE ASOCIAT CU CLASA NOASTRA { return false; // RETURNAM FALSE } if(this == otherUserLeagueCS) // OBIECTUL IN CAUZA ESTE O CLONA (CAZ IMPOSIBIL ORICUM) { return true; // RETURN TRUE } else{ // DACA AVEM ACELASI NUME SAU ADRESA DE MAIL INTRE UTILIZATORI INSEAMNA CA SUNT ASEMANATORI INTRE EI !! return nameUserLeagueCS.equals(((User) otherUserLeagueCS).nameUserLeagueCS) || emailAddressLeagueCS.equals(((User) otherUserLeagueCS).emailAddressLeagueCS); } } } Salvam iar cand rulam codul vom avea inregistrarea SQL in consola precum ca s-a adaugat tabela in baza de date : Iar daca vizualizam in HeidiSQL (softul instalat cu MariaDB) , conectandu ne cu credentialele aferente bazei de date vom avea : PS 1 * : MULTUMESC PENTRU ATENTIE , PENTRU RECLAMATII , SUGESTII SI PROBLEME PM ME SAU COMENTARIU IN TOPIC ; PS 2 * : SURSA CREATA SI INSPIRATA DE CATRE MINE PENTRU UTILIZATORI LEAGUECS !! PS 3 * : DACA VA PLACE , NU UITATI SA LASATI O APRECIERE !!
  15. Salut si bine ai venit pe LeagueCS !
×
×
  • Creează nouă...

Informații Importante

Termeni de Utilizare & Politică Intimitate