[ kajla @ 27.06.2001. 17:18 ] @
Da li neko moze da objasni kako funkcija fwrite() smesta podatke u fajl ako mu se kao prvi agrument da adresa strukture (struct). Evo ako neko moze na sledecem prostom primeru da objasni po kojoj logici previ fajl "housfile" odnosno, po kojoj logici ja mogu da ga citam (za hex viewer-om)
Sledeci primer je kompajliran i u DOS (Trubo C) iu Linuxu (GCC), fhread.c:

#include <stdio.h>
#include <string.h>
#define YES 1
#define NO 0

main()
{
FILE *f;
struct proba
{
unsigned int gas : 1; /* 1 bit */
unsigned int air : 1; /* 1 bit */
unsigned int dish : 1; /* 1 bit */
unsigned int wash : 1; /* 1 bit */
unsigned int block : 8; /* 8 bita */
unsigned char lot[6];
}input;

if ((f=fopen("housfile","w"))==(FILE *)NULL)
{
printf("Cannot create file "housfile"n");
exit(1);
}

input.gas=YES;
input.air=YES;
input.dish=NO;
input.wash=YES;
input.block=23;
strcpy(input.lot,"5a");
fwrite(&input,sizeof (struct proba),1,f);

fclose(f);

if ((f=fopen("housfile","r"))==(FILE *)NULL)
{
printf("Cannot open "housfile"n");
exit(1);
}

while (fread(&input,sizeof (struct proba),1,f)!=0)
{
printf("BLOCK: %d LOT: %sn",input.block,input.lot);
printf("GAS HEAT: %s CENTRAL AIR: %sn",input.gas==YES ? "YES" : "NO",
input.air==YES ? "YES" : "NO");
printf("DISHWASHER: %s WASHER-DRYER: %sn",input.dish==YES ? "YES" : "NO",
input.wash==YES ? "YES" : "NO");
puts("***********");
}

fclose(f);
}
/*
program output:

BLOCK: 23 LOT: 5a
GAS HEAT: YES CENTRAL AIR: YES
DISHWASHER: NO WASHER-DRYER: YES
***********

Fajl "hausfile" izgleda ovako:
"\x7b\xf1\x35\x61\x00\xd9\x00\x40" (u Linux-u)
"x7b\x01\x35\x61\x00\x01\x00\x00" (u DOS-u)
ukupno 8 bajta koliko je i velicina struct proba (sizeof (struct proba)).
*/
[ Vojislav Milunovic @ 27.06.2001. 19:54 ] @
Naime fread/fwrite sluze za rad sa binarnim fajlovima.Poenta je da ce svaka druga funkcija za rad na strimovima zavrsiti citanje kad naidje na kraj stringa 0x00 ili na n (fscanf).Tu nastupa nas prijatelj. fwrite/fread ... naime ove dve funkcije su klasican primer read/write syscall.
Kod ovih funkcija nije vazno da li je memorija 0x00 terminarana (string) vec je vazno koliko kopiraju sa nekog mesta u memoriji.Na taj nacin je moguce pisati strukture u file i stvarati neku vrst baze podataka wtmp (za logovanje) ili bilo sta.

Znaci fwrite ce pistai u file sa neke memorijske adrese toliko i toliko bytova.U tvom primeru otvoren je file u koji treba upisati strukturu koja je popunjena sa podacima.Normalno podaci su sa 0x00 sto vec cini file binarnim.

Code:

     size_t
     fread(void *ptr, size_t size, size_t nmemb, FILE *stream)


1. argument je memorijska adresa na koju se upisuje procitano
2. je velicina jednog bloka te memorije
3. argument je broj blokova (znaci ukupno 2arg * 3arg = ukupno_byte )
4. argument je file otvoren sa fopen()

Code:

     size_t
     fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)


Znaci isto je i ovde samo sto je ptr sada adresa sa koje se podaci upisuju u file

Znaci u ovom tvom primeru :
Code:

fwrite(&input,sizeof (struct proba),1,f);


