Laborator 10: Operații cu tablouri, structuri și alocare dinamică de memorie
Obiectivele laboratorului
În acest laborator vom studia:
- lucrul cu structuri, tablouri și alocare dinamică
- aplicații complexe: citirea/prelucrarea/afișarea eficientă a unui tablou de structuri alocate dinamic în/din fișiere text/binare
Materiale utile
Acest laborator nu are pagină nouă de teorie, însă necesită recapitularea noțiunilor indicate.
- [OCW/Suport Teoretic pentru Laborator] Alocarea dinamică a memoriei. Aplicaţii folosind tablouri
- [OCW/Suport Teoretic pentru Laborator] Prelucrarea şirurilor de caractere. Funcţii. Aplicaţii.
- [OCW/Suport Teoretic pentru Laborator] Uniuni. Aplicaţie: Matrice rare
- [OCW/Suport Teoretic pentru Laborator] Operaţii cu fişiere. Aplicaţii folosind fişiere.
Exerciții
ATENȚIE: Toate exercițiile vor fi verificate și cu valgrind. Toate sarcinile se vor realiza folosind o abordare modularizată (cu funcții). Discutați cu asistentul alegerile voastre, dacă nu sunteți siguri care ar trebui să fie semnăturile funcțiilor.
- Fie definiția de mai jos a unei structuri:
// maxim 30 de caractere printabile + '\0'
#define NAME_LEN 31
struct __attribute__((__packed__)) person {
char name[NAME_LEN];
int age;
};
// sau
typedef struct __attribute__((__packed__)) {
char name[NAME_LEN];
int age;
} person_t;
a. Scrieți un program care citește membrii unei astfel de structuri și face scrierea ei într-un fișier binar (1-gigel.bin). Reprezentarea în fișier a informației trebuie să aibă sizeof(struct person)
(sizeof(person_t)
), iar - prin convenție, toți octeții nefolosiți ai structurii (rezultați, de exemplu, prin citirea unui nume mai scurt de 30 de caractere), trebuie să fie inițializați la zero.
Important! În codul programului vostru trebuie să aveți exact un apel al funcției fwrite
(nu mai multe).
Exemplu:
Se vor citi următoarele date de la stdin
:
Gigel 25
Se va genera fișierul 1-gigel.bin având următorul conținut:
$ hexdump -C 1-gigel.bin
00000000 47 69 67 65 6c 00 00 00 00 00 00 00 00 00 00 00 |Gigel...........|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 19 |................|
00000020 00 00 00 |...|
00000023
// putem inspecta si dimensiunea fișierul: 35 bytes (0x23)
// 35 = 31 (NAME_LEN bytes pentru name) + 4 (19 00 00 00 == 25)
$ ls -l gigel.bin
-rw-r--r-- 1 dorinel wheel 35 Nov 26 00:33 1-gigel.bin
b. Scrieți un program care citește structura din fișierul general anterior și afișează, pe ecran, numele și vârsta persoanei.
Important! În codul programului vostru trebuie să aveți exact un apel al funcției fread
(nu mai multe).
- Fie varianta alternativă a structurii:
struct person {
char *name;
int age;
};
// sau
typedef struct {
char *name;
int age;
} person_t;
// Obs. name are lungime variabilă și se alocată dinamic
a. Refaceți exercițiul 1.a. considerând folosirea câmpului nume alocat dinamic. Noul fișier se va numi 2-gigel.bin.
Restricția de a folosi un singur apel de fwrite
nu se mai păstrează.
De data aceasta folosiți convenția de la laboratorul trecut (de a preceda câmpul nume de lungimea lui în octeți, sub forma unui int) și asigurați-vă că structura ocupă exact același număr de octeți ca cea din exemplul următor.
Exemplu:
Se vor citi următoarele date de la stdin
:
Gigel 25
Se va genera fișierul 2-gigel.bin având următorul conținut:
$ hexdump -C 2-gigel.bin
00000000 06 00 00 00 47 69 67 65 6c 00 19 00 00 00 |....Gigel.....|
0000000e
// putem inspecta si dimensiunea fișierul: 14 bytes (0x0e)
// 14 = 4 (06 00 00 00 == lungime in bytes) + 6 ("Gigel\0") + 4 (19 00 00 00 == 25)
$ ls -l 2-gigel.bin
-rw-r--r-- 1 dorinel wheel 14 Nov 26 00:48 gigel2.bin
b. Scrieți un program care citește structura creată la punctul anterior și afișează informațiile persoanei pe ecran.
Restricția de a folosi un singur apel de fread
nu se mai păstrează.
Mențiune! Afișarea câmpurilor se va face obligatoriu, prin utilizarea structurii, după crearea unei variabile de acel tip.
- Creați un program care citește de la tastatură un număr natural
n
, apoi scrie n structuri, de tipul celor din exercițiul 2, cu date citite de lastdin
într-un fișier binar 3-gigel.bin. Formatul de reprezentare a array-ului trebuie să eficient.
Verificați corectitudinea modului de reprezentare prin crearea unui program care citește cele n structuri din fișier și afișează detaliile persoanelor din acele structuri.
Mențiune! Afișarea structurilor se va face obligatoriu, prin utilizarea structurii, după citirea întregului array în memorie.
Pentru o aprofundare mai bună a conceptelor prezentate în laborator, vă recomandăm să parcurgeți materialele din arhivele demo_parsing.zip și demo_struct_binary_files.zip de pe Moodle.