Tip conținut
Profiluri
Forumuri
Calendar
Orice postat de NOT a MERCEDES
-
** Obiective ** Prezentarea , limitarile impuse dar si exemplificari (in cod C/C++) pe tema supraincarcarii functiilor/metode (clase) . ** Prezentare Concept ** Supraincarcarea functiilor (in C sau C++ din afara claselor) sau a metodelor reprezinta conceptul prin care putem declara si implementa , doua sau mai multe functii cu acelasi nume . NOTA ** : Metode sunt functii situate in cadrul unei clase (membrii) !! Totusi , exista anumite limitari : ** Conditii de Implinit ** FUNCTIILE SAU METODELE TREBUIE SA DIFERE PRIN NUMARUL SI TIPUL DE DATE AL ARGUMENTELE ASOCIATE ACESTUIA !! NU E DE AJUNS SA SCHIMBAM DOAR TIPUL DE DATE RETURNAT !! De exemplu , putem/nu putem supraincarca : // AMBELE NU SE POT SUPRAINCARCA void showObject(); // AICI ORI UNA ORI ALTA int showObject(); // E OK , SE POT SUPRAINCARCA (DIFERA TIPUL DE DATE DINTRE ELE) void showObject(unsigned A); void<(sau alt tip de date)> showObject(float B); // <> --> E DOAR INFORMATIONAL // NU SE POT SUPRAINCARCA void showObject(unsigned A,unsigned B); void showObject(bool A , unsigned B); // ASA DA void showObject(unsigned A , unsigned B , unsigned C); void showObject(bool A,unsigned B); //// si tot asa .. ** Exemplu de Lucru cu functii/metode ** Adaugim , din proiectul trecut , cinci functii supraincarcate : // user.h --> declarare //// ... class User{ ////.... // Alte Functii // Vizualizare Obiect void objectToString() const; // Afisam Obiectul cum este // Astea doua jos merg supraincarcate deoarece avem argumentul schimbat void objectToString(unsigned nrPosts); // Afisam Obiectul cu Numarul de Posturi schimbat in functie de parametru //int objectToString(unsigned nrPosts); --> ASA NU FUNCTIONEAZA void objectToString(const char* username); // AFISAM CU NUMELE DE UTILIZATOR SCHIMBAT // Astea doua jos merg supraincarcate deoarece avem 1 argument in plus void objectToString(unsigned nrPosts, const char* username,unsigned isBanned); // IDEM SUS + NUMELE DE UTILIZATOR void objectToString(unsigned nrPosts, const char* username); // AFISAM CU STATUS DE BANAT SCHIMBAT SI NUME D EUTILIZATOR }; Le implementam pe fiecare : /// User.cpp ///restu de cod // METODE SUPRAINCARCATE void User::objectToString(unsigned nrPosts) // Metoda 2 (Supraincarcata ) { this->nrPosts = nrPosts; // Setam o valoare preluat din parametru objectToString(); // O apelam pe prima pentru afisare } void User::objectToString(const char* username) { stringHandling->setString(username); // Setam numele intr-un container StringLGCS::allocAndFetchString(&this->username, stringHandling->getString()); // il setam objectToString(); /// afisam obiectul } void User::objectToString(unsigned nrPosts, const char* username, unsigned isBanned) { this->nrPosts = nrPosts; // setam numarul de posturi this->isBanned = isBanned; // setam statusul objectToString(username); // schimbam numele + afisam obiectul } void User::objectToString(unsigned nrPosts, const char* username) { this->nrPosts = nrPosts; // setam numarul de posturi objectToString(username); // schimbam numele + afisam obiectul } Testam codul invocand cele 5 metode supraincarcate : /// entryPoint.cpp #include "User.h" // Includem Clasa de Utilizatori int main() { User user1("Alin", "alin@gmail.com", "alipassword"); // Apelam Constructor Default (Implicit) user1.objectToString(); // AFISAM OBIECTUL CU PARAMETRII DIN CONSTRUCTOR user1.objectToString(12); // AFISAM OBIECTUL + 12 POSTURI user1.objectToString("MARIUS"); // AFISAM OBIECTUL CU NUMELE SCHIMBAT user1.objectToString(25,"VASILE"); // AFISAM OBIECTUL CU NUMELE SCHIMBAT + NUMAR DE POSTURI user1.objectToString(30, "IONEL", true); // AFISAM OBIECTUL CU NUMELE SCHIMBAT + NUMAR DE POSTURI + SCHIMBAT STATUS } REZULTATUL : { ID Utilizator : 0 , Nume Utilizator : Alin , Adresa Mail : alin@gmail.com , Parola Utilizator : alipassword , Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } { ID Utilizator : 0 , Nume Utilizator : Alin , Adresa Mail : alin@gmail.com , Parola Utilizator : alipassword , Numar Posturi : 12, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } { ID Utilizator : 0 , Nume Utilizator : MARIUS , Adresa Mail : alin@gmail.com , Parola Utilizator : alipassword , Numar Posturi : 12, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } { ID Utilizator : 0 , Nume Utilizator : VASILE , Adresa Mail : alin@gmail.com , Parola Utilizator : alipassword , Numar Posturi : 25, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } { ID Utilizator : 0 , Nume Utilizator : IONEL , Adresa Mail : alin@gmail.com , Parola Utilizator : alipassword , Numar Posturi : 30, STATUS BANAT : ESTE INTERZIS PE LEAGUECS!!, }
-
linked list [Structuri de Date - C] Inserare in Liste Inlantuite (Partea 2)
NOT a MERCEDES a postat un topic în Windows
** Declarare functii de inserare , printare si stergere totala ** // Lists.h #pragma once #include "stdlib.h" // malloc/free #include "string.h" // memcpy typedef struct LinkedList{ // LISTA INLANTUITA GENERICA (O PUTEM FOLOSI CU ORICE TIP DE DATE FARA SA DECLARAM MAI MULTE STRUCTURI) void* Data; // Pastram informatia pentru elementul curent struct LinkedList* nextElement;// Ne corelam cu urmatorul element }Linked_List; void insertAtHead(Linked_List** head, void* data, size_t sizeData); // Inseram de la inceputul listei (Transfer prin adresa , inseram date in lista) void insertAtEnd(Linked_List** head, void* data, size_t sizeData); // Inseram la sfarsitul listei void printLinkedList(Linked_List* head, void(*printDataGeneric)(void*)); // Printam lista void freeLinkedList(Linked_List** head, void(*deleteDataGeneric)(void*)); // Eliberam Lista ** Inserare de la inceput ** Implementam functia de inserare la inceput in "Lists.c" : // Lists.c #include "Lists.h" // Includem Headerul void insertAtHead(Linked_List** head,void* data,size_t sizeData) { // PRIMESTE CA PARAMETRU LISTA PRELUATA PRIN ADRESA (PENTRU MODIFICARI) , INFORMATIA PE CARE O PRIMESTE NODUL SI DIMENSIUNEA ACESTEIA } Inseram date in Nod : // Lists.c #include "Lists.h" // Includem Headerul void insertAtHead(Linked_List** head,void* data,size_t sizeData) { // PRIMESTE CA PARAMETRU LISTA PRELUATA PRIN ADRESA (PENTRU MODIFICARI) , INFORMATIA PE CARE O PRIMESTE NODUL SI DIMENSIUNEA ACESTEIA //// 1. ADAUGAM INFORMATIA CATRE NOD // Alocam un bloc nou de memorie pentru segmentul pe care l introducem Linked_List* newNode = (Linked_List*)malloc(sizeof(Linked_List)); // Inseram date in bloc newNode->Data = malloc(sizeData); // Alocam spatiu pentru informatie memcpy_s(newNode->Data,sizeData,data,sizeData); // Transferam informatia spre blocul nou } Construim legatura cu Urmatorul Nod : // Lists.c #include "Lists.h" // Includem Headerul void insertAtHead(Linked_List** head,void* data,size_t sizeData) { // PRIMESTE CA PARAMETRU LISTA PRELUATA PRIN ADRESA (PENTRU MODIFICARI) , INFORMATIA PE CARE O PRIMESTE NODUL SI DIMENSIUNEA ACESTEIA //// 1. ADAUGAM INFORMATIA CATRE NOD // Alocam un bloc nou de memorie pentru segmentul pe care l introducem Linked_List* newNode = (Linked_List*)malloc(sizeof(Linked_List)); // Inseram date in bloc newNode->Data = malloc(sizeData); // Alocam spatiu pentru informatie memcpy_s(newNode->Data,sizeData,data,sizeData); // Transferam informatia spre blocul nou /// 2. CONSTRUIM LEGATURA CU URMATORUL NOD newNode->nextElement = *head; // URMATORUL NOD VA FI CAPUL CURENT (PRIMUL ELEMENT ) *head = newNode; // NOUL NOD VA FI CAPUL /*** Reprezentare Vizuala : SA presupunem ca dorim sa introducem : 5 , 4 , 2 , 7, 6 (In Lista ) 1. 5 -> NULL 2. 4 -> 5 -> NULL 3. 2 -> 4 -> 5 -> NULL 4. 7 -> 2 -> 4 -> 5 -> NULL 5. 6 -> 7 -> 2 -> 4 -> 5 -> NULL ***/ } ** Inserare de La Capat ** Implementam functia de inserare la sfarsitul listei : // Lists.c void insertAtEnd(Linked_List** head, void* data, size_t sizeData) { // IDEM , DIFERA DOAR MODUL DE FORMARE A LEGATURILOR //// 1. ADAUGAM INFORMATIA CATRE NOD // Alocam un bloc nou de memorie pentru segmentul pe care l introducem Linked_List* newNode = (Linked_List*)malloc(sizeof(Linked_List)); // Inseram date in bloc newNode->Data = malloc(sizeData); // Alocam spatiu pentru informatie memcpy_s(newNode->Data, sizeData, data, sizeData); // Transferam informatia spre blocul nou // INFORMATIA SE ADAUGA LA FEL DOAR DIFERA LEGATURILE newNode->nextElement = NULL; // Setam ca nodul construit sa fie ultimul element // CONTINUARE } Daca lista este goala : if (*head == NULL) // Daca nu avem elemente in lista *head = newNode; // NODUL VA DEVENI CAPUL LISTEI Daca NU : void insertAtEnd(Linked_List** head, void* data, size_t sizeData){ // RESTU CODULUI else { // ALTFEL VOM PARCURGE LISTA PANA LA FINAL Linked_List* lastNode = *head; while (lastNode->nextElement != NULL) // Parcurgem pana la ultimul element lastNode = lastNode->nextElement; // Parcurgem nod cu nod (sau segment) lastNode->nextElement = newNode; // Urmatorul element al ultimului nod va fi cel construit aici } /*** Reprezentare vizuala : 5 , 3 , 2 , 6 , 7 1. 5 -> NULL ; 2 5 -> 3 -> NULL ; 3. 5 -> 3 -> 2 -> NULL; 4. 5 -> 3 -> 2 -> 6 -> NULL; 5. 5 -> 3 -> 2 -> 6 -> 7 -> NULL; ***// } ** Afisare Lista Generica ** Afisarea listei se va efectua generic (adaptata la tipul de date pe care l vom folosi, in cazul nostru Utilizator) : // Lists.c void printLinkedList(Linked_List* head,void(*printDataGeneric)(void*)) { // Preluam lista prin copie dar si o functie pointer care ne permite sa printam un tip de date pe care l dorim (In cazul nostru , Utilizatori) while (head != NULL) // NAVIGAM PANA NU MAI EXISTA ELEMENTE { (*printDataGeneric)(head->Data); // Printam INFORMATIA DIN NOD ADAPTATA LA TIPUL DE DATE PE CARE L VREM NOI head = head->nextElement; // NAVIGAM LA URMATORUL ELEMENT } } ** Stergere Lista Generica ** Stergerea listei se va efectua generic (adaptata la tipul de date pe care l vom folosi , in cazul nostru Utilizator) : void freeLinkedList(Linked_List** head, void(*deleteDataGeneric)(void*)) { // Preluam nodul actual sa l putem sterge Linked_List* nodeToBeDeleted = head; // Stergerea se face de la primul spre ultimul while (*head != NULL) //navigam PANA la capat { nodeToBeDeleted = *head; // Preluam referinta capului *head = (*head)->nextElement; // Mutam capul la urmatorul element //// Stergem informatia din nodul actual (*deleteDataGeneric)(nodeToBeDeleted->Data); // Stergem Generic (Adaptata la tipul nostru de date) free(nodeToBeDeleted->Data); // Stergem blocul de memorie ocupata de informatie free(nodeToBeDeleted); // Stergem nodul in sine } *head = NULL; // SETAM LISTA PE NULL } Testam functiile in programul principal : // entryPoint.c /* Legam toate entry point toate headerele dependente */ #include "../StructuriDate/roles.h" #include "../StructuriDate/fileHandling.h" #include "../StructuriDate/User.h" #include "../StructuriDate//Lists.h" // stringHandling.h nu este dependent de entry point // // CONSTANTELE MACRO SUNT UTILE CA LE PUTEM UTILIZA LA NIVEL GLOBAL (PE TOT FISIERUL) // NOTA** : E O PRACTICA BUNA DE A FOLOSI MACRO SPRE DEOSEBIRE DE CONSTANTE "MAGICE" (NUMERE PRIN COD) #define NR_FILES 2 // STABILIM UN NUMAR DE FISIERE int main() { FILE** file = NULL; file = (FILE**)malloc(sizeof(FILE*)*NR_FILES); // DECLARAM O COLECTIE DE FISIERE file[0] = openFile(FILENAME_INPUT_ROLES, READMODE_TXT); // CITIM ROLURILE DINTR-UN FISIER TEXT file[1] = openFile(FILENAME_USER_INPUT, READMODE_TXT); // CITIM UTILIZATORI DINTR-UN FISIER TEXT // dateIntrareLeagueCS.txt && dateIntrareRoluriLeagueCS.txt TREBUIE SA EXISTE IN DIRECTOR (ALTFEL VA ESUA) Role* roles = fetchRoles(file[0]); // Am primit lista cu rolurile User* users = fetchUsersFromTxtFile(file[1],roles); // Am primit informatia despre utilizatori Linked_List* list = NULL; // Declaram lista nula for (int i = 0; i < 3; i++) // Primii 3 ii inseram de la cap insertAtHead(&list, users + i, sizeof(users[i])); // inseram al doilea element al listei ca cap al listei (1) for (int i = 3; i < 6; i++) // Ceilalti de la coada insertAtEnd(&list, users + i, sizeof(users[i])); // inseram al doilea element al listei ca cap al listei (1) printLinkedList(list, printUser); // ELIBERAM RESURSELE freeLinkedList(&list, freeUser); // Eliberam Nodurile + Lista va fi NULA freeRoles(&roles); // Eliberam resursele ocupate de entitate free(users); // Stergem colectia closeFiles(&file,NR_FILES); // Eliberam resursele ocupate de fisiere if (file == NULL) printf("COLECTIA DE FISIERE A FOST ELIBERATA CU SUCCES !! "); return 0; } Si vom avea rezultatul : **FISIERUL dateIntrareRoluriLeagueCS.txt S-A DESCHIS CU SUCCES !** **FISIERUL dateIntrareUtilizatoriLeagueCS.txt S-A DESCHIS CU SUCCES !** User 0 : { ID UTILIZATOR: 2 , NUME UTILIZATOR: Alivcxvxcn , ADRESA MAIL UTILIZATOR: alidsadvfcn@gmail.com , PAROLA : dsewqqewqadc , NUMAR POSTURI : 550 , ESTE BANAT : NU , ROLURI DETINUTE : { ID ROL : 3 | NUME ROL : Super Moderator ID ROL : 1 | NUME ROL : Utilizator Premium } }User 1 : { ID UTILIZATOR: 1 , NUME UTILIZATOR: Alinds , ADRESA MAIL UTILIZATOR: alidasdsan@gmail.com , PAROLA : dsavvcvdc , NUMAR POSTURI : 50 , ESTE BANAT : NU , ROLURI DETINUTE : { ID ROL : 0 | NUME ROL : Membru ID ROL : 1 | NUME ROL : Utilizator Premium } }User 2 : { ID UTILIZATOR: 0 , NUME UTILIZATOR: Alin , ADRESA MAIL UTILIZATOR: alidsadan@gmail.com , PAROLA : dsdasdadsadadc , NUMAR POSTURI : 100 , ESTE BANAT : NU , ROLURI DETINUTE : { ID ROL : 0 | NUME ROL : Membru ID ROL : 3 | NUME ROL : Super Moderator ID ROL : 4 | NUME ROL : Administrator ID ROL : 1 | NUME ROL : Utilizator Premium } }User 3 : { ID UTILIZATOR: 3 , NUME UTILIZATOR: Alifdsfn , ADRESA MAIL UTILIZATOR: alewewin@gmail.com , PAROLA : dsfdsfsdfsadc , NUMAR POSTURI : 3300 , ESTE BANAT : NU , ROLURI DETINUTE : { ID ROL : 0 | NUME ROL : Membru ID ROL : 1 | NUME ROL : Utilizator Premium ID ROL : 2 | NUME ROL : Moderator ID ROL : 3 | NUME ROL : Super Moderator ID ROL : 4 | NUME ROL : Administrator } }User 4 : { ID UTILIZATOR: 4 , NUME UTILIZATOR: Alie2qweqn , ADRESA MAIL UTILIZATOR: alcxsaxcadsain@gmail.com , PAROLA : dsvcvvvvadc , NUMAR POSTURI : 11100 , ESTE BANAT : NU , ROLURI DETINUTE : { ID ROL : 0 | NUME ROL : Membru } }User 5 : { ID UTILIZATOR: 5 , NUME UTILIZATOR: Alidasdadan , ADRESA MAIL UTILIZATOR: alidasdassdadn@gmail.com , PAROLA : dsvvvvvvvvradc , NUMAR POSTURI : 134300 , ESTE BANAT : NU , ROLURI DETINUTE : { ID ROL : 0 | NUME ROL : Membru ID ROL : 2 | NUME ROL : Moderator ID ROL : 1 | NUME ROL : Utilizator Premium ID ROL : 3 | NUME ROL : Super Moderator } }COLECTIA DE FISIERE A FOST ELIBERATA CU SUCCES !! OBS 1 ** : PRIMELE 3 SUNT INSERATE (2->1->0) IAR ULTIMELE 3 (3->4->5) (VA ORIENTATI DUPA ID-URI) !! NOTA ** : DACA INTERVIN COMPLICATII , PM ME SAU REPLY !-
- generic list
- void pointer
-
(și 2 altele)
Setat cu taguri:
-
linked list [Structuri de Date - C] Inserare in Liste Inlantuite (Partea 1)
NOT a MERCEDES a postat un topic în Windows
** Obiective ** Construim o structura de Utilizatori LGCS cu campuri precum : ID , Nume , Adresa de Mail , Parola , NrPosturi , isBanned dar si rolurile din care face parte ; Constituim o lista inlantuita (generica) cu toate componentele acestuia (POINTER DE REFERINTA SI INFORMATIE) Inseram date dintr-un fisier text (pe care l voi pune in atasament) . Completam lista cu toate datele din fisier ; Afisam & Eliberam Toata Lista . NOTA ** : Vom folosi proiectul din tutorialele trecute de Structuri . (Cu Roluri) ** Declarare Structura Utilizatori LGCS ** // User.h typedef struct User { // INFORMATIE UTILIZATOR unsigned id; // ID UTILIZATOR char* username; // NUME UTILIZATOR char* email; // ADRESA MAIL UTILIZATOR char* password; // PAROLA UTILIZATOR unsigned nrPosts; // NUMAR POSTURI unsigned isBanned; // NU AVEM VALOARE BOOLEANA IN C (bool) ==> "1" E TRUE && "0" E FALSE Role* roles; // Colectie de grupuri din care face parte utilizatorul }User; ** Declarare Lista Inlantuita ** // Lists.h ----> FISIER NOU typedef struct Linked_List{ // LISTA INLANTUITA GENERICA (O PUTEM FOLOSI CU ORICE TIP DE DATE FARA SA DECLARAM MAI MULTE STRUCTURI) void* Data; // Pastram informatia pentru elementul curent Linked_List* nextElement; // Ne corelam cu urmatorul element }LinkedList; // Asta reprezinta o eticheta pentru structura ==> Scriem "LinkedList" inloc de "struct Linked_List" NOTA ** : "void*" REPREZINTA un caz particular in C , o modalitatea de a substitui mai multe tipuri de date pentru a EVITA declararea Listei pentru fiecare tip de date . De exemplu , daca doresc ca lista sa fie folosita apoi , pentru structura "studenti" sau "masini" sau altceva , o putem refolosi fara sa facem lista pentru fiecare tip de structura . (tip de date) ** Preluare Utilizator din Fisier ** Declaram o functie pentru incarcarea datelor din fisier in vederea initializarii structuri : // User.h /// Structura & Restu Codului #include "roles.h" // Avem nevoie pentru tipul de date Role #define FILENAME_USER_INPUT "dateIntrareUtilizatoriLeagueCS.txt" // Definim un nume pentru intrare User* fetchUsersFromTxtFile(FILE* inputTxt,Role* roles); // Incarcam o colectie de utilizatori din fisier Ne asiguram ca putem stoca suficient spatiu pentru fiecare linie : // stringHandling.h // Restu Codului #define MAX_STRING_LINE 256 // Alocam maxim 256 de caractere pentru linii Trecem la implementarea codului pentru incarcarea utilizatorului din fisier !! // user.c #include "User.h" // legam cu fisierul asociat acestuia (de unde vin declaratiile) User* fetchUsersFromTxtFile(FILE* inputTxt, Role* roles) // Implementam functia de inserare a datelor { // Implementare } Verificam daca fisierul este eligibil pentru inserare : // user.c User* fetchUsersFromTxtFile(FILE* inputTxt, Role* roles) // Implementam functia de inserare a datelor { if (!checkFile(inputTxt)) return NULL; // Fisier Invalid + Returnam o valoare NULA Colectiei } Daca totul e ok , declaram o colectie de utilizatori dar si un contor pentru indexare : // user.c User* fetchUsersFromTxtFile(FILE* inputTxt, Role* roles) // Implementam functia de inserare a datelor { if (!checkFile(inputTxt)) return NULL; // Fisier Invalid + Returnam o valoare NULA Colectiei unsigned i = 1; // Pentru accesarea elementelor curente va fi (i-1) User* newUser = (User*)malloc(sizeof(User)); // Alocam pentru un utilizator (MOMENTAN) } Adaugam o colectie de caractere , ca intermediar , pentru preluare a linie cu linie din fisier : // user.c User* fetchUsersFromTxtFile(FILE* inputTxt, Role* roles) // Implementam functia de inserare a datelor { if (!checkFile(inputTxt)) return NULL; // Fisier Invalid + Returnam o valoare NULA Colectiei unsigned i = 1; // Pentru accesarea elementelor curente va fi (i-1) User* newUser = (User*)malloc(sizeof(User)); // Alocam pentru un utilizator (MOMENTAN) char bufferLine[MAX_STRING_LINE]; // Cu spatiu alocat explicit mai sus } Citim linie cu linie din fisier cu "fgets" (pana la finalul fisierului) iar continutul (toata linia) o oferim colectiei declarate mai sus : // user.c User* fetchUsersFromTxtFile(FILE* inputTxt, Role* roles) // Implementam functia de inserare a datelor { if (!checkFile(inputTxt)) return NULL; // Fisier Invalid + Returnam o valoare NULA Colectiei unsigned i = 1; // Pentru accesarea elementelor curente va fi (i-1) User* newUser = (User*)malloc(sizeof(User)); // Alocam pentru un utilizator (MOMENTAN) char bufferLine[MAX_STRING_LINE]; // Cu spatiu alocat explicit mai sus while ((fgets(bufferLine, MAX_STRING_LINE, inputTxt)) != NULL) // Citim Linie cu Linie din Fisier { // Implementare } } Citim si inseram in colectia de Utilizatori , informatiile despre ID , NUME , EMAIL , PAROLA , NUMAR POSTURI SI DACA E BANAT : // user.c User* fetchUsersFromTxtFile(FILE* inputTxt, Role* roles) // Implementam functia de inserare a datelor { if (!checkFile(inputTxt)) return NULL; // Fisier Invalid + Returnam o valoare NULA Colectiei unsigned i = 1; // Pentru accesarea elementelor curente va fi (i-1) User* newUser = (User*)malloc(sizeof(User)); // Alocam pentru un utilizator (MOMENTAN) char bufferLine[MAX_STRING_LINE]; // Cu spatiu alocat explicit mai sus while ((fgets(bufferLine, MAX_STRING_LINE, inputTxt)) != NULL) // Citim Linie cu Linie din Fisier { char*Token, *nextToken; // Prima va retine informatia curenta iar cealalta referinta la cea mai ramas din linie // Inseram Date /// ID Token = strtok_s(bufferLine,DELIMITATER,&nextToken); // Preluam ID-ul din linie in format de STRING newUser[i-1].id = atoi(Token); // Convertim din string in intreg + Il Incarcam in Structura // NUME Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam NUMELE din linie in format de STRING allocAndFetchString(&newUser[i-1].username,Token); // Il Incarcam in Structura // Adresa de Mail Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam EMAIL din linie in format de STRING allocAndFetchString(&newUser[i-1].email, Token); // Il Incarcam in Structura // Parola Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam EMAIL din linie in format de STRING allocAndFetchString(&newUser[i-1].password, Token); // Il Incarcam in Structura // NrPosts Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam NUMARUL DE POSTURI DIN STRUCTURA newUser[i-1].nrPosts = atoi(Token); // CONVERTIM DIN STRING IN INTREG SI IL INCARCAM // e Banat Token = strtok_s(NULL, DELIMITATER, &nextToken); // IDEM newUser[i-1].isBanned = atoi(Token); } } Acum , traversam toate rolurile inserate din tutorialul anterior iar apoi le vom asocia cu id-urile rolurilor din care face parte utilizatorul curent : // user.c User* fetchUsersFromTxtFile(FILE* inputTxt, Role* roles) // Implementam functia de inserare a datelor { if (!checkFile(inputTxt)) return NULL; // Fisier Invalid + Returnam o valoare NULA Colectiei unsigned i = 1; // Pentru accesarea elementelor curente va fi (i-1) User* newUser = (User*)malloc(sizeof(User)); // Alocam pentru un utilizator (MOMENTAN) char bufferLine[MAX_STRING_LINE]; // Cu spatiu alocat explicit mai sus while ((fgets(bufferLine, MAX_STRING_LINE, inputTxt)) != NULL) // Citim Linie cu Linie din Fisier { char*Token, *nextToken; // Prima va retine informatia curenta iar cealalta referinta la cea mai ramas din linie // Inseram Date /// ID Token = strtok_s(bufferLine,DELIMITATER,&nextToken); // Preluam ID-ul din linie in format de STRING newUser[i-1].id = atoi(Token); // Convertim din string in intreg + Il Incarcam in Structura // NUME Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam NUMELE din linie in format de STRING allocAndFetchString(&newUser[i-1].username,Token); // Il Incarcam in Structura // Adresa de Mail Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam EMAIL din linie in format de STRING allocAndFetchString(&newUser[i-1].email, Token); // Il Incarcam in Structura // Parola Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam EMAIL din linie in format de STRING allocAndFetchString(&newUser[i-1].password, Token); // Il Incarcam in Structura // NrPosts Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam NUMARUL DE POSTURI DIN STRUCTURA newUser[i-1].nrPosts = atoi(Token); // CONVERTIM DIN STRING IN INTREG SI IL INCARCAM // e Banat Token = strtok_s(NULL, DELIMITATER, &nextToken); // IDEM newUser[i-1].isBanned = atoi(Token); // Grupurile din care face parte unsigned j = 1; // (Accesul la itemul curent se va face la (j-1)) while ((Token = strtok_s(NULL, DELIMITATER, &nextToken)) != NULL) // Preluam ID cu ID { unsigned targetIdRole, k = 0; targetIdRole = atoi(Token); // Convertim ID-ul din string in intreg do { if (targetIdRole == roles[k].id) // DACA AM REGASIT ID-UL IN COLECTIE DE ROLURI { newUser[i-1].roles = j == 1 ? (Role*)malloc(sizeof(Role)) // DACA SUNTEM LA PRIMA ITERATIE : (Role*)realloc(newUser[i-1].roles, sizeof(Role) * j); // DACA SUNTEM LA J ITERATIE // Preluam Referintele (ODATA ELIBERATE ROLURILE SI ELE ISI VOR PIERDE INFORMATIA ) newUser[i-1].roles[j-1].id = roles[k].id; newUser[i-1].roles[j-1].nameRole = roles[k].nameRole; newUser[i-1].roles[j-1].isLastRole = 0; // NU ESTE ULTIMUL ELEMENT DIN LISTA break; // NU ARE ROST SA PARCURGEM TOATA STRUCTURA } k++; // Incrementam cu un pas } while(!roles[k-1].isLastRole); // Parcurgem toate rolurile PANA AJUNGEM LA ULTIMUL j++; // Marim colectia cu un element } newUser[i-1].roles[j-2].isLastRole = 1; // ESTE ULTIMUL ELEMENT DIN LISTA } } Verificam daca mai avem continut in fisier . Daca da , vom realoca un nou utilizatori (in functie de cati utilizatori sunt introdusi in fisier) . Daca nu , se opreste iteratia si se returneaza ce am adaugat : // user.c User* fetchUsersFromTxtFile(FILE* inputTxt, Role* roles) // Implementam functia de inserare a datelor { if (!checkFile(inputTxt)) return NULL; // Fisier Invalid + Returnam o valoare NULA Colectiei unsigned i = 1; // Pentru accesarea elementelor curente va fi (i-1) User* newUser = (User*)malloc(sizeof(User)); // Alocam pentru un utilizator (MOMENTAN) char bufferLine[MAX_STRING_LINE]; // Cu spatiu alocat explicit mai sus while ((fgets(bufferLine, MAX_STRING_LINE, inputTxt)) != NULL) // Citim Linie cu Linie din Fisier { char*Token, *nextToken; // Prima va retine informatia curenta iar cealalta referinta la cea mai ramas din linie // Inseram Date /// ID Token = strtok_s(bufferLine,DELIMITATER,&nextToken); // Preluam ID-ul din linie in format de STRING newUser[i-1].id = atoi(Token); // Convertim din string in intreg + Il Incarcam in Structura // NUME Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam NUMELE din linie in format de STRING allocAndFetchString(&newUser[i-1].username,Token); // Il Incarcam in Structura // Adresa de Mail Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam EMAIL din linie in format de STRING allocAndFetchString(&newUser[i-1].email, Token); // Il Incarcam in Structura // Parola Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam EMAIL din linie in format de STRING allocAndFetchString(&newUser[i-1].password, Token); // Il Incarcam in Structura // NrPosts Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam NUMARUL DE POSTURI DIN STRUCTURA newUser[i-1].nrPosts = atoi(Token); // CONVERTIM DIN STRING IN INTREG SI IL INCARCAM // e Banat Token = strtok_s(NULL, DELIMITATER, &nextToken); // IDEM newUser[i-1].isBanned = atoi(Token); // Grupurile din care face parte unsigned j = 1; // (Accesul la itemul curent se va face la (j-1)) while ((Token = strtok_s(NULL, DELIMITATER, &nextToken)) != NULL) // Preluam ID cu ID { unsigned targetIdRole, k = 0; targetIdRole = atoi(Token); // Convertim ID-ul din string in intreg do { if (targetIdRole == roles[k].id) // DACA AM REGASIT ID-UL IN COLECTIE DE ROLURI { newUser[i-1].roles = j == 1 ? (Role*)malloc(sizeof(Role)) // DACA SUNTEM LA PRIMA ITERATIE : (Role*)realloc(newUser[i-1].roles, sizeof(Role) * j); // DACA SUNTEM LA J ITERATIE // Preluam Referintele (ODATA ELIBERATE ROLURILE SI ELE ISI VOR PIERDE INFORMATIA ) newUser[i-1].roles[j-1].id = roles[k].id; newUser[i-1].roles[j-1].nameRole = roles[k].nameRole; newUser[i-1].roles[j-1].isLastRole = 0; // NU ESTE ULTIMUL ELEMENT DIN LISTA break; // NU ARE ROST SA PARCURGEM TOATA STRUCTURA } k++; // Incrementam cu un pas } while(!roles[k-1].isLastRole); // Parcurgem toate rolurile PANA AJUNGEM LA ULTIMUL j++; // Marim colectia cu un element } newUser[i-1].roles[j-2].isLastRole = 1; // ESTE ULTIMUL ELEMENT DIN LISTA if (!feof(inputTxt)) // Daca mai sunt date in fisier newUser = realloc(newUser, sizeof(User) * (++i)); // Mai alocam un utilizator } return newUser; // Returnam colectia } IN TUTORIALUL ACESTA NU VOI INTRODUCE IN LISTE , UTILIZATORI DAR VOM AFISA CONTINUTUL SI LE VOM STERGE (SUB FORMA DE ARRAY) (ASA CA BONUS ) Declaram functiile de afisare si stergere : // User.h // Restu codului void printUser(User user); void freeUser(User user); Le implementam : /// User.c // Restu Codului void printUser(User user) { static unsigned i = 0; // Retinem i pe toate apelurile printf_s("User %d : { \n",i); printf_s("\tID UTILIZATOR: %d ,\n",user.id); printf_s("\tNUME UTILIZATOR: %s ,\n",user.username); printf_s("\tADRESA MAIL UTILIZATOR: %s ,\n",user.email); printf_s("\tPAROLA : %s ,\n",user.password); printf_s("\tNUMAR POSTURI : %d ,\n", user.nrPosts); printf_s("\tESTE BANAT : %s ,\n", user.isBanned ? "DA" : "NU"); printf_s("\t\tROLURI DETINUTE : {\n"); unsigned j = 0; do { printf_s("\n\tID ROL : %d | NUME ROL :%s",user.roles[j].id,user.roles[j].nameRole); j++; } while(!user.roles[j-1].isLastRole); printf_s("\n}\n}"); i++; } void freeUser(User user) { //Stergem sirurile de caractere free(user.username); free(user.email); free(user.password); // ROLURILE VOR FI STERSE SEPARATE in functia freeRoles() } Acum , afisam in functia principala utilizatorii iar pe urma , ii stergem : // entryPoint.c /* Legam toate entry point toate headerele dependente */ #include "../StructuriDate/roles.h" #include "../StructuriDate/fileHandling.h" #include "../StructuriDate/User.h" #include "../StructuriDate//Lists.h" // stringHandling.h nu este dependent de entry point // // CONSTANTELE MACRO SUNT UTILE CA LE PUTEM UTILIZA LA NIVEL GLOBAL (PE TOT FISIERUL) // NOTA** : E O PRACTICA BUNA DE A FOLOSI MACRO SPRE DEOSEBIRE DE CONSTANTE "MAGICE" (NUMERE PRIN COD) #define NR_FILES 2 // STABILIM UN NUMAR DE FISIERE int main() { FILE** file = NULL; file = (FILE**)malloc(sizeof(FILE*)*NR_FILES); // DECLARAM O COLECTIE DE FISIERE file[0] = openFile(FILENAME_INPUT_ROLES, READMODE_TXT); // CITIM ROLURILE DINTR-UN FISIER TEXT file[1] = openFile(FILENAME_USER_INPUT, READMODE_TXT); // CITIM UTILIZATORI DINTR-UN FISIER TEXT // dateIntrareLeagueCS.txt && dateIntrareRoluriLeagueCS.txt TREBUIE SA EXISTE IN DIRECTOR (ALTFEL VA ESUA) Role* roles = fetchRoles(file[0]); // Am primit lista cu rolurile User* users = fetchUsersFromTxtFile(file[1],roles); // Am primit informatia despre utilizatori for (int i = 0; i < 6; i++) { // CUNOASTEM CA SUNT SASE ENTITATI printUser(users[i]); // Accesul prin index (Array) --> AFISAM UTILIZATORUL CURENT freeUser(users[i]); // STERGEM UTILIZATORUL CURENT } // ELIBERAM RESURSELE freeRoles(&roles); // Eliberam resursele ocupate de entitate free(users); // Stergem colectia closeFiles(&file,NR_FILES); // Eliberam resursele ocupate de fisiere if (file == NULL) printf("COLECTIA DE FISIERE A FOST ELIBERATA CU SUCCES !! "); return 0; } Si primim ca output : **FISIERUL dateIntrareRoluriLeagueCS.txt S-A DESCHIS CU SUCCES !** **FISIERUL dateIntrareUtilizatoriLeagueCS.txt S-A DESCHIS CU SUCCES !** User 0 : { ID UTILIZATOR: 0 , NUME UTILIZATOR: Alin , ADRESA MAIL UTILIZATOR: alidsadan@gmail.com , PAROLA : dsdasdadsadadc , NUMAR POSTURI : 100 , ESTE BANAT : NU , ROLURI DETINUTE : { ID ROL : 0 | NUME ROL : Membru ID ROL : 3 | NUME ROL : Super Moderator ID ROL : 4 | NUME ROL : Administrator ID ROL : 1 | NUME ROL : Utilizator Premium } }User 1 : { ID UTILIZATOR: 1 , NUME UTILIZATOR: Alinds , ADRESA MAIL UTILIZATOR: alidasdsan@gmail.com , PAROLA : dsavvcvdc , NUMAR POSTURI : 50 , ESTE BANAT : NU , ROLURI DETINUTE : { ID ROL : 0 | NUME ROL : Membru ID ROL : 1 | NUME ROL : Utilizator Premium } }User 2 : { ID UTILIZATOR: 2 , NUME UTILIZATOR: Alivcxvxcn , ADRESA MAIL UTILIZATOR: alidsadvfcn@gmail.com , PAROLA : dsewqqewqadc , NUMAR POSTURI : 550 , ESTE BANAT : NU , ROLURI DETINUTE : { ID ROL : 3 | NUME ROL : Super Moderator ID ROL : 1 | NUME ROL : Utilizator Premium } }User 3 : { ID UTILIZATOR: 3 , NUME UTILIZATOR: Alifdsfn , ADRESA MAIL UTILIZATOR: alewewin@gmail.com , PAROLA : dsfdsfsdfsadc , NUMAR POSTURI : 3300 , ESTE BANAT : NU , ROLURI DETINUTE : { ID ROL : 0 | NUME ROL : Membru ID ROL : 1 | NUME ROL : Utilizator Premium ID ROL : 2 | NUME ROL : Moderator ID ROL : 3 | NUME ROL : Super Moderator ID ROL : 4 | NUME ROL : Administrator } }User 4 : { ID UTILIZATOR: 4 , NUME UTILIZATOR: Alie2qweqn , ADRESA MAIL UTILIZATOR: alcxsaxcadsain@gmail.com , PAROLA : dsvcvvvvadc , NUMAR POSTURI : 11100 , ESTE BANAT : NU , ROLURI DETINUTE : { ID ROL : 0 | NUME ROL : Membru } }User 5 : { ID UTILIZATOR: 5 , NUME UTILIZATOR: Alidasdadan , ADRESA MAIL UTILIZATOR: alidasdassdadn@gmail.com , PAROLA : dsvvvvvvvvradc , NUMAR POSTURI : 134300 , ESTE BANAT : NU , ROLURI DETINUTE : { ID ROL : 0 | NUME ROL : Membru ID ROL : 2 | NUME ROL : Moderator ID ROL : 1 | NUME ROL : Utilizator Premium ID ROL : 3 | NUME ROL : Super Moderator } }COLECTIA DE FISIERE A FOST ELIBERATA CU SUCCES !! NOTA ** : PENTRU A FUNCTIONA ALGORITMUL , SE POT ADAUGA UTILIZATORI LA DISCRETIA VOASTRA DOAR SA PASTREZE MODELUL : id | nume | email | parola | nrPosturi | banat(1/0) | (AICI SE ADAUGA ID-URILE ROLURILOR DIN CARE FACE PARTE DESPARTITE DE "|") ==> LINIE .... .... ... AVETI SABLONUL IN ATASAMENT dateIntrareUtilizatoriLeagueCS.txt-
- file handling
- c
-
(și 3 altele)
Setat cu taguri:
-
linked list [Structuri de Date - C] Introducere in Liste Inlantuite
NOT a MERCEDES a postat un topic în Windows
** Obiectiv ** Prezentare Generala A Listelor (ca structura de date) ; Afisare , printr-o diagrama , conexiunea dintre elementele listei ; Prezentare Avantaje si Dezavantaje spre deosebire de tablourile de dimensiune (arrays) . ** Listele ** Listele Inlantuite sunt structuri de date complexe , care pot inregistra , citi , modifica sau sterge anumite informatii , pe mai multe segmente(elemente) , referitor la un obiect . De exemplu , pe o lista putem stoca informatii pentru fiecare utilizator al structurii create . Mai mult , FIECARE SEGMENT ESTE LEGAT DE VECINII LUI (In functie de tipul de lista) . De regula , fiecare segment este alcatuit din doua lucruri : INFORMATIE (De exemplu , numele de utilizator , adresa de mail , parole , id etc.) POINTERUL CU REFERINTA SPRE URMATORUL ELEMENT (ELEMENTUL DE LEGATURA CU URMATORUL) ** Avantaje && Dezavantaje ** Pare a fi o structura similara cu tablourile de dimensiune (arrays) dar exista DIFERENTE : Din punct de vedere al memoriei alocate , pentru fiecare element al listei se cere o alocare atat elementului in sine cat si informatiei stocate (daca avem siruri de caractere sau colectii) spre deosebire de "arrays" , unde alocam doar tabloul in sine . (in functie de numarul de elemente * la spatiul ocupat de fiecare element) . Pe de alta parte , in liste alocam DOAR ELEMENTELE pe care le folosim spre deosebire de tablouri , unde trebuie sa aloci toate elementele , INDIFERENT DACA LE FOLOSESTI SAU NU !! . Din punct de vedere al operatiunilor de stergere & inserare , listele prezinta o eficacitate detasata . Din punct de vedere al accesul elementelor , "arrays-urile" ne permit accesul aleatoriu la un element spre deosebire de liste , unde trebuie sa parcurgem element cu element . (secvential ) PE SCURT , RECOMAND SA FOLOSIM LISTE CAND NU DORIM SA RISIPIM MEMORIE SI DORIM SA MANIPULAM DATE (INSERTII , STERGERI , MODIFICARI) . Pe de alta parte , daca dorim sa accesam mai repede anumite elemente , alegem tablourile . NOTA ** : In tutorialul urmator , vom incepe sa efectuam operatiuni cu liste inlantuite !! -
** OBIECTIV ** Prin aceasta postare , dorim sa explicam si sa implementam , folosind codul de POO , conceptul de COPIERE(CLONARE) SUPERFICIALA (aka "Shallow Copy") a unui obiect !! ** Clonarea Unui Obiect ** CLONAREA/COPIEREA UNUI OBIECT reprezinta procedeul de COPIERE a informatiei (membrii clasei) dintr-un obiect (instanta) EXISTENT intr-un obiect NOU (REPLICA) . Acum , ne intrebam de ce sa clonam un obiect , in ce circumstante avem nevoie de acest concept , cu ce ne ajuta ? Pe scurt , ne sprijina prin comoditate . Ne furnizeaza o copie a unui obiect fara sa afectam obiectul original ("COPII DEFENSIVE") . Clonarea unui Obiect se poate efectua , valabil in toate limbajele de programare POO (Java,Python,JavaScript,C# etc.) , sub forma de copie : "Superficiala" sau "Shallow Copy" , se initiaza membrii clasei din obiectul clona , cu REFERINTELE din obiectul original . Pe scurt , orice modificare care survine asupra obiectului clona , VA AFECTA si OBIECTUL ORIGINAL !! (SUNT DEPENDENTE UNA DE CEALALTA) "Adanca" sau "Deep Copy" , se initiaza membrii clasei din obiectul clona , cu VALORILE din obiectul original FARA SA FIE DEPENDENTE UNA DE CEALALTA . Pe scurt , orice modificare a obiectului clona , NU VA AFECTA OBIECTUL ORIGINAL !! (SUNT INDEPENDENTE UNA DE CEALALTA) ** Constructor de Copiere ** Constructorul de copiere reprezinta al treilea tip de constructori , pe langa cel cu parametrii si implicit , si modalitatea de construire a clonelor . Aici se initializeaza membrii obiectului clona cu referintele/valorile membriilor clasei . // CONSTRUCTOR DE COPIERE -- FORMAT constructor_copiere(const NUME_CLASA& obiect_original) // Primim ca parametru , REFERINTA OBIECTULUI ORIGINAL { // AICI SE EFECTUEAZA CLONAREA OBIECTULUI ORIGINAL } NOTA** : DE ASEMENEA , IN CONSTRUCTORUL DE COPIERE PUTEM FOLOSI LISTA DE INITIALIZARE A MEMBRIILOR !!! ** IMPLEMENTARE CLONA SUPERFICIALA ** Adaugam un constructor de copiere , in cadrul clasei "Utilizator" : // user.h class User{ /// RESTU CODULUI User(const User& otherUser); // PREIA REFERINTA OBIECTULUI ORIGINAL (DECLARARE CONSTRUCTOR DE COPIERE) }; + Implementare : // User.cpp User::User(const User& originalObject) // CONSTRUCTOR DE COPIERE (COPIERE SUPERFICIALA ) : id{ originalObject.id }, nrPosts{ originalObject.nrPosts }, isBanned{originalObject.isBanned}, username{ originalObject.username }, email{ originalObject.email }, password{originalObject.password}, stringHandling{originalObject.stringHandling} { //**** OBIECTE ISI IMPART REFERINTELE (POINTERI ISI IMPART REFERINTELE) /* OBIECT ORIGINAL OBIECT CLONA username 0xda34133 --> username 0xda34133 (ISI IMPART ACEEASI ZONA DE MEMORIE) "IONEL" "IONEL" (AUTOMAT , ACEEEASI VALOARE) ==> DACA NUMELE DE UTILIZATOR(EMAIL,STRINGHANDLER,PASSWORD) SE SCHIMBA IN OBIECTUL CLONA , ATUNCI VOR APAREA MODIFICARI SI IN CEL ORIGINAL */ } In programul principal , vom initializa patru obiecte cu tipuri diferite de constructori (cu parametrii , implicit si 2 de copiere) si le vom afisa : // entrypoint.cpp #include "User.h" // Includem Clasa de Utilizatori int main() { User *user3, *user4; { User user1, user2("Vasile", "vasile@gmail.com", "vasileparola"); // Declaram doua instante (una cu constructoru implicit + constructor cu parametrii ) user1.setUsername("IONEL"); // PRODUCEM 2 CLONE user3 = new User(user1); // Clonam Obiectul 1 user4 = new User(user2); // Clonam Obiectul 2 // VIZUALIZAM OBIECTELE ATUNCI CAND OBIECTELE ORIGINALE SUNT IN CONTEXT user1.objectToString(); user2.objectToString(); std::cout << " AFISAM CLONE IN INTERIOURUL CONTEXTULUI : \n"; user3->objectToString(); // Clona Utilizatorului 1 user4->objectToString(); // Clona Utilizatorului 2 std::cout << std::endl; // DINSTANTIEM CU O LINIE CELE DOUA VIZUALIZARI } // AFISAM CLONELE ATUNCI CAND OBIECTELE ORIGINALE AU IESIT DIN CONTEXT (S-A APELAT DESTRUCTORUL) std::cout << " AFISAM CLONE IN AFARA CONTEXTULUI (CAND OBIECTUL ORIGINAL A IESIT DIN CONTEXT) : \n"; user3->objectToString(); // Clona Utilizatorului 1 user4->objectToString(); // Clona Utilizatorului 2 return 0; } Si primim ca rezultat : { ID Utilizator : 0 , Nume Utilizator : IONEL , Adresa Mail : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Parola Utilizator : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } { ID Utilizator : 1 , Nume Utilizator : Vasile , Adresa Mail : vasile@gmail.com , Parola Utilizator : vasileparola , Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } AFISAM CLONE IN INTERIOURUL CONTEXTULUI : { ID Utilizator : 0 , Nume Utilizator : IONEL , Adresa Mail : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Parola Utilizator : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } { ID Utilizator : 1 , Nume Utilizator : Vasile , Adresa Mail : vasile@gmail.com , Parola Utilizator : vasileparola , Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } AFISAM CLONE IN AFARA CONTEXTULUI (CAND OBIECTUL ORIGINAL A IESIT DIN CONTEXT) : { ID Utilizator : 0 , Nume Utilizator : ŢŢŢŢŢŢŢŢŢŢ , // ZONA INVALIDA DE MEMORIE Adresa Mail : ŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢ , // ZONA INVALIDA DE MEMORIE Parola Utilizator : ŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢ , // ZONA INVALIDA DE MEMORIE Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } { ID Utilizator : 1 , Nume Utilizator : ŢŢŢŢŢŢŢŢŢŢŢ , // ZONA INVALIDA DE MEMORIE Adresa Mail : ŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢ , // ZONA INVALIDA DE MEMORIE Parola Utilizator : ŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢ , // ZONA INVALIDA DE MEMORIE Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } NOTA* : TOTUSI , EXISTA O PROBLEMA CU ACEST PROCEDEU DE CONSTRUCTIE A CLONEI . De ce ? Daca se impart aceleasi zone de memorie , riscam sa accesam adrese invalide , astfel daca apelam destructorul pentru obiectele clone : // entryPoint.cpp int main() { // Restu Codului delete user3, user4; // AICI VOM PRIMI EROARE PENTRU CA ELIBERAM ZONE INEXISTENTE DE MEMORIE } DIN ACEASTA CAUZA , SE PREFERA CELALALT TIP DE CONSTRUCTIE , PE CARE L VOM DISCUTA IN TUTORIALUL URMATOR !!
-
** OBIECTIV ** Prin aceasta postare , dorim sa explicam si sa implementam , folosind codul de POO , conceptul de COPIERE(CLONARE) ADANCITA (aka "Deep Copy") a unui obiect !! Clonarea , din aceasta perspectiva , se va efectua FARA a creea dependente intre obiecte . In sensul ca , va prelua valorile din obiectele originale DAR se vor construi NOI zone de memorie !!! ** IMPLEMENTARE CLONA ADANCITA ** Adaugam un constructor de copiere , in cadrul clasei "Utilizator" (SIMILAR CU CEL SUPERFICIAL , LA DECLARATIE) : // user.h class User{ /// RESTU CODULUI User(const User& otherUser); // PREIA REFERINTA OBIECTULUI ORIGINAL (DECLARARE CONSTRUCTOR DE COPIERE) }; + Implementare : // User.cpp User::User(const User& originalObject) // CONSTRUCTOR DE COPIERE (COPIERE ADANCITA) : id{ originalObject.id }, nrPosts{ originalObject.nrPosts }, isBanned{originalObject.isBanned}, stringHandling{new StringLGCS(originalObject.username)} { //**** POINTERI ISI IMPART VALORILE , NU REFERINTELE /* OBIECT ORIGINAL OBIECT CLONA username 0xda34133 --> username 0xdc999 (ZONE SEPARATE DE MEMORIE ) "IONEL" "IONEL" (VALORI SIMILARE) */ StringLGCS::allocAndFetchString(&this->username, stringHandling->getString()); // Setam Numele de Utilizator stringHandling->setString(originalObject.email); // Schimbam sirul cu urmatoarea informatie StringLGCS::allocAndFetchString(&this->email, stringHandling->getString()); // Setam Adresa De Mail stringHandling->setString(originalObject.password); StringLGCS::allocAndFetchString(&this->password, stringHandling->getString()); // Setam Parola } In programul principal , vom initializa patru obiecte cu tipuri diferite de constructori (cu parametrii , implicit si 2 de copiere) si le vom afisa : // entryPoint.cpp #include "User.h" // Includem Clasa de Utilizatori int main() { User *user3, *user4; { User user1, user2("Vasile", "vasile@gmail.com", "vasileparola"); // Declaram doua instante (una cu constructoru implicit + constructor cu parametrii ) user1.setUsername("IONEL"); // PRODUCEM 2 CLONE user3 = new User(user1); // Clonam Obiectul 1 user4 = new User(user2); // Clonam Obiectul 2 // VIZUALIZAM OBIECTELE ATUNCI CAND OBIECTELE ORIGINALE SUNT IN CONTEXT user1.objectToString(); user2.objectToString(); std::cout << " AFISAM CLONE IN INTERIOURUL CONTEXTULUI : \n"; user3->objectToString(); // Clona Utilizatorului 1 user4->objectToString(); // Clona Utilizatorului 2 std::cout << std::endl; // DINSTANTIEM CU O LINIE CELE DOUA VIZUALIZARI } // AFISAM CLONELE ATUNCI CAND OBIECTELE ORIGINALE AU IESIT DIN CONTEXT (S-A APELAT DESTRUCTORUL) std::cout << " AFISAM CLONE IN AFARA CONTEXTULUI (CAND OBIECTUL ORIGINAL A IESIT DIN CONTEXT) : \n"; user3->objectToString(); // Clona Utilizatorului 1 user4->objectToString(); // Clona Utilizatorului 2 delete user3, user4; // TOTUL ESTE OK , SUNT ZONE SEPARATE DE MEMORIE return 0; } Si primim ca rezultat : { ID Utilizator : 0 , Nume Utilizator : IONEL , Adresa Mail : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Parola Utilizator : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } { ID Utilizator : 1 , Nume Utilizator : Vasile , Adresa Mail : vasile@gmail.com , Parola Utilizator : vasileparola , Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } AFISAM CLONE IN INTERIOURUL CONTEXTULUI : { ID Utilizator : 0 , Nume Utilizator : IONEL , Adresa Mail : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Parola Utilizator : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } { ID Utilizator : 1 , Nume Utilizator : Vasile , Adresa Mail : vasile@gmail.com , Parola Utilizator : vasileparola , Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } AFISAM CLONE IN AFARA CONTEXTULUI (CAND OBIECTUL ORIGINAL A IESIT DIN CONTEXT) : { ID Utilizator : 0 , Nume Utilizator : IONEL , Adresa Mail : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Parola Utilizator : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } { ID Utilizator : 1 , Nume Utilizator : Vasile , Adresa Mail : vasile@gmail.com , Parola Utilizator : vasileparola , Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } NOTA * : IN CONCLUZIE , in aceasta abordare , spre deosebire de cealalta ("superficiala") , sunt construite zone de memorie NOI (DOAR VALOAREA ESTE PRELUATA DIN OBIECTELE ORIGINALE) ASTFEL DEVENIND OBIECTE INDEPENDENTE UNA DE CEALALTA , IN CIUDA CA SI IMPART ACELEASI VALORI !! TOTODATA , VOI RECOMANDA ACEASTA MODALITATE PENTRU EVITAREA ERORILOR !!
-
Multumesc pentru feedback si sutinere . Pe zi ce trece , imi dau silinta sa aduc tutoriale la standarde cat mai bune dar si interpretabile pentru persoanele care sunt la inceput sau progreseaza . Toate bune !
- 2 răspunsuri
-
- lista constructor membrii
- constante
-
(și 2 altele)
Setat cu taguri:
-
** Obiectiv ** In tutorialul acesta , vom prezenta o alternativa , mult mai corecta , pentru initializarea membriilor unei clase , in semnatura constructorului . NOTA ** : Codul va fi preluat din proiectul de la tutorialele trecute de POO . (Cu mici modificari evidentiate ) ** Model ** constructor(x,y,z,...,c) : m_x{x},m_y{y},m_z{z},......,m_c{c} { // Continut Constructor } // m_x --> membru al clasei && x = parametru(variabila cu stocare locala) ** Initializarea variabilelor & Pointerilor ** // User.cpp //** Implementarea Constructorilor **// User::User() : id{ 0 }, nrPosts{ 0 }, isBanned{ false } , stringHandling{ new StringLGCS()} // Lista Constructor Membrii de Initializat { // Constructor Fara Parametrii // Alocam si Initializam date cu informatii IMPLICITE (DEFAULT ) /// FUNCTIILE STATICE SE INVOCA FOLOSIND "::" !!! StringLGCS::allocAndFetchString(&this->username, stringHandling->getString()); StringLGCS::allocAndFetchString(&this->email, stringHandling->getString()); StringLGCS::allocAndFetchString(&this->password, stringHandling->getString()); } // Idem User::User(unsigned id, const char* username, const char* email, const char* password) : id{ id }, nrPosts{ 0 }, isBanned{ false },stringHandling{new StringLGCS(username)} // IDEM { StringLGCS::allocAndFetchString(&this->username, stringHandling->getString()); // Setam Numele de Utilizator stringHandling->setString(email); // Schimbam sirul cu urmatoarea informatie StringLGCS::allocAndFetchString(&this->email , stringHandling->getString()); // Setam Adresa De Mail stringHandling->setString(password); StringLGCS::allocAndFetchString(&this->password, stringHandling->getString()); // Setam Parola } NOTA 1 ** : ACEASTA ABORDARE SE APLICA DOAR CONSTRUCTORILOR , IN SEMNATURA ACESTORA ; NOTA 2** : IN CADRUL ACESTEIA , NU ESTE NECESAR DIFERENTIEREA DINTRE MEMBRII CLASEI (Declaratia din AFARA ACOLADEI) SI CEI LOCALI (Partea din ACOLADA) NOTA 3** : PUTEM APELA , DE ASEMENEA , FUNCTII IN INTERIORUL ACOLODELOR , CONDITIA E SA RETURNEZE TIPUL DE DATE CORESPONDENT MEMBRULUI . ** Initializare Constante & Valori Statice ** O utilitate foarte importanta a acestei forme de initializare , e faptul ca ne permite sa initializam CONSTANTE !!! Pe aceasta cale , ii vom atribui id-ului fiecarui utilizator , o valoare constanta si incrementat la fiecare instantiere printr-o variabila statica . // user.h class User{ const unsigned id; // COD UNIC DE IDENTIFICARE UTILIZATOR CONSTANT --> II APLICAM ID-UL UN ATRIBUT CONSTANT (EL NU SE SCHIMBA) static inline unsigned s_id; // VALOARE STATICA INTERMEDIARA --> ADAUGAM O VALOARE STATICA PENTRU A RETINE NUMARUL DE INSTANTIERI User(const char* username, const char* email, const char* password); // --> MODIFICAM CONSTRUCTORUL , NU AVEM NEVOIE DE PARAMETRUL ID !! // Restul de declaratii }; Noua Implementare a constructorilor : /// user.cpp //** Implementarea Constructorilor **// User::User() : id{s_id++}, nrPosts{ 0 }, isBanned{ false }, // lui id ii se atribuie valoarea lui s_id iar apoi s_id se incrementeaza cu o unitate stringHandling{ new StringLGCS()} // Lista Constructor Membrii de Initializat { // Constructor Fara Parametrii // Alocam si Initializam date cu informatii IMPLICITE (DEFAULT ) /// FUNCTIILE STATICE SE INVOCA FOLOSIND "::" !!! StringLGCS::allocAndFetchString(&this->username, stringHandling->getString()); StringLGCS::allocAndFetchString(&this->email, stringHandling->getString()); StringLGCS::allocAndFetchString(&this->password, stringHandling->getString()); } // Idem User::User(const char* username, const char* email, const char* password) : id{s_id++}, nrPosts{ 0 }, isBanned{ false }, stringHandling{new StringLGCS(username)} // IDEM { StringLGCS::allocAndFetchString(&this->username, stringHandling->getString()); // Setam Numele de Utilizator stringHandling->setString(email); // Schimbam sirul cu urmatoarea informatie StringLGCS::allocAndFetchString(&this->email , stringHandling->getString()); // Setam Adresa De Mail stringHandling->setString(password); StringLGCS::allocAndFetchString(&this->password, stringHandling->getString()); // Setam Parola } Revenim la functia principala , instantiem 5 obiecte de tip Utilizator si le afisam : #include "User.h" // Includem Clasa de Utilizatori int main() { User user1, user2("Vasile", "vasile@gmail.com", "vasileparola"), user3, user4, user5; // Declaram doua instante (una cu constructoru implicit + constructor cu parametrii ) // Vizualizam Instantele user1.setUsername("IONEL"); user5.setEmail("psadad@gmail.com"); user4.setPassword("psadxc"); user1.objectToString(); // Vizualizam Instanta 1 user2.objectToString(); // Vizualizam Instanta 2 user3.objectToString(); // Vizualizam Instanta 3 user4.objectToString(); // Vizualizam Instanta 4 user5.objectToString(); // Vizualizam Instanta 5 return 0; } Afisand Obiecte , vom avea urmatorul rezultat : { ID Utilizator : 0 , Nume Utilizator : IONEL , Adresa Mail : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Parola Utilizator : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } { ID Utilizator : 1 , Nume Utilizator : Vasile , Adresa Mail : vasile@gmail.com , Parola Utilizator : vasileparola , Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } { ID Utilizator : 2 , Nume Utilizator : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Adresa Mail : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Parola Utilizator : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } { ID Utilizator : 3 , Nume Utilizator : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Adresa Mail : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Parola Utilizator : psadxc , Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } { ID Utilizator : 4 , Nume Utilizator : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Adresa Mail : psadad@gmail.com , Parola Utilizator : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } CONCLUZIE : PENTRU FIECARA INSTANTA , NI SE GENEREAZA UN COD UNIC DIFERIT , IN FUNCTIE DE ORDINEA INITIALIZARII !!!
- 2 răspunsuri
-
- lista constructor membrii
- constante
-
(și 2 altele)
Setat cu taguri:
-
files handling [Structuri de Date - C] Fisiere & Articole (Partea 2)
NOT a MERCEDES a postat un topic în Windows
** Obiectiv ** Prin acest tutorial , dorim , pe baza proiectul actual , sa printam rezultatele atat intr-un fisier text (inteles de utilizator) cat si binar (inteles de catre calculator) . ** Implementare ** 1. In Contextul "fileHandling" , definim doua CONSTANTE (Pentru Scriere in Binar si in Fisier Text) si doua functii pentru validarea unui fisier dar si pentru eliberarea colectiilor de fisiere (+ inchiderea fiecarui fisier care face parte) // fileHandling.h #include "stdlib.h" // pentru malloc/free #define WRITEMODE_TXT "w" // CONSTANTA SCRIERE IN FISIERE TEXT (IN)EXISTENTE IN DIRECTOR #define WRITEMODE_BINARY "wb" // CONSTANTA SCRIERE IN FISIERE BINARE (IN)EXISTENTE IN DIRECTOR int checkFile(FILE* file); // validam fisierul void closeFiles(FILE*** files, const unsigned nrFiles); // Preluam prin adresa colectia de fisiere + numarul acestora // ++ RESTU DE FISIER Implementarea Acestora : // fileHandling.c // Restu de fisier int checkFile(FILE* file) { return file ? 1 : 0; // VERIFICAM DACA FISIERUL EXISTA IN MEMORIE } void closeFiles(FILE*** files,const unsigned nrFiles) // Eliberam colectia de fisiere { for (int i = 0; i < nrFiles; i++) fclose((*files)[i]); // Eliberam fiecare fisier // Eliberam colectia de fisiere free(*files); *files = NULL; } 2. In Contextul "roles" , declaram numele fisierelor pe care dorim sa le operam (scriere) dar si functiile de afisare in fisiere a rolurilor : // roles.h // ++ restu de fisier #include "fileHandling.h" #define FILENAME_OUTPUT_ROLES "dateIesireRoluriLeagueCS.txt" #define FILENAME_OUTPUT_ROLES_BINARY "dateIesireRoluriLeagueCS.bin" // Functiile pentru afisare void showRolesOnFile(Role* roles, FILE* rolesOuputText); void writeRolesOnBinaryData(Role* roles, FILE* rolesOutputBinary); Si Implementarile acestora : //roles.c // ++ Restu de fisier void showRolesOnFile(Role* roles, FILE* rolesOuputText) { // fprintf_s --> este functia care ne permite sa scriem in fisiere if (!checkFile(rolesOuputText) || roles == NULL) // Avem un fisier invalid return; // NU CONTINUAM //Daca e ok unsigned i = 0; fprintf_s(rolesOuputText," Colectia de Roluri : { \n"); do { // Parcurgem colectia de roluri fprintf_s(rolesOuputText,"ID ROL : %d \t NUME ROL : %s\n", roles[i].id, roles[i].nameRole); i++; } while (!roles[i - 1].isLastRole); fprintf_s(rolesOuputText," } \n\n"); } void writeRolesOnBinaryData(Role* roles, FILE* rolesOutputBinary) { if (!checkFile(rolesOutputBinary) || roles == NULL) // FACEM O VALIDARE ATAT FISIERULUI CAT SI STRUCTURII return; // NU CONTINUAM // Daca e ok , transcriem structura in fisier : // fwrite() --> este functia pentru scrierea entitatilor in binar // unsigned i = 0; do { // Parcurgem colectia de roluri fwrite(&roles[i].id,sizeof(int),1,rolesOutputBinary); // Trecem in binar id-ul fwrite(roles[i].nameRole,sizeof(char),strlen(roles[i].nameRole), rolesOutputBinary); // Trecem numele rolului in binar i++; } while (!roles[i - 1].isLastRole); } ** Rezultate ** In functia principala , vom initializa colectia cu fisierele asociate , vom afisa rolurile atat in consola cat si in fisierele binare/text . La final , le vom elibera din memorie /* Legam toate entry point toate headerele dependente */ #include "../StructuriDate/roles.h" #include "../StructuriDate/fileHandling.h" // stringHandling.h nu este dependent de entry point // // CONSTANTELE MACRO SUNT UTILE CA LE PUTEM UTILIZA LA NIVEL GLOBAL (PE TOT FISIERUL) // NOTA** : E O PRACTICA BUNA DE A FOLOSI MACRO SPRE DEOSEBIRE DE CONSTANTE "MAGICE" (NUMERE PRIN COD) #define NR_FILES 3 // STABILIM UN NUMAR DE FISIERE int main() { FILE** file = NULL; file = (FILE**)malloc(sizeof(FILE*)*NR_FILES); // DECLARAM O COLECTIE DE FISIERE file[0] = openFile(FILENAME_INPUT_ROLES, READMODE_TXT); // CITIM ROLURILE DINTR-UN FISIER TEXT file[1] = openFile(FILENAME_OUTPUT_ROLES, WRITEMODE_TXT); // SCRIEM ROLURI INTR-UN FISIER TEXT file[2] = openFile(FILENAME_OUTPUT_ROLES_BINARY, WRITEMODE_BINARY); // SCRIEM ROLURI INTR-UN FISIER TEXT // dateIntrareLeagueCS.txt && dateIntrareRoluriLeagueCS.txt TREBUIE SA EXISTE IN DIRECTOR (ALTFEL VA ESUA) Role* roles = fetchRoles(file[0]); // Am primit lista cu rolurile showRoles(roles); // Afisam Rolurile showRolesOnFile(roles, file[1]); // Le afisam intr-un fisier text writeRolesOnBinaryData(roles,file[2]); // Le afisam intr-un fisier binar // ELIBERAM RESURSELE freeRoles(&roles); // Eliberam resursele ocupate de entitate closeFiles(&file,NR_FILES); // Eliberam resursele ocupate de fisiere if (file == NULL) printf("COLECTIA DE FISIERE A FOST ELIBERATA CU SUCCES !! "); return 0; } Rezultatul in consola : **FISIERUL dateIntrareRoluriLeagueCS.txt S-A DESCHIS CU SUCCES !** // Astea doua SUNT GENERATE DE PROGRAM !! **FISIERUL dateIesireRoluriLeagueCS.txt S-A DESCHIS CU SUCCES !** **FISIERUL dateIesireRoluriLeagueCS.bin S-A DESCHIS CU SUCCES !** Colectia de Roluri : { ID ROL : 0 NUME ROL : Membru ID ROL : 1 NUME ROL : Utilizator Premium ID ROL : 2 NUME ROL : Moderator ID ROL : 3 NUME ROL : Super Moderator ID ROL : 4 NUME ROL : Administrator } COLECTIA DE FISIERE A FOST ELIBERATA CU SUCCES !! NOTA 1 ** : In atasament , veti putea vizualiza rezultatele atat in fisier binar cat si text !! NOTA 2 ** : Fisierele careia li se aplica operatiunea de scriere , sunt GENERATE DE PROGRAM DACA NU EXISTA IN DIRECTOR !! NOTA 3 ** : ACESTE CODURI SUNT DOAR ADAUGIRI(ADAPTARI) DE LA CODUL REGASIT IN TUTORIALUL ANTERIOR DE STRUCTURI !! dateIesireRoluriLeagueCS.bin dateIesireRoluriLeagueCS.txt -
Nu particip la hall of fame deoarece am intrat cu activitate tarziu , pe aceasta comunitate.
Din aceasta cauza , nu pot face o evaluare corecta , voi considera ca toata lumea din staff face o treaba corecta si sar in ajutor atunci cand e necesar.
Totusi , va multumesc frumos pentru cei ce m au nominalizat si bineinteles , cel mai bun sa castige ! Toate Bune !
-
** Problema Reala ** Operatorii de incrementare ("++") si decrementare("--") , dupa cum cunoastem , pot fi situati atat inainte de variabila cat si dupa variabila . Prima poarta denumire de pre-(in/de)crementare iar cea de a doua , post-(in/de)crementare . Am trecut "in/de" deoarece desi , sunt operatiuni diametral opuse (una creste si cealalalta scade cu o unitate) , acestea au o problema comuna . Totusi , care-i problema ? Problema e constituita de DIFERENTA dintre post/pre . Astfel , ca intr-un anumit context , ele pot avea intelesuri diferite . ** Situatia 1 ** #include <stdio.h> int main() { // Sa presupunem doua variabile intregi int i = 0, j = 0; // In Situatia 1 : i++; // PostIncrementare cu o unitate ++j; // PreIncrementare cu o unitate printf("i : %d : \t j : %d \n", i,j); // Afisam // i = 0 ; j = 0 // Ambele se insumeaza cu o unitate // La fel si Decrementarea i--; // PostDecrementare cu o unitate --j; // PreDecrementare cu o unitate printf("i : %d : \t j : %d \n", i, j); // Afisam // i == 0 ; j == 0 return 0; } OBSERVATIE ** : IN ACEST CONTEXT , NU EXISTA DIFERENTE INTRE POST/PRE (IN/DE)CREMENTARE !! ** SITUATIE 2 ** : #include <stdio.h> int main() { // SITUATIE 2 // Sa presupunem ca adaugam inca o variabila int k = 0; //** **/ Si dorim efectuam o postincrementare k = i++; // i == 1 && k == 0 // K PREIA VALOAREA LUI I (0) INAINTE DE INCREMENTARE !!! printf("k : %d : \t i : %d \n", k, i); // Afisam j = i--; // j == 1 && i = 0 // J PREIA VALOAREA LUI I (1) INAINTE DE DECREMENTARE !!! printf("j : %d : \t i : %d \n", j, i); // Afisam // PRE-IN(DE)CREMENTARE k = ++i; /// k == 1 & i == 1 // LUI K II SE ATRIBUIE VALOAREA DEJA INCREMENTATA A LUI I !! printf("k : %d : \t i : %d \n", k, i); // Afisam j = --i; // j == 0 && i == 0 // LUI J II SE ATRIBUIE VALOAREA DEJA DECREMENTATA A LUI I !! printf("J : %d : \t i : %d \n", j, i); // Afisam return 0; } ** PE SCURT ** : PRE(IN)DECREMENTAREA PRIORITIZEAZA INCREMENTAREA IAR APOI , ATRIBUIREA !!! (POATE FI CEVA MAI RAPID DECAT A DOUA VARIANTA !) POST(IN)DECREMENTAREA PRIORITIZEAZA ATRIBUIREA IAR APOI , INCREMENTAREA !!!
-
- operatori
- algorithms
-
(și 2 altele)
Setat cu taguri:
-
** Organizarea Claselor ** Cu cat proiectul primeste mai multe implementari , spre exemplu : mai multe clase , mai multe functii samd. , cu atat acesta devine mai greu de citit . In acest context , a aparut necesitatea de a organiza clasele pe mai multe fisiere . Pentru fiecare clasa , se constituie doua fisiere : unu de tip antent sau "header" ce detine declaratiile clasei si a componentelor acestuia . unu de tip sursa ce detine implementarile(functionalitatile) declarate. NOTA ** : Aceasta abordare ne confera o LIZIBILITATE mai buna a codului . (O intelegere mai buna a codului prin redimensionarea liniilor de cod la fiecare fisier) . Practic , mai bine preferam 6 fisiere cu cate 50 de linii de cod decat un fisier cu 300 . ** Exemplu ** Sa presupunem ca avem proiectul nostru de POO (Programarea Orientata Pe Obiecte) , codul fiind incapsulat intr-un singur fisier . Scopul acestui tutorial , va fi de a impartii acele linii de cod pe mai multe fisiere . (Ne va ajuta in tutorialele urmatoare cand vom complica lucrurile !!) 1. Declaram o clasa ce manipuleaza siruri de caractere (pentru alocarea sirurilor de caractere) : // StringLGCS.h #pragma once #include "string.h" // Pentru strcpy /// MANIPULATOR DE SIRURI DE CARACTERE class StringLGCS { private: char* string; public: StringLGCS(); StringLGCS(const char* source); ~StringLGCS(); // Getteri char* const getString(); // Setteri void setString(const char* source); // Alte Functii static inline void allocAndFetchString(char** target, const char* source); // E INDEPENDENT DE INSTANTE }; Cu implementarea : // StringLGCS.cpp #include "StringLGCS.h" // Asociem cu fisierul antent // Implementari StringLGCS::StringLGCS() // Constructor Default { const char* defaultLGCSString = "BINE AI VENIT PE COMUNITATEA LEAGUECS!!!"; allocAndFetchString(&this->string,defaultLGCSString); } // Constructor cu Parametrii StringLGCS::StringLGCS(const char* source) { allocAndFetchString(&this->string,source); } // Destructor StringLGCS::~StringLGCS() { // Eliberam memoria ocupata de sir delete string; string = NULL; } // Getteri && Setteri char* const StringLGCS::getString() { return string; } void StringLGCS::setString(const char* source) { delete this->string; // Stergem allocAndFetchString(&string,source); // Realocam pentru alt sir de caractere } inline void StringLGCS::allocAndFetchString(char** target, const char* source) { size_t sizeTarget = strlen(source) + 1; *target = new char[sizeTarget]; // Alocam Spatiu pentru sir de caractere strcpy_s(*target, sizeTarget, source); } // Alte Functii 2. Adaugam Clasa de Utilizatori : #pragma once // User.h --> Fisier Antent #include "StringLGCS.h" #include <iostream> // CLASA CU DECLARATIA MEMBRIILOR class User { private: // Sector Privat // Campuri unsigned id; // NUMAR NATURAL char* username; // SIR DE CARACTERE char* email; // SIR DE CARACTERE char* password; // SIR DE CARACTERE unsigned nrPosts; // NUMAR NATURAL bool isBanned; // E BANAT StringLGCS* stringHandling; // Manipuleaza Siruri de Caractere . public: // Sector Public /* * CONSTRUCTORI */ User(); // Constructor fara parametrii User(unsigned id, const char* username, const char* email, const char* password); // Constructor cu toti parametrii /* DESTRUCTOR */ ~User(); /* GETTERI */ unsigned const getId(); const char* const getUsername(); const char* const getEmail(); const char* const getPassword(); unsigned const getnrPosts(); bool const getisBanned(); /* SETTERI */ void setNrPosts(const unsigned nrPosts); void setIsBanned(const bool isBanned); void setUsername(const char* username); void setEmail(const char* email); void setPassword(const char* password); // Alte Functii // Vizualizare Obiect void objectToString(); // Transferam obiectul prin referinta constanta }; Cu implementarea : #include "User.h" //** Implementarea Constructorilor **// User::User() { // Constructor Fara Parametrii // Alocam si Initializam date cu informatii IMPLICITE (DEFAULT ) // Variabile cu Alocare Statica id = 0; nrPosts = 0; isBanned = false; // Variabile cu Alocare Dinamica stringHandling = new StringLGCS(); // E initializat cu o valoare implicita (default) /// FUNCTIILE STATICE SE INVOCA FOLOSIND "::" !!! StringLGCS::allocAndFetchString(&this->username, stringHandling->getString()); StringLGCS::allocAndFetchString(&this->email, stringHandling->getString()); StringLGCS::allocAndFetchString(&this->password, stringHandling->getString()); } User::User(unsigned id, const char* username, const char* email, const char* password) { this->id = id; stringHandling = new StringLGCS(username); // Apelam constructorul cu parametrii StringLGCS::allocAndFetchString(&this->username, stringHandling->getString()); // Setam Numele de Utilizator stringHandling->setString(email); // Schimbam sirul cu urmatoarea informatie StringLGCS::allocAndFetchString(&this->email , stringHandling->getString()); // Setam Adresa De Mail stringHandling->setString(password); StringLGCS::allocAndFetchString(&this->password, stringHandling->getString()); // Setam Parola this->nrPosts = 0; // Implicit this->isBanned = false; // Implicit } User::~User() { // Eliberam Resursele ocupate de siruri delete username; username = nullptr; delete email; email = nullptr; delete password; password = nullptr; delete stringHandling; stringHandling = nullptr; } unsigned const User::getId() { return this->id; } const char* const User::getUsername() { return this->username; } const char* const User::getEmail() { return this->email; } const char* const User::getPassword() { return this->password; } unsigned const User::getnrPosts() { return this->nrPosts; } bool const User::getisBanned() { return this->isBanned; } void User::setNrPosts(const unsigned nrPosts) { this->nrPosts = nrPosts; } void User::setIsBanned(const bool isBanned) { this->isBanned = isBanned; } void User::setUsername(const char* username) { stringHandling->setString(username); StringLGCS::allocAndFetchString(&this->username, username); } void User::setEmail(const char* email) { stringHandling->setString(email); StringLGCS::allocAndFetchString(&this->email, email); } void User::setPassword(const char* password) { stringHandling->setString(password); StringLGCS::allocAndFetchString(&this->password, password); } void User::objectToString() { // DOAR AFISAM CAMPURILE OBIECTULUI std::cout << "\n{" << "\nID Utilizator : " << this->id << " ,\n" << "Nume Utilizator : " << this->username << " ,\n" << "Adresa Mail : " << this->email << " ,\n" << "Parola Utilizator : " << this->password << " ,\n" << "Numar Posturi : " << this->nrPosts << ", \n" << "STATUS BANAT : " << (this->isBanned ? "ESTE INTERZIS " : "NU ESTE INTERZIS") << " PE LEAGUECS!!, \n }"; } Si Functia Centrala care ne instantiaza si afiseaza obiectele : #include "User.h" // Includem Clasa de Utilizatori int main() { User user1, user2(1, "Vasile", "vasile@gmail.com", "vasileparola"); // Declaram doua instante (una cu constructoru implicit + constructor cu parametrii ) // Vizualizam Instantele user1.setUsername("IONEL"); user1.objectToString(); // Vizualizam Instanta 1 user2.objectToString(); // Vizualizam Instanta 2 return 0; } Rezultatul final fiind : { ID Utilizator : 0 , Nume Utilizator : IONEL , Adresa Mail : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Parola Utilizator : BINE AI VENIT PE COMUNITATEA LEAGUECS!!! , Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, } { ID Utilizator : 1 , Nume Utilizator : Vasile , Adresa Mail : vasile@gmail.com , Parola Utilizator : vasileparola , Numar Posturi : 0, STATUS BANAT : NU ESTE INTERZIS PE LEAGUECS!!, }
-
- class and objects
- headers
-
(și 4 altele)
Setat cu taguri:
-
** Fisiere ** Fisierele reprezinta o alta modalitate de a inregistra , de a prelucra si de a vizualiza date , pe langa cea de la tastatura . Limbajul C ne ofera capacitate de prelucrare a fiesierelor tip : fisiere text , unde putem observa caractere de tip ASCII (litere,numere,caractere speciale precum "\t" sau "\n" pentru spatiere samd.) . Poate fi inteles de catre utilizator . fisiere binare , unde observam o succesiune de biti , ce pot reprezenta informatii precum structuri de date , imagini , fisiere compresate , sunete samd. Informatia este structurata astfel incat sa fie interpretabila de catre sistem . In schimb , utilizatorul nu l poate descifra . NOTA 1 ** : Putem efectua atat operatiuni intrare(citire) cat si iesire(scriere), pentru fiecare tip de fisier . NOTA 2 ** : VOM EFECTUA ANUMITE SCHIMBARI PE PLAN DE ORGANIZARE A FUNCTIONALITATILOR . ASTFEL CA , VOM ORGANIZA TOATE FUNCTIILE IN FISIERE SEPARATE . PENTRU FIECARE CONTEXT , VOI IMPARTII DATELE IN DOUA : FISIERE HEADER SI SURSA ASOCIATA ACESTEIA . PRIMA CONTINE DECLARATIILE VARIABILELOR,CONSTANTELOR,STRUCTURILOR SAU A FUNCTIILOR IAR CEALALTA VA PREZENTA IMPLEMENTARILE ASOCIATE ACESTORA !! MAI BINE MAI MULTE FISIERE CU 50 100 LINII DE COD DECAT UNU SINGURU CU 10000 . PROBLEMA DIN ACEST TUTORIAL : Vom introduce cateva roluri dintr-un fisier text , le vom afisa si le vom sterge din memorie (la final) . 1. Primul Context --> Prelucrearea Sirurilor de Caractere stringHandling.h --> numele fisierului (DECLARATII) // CONTINUT #pragma once #include "string.h" // Pentru strcpy_s , strlen #include "stdlib.h" // Pentru malloc // FUNCTII & CONSTANTE PENTRU MANIPULAREA SIRURILOR DE CARACTERE // MACROS #define STRING_LENGHT(string) (strlen(string)+1) // NE DETERMINA LUNGIMEA SIRULUI DE CARACTERE + 1 (NULL CARACTER) // Functii void allocAndFetchString(char** target, char* source); // PE PARCURS , VOM ADAUGA FUNCTIONALITATI NOI Si fisierul cu implementarea : #include "../StructuriDate/stringHandling.h" // Legam cu fisierul header asociat acestuia void allocAndFetchString(char** target, char* source) { size_t sizeTarget = STRING_LENGHT(source); *target = (char*)malloc(sizeTarget); // Alocam cu dimensiunea ajustata strcpy_s(*target,sizeTarget, source); // Copiem informatia spre noul string } 2. Al doilea Context --> Prelucrarea Fisierelor : #pragma once #include "stdio.h" // pentru operatiuni cu fisiere #define READMODE_TXT "r" // CONSTANTA CITIRE FISIERE TEXT EXISTENTE IN DIRECTOR /* * Primul parametru "file" va fi asociat cu fisierul pe care l deschidem * Al doilea parametru , e numele fisierului * Al treila parametru , e modalitatea de citire&scriere (SUNT 12 MODALITATI DE CITIRE/SCRIERE) * "w" --> citim fisiere text (EXISTA DEJA --> IL VA SUPRASCRIE && DACA NU --> IL VA CONSTRUI AUTOMAT) ; * "r" --> citim fisiere text (DACA NU EXISTA --> VA RETURNA EROARE) ; * "a" --> adaugare informatie fisier text (EXISTA DEJA --> IL VA SUPRASCRIE && DACA NU --> IL VA CONSTRUI AUTOMAT) ; * "wb" --> scriem in fisiere binare (idem "w") ; * "rb" --> citim in fisiere binare (idem "r") ; * "ab" --> citim in fisiere binare (idem "a") ; * "w+" --> citim & scriem in fisiere text (idem "w") ; * "r+" --> citim & scriem in fisiere text (idem "r") ; * "a+" --> citim & scriem & modificam in fisiere text (idem "a") ; * "wb+" --> citim & scriem in fisiere binare (idem "w"); * "rb+" --> citim & scriem in fisiere binare (idem "r") ; * "ab+" --> citit & scriem & modificam in fisiere binare (idem "a"); * */ // Functie care returneaza un fisier la care se asociaza numele acestuia // cat si modalitatea de citire/scriere FILE* openFile(const char* nameFile, const char* readMode); Si implementarea acestuia : fileHandling.c --> numele fisierului #include "../StructuriDate/fileHandling.h" // Asociem cu fisierul header a acestuia FILE* openFile(const char* nameFile, const char* readMode) // Aplicam modificari catre pointer { FILE* file = NULL; errno_t errFileOpen = fopen_s(&file, nameFile, readMode); // Deschidem fisierul in functie de parametrii ceruti if (errFileOpen) // DACA A INTAMPINAT O EROARE (DE EXEMPLU : NU GASESTE FISIERUL TEXT IN DIRECTOR UNDE SE AFLA SI SURSELE !!) printf("Error : %d \n", errFileOpen); else // DACA TOTUL E IN REGULA printf("**FISIERUL %s S-A DESCHIS CU SUCCES !**\n", nameFile); return file; } 3. Al treilea Context --> Operatiuni de inserare , parcurgere , modificare si stergere pentru roluri : #pragma once #include <stdlib.h> // Pentru malloc realloc #include <stdio.h> // Pentru operatiuni de intrare/iesire #include "../StructuriDate/stringHandling.h" // Folosim functiile si Constantele din acest header (allocAndFetchString) // Definim constante necesare #define MAX_BUFFER_STRING_ROLES 30 // MAXIM BITI ALOCATI PENTRU ROLURI #define DELIMITATER "|" // Delimitator pentru separarea datelor (id de nume) #define FILENAME_INPUT_ROLES "dateIntrareRoluriLeagueCS.txt" // ACEST NUME TREBUIE SA AIBA FISIER SA POATA FI CITIT // Definim Structura pentru fiecare rol typedef struct Roles { // Definim articolul Roluri cu doua campuri unsigned id; char* nameRole; unsigned isLastRole; // Aflam daca este ultimul rol }Role; // Sub aceasta eticheta putem construi instante // Definim functii pentru incarcarea , accesarea , modificarea si stergerea acestora . Role* fetchRoles(FILE* rolesInput); // Incarcam Rolurile in memorie void showRoles(Role* roles); // Afisam Rolurile void freeRoles(Role* roles); // Stergem rolurile din memorie Si implementarea acestuia : roles.c --> numele fisierului #include "../StructuriDate/roles.h" // Legam cu headerul asociat acestuia Role* fetchRoles(FILE* rolesInput) // Preluam din fisier { if (rolesInput == NULL) // FISIER NEASOCIAT SAU INVALID return NULL; // RETURNAM NULL // Daca nu Role* roles = (Role*)malloc(sizeof(Role)); // Alocam un rol pe moment char bufferLine[MAX_BUFFER_STRING_ROLES]; // Va Stoca liniile unsigned i = 1; while (fgets(bufferLine,MAX_BUFFER_STRING_ROLES, rolesInput)) // Citim fiecare linie pana nu mai avem de citi { char* pieceOfLine, * nextPieceOfLine; pieceOfLine = strtok_s(bufferLine, DELIMITATER, &nextPieceOfLine); // Preluam ID-ul (PRIMA PARTE A LINII) roles[i - 1].id = atoi(pieceOfLine); // CONVERTIM LINIA IN intreg prin "atoi" pieceOfLine = strtok_s(NULL, DELIMITATER, &nextPieceOfLine); // Preluam NUMELE (PARTEA A DOUA A LINII) allocAndFetchString(&roles[i-1].nameRole,pieceOfLine); if (!feof(rolesInput)) // Verificam daca suntem la finalul fisierului { roles[i - 1].isLastRole = 0; // Inca nu avem ultimul rol roles = realloc(roles, sizeof(Role) * (++i)); // Mai alocam spatiu pentru un rol } else //Daca da roles[i - 1].isLastRole = 1; // Avem ultimul rol } return roles; } void showRoles(Role* roles) { unsigned i = 0; printf_s(" Colectia de Roluri : { \n"); do { // Parcurgem colectia de roluri printf_s("ID ROL : %d \t NUME ROL : %s\n", roles[i].id, roles[i].nameRole); i++; } while (!roles[i-1].isLastRole); printf_s(" } \n\n"); } void freeRoles(Role** roles) { unsigned i = 0; do // Parcurgem fiecare Rol { free((*roles)[i].nameRole); // Si eliberam memoria alocata de numele rolului i++; } while (!(*roles)[i - 1].isLastRole); free(*roles); // Eliberam colectia *roles = NULL; } Al patrulea context --> Este reprezentat de "entry pointul" (punctul de start) a proiectului (Aici doar gestionam functionalitatile) : /* Legam toate entry point toate headerele dependente */ #include "../StructuriDate/roles.h" #include "../StructuriDate/fileHandling.h" // stringHandling.h nu este dependent de entry point int main() { FILE* file; file = openFile(FILENAME_INPUT_ROLES,READMODE_TXT); // dateIntrareLeagueCS.txt && dateIntrareRoluriLeagueCS.txt TREBUIE SA EXISTE IN DIRECTOR (ALTFEL VA ESUA) Role* roles = fetchRoles(file); // Am primit lista cu rolurile showRoles(roles); // Afisam Rolurile // ELIBERAM RESURSELE freeRoles(&roles); // Eliberam resursele ocupate de entitate fclose(file); // Eliberam resursele ocupate de fisier return 0; } Primim ca rezultat : Colectia de Roluri : { ID ROL : 0 NUME ROL : Membru ID ROL : 1 NUME ROL : Utilizator Premium ID ROL : 2 NUME ROL : Moderator ID ROL : 3 NUME ROL : Super Moderator ID ROL : 4 NUME ROL : Administrator } Pe scurt , am declarat si am asociat un fisier pentru a obtine date din el . Pe urma , am incarcat datele intr-o colectie de Roluri(roles , unde i poate fi in functie de cate linii s - au introdus in fisier , cu conditia de A RESPECTA MODELUL !! (id | nume_rol)) . Dupa , am afisat in consola si am eliberat resursele ocupate de colectie cat si de fisier . NOTA ** : Voi face cat de curand , un repository (GitHub) pentru a intelege mai bine organizarea fisierelor !! dateIntrareRoluriLeagueCS.txt
-
- files handling
- structures
-
(și 3 altele)
Setat cu taguri:
-
Intr-adevar , e mult mai usor sa gestionezi un smart pointer care ne fac toate lucrurile (alocare prin constructor,eliberare prin destructor etc.) dar vreau sa arat , totusi , mecanismele din spate intr-un mod cat mai interactiv pentru incepatori (sau macar incerc) . Asa as fi putut sa folesesc string pentru "char*" , vectori si iteratori pentru colectii samd. (imi era extrem de usor) dar tind cititorului , sa i ofera o intelegere mai buna asupra cum functioneaza pointeri si colectiile , intr-un mod cat mai simplu de inteles. Oricum , voi tine si tutoriale viitoare si despre containere STL pentru a ne usura munca si a evita erorile . Multumesc frumos pentru obiecte , o seara faina !
-
Bine ai venit in comunitate !
-
** Referintele ** Referintele sunt tipuri de date complexe , gasite in C++ (nu in C) , care au abilitatea de a primi o referinta a oricarei variabile fara a se construi o copie . De ce ne ajuta referintele ? Cu ajutorul lor , putem transfera variabile catre o alta functie , intr-o maniera mai optima , fara a construi o copie acestuia . Cu aceasta modalitate , deducem ca exista 3 mari optiuni de transfer a parametrilor de la o functia la alta : prin valoare , argumentul va prelua o copie pe care o putem folosi pentru accesarea unei informatii . NU SE MODIFICA DUPA IESIREA DIN SUBPROGRAM ; (VALABIL IN C & C++) ; prin adresa , argumentul primeste o adresa pe care o poate folosi pentru accesarea sau inserarea/stergere/modificare a informatiei . SE MODIFICA DUPA IESIREA DIN SUBPROGRAM ; (VALABIL SI IN C SI C++) prin referinta , argumentul primeste o referinta (alias) care o poate folosi precum adresa (inserare,stergere,modificare) dar evitand pointeri . SE MODIFICA DUPA IESIREA DIN SUBPROGRAM . (RETINE : SE REGASESTE DOAR IN C++ , NU IN C) INDICATIE 1 * : Daca avem o variabila simpla (tipuri de date simple , arrays sau pointeri) folosim transferul prin valoare . (DOAR IN ACEST CONTEXT) !! INDICATIE 2* : Daca transferam obiecte (mai ales, cu multe campuri) , preferam transferul prin referinta !! ** Exemplu in C++ ** : *Transfer prin valoare : void setNrPosts(const unsigned nrPosts) // Transfer prin valoare (DOAR ACCESAM DATE DIN EL NU SI MODIFICAM) // IN ACEST CONTEXT SE PREFERA TRANSFERUL PRIN VALOARE (NU MODIFICAM SI AVEM DATE SIMPLE) { if (nrPosts > 0) // doar daca numarul de Posturi e mai mare decat 0 { this->nrPosts = nrPosts; // Atribuim membrului valoarea argumentului } } *Transfer prin adresa : void atribuireSirCaractere(char** target, const char* source) // Transfer prin adresa { // SE APLICA MODIFICARI ASUPRA ARGUMENTULUI + TREBUIE SA FIE POINTER DEOARECE ALOCAM NOI ZONE DE MEMORIE PENTRU SIRUL DE CARACTERE (TRANSFER PRIN ADRESA) // IN ACEST CONTEXT , TREBUIE SA OPTAM PENTRU TRANSFERUL PRIN ADRESA (AVEM NEVOIE CA ARGUMENTUL SA FIE POINTER!!) size_t bufferString = strlen(source) + 1; *target = new char [bufferString]; strcpy_s(*target, bufferString, source); } *Transfer prin referinta : void objectToString(Utilizator& const user) // Transferam obiectul prin referinta constanta (TRANSFERAM UN OBIECT) { // OBIECTULUI II SE VA CONSTRUI O REFERINTA CONSTANTA (NU APLICAM MODIFICARI PE ACEL OBIECT) // IN ACEASTA SITUATIE , ESTE DE PREFERABIL TRANSFERUL PRIN REFERINTA !! // DOAR AFISAM CAMPURILE OBIECTULUI cout << "\n{" << "\nID Utilizator : " << user.getId() << " ,\n" << "Nume Utilizator : " << user.getUsername() << " ,\n" << "Adresa Mail : " << user.getEmail() << " ,\n" << "Parola Utilizator : " << user.getPassword() << " ,\n" << "Numar Posturi : " << user.getnrPosts() << ", \n" << "Este Banat : " << (user.getisBanned() ? "ESTE BANAT" : "NU ESTE BANAT") << " ,\n}"; } Bineinteles , putem aplica modificari asupra referintei : .... RESTUL CODULUI (IL REGASITI IN TUTORIALELE DE POO TRECUTE) void changeObjectContent(Utilizator& user) // TRANSFER PRIN REFERINTA MODIFICABILA { user.setNrPosts(5); // APLICAM MODIFICARE ASUPRA REFERINTEI !! } int main() { Utilizator utilizator; changeObjectContent(utilizator); // Schimbam Continutul objectToString(utilizator); // Afisam Obiectul return 0; // Aici se declanseaza destructorul VASILE (La finalul functiei/programului) } Si vom avea ca rezultat : { ID Utilizator : 0 , Nume Utilizator : IMPLICIT , Adresa Mail : implicit@gmail.com , Parola Utilizator : implicitParola , Numar Posturi : 5, Este Banat : NU ESTE BANAT , } DESTRUCTORUL utilizatorului IMPLICIT A FOST DECLANSAT CU SUCCES !!
-
Dupa o seara energica la sala
-
Bine ai venit !
-
articole [Structuri de Date - C] Introducere in Structuri de Date (Articole)
NOT a MERCEDES a postat un topic în Windows
** Articole in C ** Articolele sunt tipuri de date complexe care stocheaza diferite informatii (de mai multe tipuri de date) dintr-un anumit camp . De exemplu , sa presupunem campul "utilizator" , poate stoca id-ul , numele , parola , data inregistrarii etc. (diferite tipuri de date) Articolele(din C) reprezinta aceeasi ideie de baza precum clasele din C++ doar ca nu se aplica principiile POO (Nu avem concept de incapsulare , polimorfism , mostenire etc.) NOTA** : Nu confundam cu articolele din C++ care dobandesc caracteristici POO , mai putin incapsulare (toti membrii sunt publici) spre deosebire de clasa . (unde avem si privat si protected) ** Exemplu in C ** : Definim doua articole (cu o legatura intre ele) : // Articole typedef struct Roles { // Definim articolul Roluri cu doua campuri unsigned id; char* nameRole; }Role; // Sub aceasta eticheta putem construi instante typedef struct Users { // Definim articolul Utilizatori cu 6 campuri // Articol sub alt Articol (nested) unsigned idUser; // numar natural unsigned nrPosts; // numar natural char* username; // un sir de caractere char* email; // un alt sir de caractere char* password; // alt sir de caractere Role* roles; // o colectie de roluri unsigned nrRoles;// Retinem in cate grupe se afla }User; // Sub aceasta eticheta putem construi instante /// NOTA ** : IN STRUCTURI NU PUTEM AVEA FUNCTII (In C++ e alta poveste) In a doua faza , definim rolurile pe care utilizator le poate avea : /// DEFINIM PRIN MACRO (SIRURI DE CARACTERE CONSTANTE) CATEVA ROLURI #define MEMBER "membru" #define PREMIUM "premium" #define MODERATOR "moderator" #define SUPERMODERATOR "superModerator" #define ADMINISTRATOR "administrator" /// DEFINIM NR_ROLURI MAXIM #define NR_ROLES 5 #define MAX_BUFFER_STRING 50 // Numar maxim de biti alocat pentru siruri de caractere (un caracter = un byte) Role* getRoles() // Returnam o colectie de NR_ROLES(5 roluri) { Role* roles = (Role*)malloc(sizeof(Role) * NR_ROLES); // Alocam o colectie de 5 roluri (Un Array de 5 ROLURI) const char* const newRoles[] = { MEMBER,PREMIUM,MODERATOR,SUPERMODERATOR,ADMINISTRATOR }; // INCARCAM TOATE ROLURILE INTR-O CONSTANTA DE SIRURI DE CARACTERE for (int i = 0; i < NR_ROLES; i++) // PARCURGEM CELE 5 ROLURI { roles[i].id = i; // Atribui cu indexul // atribuim rolurile din constanta in campul "nume roluri" din cadrul articolului roluri size_t bufferName = strlen(newRoles[i]) + 1; // roles[i].nameRole = (char*)malloc(sizeof(bufferName)); // Alocam spatiu pentru campu nostru strcpy_s(roles[i].nameRole,bufferName, newRoles[i]); // Copiem informatia } return roles; // Returnam rolurile inregistrate (articol incarcat) } Nota 1* : MACRO (alea cu "#define") sunt Constante care pot fi accesate la nivelul fisierului . (in toate subprogramele , mai putin cele de sus de declaratia acestora) ; Nota 2* : Cand articolul este pointer , pentru accesarea membriilor se foloseste sageata "->" . A treia parte , consta in incarcarea unui utilizator cu campurile :{ id,nume,email,parola,nrPosturi,roluri detinute} , de la tastatura : // Functia unde inregistram de la tastatura sirurile de caractere + le livram catre membrii articolului void getAndAllocString(char** target) // Alocam Dinamic fiecare sir de caracter { char temp[MAX_BUFFER_STRING]; // Definim o variabila intermediara care ne preia datele primite ca input scanf_s("%s",temp,MAX_BUFFER_STRING); // Luam Sirul de caractere de la tastatura size_t sizeString = sizeof(temp) + 1; // Alocam doar necesarul *target = (char*)malloc(sizeof(char) * sizeString); // Alocam doar memoria necesara strcpy_s(*target, sizeString, temp); // Transferam catre sirul de caractere } void insertUser(User* user , Role* role ) // L am pus pointer sa putem modifica datele , pe rol nu avem nevoie de modificari dar e colectie { printf("\n Introdu un id : "); scanf_s("%d", &user->idUser); // user.idUser ==> FOLOSIND sageata (pentru ca user e pointer) (->) accesam membrii printf("\n Introdu un nume de Utilizator : "); getAndAllocString(&user->username); printf("\n Introdu o adresa de Mail : "); getAndAllocString(&user->email); printf("\n Introdu o parola : "); getAndAllocString(&user->password); printf("\n Introdu un numar de posturi : "); scanf_s("%d", &user->nrPosts); printf("\n Dati mi un nivel de autoritate : (Pana la 5) "); scanf_s("%d", &user->nrRoles); if (user->nrRoles > NR_ROLES) // Daca nu respecta conditia user->nrRoles = 1; // Ii atribuim doar un Rol user->roles = (Role*)malloc(sizeof(Role) * user->nrRoles); // Alocam NUMARUL DE ROLURI PE CARE UTILIZATORUL IL DETINE // NOTA * : /// Aici : nrRoles = 1 ==> "membru" && nrRoles = 2 ==> "membru" & "premium" && nrRoles = 3 ==> "membru" && "premium" && "moderator" samd. // AM FOST PUTIN LENES , AM VRUT DOAR SA ARAT ACCESUL LA COLECTIA DE ROLURI ASOCIAT UTILIZATORULUI RESPECTIV for (int i = 0; i < user->nrRoles; i++) user->roles[i] = role[i]; // in functie de numarul de roluri } Afisam si eliberam utilizatorul : #include <stdio.h> // Pentru operatiuni de intrare si iesire (printf , scanfs ) #include <stdlib.h> // Pentru malloc , free #include <string.h> // Pentru operatiuni cu siruri de caracter ... Restul Codului ... void showStructure(User user) // Afisam Structura { printf_s("Utilizator : \n{\n *ID Utilizator : %d, \n *Nume Utilizator : %s, \n *Adresa Mail : %s, \n *Parola : %s ,\n *Numar Posturi : %d, \n", user.idUser, user.username, user.email, user.password, user.nrPosts); printf_s(" *Grupuri din care face parte : { \n "); for (int i = 0; i < user.nrRoles; i++) printf_s("\t*id Grup : %d | *nume Grup : %s , \n" , user.roles[i].id , user.roles[i].nameRole); // Afisam Id-urile si Grupurile asociate printf("} \n\n }"); } // NU UITAM SA ELIBERAM MEMORIA // NOTA* : TOT CE SE ALOCA SE ELIBEREAZA !!!!! void freeMemoryRoles(Role* role) { // ** Eliberam Rolurile (In aceeasi maniera cum le am alocat) for (int i = 0; i < NR_ROLES; i++) free(role[i].nameRole); // Eliberam sirurile de caracter // ** Eliberam colectia in sine free(role); role = NULL; } void freeMemoryUser(User user) { // Eliberam sirurile de caractere free(user.username); free(user.email); free(user.password); free(user.roles); // Eliberam colectia de grupuri } // Executia Subprogramelor int main() { Role* newRoles = getRoles(); // Injectam colectia cu o serie de roluri User utilizator1; // adaugam date intr-un utilizator ; insertUser(&utilizator1,newRoles); // Inseram in Structura showStructure(utilizator1); // Afisam Structura // Eliberam memoria alocata freeMemoryUser(utilizator1); freeMemoryRoles(newRoles); return 0; } Si avem ca rezultat : Utilizator : { *ID Utilizator : 1, *Nume Utilizator : alin, *Adresa Mail : alin@gmail.com, *Parola : esacca , *Numar Posturi : 443, *Grupuri din care face parte : { *id Grup : 0 | *nume Grup : membru , *id Grup : 1 | *nume Grup : premium , *id Grup : 2 | *nume Grup : moderator , } } NOTA 1* : Toate datele au fost introduse de la tastatura !! NOTA 2* : Putem introduce mai multi utilizatori !! (Voi face la urmatorul tutorial !! ) NOTA 3*: Aveti codul sursa in atasament !!! entryPoint.c -
acceptat Cerere Grad - King Of Underground
NOT a MERCEDES a postat un topic în Aplică pentru grad Forum
Nume : Marius Vârstă : 25 (din ianuarie) De ce dorești să aplici pentru acest grad? : Pentru a gestiona si de a ma asigura ca se respecta regulile in cadrul categoriei la care postez (ceea de IT /Tehnologie , ma rog) Ce sectiune dorești spre moderare? : IT Ce îmbunătătiri poti aduce sectiunii moderate? : Subiecte noi (in limita timpului meu) si buna desfasurare a lucrurilor . Explică activitatea ta pe forum și sectiune din ultima vreme : Momentan , deschid topicuri cu scop educativ in materie de programare . Ești conștient că vei fi pus într-o perioadă de probă, iar dacă nu te vei descurca riști să fii suspendat? Desigur , asa functioneaza in orice staff . (ca vorbim comunitate sau realitate) Ești recomandat de cineva din comunitate? : Mi a sugerat Dexter sa aplic ca moderator . Alte precizări : Incerc sa fiu activ , in ciuda programului meu incarcat . Poti intra pe teamspeak la ședinte? : Incerc . (Sa fie totusi mai spre seara si anuntate cu 2-3 zile.) -
** Iterativitate vs Recursivitate ** Algoritmii , in general , pot fi implementati iterativ sau recursiv . Astfel ca , intr-o abordare iterativa folosim bucle (loopuri) iar in cea recursiva , folosim apelul repetitiv a unei functii , pentru repetarea unor parti din cod . Totusi , avem pe de o parte avantaje si dezavantaje , pentru fiecare tip de abordare. Astfel ca : Pe parte de eficienta & putere , iterativitatea este mult mai avantajoasa in defavoarea recursivitatii . In sensul ca , apelul repetat al functiilor pot consuma din memoria stack si pot ingreuna programul sau chiar , sa producem un blocaj de tip "stackoverflow" . (Supraincarcarea memoriei stack) . Plus , pe partea de iterativitate , avem un control mai bun pe numarul de repetari . Pe de alta parte , recursivitatea ofera posibilitatea de a construi un cod elegant , usor de mentinut . (Mai ales , daca discutam de o problema de natura recursiva !!) . ** Exemple in C ** Sa presupunem ca vrem sa aflam suma numerelor introduse la tastura . Abordare Iterativa #include <stdio.h> #include <stdlib.h> // Pentru malloc & free int insertArray(int** arr) // RETURNAM LUNGIMEA COLECTIEI { *arr = (int*)malloc(sizeof(int)); // Alocam colectie doar pentru un numar (MOMENTAN) char yesOrNo = 'n'; int bufferArr = 1; do { if (yesOrNo == 'y') { bufferArr++; // Marim lungimea colectiei cu +1 element *arr = (int*)realloc(*arr, sizeof(int) * bufferArr); // Mai alocam spatiu pentru un numar } printf("Dati-mi un numar : "); scanf_s("%d", &(*arr)[bufferArr-1]); // Inseram un nou element in colectie de la tastatura printf("Continuam [y/n] ?"); scanf_s(" %c", &yesOrNo, 1); // Daca yesOrNo = y (continuam) altfel iesim din functie } while (yesOrNo != 'n'); // Continuam bucla atat cat yesOrNo e DIFERIT DE 'n' return bufferArr; } int sumArray(int arr[],int bufferArr) { int sum = 0; // Initializam cu 0 for (int i = 0; i < bufferArr; i++) // Parcurgem toata colectia { sum += arr[i]; // Insumam toate elementele colectiei } return sum; } int main() { int* a = NULL; int bufferArr = insertArray(&a); // Trimitem pointerul a prin adresa (VOM MODIFICA STRUCTRURA ACESTUIA IN FUNCTIE ) si // ++ Vom returna lungimea finala in bufferArr // Afisam suma colectiei printf("\n INSUMAND TOATE VALORILE COLECTIEI VOM AVEA CA REZULTAT : %d ", sumArray(a,bufferArr)); // Eliberam Memoria Ocupata de Array (Sa prevenim Memory Leak) free(a); // Eliberam Colectia in sine a = NULL; // Setam NULL Pointer return 0; } Nota ** : In aceasta abordare , se pot observa in ambele functii , utilizarea buclelor (do-while si for) pentru inserarea , traversarea si accesarea membriilor din colectie !! Abordare Recursiva : Subprogramul de introducere a numerelor in colectie : int insertArray(int** arr) // RETURNAM LUNGIMEA COLECTIEI { // AM ALOCAT IN AFARA FUNCTIEI +1 element ca tot acest va deveni repetitiv char yesOrNo; static int index = 1; // STATIC sa retinem indexu intre apelurile recursive a functiei printf("Dati-mi un numar : "); scanf_s("%d",&(*arr)[index-1]); // Inseram un nou element in colectie de la tastatura printf("Continuam[y/n] ?"); scanf_s(" %c", &yesOrNo,1); // Primim confirmarea de la utilizare de a continua sau nu inserarea if (yesOrNo == 'n') // Daca nu continuam inserarea { return 1; // Oprim algoritmul (1 si nu 0 deoarece luam in calcul si primul element al listei ) } else { index++; // Indexu se mareste cu un element *arr = realloc(*arr, index * sizeof(int)); // Realocam inca o zona de memorie return 1 + insertArray(arr); // Apelam din nou functia de inserare pentru noul element (++ adaugam un nou elemnt ) } } Subprogramul de insumare a elementelor din colectie : int sumArray(int arr[],int bufferArr) { if (bufferArr <= 0) // Daca indexu ajunge la 0 { return 0; // returnam 0 in suma } else { int sum = sumArray(arr, bufferArr - 1) + arr[bufferArr - 1]; // Colectia se INSUMEAZA CU APELUL REPETITIV // al functiei ==> arr[bufferArr-1] + arr[bufferArr-2] + arr[bufferArr-3] + ... + arr[0] /* * * De exemplu daca avem arr = {5,3,4,5,2 } & Lungimea Colectiei : 5 sum = 2 + {5,3,4,5} ; bufferArr = 5 ; sum = 2 + 5 + {5,3,4} ; bufferArr = 4 ; sum = 7 + 4 + {5,3} ; bufferArr = 3 ; sum = 11 + 3 + {5} ; bufferArr = 2 ; sum = 14 + 5 ; bufferArr = 1 ; sum = 19 + 0 ; // BufferArr = 0 ==> Se incheie algoritmul sum = 19 ; */ return sum; } } Functia principala cu apelurile la functiile respective : #include <stdio.h> #include <stdlib.h> // Pentru realloc , malloc & free int main() { int* a = (int*)malloc(sizeof(int)); // Alocam o zona de memorie int int bufferArr = insertArray(&a);// Trimitem pointerul a prin adresa (VOM MODIFICA STRUCTRURA ACESTUIA IN FUNCTIE ) si // ++ Vom returna lungimea finala in bufferArr printf("\n INSUMAND TOATE VALORILE COLECTIEI VOM AVEA CA REZULTAT : %d ", sumArray(a,bufferArr)); // Eliberam Memoria Ocupata de Array (Sa prevenim Memory Leak) free(a); // Eliberam Colectia in sine a = NULL; // Setam NULL Pointer return 0; } NOTA 1 ** : Operatiunile de inserare , parcurgere si accesare , din cadrul colectiei , sunt efectuate prin apelurile repetitive/recursive a functiei . NOTA 2 ** : Apelurile recursive trebuie sa se faca intr-un mod controlat (Prin if-else) , altfel pot genera erori sau repetari , la infinit , al functiei . (Vom vedea in tutorialele ce urmeaza !!)
-
class & objects [Programarea Orientata pe Obiecte] Pointerul "this"
NOT a MERCEDES a postat un topic în Windows
** " Ce este pointerul "this" " ? ** Pointerul "this" reprezinta o modalitate de a accesa membrii unei clase , in interiorul acesteia . Apare ca necesitate pentru evitarea conflictelor de "nume" (declarat) dintre membrii clasei si parametrii locali (argumentele unei functii , variabile locale etc.) . NOTA ** : Pointerul "this" reprezinta un concept STRICT C++ . Cu alte cuvinte , in celalalte limbaje cu paradigma POO nu avem acest concept deoarece nu exista pointeri . ** Exemplu Utilizare in C++ ** NOTA ** : Codul preluat este preluat din tutorialele trecute !! Sa presupunem ca avem constructorul cu parametrii : Utilizator(unsigned _id, const char* _username, const char* _email, const char* _password) // Constructor cu Parametrii Esentiali (Un utilizator NOU nu poate sa aiba ban sau posturi) { // Variabile cu Alocare Statica id = _id; // Preluam din parametru nrPosts = 0; // IMPLICIT 0 POSTURI LA CONSTRUCTIA UTILIZATORULUI isBanned = false; // NU E BANAT // Variabile cu Alocare Dinamica atribuireSirCaractere(&username, _username); atribuireSirCaractere(&email, _email); atribuireSirCaractere(&password, _password); } Totul e ok deoarece am evitat conflictul de "nume" dintre membrii clasei si parametrii . Practic , am pus un caracter suplimentar , "_" , ce face diferenta . Altfel : Utilizator(unsigned id, const char* username, const char* email, const char* password) // Schimba numele declarat asociate argumentelor constructorului ! // Constructor cu Parametrii Esentiali (Un utilizator NOU nu poate sa aiba ban sau posturi) { /// MEREU O VARIABILA LOCALA SAU UN ARGUMENT VOR AVEA PRIORITATE IN FATA MEMBRIILOR PRIVIND NUMELE !! // Variabile cu Alocare Statica /// APARE CONFLICTUL DE NUME SI VOR AVEA URMATOARELE EFECTE (RUNTIME SI LOGICE) : id = id; // ARGUMENTUL ID = ARGUMENTUL ID ; // Urmatorii doi sunt OK deoarece primesc valori implicite !! (Eventual la setteri vor aparea conflicte daca se pune acelasi nume la argument cu al membrului ) nrPosts = 0; // IMPLICIT 0 POSTURI LA CONSTRUCTIA UTILIZATORULUI isBanned = false; // NU E BANAT // Variabile cu Alocare Dinamica atribuireSirCaractere(&username, username); /// EROARE RUNTIME ==> USERNAME E SIR DE CARACTER CONSTANT IAR LA INCERCAREA DE A ACCESA MEMBRUL "USERNAME" va esua programul cu eroare la accesarea unei zone de memorie neexistenta !! (Pentru ca nu i s-a atribuit nimic) atribuireSirCaractere(&email, email); /// IDEM ca la prima atribuireSirCaractere(&password, password); /// IDEM ca la prima } Daca vrem sa pastram acelasi nume atat pentru membru cat si pentru argument , aplicam pointerul "*this" : Utilizator(unsigned id, const char* username, const char* email, const char* password) // Constructor cu Parametrii Esentiali (Un utilizator NOU nu poate sa aiba ban sau posturi) { // Variabile cu Alocare Statica this->id = id; // Accesam Membru cu pointerul this-> (Sageata ca E POINTER) (*this).nrPosts = 0; // SAU ASA isBanned = false; // Nu exista conflict de nume , NU AVEM DE CE sa l folosim // Variabile cu Alocare Dinamica atribuireSirCaractere(&this->username, username); atribuireSirCaractere(&(*this).email, email); atribuireSirCaractere(&this->password,password); ///// ORI "this->" ORI "(*this)." NU ARE IMPORTANTA (Recomand totusi prima varianta) } NOTA 1 * : IL PUTEM FOLOSI DOAR IN INTERIORUL CLASEI (In constructor,destructor,functii etc.) doar pentru acest scop !! NOTA 2* : NU SE POATE FOLOSI IN CADRUL FUNCTIILOR STATICE SI PENTRU ACCESAREA MEMBRIILOR STATICI (INDIFERENT CA FAC PARTE SAU NU DIN CLASA) !!-
- 1
-
-
- class & objects
- this
-
(și 1 alta)
Setat cu taguri:
-
destructor [Programare Orientata Pe Obiecte - C++] Destructor
NOT a MERCEDES a postat un topic în Windows
** Ce reprezinta si importanta acestuia in paradigma OOP ** Un destructor reprezinta o functie "speciala" care se ocupa de eliberarea memoriei alocate de membrii unei instante (Inchidem fisiere , diverse servicii etc.) . Practic , in constructor alocam memorie pentru membrii iar in destructor , le eliberam . ** Caracteristici ** Sunt membrii asemenea constructorilor , nu permit argumente si nu returneaza valori ; Se declanseaza , automat , la distrugerea obiectului (La iesirea din context sau la operatorul "delete") fara a fi solicitat explicit . (adica mentionat) ; NU poate fi constant sau static ; (Asemenea Constructorului) ; NU POT EXISTA MAI MULTI DESTRUCTORI (DOAR UNUL) !!! ** Nota 1 : NU EXISTA DESTRUCTOR IN majoritatea Limbajelor (cu paradigma OOP) precum C# , Java , Python etc. , deoarece au un sistem dedicat pentru gestionarea resurselor alocate !!! ** Nota 2 : E FOARTE IMPORTANT SA FOLOSIM DESTRUCTORI , de fiecare data , PENTRU A ELIBERA TOATA MEMORIA REZIDUALA ("Memory Leak") !! ** Declaratie Destructor ** ~<nume_clasa>(){ // Aici Eliberam Toata Memoria Reziduala } // De exemplu , daca avem clasa "Utilizator" , definim destructoru : ~Utilizator(){ // Continut Destructor } ** Exemplu de Utilizare Destructor ** 1. Sa presupunem ca avem o clasa "Utilizator" cu campurile : class Utilizator { private: // Sector Privat // Campuri unsigned id; // NUMAR NATURAL char* username; // SIR DE CARACTERE char* email; // SIR DE CARACTERE char* password; // SIR DE CARACTERE unsigned nrPosts; // NUMAR NATURAL bool isBanned; // E BANAT }; 2. Alocam si Initializam datele prin doi constructori : class Utilizator{ // Campuri ... public: // Sector Public /* * CONSTRUCTORI */ Utilizator() { // Constructor Default // Alocam si Initializam date cu informatii IMPLICITE (DEFAULT ) // Variabile cu Alocare Statica id = 0; nrPosts = 0; isBanned = false; // Variabile cu Alocare Dinamica atribuireSirCaractere(&username, "IMPLICIT"); atribuireSirCaractere(&email, "implicit@gmail.com"); atribuireSirCaractere(&password, "implicitParola"); } Utilizator(unsigned _id, const char* _username, const char* _email, const char* _password) // Constructor cu Parametrii Esentiali (Un utilizator NOU nu poate sa aiba ban sau posturi) { // Variabile cu Alocare Statica id = _id; // Preluam din parametru nrPosts = 0; // IMPLICIT 0 POSTURI LA CONSTRUCTIA UTILIZATORULUI isBanned = false; // NU E BANAT // Variabile cu Alocare Dinamica atribuireSirCaractere(&username, _username); atribuireSirCaractere(&email, _email); atribuireSirCaractere(&password, _password); } }; 3. Sa nu uitam de functia "atribuireSirCaractere" (Declarata inafara functiei) care ne permite sa alocam & atribuim siruri de caractere : void atribuireSirCaractere(char** target, const char* source) { size_t bufferString = strlen(source) + 1; *target = new char [bufferString]; strcpy_s(*target, bufferString, source); } 4. Adaugam cativa getteri si setteri pentru afisare /* Getteri & Setteri */ const unsigned const getId() { return id; } const char* const getUsername() { return username; } const char* const getEmail() { return email; } const char* const getPassword() { return password; } const unsigned const getnrPosts() { return nrPosts; } const bool const getisBanned() { return isBanned; } // Setteri // NU Putem seta ID-ul cuiva void setNrPosts(const unsigned _nrPosts) { if (_nrPosts > 0) // doar daca numarul de Posturi e mai mare decat 0 { nrPosts = _nrPosts; } } void setIsBanned(const bool _isBanned) { isBanned = _isBanned; } void setUsername(const char* _username) { // Realocam spatiu pentru Nume Utilizator delete username; // Delete Existing Memory // Allocate New Memory atribuireSirCaractere(&username, _username); } void setEmail(const char* _email) { // Realocam Spatiu pentru Mail delete email; // Delete Existing Memory // Allocate New Memory atribuireSirCaractere(&email, _email); } void setPassword(const char* _password) { // Realocam Spatiu pentru Parola delete password; // Delete Existing Memory // Allocate New Memory atribuireSirCaractere(&password,_password); } 5. Adaugam Destructorul clasei : class Utilizator{ // Restul Clasei... // Destructor ~Utilizator() { cout << "\nDESTRUCTORUL utilizatorului " << username << " A FOST DECLANSAT CU SUCCES !!\n"; // Eliberam memoria ocupata de variabilele alocate dinamic delete username; delete email; delete password; // Setam Pointeri pe NULL username = nullptr; email = nullptr; password = nullptr; } }; 6. In functia principala (main) , declaram obiecte noi , le initializam si vedem actiunea destructorului : #include <iostream> // Pentru OBIECTELE std::cout , std::cin using namespace std; // Pentru a substitui "std::cout" cu "cout" , "std::cin" cu "cin" etc. void atribuireSirCaractere(char** target, const char* source) { /// detalii .. } class Utilizator{ // detalii .. }; /* Functie Personalizata pentru a afisa Obiectele */ void objectToString(Utilizator& const user) // Transferam obiectul prin referinta constanta) { // DOAR AFISAM CAMPURILE OBIECTULUI cout << "\n{" << "\nID Utilizator : " << user.getId() << " ,\n" << "Nume Utilizator : " << user.getUsername() << " ,\n" << "Adresa Mail : " << user.getEmail() << " ,\n" << "Parola Utilizator : " << user.getPassword() << " ,\n" << "Numar Posturi : " << user.getnrPosts() << ", \n" << "Este Banat : " << (user.getisBanned() ? "ESTE BANAT" : "NU ESTE BANAT") << " ,\n}"; } int main() { Utilizator userVasile(1, "Vasile", "vasile@gmail.com", "vasileParola"); // Alocati static Utilizator* userIon = new Utilizator(2, "Ion", "ion@gmail.com", "ionParola"); { // Scenariul 1 : Obiect alocat static si construit sub un context , loop etc. Utilizator defaultUser; // Setam date noi defaultUser.setUsername("Alin"); defaultUser.setEmail("alin@gmail.com"); defaultUser.setPassword("alinPassword"); defaultUser.setNrPosts(50); objectToString(defaultUser); // Afisam Obiectul // Iesim din Context (La sfarsitul acestor acolade , obiectul iese din context si declanseaza destructorul ) } // Scenariul 2 : Obiect alocat static si construit in main objectToString(userVasile); // Afisam Vasile // Scenariul 3 : Obiect alocat dinamic si construit in main objectToString(*userIon); // Afisam Ion delete userIon; // Aici se declanseaza destructorul ION userIon = nullptr; return 0; // Aici se declanseaza destructorul VASILE (La finalul functiei/programului) } 6. Dand executie , vom avea urmatorul rezultat : { ID Utilizator : 0 , Nume Utilizator : Alin , Adresa Mail : alin@gmail.com , Parola Utilizator : alinPassword , Numar Posturi : 50, Este Banat : NU ESTE BANAT , } DESTRUCTORUL utilizatorului Alin A FOST DECLANSAT CU SUCCES !! { ID Utilizator : 1 , Nume Utilizator : Vasile , Adresa Mail : vasile@gmail.com , Parola Utilizator : vasileParola , Numar Posturi : 0, Este Banat : NU ESTE BANAT , } { ID Utilizator : 2 , Nume Utilizator : Ion , Adresa Mail : ion@gmail.com , Parola Utilizator : ionParola , Numar Posturi : 0, Este Banat : NU ESTE BANAT , } DESTRUCTORUL utilizatorului Ion A FOST DECLANSAT CU SUCCES !! DESTRUCTORUL utilizatorului Vasile A FOST DECLANSAT CU SUCCES !! SCENARIUL 1 : Observam ca destructorul obiectului "IMPLICIT" s-a declansat la sfarsitul acoladelor , unde a iesit din context ; SCENARIUL 2 : Destructorul obiectului "Ion" (alocat dinamic) s-a declansat , automat , la intalnirea cu operatorul "delete" . (Se distruge obiectul si iese din context) ; SCENARIUL 3 : Destructorul obiectului "Vasile" s-a declansat la sfarsitul programului (dupa ce am returnat 0 in "main") .-
- memory management
- constructor
-
(și 3 altele)
Setat cu taguri:
-
sorting [Algoritmi si Structuri de Date - C] Bubble Sort
NOT a MERCEDES a postat un topic în Windows
** Bubble Sort ** Bubble Sort sau Sortare cu Bule , este similara cu cea de selectie doar ca se compara vecinii intre ei . Consta in doua bucle iar algoritmul ia sfarsit cand nu mai exista interschimbari . ** Interpretare ** Avem o colectie cu 6 elemente : [4 , 55 , 22, 67 , 89, 90] --> valori [0 , 1 , 2 , 3, 4 ,5 ] --> indecsi Sa presupunem ca cerem sa o ordonam descrescator !!! La prima indexare : i = 0 1. 4 < 55 ==> 4 mai mic decat 55 --> efectuam interschimbare : [55,4,22,67,89,90] ; 2. 4 < 22 ==> 4 mai mic decat 22 --> efectuam interschimbare : [55,22,4,67,89,90] ; 3. 4 < 67 ==> 4 mai mic decat 67 --> efectuam interschimbare : [55,22,67,4,89,90] ; 4. 4 < 89 ==> 4 mai mic decat 89 --> efectuam interschimbare : [55,22,67,89,4,90] ; 5. 4 < 90 ==> 4 mai mic decat 90 --> efectuam interschimbare : [55,22,67,89,90,4] ; La a doua indexare : i = 1; 1. 55 > 22 ==> 55 mai mare decat 22 --> continuam ; 2. 22 < 67 ==> 22 mai mic decat 67 --> efectuam interschimbare : [55,67,22,89,90,4] ; 3. 22 < 89 ==> 22 mai mic decat 89 --> efectuam interschimbare : [55,67,89,22,90,4] ; 4. 22 < 90 ==> 22 mai mic decat 90 --> efectuam interschimbare : [55,67,89,90,22,4] ; 5. 22 > 4 ==> 22 mai mare decat 4 --> continuam La a treia indexare : i = 2 ; 1. 55 < 67 ==> 67 mai mare decat 55 --> efectuam interschimbare : [67,55,89,90,22,4] ; 2. 55 < 89 ==> 55 mai mic decat 89 --> efectuam interschimbare : [67,89,55,90,22,4] ; 3. 55 < 90 ==> 55 mai mic decat 90 --> efectuam interschimbare : [67,89,90,55,22,4] ; 4. 55 > 22 ==> 55 mai mare decat 22 --> continuam 5. 22 > 4 ==> 22 mai mare decat 4 --> continuam La a patrea iteratie : i = 3 ; 1. 67 < 89 ==> 67 mai mic decat 89 ==> efectuam interschimbare : [89,67,90,55,22,4] ; 2. 67 < 90 ==> 67 mai mic decat 90 ==> efectuam interschimbare : [89,90,67,55,22,4] ; 3. 67 > 55 ==> 67 mai mare decat 55 ==> continuam ; 4. 55 > 22 ==> 55 mai mare decat 22 ==> continuam ; 5. 22 > 4 ==> 22 mai mare decat 4 ==> continuam ; La a cincea iteratie : i = 4 ; 1. 89 < 90 ==> 89 mai mic decat 90 ==> efectuam interschimbare : [90,89,67,55,22,4] ; 2. 89 > 67 ==> 89 mai mare decat 67 ==> continuam ; 3. 67 > 55 ==> 67 mai mare decat 55 ==> continuam ; 4. 55 > 22 ==> 55 mai mare decat 22 ==> continuam ; 5. 22 > 4 ==> 22 mai mare decat 4 ==> continuam ; La a sasea iteratie : i = 5 ; 1. 90 > 89 ==> 90 mai mare decat 89 ==> continuam ; 2. 89 > 67 ==> 89 mai mare decat 67 ==> continuam ; 3. 67 > 55 ==> 67 mai mare decat 55 ==> continuam ; 4. 55 > 22 ==> 55 mai mare decat 22 ==> continuam ; 5. 22 > 4 ==> 22 mai mare decat 4 ==> continuam ; ==> NIMIC DE INTERSCHIMBAT ==> SFARSIT ALGORITM NOTA ** : Daca dorim ordine crescatoare , doar inversam comparatiile !! ** Interpretare cod C ** #include <stdio.h> #include <stdlib.h> // Pentru malloc & free int* bubbleSort(int *arr,int bufferArray) { int stillUnordered = 0; // Valoare 0 (Nu exista bool in C) for (int i = 0; i < bufferArray - 1; i++) { for (int j = 0; j < (bufferArray-i-1); j++) { if (arr[j] < arr[j + 1]) // "<" pentru descrescator si ">" pentru crescator { // Efectuam Interschimbarea int temp = arr[j]; arr[j] = arr[j + 1]; // Arr[j+1] ii va lua locul lu arr[j] arr[j + 1] = temp; // Valoarea mai mica o ducem mai in spate stillUnordered = 1; } } if (stillUnordered != 1) // Algoritmul s-a finalizat { break; // Nu mai e necesar sa rulam tot loopul } } return arr; // Returnam colectia ordonata } 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 la intamplare : \n",arrayBuffer); for (int i = 0; i < arrayBuffer; i++) { printf("colectie[%d] = ", i); scanf_s("%d", &a[i]); // Inseram numerele de la tastatura } a = bubbleSort(a,arrayBuffer); // Transferam colectia prin valoare si rezultatul o egalam cu a /// Printam Colectia printf("Printam colectia ordonata : \n"); for (int i = 0; i < arrayBuffer; i++) { printf("v[%d]=%d\n", i, a[i]); } // 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 USOR DE IMPLEMENTAT SI INTELES !! NOTA 2 ** : CU CAT COLECTIA E MAI MARE CU ATAT ALGORITMUL DEVINE MAI INEFICIENT (Timp de Executie mai mare ) ; NOTA 3 ** : DIN PRICINA NUMEROASELOR COMPARATII , SE PREFERA ALGORITMUL DE SELECTIE IN DEFAVOAREA ACESTUIA !!-
- bubble sort
- c
-
(și 2 altele)
Setat cu taguri: