char* in string umwandeln?
-
Hallo!
Ich muss ein Binärfile einlesen. Ich habe mit read einmal das gesamte Binärfile in ein char* eingelesen.
Jetzt benötige ich einzelne Teile daraus. Deswegen meine Idee: Ich wandle das char* in einen String um und kann dann mittels substr auf die entsprechenden Teile zugreifen.
So habe ich das gemacht (wobei length die Länge des Files ist)
char input_buffer[length + 1]; file.read ( input_buffer, length ); input_buffer[length] = '\0'; string input = input_buffer;
Wenn ich die Werte vom input_buffer (dem char*) auf int caste und ausgebe, dann stimmen sie mit dem file überein.
Wenn ich aber die Werte vom input (dem string) auf int caste und ausgebe, dann stimmen sie nicht mit dem file überein (die ersten paar Werte stimmen noch)Es liegt also nicht am Einlesen, sondern am Umwandeln des char* in den String.
Die "Werte" des Binärfiles sind übrigens unsigned char.
Wo liegt der Fehler?
mfg
-
Zeig mal her, wie du das ganze castest.
-
Danke für die Antwort!
Die Ausgabe ist nur zum Testen (die 338 ist die Größe meines Testfiles):
std::cout << std::endl; for (unsigned int count = 0; count < 338; count++) { std::cout << static_cast<int>(input[count]) << " "; }; std::cout << std::endl;
std::cout << std::endl; for (unsigned int count = 0; count < 338; count++) { std::cout << static_cast<int>(input_buffer[count]) << " "; }; std::cout << std::endl;
mfg
-
Ich habe bemerkt, dass die ersten 48 Elemente gleich sind und bei den restlichen 290 Unterschiede sind (aber auch nicht alle).
Das 48 Element ist aber kein spezielles. Das 43., 44., 45., 46., 47., 49., 50., 51.,.... haben im File den selben char-Wert. Woran könnte das liegen?
mfg
-
Du kannst nicht einfach casten.
#include <sstream> std::stringstream ss; for (unsigned int count = 0; count < input_buffer.size(); ++count) { ss << static_cast<int>(input_buffer[count]) << " "; }; std::string s = ss.str();
Simon
-
Danke für die Antwort!
Ich habe bemerkt, dass input.size() den Wert 38 zurück gibt, obwohl das char-array 338 Elemente hat. Mein Binärfile ist so aufgebaut, dass ab Stelle 38 viele Nullen folgen.
Ich glaube, ich muss mit dem char-array weiter arbeiten.
-
Vermutlich liest Du das File nicht binär ein.
Wie öffnest Du das File?
Simon
-
Du kannst das char-array das du aus dem Binärfile hast nicht einfach als String interpretieren. Im Binärfile können mittendrin Nullchars ('\0') auftauchen, so dass dein String dort abgeschnitten würde.
Da es sich um binäre Daten und nicht um Zeichen handelt, würde ich auch kein char sondern unsigned char benutzen und den ganzen Krempel in einen std::vector<unsigned char) oder wenn du den kontinuierlichen Speicher nicht brauchst in eine std::deque<unsigned char> stecken an Stelle des Strings.
-
@theta:
So lese ich ein:std::ifstream file(filename, std::ios::in | std::ios::binary);
@pumuckl:
Genau das denke ich auch.
Bei deinem Vorschlag habe ich das Problem, dass ich einen Vector nicht so komfortabel zerstückeln kann wie mit substr().Ich habs jetzt so gelöst, dass ich mein char-array (input_buffer) auf einen stringstream schreibe:
std::stringstream input_stream; for (int count = 0; count <= length; ++count) { input_stream << static_cast<unsigned char>(input_buffer[count]); };
Jetzt kann ich über input_stream.str().substr(x, y) auf Bereiche zugreifen, wie ich will. Gibt es an dieser Methode etwas auszusetzen? Oder was wäre besser?
mfg
-
Bin mir nicht sicher ob mein Vorschlag mit dem stringstream das ist was Du möchtest.
Beschreibe doch mal anhand eines Bsp. was Du möchtest, so ala:
File Inhalt (hex): 00 01 02
Inhalt im vector<unsigned char>: 0x00, 0x01, 0x02
String Inhalt: "00 01 02"Simon
-
feuerball schrieb:
@pumuckl:
Genau das denke ich auch.
Bei deinem Vorschlag habe ich das Problem, dass ich einen Vector nicht so komfortabel zerstückeln kann wie mit substr().Stimmt zwar, aber du kannst dir problemlos eine entsprechende Funktion für vector oder deque schreiben:
template <class RandomAccessContainer> RandomAccessContainer subrange(RandomAccessContainer const& source, RandomAccessContainer::size_type beginIndex, RandomAccessContainer::size_type endIndex) { RandomAccessContainer::const_iterator begin = source.begin(); return RadomAccessContainer(begin + beginIndex, begin + endIndex); } int main() { std::vector<unsigned char> vec; /* fill vec... */ std::vector<unsigned char> interestingPartOfVec = subrange(vec, 5, 18); }
Ich würd eher sowas machen als mit string, stringstreams oder sowas zu arbeiten - die können nur char und sind für die Verarbeitung von unsigned chars nicht gedacht.
-
pumuckl schrieb:
Ich würd eher sowas machen als mit string, stringstreams oder sowas zu arbeiten - die können nur char und sind für die Verarbeitung von unsigned chars nicht gedacht.
Mal unabhängig davon, ob es hier sinnvoll ist - die Kompatibilität zu
unsigned char
kann leicht eingerichtet werden:typedef std::basic_stringstream<unsigned char> uchar_sstream; typedef std::basic_string<unsigned char> uchar_string;
-
Vielen Dank für die Antworten!
@theta:
So zB
File Inhalt (hex): 0F 0A 0F 10 00 00 00 00 00 00 01 02 00 03 04 usw.
Inhalt im vector<unsigned char>: 0x0F 0x0A 0x0F 0x10 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x02 0x00 0x03 0x04 usw.my_vector[1] sollte mir 0A zurück geben.
Und jetzt brauche ich zB die Werte 10 00 00 00 00. Die Reihenfolge bleibt gleich. Es sollte nur ein Teil davon genommen werden.
@pumuckl:
Ich habe noch nie was mit Templates gemacht. Aber ich habe mich jetzt etwas eingelesen und verstehe grundsätzlich deinen Code und auch was Templates machen.Nur er compiliert nicht: "»RandomAccessContainer::size_type« is not a type" usw.
Ich komme nicht dahinter, was ich ändern soll
Was ist daran falsch?mfg
-
@feuerball,
pumuckl ist MSVS verwöhnttemplate <class RandomAccessContainer> RandomAccessContainer subrange(RandomAccessContainer const& source, typename RandomAccessContainer::size_type beginIndex, typename RandomAccessContainer::size_type endIndex) { typename RandomAccessContainer::const_iterator begin = source.begin(); return RadomAccessContainer(begin + beginIndex, begin + endIndex); }
Du musst dem Kompiler über
typename
mitteilen, dass es sich bei z.B.RandomAccessContainer::size_type
um einen Typ handelt, sonst nimmt er an, dass es sich dabei um eine Variable handelt.Grüssli