Jump to content

SUBIECTE NOI
« 1 / 5 »
RSS
Scoatere antifurt airtag de pe ha...

Magnet in loc de clește pent...

Cumparat/Locuit in apartament si ...

Pot folosi sistemul PC pe post de...
 Sokol cu distorsiuni de cross-over

Filtru apa potabila cu osmoza inv...

Kanal D va difuza serialul “...

Upgrade xiaomi mi11
 securitate - acum se dau drept - ...

Farmacia Dr Max - Pareri / Sugest...

De unde cumparati suspensii / gar...

[UNDE] Reconditionare obiecte lemn
 Infiltratii casa noua

sugestie usa interior

ANAF si plata la selfpay

Imprimanta ciss rezista perioade ...
 

Stocarea datelor

- - - - -
  • Please log in to reply
11 replies to this topic

#1
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,236
  • Înscris: 24.02.2007
Reprezentarea datelor

În IT lucrăm cu date însă cum sunt reprezentate aceste date? Cum ajungem de la 10010010101010101001 la documente, imagini sau chiar muzică?

În viața de zi cu zi folosim numere în baza zece, numere ce sunt la rândul lor compuse din cifre. Baza zece înseamnă că avem 10 cifre disponibile (0, 1, 2, 3, 4, 5, 6, 7, 8, 9). Când dorim o valoare mai mare decât valoarea cifrei maxime (9), alăturăm mai multe cifre (de exemplu 29 e compus din două cifre: 2 și 9). Dacă prin folosirea unei singure cifre putem reprezenta 10 valori distince, prin folosirea a două cifre putem reprezenta 102 valori distincte (0-99), prin folosirea a trei cifre, 103 valori distincte (0-999) etc. Vedeți legătura?

Ei, IT-ul nu știe să lucreze cu baza zece (jos, la nivel electronic), așa că face uz de o altă bază, cea mai simplă, baza 2. În baza 2 nu mai avem zece valori (0-9) ci doar două (0-1). Pentru a reprezenta valori mai mari, se alătură mai multe valori de 0-1, astfel încât: prin alăturarea a două valori se pot reprezenta 22 = 4 valori distince (00, 01, 10, 11), prin alăturarea a trei valori se pot reprezenta 23 = 8 valori distince (000, 001, 010, 011, 100, 101, 110, 111) etc.

Unitatea de bază în IT este deci bit-ul (0 sau 1). Când lucrați însă cu memoria (RAM sau cea pe disc), nu veți putea lucra în mod direct chiar la nivel de bit; nu veți putea cere sistemului să va aloce 5 biți memorie, sau crea un fișier pe disc ce stochează doar 3 biți de informație. În viața de zi cu zi (de programatori) veți lucra cu un multiplu al bit-ului și anume octetul (byte).

1 byte = 8 biți

Un byte poate stoca 28 = 256 valori distince (0-255), iar atunci când se alocă memorie sau se scrie ceva pe disc, se vor scrie n bytes (n număr natural nenul).

În C pentru a stoca o valoare între 0 și 255 se va folosi unsigned char.
unsigned char a =  15;
unsigned char b = 105;


Quote

Dar dacă vreau să stochez o valoare negativă?

Având la dispoziție 256 valori distincte ce pot fi stocate într-un byte, putem considera că jumătate dintre ele ar fi pozitive, iar jumătate negative. În acest caz apare însă nevoia unei convenții: noi hotărâm, de exemplu, că valorile 10000000 - 11111111 ar reprezenta valori negative, însă trebuie ca și ceilalți (cărora le dăm datele) să respecte aceeași convenție pentru a ne putea întelege.

O astfel de convenție există deja și se numește complement de doi și ne permite ca, folosind 1 byte (8 biți), să stocăm 128 valori pozitive (0-127) și 128 valori negative (-128 - -1):

char a = 15;
char b = -115;


Foarte des se face uz și de reprezentarea datelor utilizând baza 16: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. O cifră în baza 16 putând reprezenta 16 valori distincte, pentru a reprezenta cele 256 stocabile într-un byte e nevoie de doar două cifre în baza 16 (162 = 256): 00 - FF. Pentru a preciza în C o valoare în baza 16 se va folosi prefixul "0x".

unsigned char b = 0x69; (echivalent cu unsigned char b = 105;)


De regulă, atunci când specificăm o valoare în sistem zecimal (b = 105), compilatorul o consideră drept valoare cu semn, iar când specificăm valoarea în sistem hexazecimal, compilatorul e sigur ca dorim o valoare fără semn.

În memorie, valoarea 105 va fi reprezentată drept 01101001 indiferent că-i zicem b = 105 sau b = 0x69.

Quote

Bun, și dacă vreau sa stochez o valoare mai mare, gen anul 2013

Când un byte nu-i destul... mai adăugăm unul :D. Doi octeți (16 biți) vor putea stoca 216 = 65536 valori distincte: 0-65535 dacă se lucrează fără semn, respectiv -32768 - 32767 dacă reprezentăm valori cu semn. Short se va folosi în acest caz în C:

short a = 2013;
unsigned short b = 0xFFFF; 


Utilizând mai mult de 1 byte pentru a stoca o valoare, apare o dilemă: dacă vreau să stochez valoarea 1 o stochez drept 00000001 00000000 sau 00000000 0000001? Pentru mai multe detalii despre aceasta problema, a se studia Endianness.

endian

Quote

Dar dacă vreau să stochez valoarea 100000?

La prima vedere ați zice că s-ar folosi un tip de date pe 3 bytes, însă (deoarece 3 nu e o putere a lui 2) un acest tip de date nu există (evident s-ar putea emula folosi un array de 3 char, de exemplu, dar nu-i optim). Se va folosi un tip de date pe 4 bytes (int în cazul unui sistem pe 32 biți), ce permite stocarea a 232 = 4294967296 valori distincte.

Dimensiunea tipurilor de date implicite nu este constantă, ci diferă funcție de sistem (tip de procesor). Pentru a verifica pe câți bytes este stocată valoarea dintr-un anumit tip de date, se poate folosi sizeof:

int *a = (int*)malloc(10 * sizeof(int)); //aloc memorie pentru 10 valori int, fără să țin eu minte cât ocupă fiecare


Quote

Dacă vreau să stochez mai multe valori?

Pentru a stoca mai multe valori, pe lângă evidenta soluție a declarării mai multor variable, mai există două soluții facile:

  • Utilizarea unui vector (array)
    int a[10]; //cele 10 valori sunt stocate în memorie una după alta
    
    
  • Utilizarea unei structuri
    struct tipStructura 
    {
    	char a;
    	char b;
    	char c;
    	int d;
    };
    
    
    Valorile membrilor sunt stocate în memorie tot una după alta, însă mai apare ceva aparte: padding (spații goale) cu zero.

Interpretarea datelor

Quote

Dacă vad, de exemplu, valorile hexa 14 1D 20 CC EF AC A0 A9, de unde stiu ce reprezintă? De unde stiu că sunt două int-uri fără semn și nu un vector de 4 short fără semn?

Răspunsul e simplu: nu știu. Atunci când cineva îmi oferă niște date (fie pe hârtie, fie pe un suport digital), acesta trebuie să-mi pună la dispoziție și modul în care ar trebui să interpretez acele date.

În continuare vreau să prezint un exemplu mai practic: cum citesc dimensiunile unei poze .bmp?

Fie poza .bmp din atașament. Dacă o deschid cu orice soft de vizualizare imagini, acesta îmi va arăta ca e vorba de o imagine de 1025x520 pixeli. Cum a citit însă programul acestă informație?

Dacă deschid cu un editor hex fișierul în cauză, nu înțeleg mai nimic din ce-i acolo:

Quote

42 4D 56 68 18 00 00 00 00 00 36 00 00 00 28 00
00 00 01 04 00 00 08 02 00 00 01 00 18 00 00 00
...

