• Liebe User, bitte beachtet folgendes Thema: Was im Forum passiert, bleibt im Forum! Danke!
  • Hallo Gemeinde! Das Problem leidet zurzeit unter technischen Problemen. Wir sind da dran, aber das Zeitkontingent ist begrenzt. In der Zwischenzeit dürfte den meisten aufgefallen sein, dass das Erstellen von Posts funktioniert, auch wenn das Forum erstmal eine Fehlermeldung wirft. Um unseren Löschaufwand zu minimieren, bitten wir euch darum, nicht mehrmals auf 'Post Reply' zu klicken, da das zur Mehrfachposts führt. Grußworte.

binary daten in c/c++

Mitglied seit
09.11.2002
Beiträge
880
Reaktionen
0
Hallo erstmal.
Ich habe da ein kleines Problem, nämlich eine Datei die reine Binärdaten enthält. Soweit so gut, nur: Die Datei wurde mit einem FORTRAN-Programm geschrieben und enthält Zahlen mit verschiedener floting point Genauigkeit. Die will ich mit C in double Variablen einlesen. Wie geht das?

Aufbau der Datei:
2 byte integer wert (gibt an, wieviele floating point werte folgen)
4 byte floating point
...

Meine Idee: Ich lese 2 byte in einen buffer, mittels 256*1.byte + 2.byte bekomme ich daraus den integer wert. das funktioniert auch wie erwartet - denke ich, zumindest bekomme ich einen sinnvollen wert, wobei das umgekehrte auch relativ sinnvoll ist, also little vs big endian...

Aber danach kann ich ja nur byteweise einlesen, also wie mache ich aus 4 byte in einem buffer einen double mit sizeof(double)=8?
gibt es da konvertierungsroutinen oder muß ich jetzt selber per hand eine schreiben - was blöd wäre, weil ich - im gegensatz zu int, char, long, etc - a priori erstmal gar nicht weiß wie ein double überhaupt aufgebaut ist.

Code:
bool Fitwindow::readModelFile(QString s)
{
	QFile file(s);
	file.open(QIODevice::ReadOnly);
	QDataStream stream(&file);
	char buf[2];
	stream.readRawData(buf,2);
	int nf = buf[0]*256+buf[1]
	
	double *wave = (double *) malloc(nf*sizeof(double));
	
	for (int i=0; i<nf; i++) {
		stream.readRawData( ((char *) &wave[i]), 4); // funktioniert natürlich nicht, aber wie sonst?
	}
	
	file.close();
	free(wave);
	return true;
}

hmm, hoffe mein problem ist einigermaßen klar.

Zusammenfassung:
Wie lese ich aus einer datei binärdaten, deren größe nicht unbedingt der größe von float oder double entspricht?
das ist doch sicher kein Problem mit dem nur ich alleine dastehe, da muß es doch lösungen geben?
Danke sehr!
 
Mitglied seit
01.06.2007
Beiträge
761
Reaktionen
0
http://www.captain.at/howto-java-convert-binary-data.php

Is zwar für Java, aber vielleicht kannst damit ja was anfangen ;)

Ich seh eigentlich nur zwei Probleme:

return Double.longBitsToDouble(accum);

&

return Float.intBitsToFloat(accum);

Das sind leider nativ implementierte Methoden, daher weiß ich nicht genau was die machen. Vielleicht hilft dir die Beschreibung in der API weiter http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Double.html#longBitsToDouble(long)
 
Mitglied seit
21.07.2002
Beiträge
545
Reaktionen
0
Als float einlesen und dann hinterher in doubles umwandeln falls nötig ist sicherlich die einfachste methode. Ansonsten kannst du dir auch das floating-point format für 4 byte und 8 byte raussuchen und dann aus den 4 byte die du aus der datei kriegst dein 8 byte double per bit-operatoren zusammenbasteln, sinn macht das aber nicht.

Und hm, gewöhn dir für C++ direkt new/delete statt malloc/free an, auch wenns hier jetzt keinen unterschied macht.
 

ROOT

Technik/Software Forum, Casino Port Zion
Mitglied seit
17.11.2002
Beiträge
7.052
Reaktionen
38
Ort
MS
Original geschrieben von Invincible[UFF]
Als float einlesen und dann hinterher in doubles umwandeln falls nötig ist sicherlich die einfachste methode.

#2.

new oder malloc ist übrigens Geschmackssache, auch in C++ macht malloc Sinn, vor allem wenn man kein Bock auf großes Exceptionhandling hat. Der Nullpointer-Test funktioniert nämlich nur mit new(nothrow) zuverlässig, und das wird nicht wirklich überall unterstützt.
 
Mitglied seit
09.11.2002
Beiträge
880
Reaktionen
0
Danke! Also float einlesen... aber wenn sich der Rechner ändert, auf dem ich daß kompiliere, wenn float also zB zu groß wäre?
Ich dachte halt es wäre einfach getan mit Angeben wieviele Bytes es sein sollen und diesen Buffer mit n Bytes dann nach double casten.
Vor allem auch, weil sich das binärdatenformat ändern kann, und ich also ziemlich verwickelte funktionen bauen müßte um das alles abzudecken. da wäre ein einfaches "nimm die nächsten 4 byte auf dem puffer und mache daraus ein double, so groß wie es auf diesem system halt ist" schon komfortabel.

Ach ja, und danke für den Hinweis wegen malloc(). Ich verwende es trotzdem - und es funktioniert sogar :-)

Danke und gute Nacht!
 
Mitglied seit
09.11.2002
Beiträge
880
Reaktionen
0
Mitglied seit
21.07.2002
Beiträge
545
Reaktionen
0
Original geschrieben von Meta-Tron
Danke! Also float einlesen... aber wenn sich der Rechner ändert, auf dem ich daß kompiliere, wenn float also zB zu groß wäre?