Pisati sa memorijske lokacije gde se nalazi ova struktura input,velcinina bloka = velicina strukture,upisati jedan blok u FILE *f i posle na isti nacin mozes da procitas to.Samo koristi fread()

[Ovu poruku je menjao predator dana 06-27-2001 u 06:56 PM GMT]
[ kajla @ 27.06.2001. 23:26 ] @
Ma znam ja kako ovaj primer radi, nego ono sto mene zanima je sledece:

pomocu ovog primera sam napravio binarni fajl "hausfile", e sada kako ja SAMO pomocu Hex Viewer-a(nekoristeci se C-om) da vidim koje su vrednosti svakog clana strukture.
[ Vojislav Milunovic @ 27.06.2001. 23:44 ] @
Pa tako nesto ne moze...mislim moze ali moras da znas tacno sta i gde se nalazi u toj strukturi.Neverujem da ces bas da rekonstruises sav taj dump file u binarno pa da onda odredujes sta ide u koji clan (imas bit clanove u ovoj struktur).

Zato se uvek naprave dva programa:
1. za pisanje u dati file
2. za citanje

ili oba u jednom 2 in 1
[ kajla @ 28.06.2001. 22:36 ] @
Citat:
predator je napisao:
Pa tako nesto ne moze...mislim moze ali moras da znas tacno sta i gde se nalazi u toj strukturi.Neverujem da ces bas da rekonstruises sav taj dump file u binarno pa da onda odredujes sta ide u koji clan (imas bit clanove u ovoj struktur).

Pa na koju foru rekonstruise fread()?

Kolko sam ja nesto gledao fajl:

"x7bx01x35x61x00x01x00x00" (DOS)

u prva dva bajta su stmestene prvih pet varijablu u strukturi(gas,air,wash,dish,block), a u preostalih 6 bajta je stmestena varijabla lot.

sada kad prevedes u binarno ta dva bajta:

01111011 00000001

sada posto su vrednosti prvih pet varijabli sledece(binarno):


input.gas=1(YES);
input.air=1(YES);
input.dish=0(NO);
input.wash=1(YES);
input.block=10111(23);

sad ti provali koji bit ide kojoj varijabli?
[ Vojislav Milunovic @ 29.06.2001. 15:10 ] @
Pa sa neke promenljive upises nesto i posle to procitas na tu promneljivu...isto ce da se popuni.

znaci struct ovaj tvoj kad upises i posle kad ga procitas podaci iz fajla ce memoriju te strukture popuniti onako kako si upisao;

Imas
struct pera{
int gg;
char bb;
};

kad popunis ovu strukturu i nju upises u file to se podaci sa te memorijske lokacije upisuju u file.
Kada procitas to iz file-a na tu memorijsku lokaciju,struktura se sama popuni.
Kao da imas niz:
voja
predator

i to je tako upisano u file i kad procitas to opet ces imati:
voja
predator

na nekoj memorijskoj lokaciji
[ kajla @ 30.06.2001. 23:57 ] @
Dobro, dobro....ali kako onda radi funkcija koja stampa odredjen clan strukture. Jer ona nekako mora da vidi koje bite da pokupi i istampa ih.

poz.
[ Vojislav Milunovic @ 01.07.2001. 01:08 ] @
Pa nema tu niakke funkcije koja ce to da stampa osim main().
Otvoris taj file...popunis strukturu sa tim podacima iz file-a,onda samo uradis

printf("%dn",struktura->godine);

i to je cela mudrost...
[ kajla @ 01.07.2001. 12:09 ] @
Da zanam to.

poz.
[ tOwk @ 01.07.2001. 16:12 ] @
Prvo jedan savet: da bi se lakše čitala struktura iz nekog hex editora, dodaj 4 rezervisana bita posle 4 polja po jedan bit (npr. unsigned int rez:4; ), ili prebaci ta 4 polja na kraj strukture. Ovo se može rešiti i dodeljivanjem podatku block, umesto :8 dužine, tipa unsigned char (znači unsigned char block;) - tada kompajler automatski poravna početak block podatka na 8 bita.
U ovakvom slučaju je moguće čitati strutkturu veoma jednostavno iz hex editora. Tada bi fajl izgledao nešto kao (X stoji tamo gde može svašta biti):

