BinärCode in Memofeld darstellen (HexToBin?)
-
Hallo liebe Programmiergemeinde,
ich möchte an dieser Stelle einen schon sehr alten Beitrag (http://www.c-plusplus.net/forum/109142) nocheinmal aufwärmen, da ich zuversichtlich bin, dass sich hier jemand findet der mir aus der Patsche helfen kann.
Die von mir zu lösende Aufgabe klingt eigentlich ähnlich, wie die Eröffnung von DRIVER26. Eigentlich möchte ich eine Datei - welche Binärdaten enthält - in einem Memofeld darstellen. Diese Daten sollen zum einen im Hex-Code dargestellt werden und zum anderen binär (die Daten liegen bspw. folgendermaßen vor: 0E F1...->00001110 11110001). Den ersten Teil konnte ich mit einem kleinen Umweg über einen AnsiString, einer Schleife und anschließender IntToHex-Funktion auch entsprechend im Memo darstellen. Jedoch beim zweiten Teil will es einfach nicht gelingen. Es werden einfach nur kryptische Zeichen dargestellt, aber eben keine Einsen und Nullen.
Den im oben genannten Beitrag verwendeten Code habe ich nur mit folgender Zeile ergänzt:
Memo2->Text=Memo2->Text + f;
...und dieser im Netz gefundene Code stellt zwar klasse die Einsen dar, jedoch bekomme ich das cout nicht so umgesetzt, das ich es in einem Memofeld darstellen kann.
char buff[8]; //entsprechend ändern!! ifstream infile("test.dat", ios::binary); while(!infile.eof()) { infile.getline(buff, sizeof(buff)); } vector < bitset<8> > b; for (int i=0; i<sizeof(buff); i++) b.push_back(buff[i]); for (int i=0; i<b.size(); i++) cout << b[i] << endl; getch();
Ich würde mich sehr über einen hilfreichen Tip freuen.
-
-
Datei in einen Puffer einlesen, z.B.
std::vector<char>
. Dazu stellst du zuerst die Dateigröße fest, reservierst entsprechend viele Elemente im Vektor und liest die Datei in einem Rutsch ein. Dazu musst allerdings den Sonderfall für Dateilänge 0 betrachten. -
Gehe die einzelnen Zeichen im Vektor, formatiere sie entsprechend (hex/bin) und füge sie in dein Memo ein. Wenn´s schnell gehen soll geh´ den Umweg über einen
std::ostringstream
, anstatt die Daten sofort in das Memo einzutragen.
Den Weg über ein
std::bitset
würde ich nicht gehen. Für eine Bitdarstellung eines 8 bit char gibt´s einfachere Lösungen.Leider stellst du keine konkrete Frage, schilderst kein konkretes Problem und postest auch keinen kompilierbaren Quelltext. Im allgemeinen werden hier Forum nur Hilfestellungen und keine Komplettlösungen geboten, da ist in deinem Fall etwas mehr Initiative gefordert.
-
-
mrsample schrieb:
jedoch bekomme ich das cout nicht so umgesetzt, das ich es in einem Memofeld darstellen kann.
So richtig verstehe ich die Frage nicht, meinst du jetzt so was ?
void __fastcall TfrmMain::btnTestClick(TObject *Sender) { // Nur um schnell Inhalt zu erzeugen vector < bitset<8> > v; bitset<8> b(string("01011011")); v.push_back(b); // Das hier ? Memo1->Lines->Append(v[0].to_string().c_str()); }
-
Danke für die rasche Meldung.
@DocShoe: Danke für deine Hinweise, es ist das erste Mal das ich mich in einem Forum melde und bin noch nicht so sicher im Umgang mit den so geläufigen Regeln innerhalb eines Forums. Ich war eigentlich schon froh, den Quelltext ordentlich dargestellt zu bekommen. Deine beiden Hinweise bezüglich des Quelltextes (1. und 2.) beziehen sich natürlich auf den in diesem Thread gezeigten Quelltext. Diesen habe ich nur zur Veranschaulichung eingebracht, da dieser komplett funktionfähig ist. Ich kann sie für mich nur nicht umsetzten, da ich nicht so tief in der Materie stehe wie Du. Es tut mir leid, dass ich mich nicht kongreter ausdrücken kann, als ich es versucht habe.
Dies ist nun der bisherige Code in den ich das beschriebene Problem aus http://www.c-plusplus.net/forum/109142 einbinden möchte.void __fastcall TForm1::Button2Click(TObject *Sender) { TFileStream *fs = new TFileStream("test.dat", fmOpenRead); AnsiString str; str.SetLength(fs->Size); fs->Position = 0; fs->Read(str.c_str(), fs->Size); Memo2->Clear(); for(int n=1; n<=str.Length();n++) { Memo2->Text=Memo2->Text + IntToHex((unsigned char) str[n],2) + " "; if(n == str.Length()) Memo2->Text= Memo2->Text + "\r\n"; str_a = IntToHex((unsigned char) str[n],2); } AnsiString f; char buffer[10]; HexToBin(str_a.c_str(),buffer,10); f=buffer; Memo2->Text= Memo2->Text + buffer; delete fs; }
Leider wird im Memofeld nur die HEX Darstellung richtig gezeigt und die Binärdarstellung zeigt ein kryptisches Zeichen und eben nicht die erwarteten Einsen und Nullen. Verbirgt sich hinter HexToBin nicht das von mir vermutete?
Ja im Prinzip ist es das was ich meine. Dein Code bringt bei mir allerdings folgende Fehlermeldung in der letzen Zeile:
[/code]
// Das hier ?
Memo1->Lines->Append(v[0].to_string().c_str());
[code="cpp"]
E2316:'c_str' is not member of 'basic_string<_CharT,_Traits,_Alloc>'Ich benutze übrigens den C++ BBuilder 6.
----Ich nun für ein wenig mehr Verständlichkeit gesorgt zu haben. Vielen Dank schon im Voraus.
-
mrsample schrieb:
Ja im Prinzip ist es das was ich meine. Dein Code bringt bei mir allerdings folgende Fehlermeldung in der letzen Zeile:
Der Code funktioniert im C++ Builder XE2, da ist das Beispiel herkopiert.
mrsample schrieb:
Ich benutze übrigens den C++ BBuilder 6.
Das solltest Du bei deinen Fragen erwähnen. Das Teil ist immerhin über 10 Jahre alt.
HexToBin habe ich noch nie benutzt. Was sagt den der Debugger, wenn du da beim Aufruf von HexToBin einen Breakpoint setzt ? Wie sieht der Inhalt von buffer nach dem Funktionsaufruf aus ?
-
Das sieht doch schon mal nicht ganz falsch aus
Zeile 14:
Die Zeile fügt am Ende des Textes einen Zeilenumbruch ein. Ist das so gewollt oder soll nach einer bestimmten Anzahl von Hex-Zahlen ein Zeilenumbruch eingefügt werden. Falls nur am Ende des Textes ein Zeilenumbruch anhängen willst kannst du das auch einfach hinter der Schleife machen und brauchst nicht in der Schleife zu prüfen.Zeile 15:
Was passiert hier?
Laut Doku liest sich das so, dassBinToHex
einen Speicherbereich hexadezimal in einem String ablegt undHexToBin
das Ganze rückwärts macht.Du musst dir wohl selbst eine Funktion schreiben, die einen
char
erwartet und einen AnsiString mit der Binärdarstellung des char zurückgibt.
-
mrsample schrieb:
Ja im Prinzip ist es das was ich meine. Dein Code bringt bei mir allerdings folgende Fehlermeldung in der letzen Zeile:
[/code]
// Das hier ?
Memo1->Lines->Append(v[0].to_string().c_str());
[code="cpp"]
E2316:'c_str' is not member of 'basic_string<_CharT,_Traits,_Alloc>'Scheint so als ob hier ein #include <string> fehlt.
-
[quote="Braunstein"]
mrsample schrieb:
Scheint so als ob hier ein #include <string> fehlt.
Könnte sein, im XE2 included bitset aber string. Auch in VC++ ist das so, macht ja auch Sinn, weil bitset auch Konstruktoren mit Stringparametern hat.
Keine Ahnung, wie das im BCB6 ist und ob die alte Standardbibliothek das alles schon vollständig implementiert.
-
Habe die string.h mal mit eingebunden...es kommt die gleiche Fehlermeldung.
Zur Zeit steht im buffer beim Aufruf nur das letzte Zeichen des Dateiinhaltes (in Hex)...eigentlich sollte ja alles aus str drinnen stehen. Geht aber irgendwie nicht. Sobald ich den kompletten AnsiString beschreiben möchte
str_a[n] = IntToHex((unsigned char) str[n],2);
bekomme ich die Fehlermeldung: 'Cannot convert 'AnsiString' to 'Char'.
Das mit Zeile 14. war ein guter Hinweis...danke.
Und das mit der eigenen Funktion ist da wohl eine Nummer zu groß für mich. Ich dachte eigentlich, dass es nicht so ungewöhnlich ist ein Zeichen in Binärdarstellung in einem Memo darzustellen und bin davon ausgegangen, das dies HexToBin möglich macht.
-
@Alle
Vielen Dank für eure Denkanstöße...
, ich habe es nun doch lösen können, mit folgendem Code:
void __fastcall TForm1::Button3Click(TObject *Sender) { string bits; AnsiString ansibits; char buff[8]; //entsprechend ändern!! ifstream infile("test.dat", ios::binary); while(!infile.eof()) { infile.getline(buff, sizeof(buff)); } vector < bitset<8> > b; for (int i=0; i<sizeof(buff); i++) b.push_back(buff[i]); for (int i=0; i<b.size(); i++) { bits=b[i].to_string<char,char_traits<char>,allocator<char> >(); ansibits = bits.c_str(); Memo2->Lines->Append(ansibits); } }
Bis zum nächsten Beitrag
Danke
-
Das ist keine korrekte Lösung. Du liest per
getline
Daten in einen 8 Byte großen Puffer, bis das Dateiende erreicht ist. Anschließend wandelst du den Pufferinhalt in einen Binärstring um.
Was passiert, wenn eine Zeile länger als 8 Zeichen ist? Du liest zeilenweise Daten ein und behandelst die eingelesenen Daten erst dann, wenn das Dateiende erreicht ist. D.h., du behandelst nur die Daten der letzten Zeile, aber was ist mit allen anderen Zeilen? Außerdem gehtst du davon aus, dass jede Zeile genau 8 Zeichen lang ist, was passiert denn, wenn sie nur 5 Zeichen lang ist?
-
Hmm, das stimmt sicher, was du da schreibst. Jedoch ist es so - zumindest für meine Anwendung -, dass die Dateigrösse sich nie ändert uns die Struktur auch nicht. Lediglich der Inhalt der einzelnern Positionen ändert sich. Deshalb habe ich auch die Größe des Puffers so festgelegt, da ich weiß was mich erwartet. Ich bin natürlich für einen besseren Code deinerseits offen. Wie würdest Du ihn denn gestalten?
-
mrsample schrieb:
Wie würdest Du ihn denn gestalten?
Clever, so lässt du mich arbeiten, statt selbst den Code zu verbessern
#include <iostream> #include <fstream> #include <sstream> #include <vector> using namespace std; AnsiString file_to_binary_string( const AnsiString& FileName ) { ostringstream oss; ifstream ifs( FileName.c_str(), ios::binary ); if( ifs ) { // Dateigröße bestimmen und Vektor auf richtige Größe bringen ifs.seekg( 0, ios::end ); vector<char> FileData( ifs.tellg() ); ifs.seekg( 0, ios::beg ); // bei Dateigröße 0 erzeugt der Zugriff auf FileData[0] undefiniertes Verhalten, also muss dieser Fall ausgeschlossen werden if( !FileData.empty() ) { // kompletten Dateiinhalt in Vektor lesen ifs.read( &FileData[0], FileData.size() ); // alle Zeichen durchlaufen for( vector<char>::const_iterator it = FileData.begin(); it != FileData.end(); ++it ) { // ASCII Wert gegen einzelne Bitmaskierungen prüfen, MSB zuerst for( int i = 7; i >= 0; --i ) { if (*it & (1 << i) ) oss << "1"; else oss << "0"; } } } } return oss.str().c_str(); }
-
Nicht schlecht...habe es gerade mal ausprobiert. Aber wie ich sehe lag ich da mit meiner Vermutung ganz richtig - wie ich zuvor mal geschrieben hatte -, dass das eine Nummer zu hoch für mich wäre
. Naja danke nochmal.