Das sollte nicht passieren, weil zumindest float und double soweit standardisiert sind.

Ach ja, und danke für den Hinweis wegen malloc(). Ich verwende es trotzdem - und es funktioniert sogar :-)

Danke und gute Nacht!
Ich sag ja nicht dass es nicht funktioniert, es ist nur in 99% der Fälle nicht optimal.

In fällen wie dem von dir oben mag es ja egal sein, aber schon allein dass du dich nicht immer fragen musst "hm, geb ich den Speicher hier jetzt mit free oder mit delete frei ?" spricht dafür einfach bei einer der beiden Varianten zu bleiben und dann hat new insgesamt diverse vorteile:
- einfacher zu lesen
- ruft automatisch den constructor auf und initialisiert die vtable
- bringt dich dazu delete statt free zu verwenden, was dann auch den destruktor automatisch aufruft
- funktioniert mit smart pointern
- überladbar
- "typsicher"
- es bereitet dich darauf vor dieses grausame C++ möglichst schnell hinter dir zu lassen ;) (Solang du nicht dafür bezahlt wirst)
- dinge die mir gerade nicht einfallen.
 
Mitglied seit
18.07.2001
Beiträge
2.152
Reaktionen
2
Ort
Nürnberg
muss da in der new() sache mal pauschal zustimmen. man *kann* auch tausend goto-statements verwenden, sich an keinerlei code konvention halten etc... ne gute idee ist es allerdings nicht. der code wird schlechter lesbar, schlechter verstaendlich und evtl. soll den ja mal wer anders lesen.

ach ja und zu dem sample...

double und float sind wie schon gesagt standardisiert und hoffentlich halten sich c & fortran an den entsprechenden standard. einen byte array mit einer nicht standardkonformen *fliesskommazahl* von x bytes in einen double umzuwandeln wuerde lustig da ja nicht klar ist wie gross der anteil von exponent/mantisse darin ist.
siehe http://steve.hollasch.net/cgindex/coding/ieeefloat.html
 
Mitglied seit
09.11.2002
Beiträge
880
Reaktionen
0
Hmm, OK. Also zunächst: ich bin Physiker, kein Informatiker. Es hat bei mir schonmal ziemlich lange gedauert, bis ich mich überhaupt auf OOP eingelassen habe. Daher mein "gutes, altes" malloc().
Und ganz ehrlich - auch wenn ich schon 2-3 FAQs dazu gelesen habe, sehen tue ich jetzt erstmal keinen Vorteil in new. Instanzen von Klassen werden mit new erstellt, und "da wo ich früher double d[9999]; int d_max=125;" geschrieben hätte mache ich jetzt double *d = (double *) malloc(125*sizeof(double));.
Also, ich wüßte gar nicht wie man free und delete verwechseln sollte!
Wenn ich einfach nur 123 double Variablen brauche, dann will ich keinen Konstruktor und keinen Destruktor, sondern einfach nur Platz für 123*8 byte in meinem Speicher.

Das double und float standarisiert sind wußte ich nicht, dachte daß wäre genauso Plattformabhängig wie short, int und long. Ausgezeichnet, umso besser!

Und die Sache mit der Fließkommadarstellung ist mir zumindest in groben Zügen bekannt, daher ja auch meine Frage.

Nun ja, wie gesagt, ich bin in erster Linie Physiker und nicht informatiker und bin mir ziemlich sicher, daß Konzept hinter OOP noch nicht vollständig begriffen zu haben (für mich: new = OOP, malloc = "normales" Programmieren) und lasse mich da gerne eines besseren belehren - nur wie gesagt ich habe bisher nichts gefunden was mir unmißverständlich klargemacht hat, warum mallo() schlecht ist. Ich möchte da nocheinmal betonen, daß ich nach jedem malloc() einen test auf NULL-Pointer mache.

Und wenn wir schon dabei sind, gibt es auch Einwände gegen memcpy, strcmp, etc?
 
Mitglied seit
18.07.2001
Beiträge
2.152
Reaktionen
2
Ort
Nürnberg
im zeitalter von c++ wuerde ich mich halt pauschal an c++ style halten, sprich moeglichst durchgaengig mit new() ausser es gibt nen guten grund dagegen. bei reinen c programmen enthalte ich mich nem urteil und bei bestehendem code sollte man sich an dem orientieren wie der restliche code gehalten ist.

achja, die "str..." funktionen sind afaik nicht mehr ganz up-to-date. wegen der buffer-overflow problematik in sicherheitskritischem code ists eigentlich besser die entsprechenden "strn..." funktionen zu verwenden, speziell "strncpy" anstatt "strcpy".

sind keine sachen die einen umbringen wenn mans nicht tut aber sauberen code schreiben schadet im zweifel auch nicht :)
 

The_Company

Guest
Original geschrieben von ViperDK
double und float sind wie schon gesagt standardisiert und hoffentlich halten sich c & fortran an den entsprechenden standard. einen byte array mit einer nicht standardkonformen *fliesskommazahl* von x bytes in einen double umzuwandeln wuerde lustig da ja nicht klar ist wie gross der anteil von exponent/mantisse darin ist.
Das einzige was nicht stnadardisiert ist, ist die Repraesentaton von float und double auf einer gegebenen Rechner Architektur. PowerPC floats und x86 floats sehen zB auf der Festplatte nicht gleich aus. Solange man aber den gleichen Rechner benutzt, sollte das kein Problem sein, vorausgesetzt man weiss, welcher Fortran Typ welcher Typ in C ist.
 
Oben