După ce încep însă să mă documentez despre structura unui astfel de fișier (http://en.wikipedia....BMP_file_format http://msdn.microsof...6(v=vs.85).aspx), se limpezesc apele.

Headerul care mă interesează începe după primii 14 bytes:

Quote

                                          28 00
00 00 01 04 00 00 08 02 00 00 01 00 18 00 00 00
...

Urmează apoi un DWORD (4 bytes) ce reprezintă biSize, iar apoi urează cele două valori ce mă interesează (width și height), fiecare stocate tot pe căte 4 bytes.

Astfel Width: 01 04 00 00; Height: 08 02 00 00. Tinând cont că sistemele de acasă folosesc little endian, cele două valori vor fi deci Width = 0x00000401 = 1025, Height = 0x00000208 = 520; adică exact cât indică și programele dedicate.

Attached Files



#2
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,236
  • Înscris: 24.02.2007
Stocarea șirurilor de caractere

Am văzut cum pot fi reprezentate numere în memoria calculatorului, iar acum se pune problema: cum reprezint o literă, un cuvând, o propoziție?

Să o luăm încet și să vedem mai întâi cum putem reprezenta o literă.

Varianta cea mai simplă ar fi asocierea fiecărei litere cu un număr: A = 0, B = 1, C = 2, etc. Cum, în alfabetul latin, nu avem decât câteva zeci de litere, un tip de date char ar fi suficient pentru a reprezenta o literă. Pentru mai multe litere, ar fi nevoie evident de un vector de char.

Quote

Atât, asta-i tot? Credeam că-i mai complicat...

E... acesta a fost doar vârful iceberg-ului :D.

Ca în cazul oricărei convenții, și în acest caz, prima problema de care ne-am lovi ar fi că, atunci când am transmite aceste valori unui alt sistem/program, acesta ar trebui să știe să le interpreteze în același mod, și nu, de exemplu, să considere Z = 0.

Soluția la această problemă este să nu începem să inventăm noi corespondențe între litere și cifre, ci să le folosim pe acelea inventate acum mulți ani de alții și devenite standard (a auzit toată lumea de ele). Un astfel de standard este ASCII și, precum se vede în tabelul de pe site, folosește valori între 0 - 127 pentru a stoca diverse simboluri, printre care litere mici, mari, cifre, semne de punctuație etc. O astfel de valoare încape deci într-o variabilă pe 8 biti, de tip char (ne amintim că aceasta poate stoca o valoare între -128 și 127).

Quote

Bun, dar cum folosesc acest standard ASCII, stau cu tabelul în față și scriu cod de genul char a = 65?

Nicidecum. Aici limbajul C/C++ ne vine în ajutor, și ne permite să scriem valoarea unui caracter între ghilimele simple, compilatorul știind apoi automat, pe baza standardului, despre ce valoare numerică e vorba.

char a = 'A'; /* este echivalent cu */
char b = 65;


Quote

Acum că știu cum se stochează o literă, cum stochez un cuvânt întreg?

Dacă un char stochează o literă, un vector de char va stoca un cuvânt întreg.

char cuvant[6] = {'C', 'u', 'v', 'a', 'n', 't'};


Se observă înșă imediat că această variantă nu este tocmai comodă: trebuie scris fiecare caracter separat, trebuie aflat numărul total de caractere, etc. Soluția constă în scrierea întregului șir de caractere (cuvântul în acest caz) între ghilimele duble.

char cuvant[] = "Cuvant";
char *cuvant = "Cuvant";


O diferență foarte importantă, și relativ ascunsă, între aceste două variante (declararea unui vector VS unui pointer) este că, în cazul variantei a 2-a, programul va crăpa dacă se încearcă modificarea vreunui caracter din zona respectivă de memorie. Pentru a evita acest lucru, cel mai bine înlocuim varianta a 2-a cu: (astfel compilatorul va da eroare dacă încercăm c[0] = 'c')

const char *cuvant = "Cuvant";


O problemă s-a rezolvat (nu mai trebuie scris fiecare caracter în parte între ghilimele), însă mai rămâne una: de unde știm lungimea caracterului? Atunci când scriem o funcție ce procesează un vector de întregi, îi specificăm cumva și dimensiunea acelui vector (să știe când să se oprească), însă, în cazul unui și de caractere, ar fi cam incomod să tot păstrăm & transmitem alături câte o variabilă conținând dimensiunea.

Soluția la această problemă constă în stocarea la finalul șirului de caractere a valorii 0. Nu cifra '0', ci valoarea 0. Astfel, când scriem

char cuvant[] = "Cuvant";


defapt compilatorul întelege

char cuvant[7] = {'C', 'u', 'v', 'a', 'n', 't', 0};


Astfel, fiecare funcție din librăria standard C (și nu numai), când parcurge valoare cu valoare șirul de caractere, se va opri când întălnește valoarea 0. Dacă șirul nu se termina cu acea valoare, se va citi o zonă interzisă din memorie, iar programul va crăpa. Această metodă nu este lipsită și de dezavantaje, determinarea lungimii șirului fiind o operație foarte costisitoare în cazul șirurilor lungi.

Înainte de a trece mai departe, vreau să atrag atenția că există o diferență între a stoca un șir de caractere în memorie și a-l afișa pe ecran. Pentru a-l afișa pe ecran, sistemul trebuie să știe și cum să deseneze efectiv forma fiecărui simbol, iar unele valori au o semnificație specială (de exemplu spațiul sau rând nou).

Quote

M-am uitat peste tabelul asta, dar nu văd niciunde cum scriu cu diacritice?

Aici începe să se complice treaba...

Da, 127 de valori sunt suficiente atunci când scriem în engleză, dar, pe măsură ce dorim alte caractere, ajungem să simțim primele lipsuri.

Quote

Dar stai, char stocheaza defapt 256 de valori, am putea folosi celelalte 128 pentru a memora diacritice

Întradevăr, aceasta este o posibilă soluție, dar se observă și în acest caz foarte repede limitările. Pentru a scrie un text cu alfabet chirilic poate fi ok, pentru a scrie unul cu litere grecești, din nou, dar, pentru a scrie un text combinat, iar nu mai ajung caracterele.

Următoarea abordare e din nou una destul de logică: daca 8 biți n-ajung, hai să folosim 16. Astfel un caracter nu mai este stocat folosind char, ci folosind un short (pentru care s-a introdus wchar_t drept sinonim). Astfel s-ar putea reprezenta 65535 valori (mult mai bine, avem de unde alege), finalul șirului fiind marcat tot cu o valoare 0 (în acest caz însă un 0 reprezentat pe 16 biți, adică echivalentul a două valori char ambele 0). Compilatorul ne permită să întroducem un astfel de șir de caractere utilizând prefixul L.

wchat_t a = L'Î';
wchat_t cuvant[] = L"Cuvânt";


Biblioteca standard C pune la dispoție funcții pentru a lucra și cu astfel de șiruri de caractere, ele având nume similar cu cele pentru șiruri ASCII: de exemplu wcslen() în loc de strlen().

Această abordare este una frecvent utilizată (de exemplu de Windows, intern), însă prezintă și ea un mare dezavantaj: dacă majoritatea caracterelor folosite sunt cele uzuale, ASCII, se irosește spațiu, memoria ocupată fiind dublă. Dacă numărăm toate caracterele cunoscute, ajungem la concluzia că numărul acestora depășeste 65535, și am avea nevoie deci de o reprezentare pe 4 bytes (int) pentru fiecare. În acest caz însă, dacă majoritatea caracterelor folosite sunt cele ASCII, s-a ocupa de 4x mai multă memorie decât ar fi necesar.

Mai există încă o abordare, ce încearcă să elimine dezavantajele stocării folosind 16 biți, și anume stocarea variabilă folosind encoding-ul UTF-8.

UTF-8 folosește 1 byte (8 biți) pentru stocarea caracterelor regăsite și în tabelul ASCII, și mai mulți bytes pentru celelalte caractere. Astfel un text scris în limba română, ce mai are pe ici pe colo câte ceva diacritice, va ocupa un spațiu mediu mult mai apropiat de 1 byte/caracter, decât de 2. Un text însă scris în chineză, va ocupa, în medie, mai mult de 2 bytes/caracter, soluția fiind astfel mai puțin eficientă decât varianta utilizării wchar_t.

Un alt dezavantaj al utilizării UTF-8 este faptul că, pentru a citi, de exemplu, caracterul al 100-lea, nu putem simplu folosi text[99], deoarece se poate ca respectivul să fie doar al 80-lea caracter, înaintea lui fiind poziționate caractere ce necesită mai mulți bytes.

Multe biblioteci operează cu șiruri de caractere în format UTF-8, așă că trebuie stăpânit și lucrul cu acestea.

#3
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,236
  • Înscris: 24.02.2007
De la stocarea arbitrară într-un fișier la stocarea într-o bază de date SQL

Persistența datelor

Până acum am văzut cum sunt ținute datele în memoria RAM a calculatorului, însă această memorie are un mare dezavantaj: este volatilă. Adica informațiile se pierde atunci cand memoria nu mai este alimentată (calculatorul este oprit).

Cum majoritatea datelor trebuie păstrate și după ce oprim calculatorul, s-au inventat diverse dispozitive de stocare ce păstrează datele și atunci când nu sunt alimentate cu energie electrică: harddisk, dischete, stick-uri usb etc.

Scrierea datelor în fișiere

Majoritatea celor care au scris ceva C au ajuns destul de repede să scrie și în fișiere, utilizând celebrele funcții fopen(), fprintf(), fwrite(), etc. Deasemenea s-a observat că există două mari abordari: fișiere text sau fișiere binare.

În continuare dorim să scriem următoarele date despre 3 elevi: nume, prenume, varsta.

  • Fișiere text - în cazul fișierelor text toate datele sunt interpretate drept șiruri de caractere, fiind astfel ușor de citit și de către om

    Ion, Popescu, 14
    Alin, Ionescu, 16
    
    

    Pentru a putea interpreta corect datele la citire, e important să delimităm într-un mod unitar înregistrările: în acest caz printr-un newline sunt delimitați elevii și prin ',' informațiile despre ei. Deasemenea trebuie păstrată ordinea informațiilor.

  • Fișiere binare - în cazul fișierelor binare, datele sunt stocate așa cum sunt reprezentate și în memorie. Cel mai bine se observă diferența în cazul numerelor, vârsta în acest caz fiind stocată sub forma unui singur byte (14, 0x0E), și nu sub forma unui șir de caractere format din 2 bytes ('1', '4').

    Separarea înregistrărilor se realizează și ea diferit, o posibilă abordare fiind stocarea lungimii înregistrării ce urmează, înaintea acesteia.

      -- lungime înregistrare elev (dimensiune constantă 2 bytes)
      |__________-- lungime prenume -- lungime nume__________________-- varsta (dimensiune constantă 1 byte)
      |__________|__________________|________________________________|
    0x0D 0x00 | 0x03 | 'I' 'o' 'n' 0x07 'P' 'o' 'p' 'e' 's' 'c' 'u' 0x0E
    
    

Până acum totul pare simplu și am fi tentați să credem că "that's all there is to it", însă următoarele întrebări ne vor pune pe gânduri și vom realiza cât de ineficientă este defapt această abordare. Considerăm că avem vreo 10.000 înregistrări

  • Cum fac să citesc înregistrarea #5165 ?
  • Cum găsesc rapid înregistrările elevilor Georgescu?
  • Cum elimim o înregistrare?
  • Cum mai adaug o informație (ex. adresă) la fiecare înregistrare

Rumegând puțin la aceste întrebări constatăm că soluțiile posibile (având în vedere actuala structură a datelor) sunt foarte ineficiente și presupun fie analizarea înregistrare cu înregistrare fie chiar rescrierea întregului fișier.

Soluția

Soluția în acest caz o reprezintă utilizarea unui SGBD (sistem de gestiune a bazelor de date) și a limbajului SQL. SGBD-urile acționează ca un intermediar între noi și datele efective. Ele stochează datele sub formă de tabele iar noi înteracționăm cu ele prin interogări: le cerem să creeze un anumit tabel cu o anumită structură, să insereze anumite date în tabel, să ne ofere datele din tabel, etc.

Un astfel de SGBD este SQLite, ajuns în prezent la versiunea 3.7.17 și disponibil pentru majoritatea platformelor. SQLite stochează datele într-un singur fișier pe disc și ne pune la dispoziție două variante pentru a interacționa cu acest fișier (nu, nu deschidem manual fișierul cu fopen și nici nu ne interesează structura sa internă, e treaba SGBD-ului cum își gestionează intern datele):

  • O aplicație tip linie de comandă sqlite3(.exe) ce ne permite executarea interogărilor și vizualizarea rezultatelor acestora.
  • O bibliotecă pentru a face același lucru din aplicația noastră

Crearea primei baze de date SQLite

În continuare vom folosi utilitarul sqlite3(.exe) pentru a crea o bază de date conținând aceleași informații despre elevi ca mai sus.

  • Crearea bazei de date

    d:\>sqlite3 elevi.db
    SQLite version 3.7.17 2013-05-20 00:56:22
    Enter ".help" for instructions
    Enter SQL statements terminated with a ";"
    sqlite>
    
    

  • Crearea primului tabel

    sqlite> CREATE TABLE elevi (id INTEGER PRIMARY KEY AUTOINCREMENT, nume TEXT, prenume TEXT, varsta INTEGER);
    

    • id - numarul de ordine al fiecărei înregistrări (1, 2, 3, ...), va fi incrementat automat (AUTOINCREMENT)
    • PRIMARY KEY - această coloană identifică fiecare rând, având o valoare unică

  • Inserarea datelor în tabel

    sqlite> INSERT INTO elevi (nume, prenume, varsta) VALUES ('Popescu', 'Ion', 14);
    sqlite> INSERT INTO elevi (nume, prenume, varsta) VALUES ('Ionescu', 'Alin', 16);
    sqlite> INSERT INTO elevi (nume, prenume, varsta) VALUES ('Popescu', 'Gheorghe', 15);
    
    

  • Afișarea datelor din tabel

    sqlite> SELECT * FROM elevi;
    id|nume|prenume|varsta
    1|Popescu|Ion|14
    2|Ionescu|Alin|16
    3|Popescu|Gheorghe|15
    
    

  • Căutarea înregistrărilor

    sqlite> SELECT * FROM elevi WHERE prenume = 'Ion';
    id|nume|prenume|varsta
    1|Popescu|Ion|14
    
    

  • Sortarea înregistrărilor & selectarea doar a anumitor coloane

    sqlite> SELECT nume, prenume FROM elevi ORDER BY nume ASC;
    nume|prenume
    Ionescu|Alin
    Popescu|Ion
    Popescu|Gheorghe
    
    

  • Ștergerea înregistrărilor

    sqlite> DELETE FROM elevi WHERE prenume = 'Anca';
    
    

  • Adăugarea unei noi coloane

    sqlite> ALTER TABLE elevi ADD COLUMN adresa TEXT;
    
    

  • Actualizarea înregistrărilor

    sqlite> UPDATE elevi SET adresa = 'Str. Principala Nr. 1' WHERE nume = 'Popescu';
    
    sqlite> SELECT * FROM elevi;
    id|nume|prenume|varsta|adresa
    1|Popescu|Ion|14|Str. Principala Nr. 1
    2|Ionescu|Alin|16|
    3|Popescu|Gheorghe|15|Str. Principala Nr. 1
    
    

Aceste exemple arată cât de flexibile pot fi interogările SQL. Pentru învățarea & aprofundarea acestui limbaj de interogare, un punct de pornire ar fi http://www.w3schools.com/sql/ .

Accesarea datelor dintr-o aplicație C

Va urma

#4
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,236
  • Înscris: 24.02.2007
Utilizarea unei baze de date în rețea

#5
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,236
  • Înscris: 24.02.2007
ODBC

#6
Paullik

Paullik

    Active Member

  • Grup: Members
  • Posts: 1,760
  • Înscris: 05.07.2008
Salut!

Am facut niste investigatii si nu pot intelege de ce toate valorile din BMP sunt stocate in big endian.

Am creat chiar un BMP cu GIMP, ca deh, am zis ca e dani.user mai cu mot, dar nu, si in BMP-ul meu toate valorile sunt stocate in big endian.
biWidth, biHeight, biPlanes campurile astea le-am verificat, dar si "the size of the BMP file in bytes" (al doilea camp din Bitmap File Header) este tot big endian, ceea ce e putin aiurea, deoarece pe wiki zice despre bitmap file header:

Quote

All of the integer values are stored in little-endian format (i.e. least-significant byte first)

Ca sa ma conving m-am uitat in sursa GIMP si spre surpriza mea am gasit o functie care face conversia din little in big endian:
https://git.gnome.or...bmp-write.c#n81

Iar functia este este folosita ca sa scrie dimensiunea aia in bitmap file header despre care pe wiki se zice ca ar trebui sa fie little endian:
https://git.gnome.or...mp-write.c#n431

Deci, da, totul e big endian, dar de ce?
De ce sa te complici cu conversie in big (la scriere) si cu conversie din big in little (la citire) cand poti sa scrii direct in little si sa citesti direct in little?

E ceva ce mi-a scapat mie?
Avand in vedere ca si pe windows (deduc asta din imaginea lui dani.user) si pe linux se comporta la fel, banuiesc ca e un fel de conventie, dar de ce?

#7
edy_3dz

edy_3dz

    Rau sau bun

  • Grup: Senior Members
  • Posts: 3,241
  • Înscris: 30.08.2008
In primul rand, functia aia FromL transforma un long de 4 bytes in format little endian. Daca te-ai uita mai atent ai vedea ca octetii mai putini semnificativi sunt pusi in fata.
Si in al doilea rand, endianess-ul nu este dat de sistemul de operare, ci de hardware.

Edited by edy_3dz, 14 June 2013 - 20:26.


#8
Paullik

Paullik

    Active Member

  • Grup: Members
  • Posts: 1,760
  • Înscris: 05.07.2008
@edy_3dz, multumesc, m-ai facut sa ma uit mai atent, mi-am dat seama ce greseam.

Eu ma uitam la fisierele alea si ziceam: "uite ma ca sunt big endian, ce porcarie", cand defapt erau little endian.
Cu ipoteza aia gresita am plecat si am tinut-o exact invers pe tot parcursul problemei, de acolo si impresia ca FromL transforma in big endian si vazusem si FromS si am zis: asta face un short in big endian si cealalta un long in big endian.

LE:
dani.user, keep up the good work, nu am citit foarte atent, dar imi place ca am vazut ceva practic acolo (chestia cu BMP-ul pe care am explorat-o si eu).

Edited by Paullik, 14 June 2013 - 21:19.


#9
George02

George02

    Member

  • Grup: Members
  • Posts: 356
  • Înscris: 09.01.2011
In primul rand vreau sa iti multumesc in numele meu si in numele celor care nu o fac pentru aceste minunate lectii de programare . Imi super plac si au si un pi de simt al umorului in ele .

In al doilea rand vin cu o rugaminte: Ce spui , ne faci si noua un tutorial despre bazele de date relationale ? Posted Image Posted Image Posted Image

#10
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,236
  • Înscris: 24.02.2007
Mersi de aprecieri.
Un tutorial despre bazele de date relationale n-am deocamdata in plan, doar ce prezint aici despre cum interactionezi cu ele din C.

#11
George02

George02

    Member

  • Grup: Members
  • Posts: 356
  • Înscris: 09.01.2011
Ok. Mersi pentru raspuns(raspunsuri) si pentru ceea ce faci pentru aceasta comunitate numita softpedia Posted Image Posted Image Posted Image

#12
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,236
  • Înscris: 24.02.2007
Să mai revigorez acest topic, propun următorul PROIECT cu rolul de a vă plimba prin mai multe domenii, de a vă arată ce înseamnă lucrul cu date. El are deasemenea rolul de a vă introduce în diverse tehnologii și de a arată că acestea sunt importante, nu atât limbajele folosite.

  • Să se realizeze o bază de date SQLite cu:
    • Elevii unei școli (nume, prenume, clasa, ...)
    • Materiile studiate de aceștia într-un an
    • Notele primite de fiecare elev în decursul anului

  • Să se realizeze o aplicație C ce ușurează gestiunea datelor mai sus menționate
  • Să se realizeze o aplicație C ce generează rapoarte/statistici pe baza datelor de mai sus (până la urmă de asta e o bază de date standard, să o poți accesa din mai multe locuri). Statisticile vor cuprinde, de exemplu, cel mai buni elevi din fiecare clasă (nume, prenume, media anuală) și vor fi exportate atât în format HTML cât și PDF.

  • Să se mute baza de date în MySQL pentru a ușura lucrul în rețea și să se adapteze programele mai sus menționate
  • Să se realizeze o aplicație C/C++ cu interfață grafică pentru administrarea datelor
  • Să se realizeze o aplicație web în C, folosind CGI, pentru administrarea datelor în rețea/pe net și generarea rapoartelor.


O parte din cerinte se pot rezolva folosind ce am prezentat deja aici, altele cu ce s-a arătat pe alte topicuri ale acestei arii, iar altele necesită încă ”puțintică răbdare” sau studiu pe cont propriu.

Anunturi

Bun venit pe Forumul Softpedia!

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

Forumul Softpedia foloseste "cookies" pentru a imbunatati experienta utilizatorilor Accept
Pentru detalii si optiuni legate de cookies si datele personale, consultati Politica de utilizare cookies si Politica de confidentialitate