[ marko.marezz @ 24.08.2010. 15:21 ] @
Imam problem sa citanjem binarnih podataka i funkcijom fread. binarni fajl koji citam je mesavina mnogo tipova podataka koji su predstavljeni u binarnom obliku.
naime podaci idu na primer ovako:
unsigned short unsigned short double double unsigned char i tako dalje (bez praznina,znaci podatak ide odmah za podatkom)
i sad ja lepo znaci treba da ucitam ceo taj binarni fajl u neku promenljivu,zatim da se pozicioniram sa fseek na neko mesto u datoteci, a onda sa fread da procitam izabrani tip podatka.
evo ga i moj kod koji sam pisao:
Code:

FILE*    f = fopen("ac12_003.log", "rb");
rewind (f);
fseek(f,pos[0]+4,SEEK_SET);
unsigned short foo;
fread(&foo,1,sizeof(foo),f);
printf("%u\n",foo); /*ovaj deo koda brlja i ne daje prave vrednosti. treba da dobijem 3600 umesto 4110*/
unsigned char foo1;
fread(&foo1,1,sizeof(foo1),f);
printf("%u\n",foo1); /* ovaj deo koda radi sasvim ok*/
double foo2;
fread(&foo2,1,sizeof(foo2),f);
printf("%f\n",foo2);/* ovaj deo koda takodje brlja i daje neke ogromneee vrednosti-gluposti tipa 1,2345 e+138*/


Pitanje je gde gresim kod citanja podataka tipa double,tipa unsigned short , tipa long? znam sta treba da dobijem. ovaj isti kod mi savrseno radi u MatLabu(jeste da se malo razlikuje,ali je jako slican programski jezik)
Znam neke osnovne stvari o programiranju u C++,ali sam pocetnik i nije mi jasno gde gresim. da li nesto ne valja u samim argumentima funkcije fread, ili funkcije printf. probao sam i sa std::cout<<foo<<std::endl; i isto dobijam, tako da sam poceo da sumnjam da je najverovatnije greska u samoj funkciji fread. trazio sam po internetu i nesto ne mogu da nadjem odgovarajuce resenje. vrlo jednostavan problem. ali nesto me koci. imao sam programiranje davno i dosta sam stvari zaboravio, a nemam koga ni da pitam,pa se mucim od sinoc kao gresan sa dusom sto rekao nas narod. svaka pomoc i sugestija je jako dobro dosla. neka izmena koda,bilo sta. molim Vas. hvala
[ Mihajlo Cvetanović @ 24.08.2010. 15:56 ] @
Očekivana vrednost 3600 je 0E10h, a aktuelna vrednost 4110 je 100Eh. Čini se da redosled bajtova u log fajlu nije prirodni x86 redosled, i zato čitanje lepo radi samo za jednobajtne podatke. Stranica na Code Projectu lepo objašnjava razne cake u vezi sa redosledom i zamenom mesta. Glasam za peti primer, makro ByteSwap5 u saradnji sa std::swap:

http://www.codeproject.com/KB/cpp/endianness.aspx
[ marko.marezz @ 25.08.2010. 12:26 ] @
Prvo hvala na brzom odgovoru, jos juce sam video,ali pokusavam da sam provalim kako radi kod. pa ako mozete da mi objasnite bune me neke stvari oko njega.
evo ga ceo kod:
funkcija:
Code:
#include <algorithm> //required for std::swap
#define ByteSwap5(x) ByteSwap((unsigned char *) &x,sizeof(x))
void ByteSwap(unsigned char * b, int n)
{
   register int i = 0;
   register int j = n-1;
   while (i<j)
   {
      std::swap(b[i], b[j]);
      i++, j--;
   }
}


Nije mi jasno sta znaci ovo register int ? sta definise i sta je to uopste? i sta znaci ovo kad imam (unsigned chat*) &x? Pitanja su sigurno glupa,ali ne mogu vise da lupam glavu.izvinite.
Sad me mnogo vise buni sama upotreba funkcije.

Code:
double* dArray; //array in big-endian format
int n; //Number of elements
for (register int i = 0; i <n; i++) 
   ByteSwap5(dArray[i]);