"xXbx17x35x61x00xXXxXXxXX"

Prvi bajt, i to njegova 4 "low-order" bita bi sadržala svaki po odgovarajuću vrednost (b=11=1+2+8, znači bitovi 0, 1 i 3 - gas, air i wash). Sledeći bajt bi sadržao vrednost block, a zatim bi sledilo 6 bajtova sa vrednošću "5a" (ovo znači null-terminated string - tri bajta, 0x35, 0x61, 0x00), a ostatak tih 6 bajtova bi bio popunjen đubretom iz memorije (zbog toga i razlika između DOS i Linux ispisa).

Preporučen oblik strukture:

Code:

 struct proba
 {
  unsigned int gas : 1;   /* 1 bit  */
  unsigned int air : 1;   /* 1 bit  */
  unsigned int dish : 1;  /* 1 bit  */
  unsigned int wash : 1;  /* 1 bit  */
  unsigned char block; /* 8 bita */
  unsigned char lot[6];
 } input;



Ukoliko nije moguće ovako izmeniti sastav strukture, ona se može iščitati na sledeći način.


Citat:
Code:
"x7bxf1x35x61x00xd9x00x40" (u Linux-u)
"x7bx01x35x61x00x01x00x00" (u DOS-u)



U prvom bajtu razdvojimo njegove high- i low-order delove od po 4 bita: 0x7 i 0xb. Na isti način kao i prethodno, 0xb se dekodira na gas, air i wash uključene, a dish isključen. Ali sada 0x7 predstavlja low-order deo od 4 bita od polja block, a high order deo od 4 bita polja block se nalazi u drugom bajtu, na prva 4 bita - 0x1. Razlika između Linux i DOS fajla ne postoji, pošto se high-order 4 bita na Linux-u puni đubretom, a u DOS-u se nulira (ili ne??), što ide u prilog dobroj optimizaciji GCC-a pod Linux-om.

Dalje, pošto char tip zahteva poravnavanje na 8-bita (njegova veličina), tih 4 high-order bita u drugom bajtu se ne koristi u svakom slučaju. Zatim slede karakteri 0x35 ('5') i 0x61 ('a'), kao i null karakter (0x0). Ostala tri bajta su đubre.

Prema tome, da bi uspešno iščitao ovakav fajl iz hex editora, potrebno je dovoljno brzo baratati jednostavnom hex aritmetikom, kao i lako pretvarati hex brojeve u binarne (a to se lako i radi, zato se oni i koriste).

Toliko.
[ Vojislav Milunovic @ 01.07.2001. 20:13 ] @
Cek a sto bi se covek jebavao da sam provali sta gde ide kad moze da napise program u C od 5-6 linija koji ce mu popuniti tu struktur ;o)
Mislim nije nemoguce da se to uradi ali je dosaadno...Uzmes papir i nacrtas tu strukturu recimo u blokovima i onda ides bit po bit piskaras po tim blokovima...ali stvarno to je dosadno i nicemu ne vodi ;o)
[ kajla @ 05.07.2001. 18:11 ] @
pa predatore, recimo da hocu da citam taj fajl iz programa koji je pisam u drugom programskom jeziku koji nema fread()? Ako znam kako izgleda struktura mogao bi da napravim funkciju koja to radi.


poz.
[ kajla @ 05.07.2001. 18:17 ] @
Citat:
tOwk je napisao:
Prvo jedan savet: da bi se lakše čitala struktura iz nekog hex editora, dodaj 4 rezervisana bita posle 4 polja po jedan bit (npr. unsigned int rez:4; ), ili prebaci ta 4 polja na kraj strukture. Ovo se može rešiti i dodeljivanjem podatku block, umesto :8 dužine, tipa unsigned char (znači unsigned char block;) - tada kompajler automatski poravna početak block podatka na 8 bita.
U ovakvom slučaju je moguće čitati strutkturu veoma jednostavno iz hex editora. Tada bi fajl izgledao nešto kao (X stoji tamo gde može svašta biti):

