Moderators NEFERPITOU Postat Decembrie 24, 2024 Moderators Postat Decembrie 24, 2024 ** 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
Postări Recomandate