Znaci ovako. Kao ulazni argument u funkciju ByteSwap5 je tip pokazivac na double (*dArray)? a gore u definiciji funkcije je tip unsigned char? to mi nije jasno kako je moguce. Drugo nije mi jasno sta se desava sa ovim n? sta ono predstavlja. Jel to broj bajtova? ili je broj elemenata niza double koje hocu da prevedem?rekao bih da je broj bajtova jer kad stavim da je n=8 onda dobijem dobar rezultat.
Evo ga moj kod koji prijavljuje gresku. posle cu napisati i koju.
Code:

double dHelp; /*neka pomocna promenljiva*/
fread(&dHelp,1,sizeof(double),f); /*procitam tu promenljivu*/
double* dArray; //array in big-endian format
dArray=&dHelp;  
int n=8; //Number of elements---kojih elemenata???
for (register int i = 0; i <n; i++) {  /*sta je ovo register int????*/
ByteSwap5(dArray[i]);}    /*i ovo me buni kako je sad odjednom dArray niz? a gore je definisan kao pokazivac. skoro sam siguran da je ovde negde greska*/
printf("%f", *dArray);

dobijem tacan razultat,prikazem ga na cout,ali mi program prijavi gresku ovog tipa:
Unhandled exception at 0x001321c3 in program.exe: 0xC0000005: Access violation reading location 0x339a7eb4
moze li pomoc oko ovoga? sam ucim neke stvari i ne mogu ako mi neko malo samo ne pomogne?
mozda imam gresku negde drugde u programu? ali cim to stavim pod komentar sve radi kako bi trebalo.
za unsigned short sam nasao na internetu da postoji funkcija _byteswap_ushort(value), pa sa tim nisam imao problema.
hvala

[ Mihajlo Cvetanović @ 25.08.2010. 12:56 ] @
Zaboravi na ključnu reč register i obriši je u svom kodu. To se autor pravio pametan, a u pitanju je naznaka kompajleru da optimizuje kod tako što će dotičnu promenljivu da drži u nekom od internih procesorskih registara umesto u memoriji. Kao da kompajler ne zna svoj posao.

Kastovanje (unsigned char*)&x u opštem slučaju nije po C++ standardu, ali eto može da se koristi. Iako to nije po standardu ti možeš svaki pointer na bilo šta da "posmatraš" kao pointer na bilo šta drugo (u ovom slučaju pointer na unsigned char). Ovde je to korisno jer std::swap očekuje kao parametere dve unsigned char promenljive. Ako na primer dodeliš nekom double x = 3.14 to će u memoriji zauzeti 8 bajtova sa vrednostima 40 09 1E B8 51 EB 85 1F (bar se nadam, ovo sam izvukao iz C# uz pomoć BitConverter klase... nebitno). To što je u memoriji može da se posmatra i kao niz od osam bajtova, zar ne? E sa ovim kastovanjem smo upravo i rekli kompajleru da to tako posmatra.

Zaboravi i na for petlju koja je data u primeru, to je bio samo primer. Ako imaš neku promenljivu x kojoj treba zameniti bajtove onda samo pozovi ByteSwap5(x) i toj promenljivoj će biti zamenjeni bajtovi. Drugim rečima:

Code:
double foo;
fread(&foo,1,sizeof(double),f);
ByteSwap5(foo);
printf("%lf", foo);


Obrati pažnju na printf format, %lf je za double, a %f je za float.
[ marko.marezz @ 29.08.2010. 15:44 ] @
sad malo bezim sa teme, ali dobro sta da se radi,necu da otvaram drugu :-*
zasto kad sam lepo definisao konstantu pi, kao:
#define pi 3.141592653589793238462643F
i kad je pomnozim sa nekim podatkom tipa float, kao na primer:
broj=broj*pi;
gde je ovo broj podatak tipa float, dodje do gubitka tacnosti. odnosno nekoliko prvih brojeva posle tacke se poklapa i posle toga pocinje nesto nebulozno? gd egresim i da li je moguce izbeci ovakav gubitak podataka?znam da imam gubitak tacnosti jer imam iste brojeve u MatLabu,a njemu mnogo verujem ;-) hvala i jos jednom kazem,izvinjavam se sto sam otisao sa teme. Hvala za prosli odgovor mnogo je pomogao :-)
[ Mihajlo Cvetanović @ 29.08.2010. 17:34 ] @
Float nije mnogo precizan, koristi double. Ako te ni double ne zadovoljava onda moraš da koristiš neku dodatnu biblioteku za precizno računanje.