"xXbx17x35x61x00xXXxXXxXX"

Prvi bajt, i to njegova 4 "low-order" bita bi sadržala svaki po odgovarajuću vrednost (b=11=1+2+8, znači bitovi 0, 1 i 3 - gas, air i wash). Sledeći bajt bi sadržao vrednost block, a zatim bi sledilo 6 bajtova sa vrednošću "5a" (ovo znači null-terminated string - tri bajta, 0x35, 0x61, 0x00), a ostatak tih 6 bajtova bi bio popunjen đubretom iz memorije (zbog toga i razlika između DOS i Linux ispisa).

Preporučen oblik strukture:

Code:

 struct proba
 {
  unsigned int gas : 1;   /* 1 bit  */
  unsigned int air : 1;   /* 1 bit  */
  unsigned int dish : 1;  /* 1 bit  */
  unsigned int wash : 1;  /* 1 bit  */
  unsigned char block; /* 8 bita */
  unsigned char lot[6];
 } input;



Ukoliko nije moguće ovako izmeniti sastav strukture, ona se može iščitati na sledeći način.


Citat:
Code:
"x7bxf1x35x61x00xd9x00x40" (u Linux-u)
"x7bx01x35x61x00x01x00x00" (u DOS-u)



U prvom bajtu razdvojimo njegove high- i low-order delove od po 4 bita: 0x7 i 0xb. Na isti način kao i prethodno, 0xb se dekodira na gas, air i wash uključene, a dish isključen. Ali sada 0x7 predstavlja low-order deo od 4 bita od polja block, a high order deo od 4 bita polja block se nalazi u drugom bajtu, na prva 4 bita - 0x1. Razlika između Linux i DOS fajla ne postoji, pošto se high-order 4 bita na Linux-u puni đubretom, a u DOS-u se nulira (ili ne??), što ide u prilog dobroj optimizaciji GCC-a pod Linux-om.

Dalje, pošto char tip zahteva poravnavanje na 8-bita (njegova veličina), tih 4 high-order bita u drugom bajtu se ne koristi u svakom slučaju. Zatim slede karakteri 0x35 ('5') i 0x61 ('a'), kao i null karakter (0x0). Ostala tri bajta su đubre.

Prema tome, da bi uspešno iščitao ovakav fajl iz hex editora, potrebno je dovoljno brzo baratati jednostavnom hex aritmetikom, kao i lako pretvarati hex brojeve u binarne (a to se lako i radi, zato se oni i koriste).

Toliko.


pa i ja sam mislio da tako moze, al ne moze. Zapravo napravio sam nekoliko probnih fajlova i koristeci hex editor, i probao da ih iscitam takvom logikom, ali nisam dobijao tacne rezultate.

Sto se tice hex aritmetike - pretvaranje hex u bin i bin u dex je jednostavno. (u svakom slucaju uvek se moze posluziti digitronom)


poz.
[ Vojislav Milunovic @ 06.07.2001. 14:15 ] @
Citat:
kajla je napisao:
pa predatore, recimo da hocu da citam taj fajl iz programa koji je pisam u drugom programskom jeziku koji nema fread()? Ako znam kako izgleda struktura mogao bi da napravim funkciju koja to radi.


Pa pisi ti slobodno u drugom programskom jeziku ;o)
Pa nije valjda da ti mislis da zavisno od progrmskog jezika su funkcije za pisanje u file?
Gresis tu se koriste u Windowsu API funkcije samog OSa a u UNIXu su to read/write pa tako da se svi read/write sto se tice filova vrse preo ovih systemskih poziva a gcc samo to malo uprosti za korisnika (fread,fscnaf itd)
[ kajla @ 06.07.2001. 19:50 ] @
Aj ti mi napravi funkciju za citanje ovog fajla u QBasic 1.0 (DOS).


poz.
[ Vojislav Milunovic @ 06.07.2001. 20:35 ] @
Za BASIC imas forum Visual Basic pa tamo postavi to pitanje!

[Ovu poruku je menjao Gojko dana 07-09-2001 u 07:14 AM GMT]