Avatar billede hurra Novice
15. april 2009 - 12:48 Der er 7 kommentarer og
1 løsning

Binær log fil

Jeg er stødt i et problem, som jeg ikke helt kan forstå hvis jeg er den eneste der har haft. Til trods for det, kan jeg ikke finde noget på nettet om det.

Mit problem er, at jeg skal skal have gemt noget data i en fil. Da det er ret store data mængder, kunne jeg godt tænke mig at dataen bliver gemt binært.

Min log funktion tager en formaterings string + et variabelt antal argumenter. e.g.

Log("Resultat[%d]: %f", 1, 2.345);

Selve stringen vil jeg altså ikke bruge til noget(i hvert fald ikke i denne omgang), det er de variable argumenter der skal gemmes i min log fil, og det skal ikke stå som ascii tegn, som

fprintf("Resultat[%d]: %f", 1, 2.345);

Findes der en smart måde at gøre dette på? Hvis ikke, bliver det så ikke lidt af et hyr at kikke formaterings stringen igennem, og så skrive fra 1 (char) til 10 (double) bytes for hver argument? Og bliver dette afhængig af platform arkitekturen (32 eller 64 bit)? Er min tanke der over hovedet rigtigt?

Det næste problem er, hvordan læser jeg dette data igen? Jeg skal jo ha en måde at hvornår en 'linie' stopper, men jeg kan jo ikke lave en 0 termineret linie, da 0 også er en valid integer værdi.

Jeg mener at kunne huske at der er en 'serializable' methode i cli, men det hjælper mig nok ikke, da jeg skal lave mit program i gcc.
Avatar billede hurra Novice
15. april 2009 - 12:52 #1
Alternativ, forresten, kunne jeg jo i min Log methode strippe formaterings strignen for alt andet end '%EtEllerAndet'. Og så bruge fprintf til kun at skrive det variable argument.
Log("Resultat[%d]: %.3f", 1, 2.345);

Skulle så bliver til
fprintf("%d %f", 1, 2.345);

Men dette giver mig stadig mere data aå skulle logge, så jeg vil stadig hellere bruge den binære løsning.
Avatar billede arne_v Ekspert
15. april 2009 - 15:07 #2
C tillader ikke reflection.

Lav en enum med data typer og log som:

Log("dummy", INT, 1, DOUBLE, 2.345);

og saa lad din Log switche paa de enum vaerdier.
Avatar billede hurra Novice
15. april 2009 - 22:21 #3
Jeg være været lidt inde på den tanke. Jeg har lavet en funktion til at finde typerne af de enkelte argumenter, ud fra formaterings stringen.

Selvføldig vil din løsning, arne_v, være hurtigere, da der ikke er string behandlingen.

Der er ikke nogen måde hvor jeg kan starte med at tælle størrelsen af mine argumenter, e.g. for int + double = 4 + 10 = 14 bytes, og så bare

va_list args;
for(unsigned char i=0; i<14; ++i)
  fputc(filehandle, ((char*)args)[i]);

?

Og så igen på samme måde når jeg skal parse min log fil:
va_list args;
for(unsigned char i=0; i<14; ++i)
  fgetc(filehandle, ((char*)args)[i]);
vprintf(str, args);

?

Hvis ikke nogle af ovenstående virker, regner jeg med at jeg skal bruge va_arg til at plukke de enkelte argumenter og skrive dem til loggen. Hvad så når jeg skal parse log filen, er der så en måde at samle en va_list igen?
Avatar billede arne_v Ekspert
15. april 2009 - 22:36 #4
C sender bare en adresse over - du kan ikke se hvad data type det er eller hvor stor de data er.

Ah - at de skal laeses igen er jo en vigtig pointe !

Hvis det skal vaere passende fleksibelt skal du nok lade:

Log("dummy", INT, 1, DOUBLE, 2.345);

skrive:

1 char med 2
1 char med INT
1 int
1 char med DOUBLE
1 double
Avatar billede hurra Novice
15. april 2009 - 23:04 #5
Ja, at gemme ubrugeligt data ville der ikke være meget point i :)

Jeg fangede godt pointen i at jeg i va listen ikke kan se størrelsen af elementerne. Men jeg har jo størrelsen aligevel, hvis jeg bruger enum listen som du skriver.

Men problemet er så måske, at en va liste bare er en række pointere til de enkelte elementer ???

Nu er jeg måske også bare træls, jeg syntes jeg bliver ved med at spørge om det samme, og du prøver meget pedagoisk at for klare mig at jeg tager fejl :) Jeg tror bare jeg mangler (mindst) en brik i min forståelse af dette.

Når man lavet en funktions kald, er det så ikke rigtigt at alle argumenterne bliver pushed ud på stacken? Hvis de bliver det, ligger de så ikke også i rækkefølge? lige til at læse fra ende til anden, og skrive i en exempelvis en fil? Selvføldig skal jeg så vide hvor meget der er blevet pushed (både antal og størrelse af argumenter).

Når så jeg skal læse min fil igen, kan jeg så ikke pushe elementerne fra min fil tilbage på stacken, og bruge printf på helt normal vis?
Avatar billede arne_v Ekspert
16. april 2009 - 04:33 #6
En va liste er logisk set antal argumenter samt adresserne på argumenterne.

Den præcise implementation af et funktionskald varierer:
- nogle gange sendes argument over i et register
- nogle gange sendes adressen på argument over i et register
- nogle gange sendes argument over via stak
- nogle gange sendes adressen på argument over via stak

C's va er lavet så den kan implementeres på alle platforme.
Avatar billede hurra Novice
20. april 2009 - 09:18 #7
Så har jeg fået lavet noget der virker. Det bleve rimelig meget som du foreslå, arne_v.

1 int med string id
1 char med 2
1 char med INT
1 char med DOUBLE
1 int
1 double

Der er ikke noget problem i at skrive filen, men der er lidt bøvl med at få den rigtige string skrevet ud igen.

Når jeg skal skrive stringen ud igen, deler jeg den op i mindre stykker, hver med indeholdende kun én formatering parameter, e.g.
"Resultat[%d] = %.2f V"
bliver delt op i
"Resultat[%d" + "] = %.2f" + " V"

Jeg kan så parse parametrene en efter en, og få "løst" stringen.

Tak for hjælpen, og ikke mindt ihærdige forsøg på at få mig til at forstå. Kommer du ikke lige med at svar, så du kan få nogle points?
Avatar billede arne_v Ekspert
20. april 2009 - 14:58 #8
svar
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester