Frage zu C-String
-
Jetzt mal ne konstruktive Antwort:
Längen merken und memcpy (http://www.cplusplus.com/reference/clibrary/cstring/memcpy/) benutzen.
Zielbereich entsprechend dimensionieren versteht sich.
-
An memcpy hatte ich auch schon gedacht, jedoch musst du da ja noch die Länge angeben, d.h. du musst dann noch extra strlen aufrufen, was glaube ich nicht ganz so optimal ist. Warum mehr aufwand betreiben, als nötig? Ich würde auch sagen benutz strcat.
MfG
-
EOP schrieb:
Längen merken und memcpy benutzen.
Du willst ihn wohl zum Masochismus treiben.
Die beste Loesung ist nach wie vor die Verwendung von std::string.
Man muss hier nicht unnoetig C und C++ mischen.
-
raw* schrieb:
In meinem Fall kann ich keinen std::string verwenden weil Binär Daten versendet werden müssen.
Es verhält sich genau anders herum - std::string kann problemlos mit Binärdaten umgehen, während das mit C-Strings nicht möglich ist - denn ein C-String ist per Definition beim ersten NUL zu Ende.
-
Sone schrieb:
Du willst ihn wohl zum Masochismus treiben.
Nö, sonst hätte ich ihm vorgeschlagen alle deine posts zu lesen.
Athar schrieb:
Es verhält sich genau anders herum - std::string kann problemlos mit Binärdaten umgehen, während das mit C-Strings nicht möglich ist - denn ein C-String ist per Definition beim ersten NUL zu Ende.
Man kann eben nur nicht C-Funktionen wie strcat, strlen benutzen. Deshalb habe ich ja "Länge merken und memcpy" vorgeschlagen.
-
Athar schrieb:
Es verhält sich genau anders herum - std::string kann problemlos mit Binärdaten umgehen, während das mit C-Strings nicht möglich ist - denn ein C-String ist per Definition beim ersten NUL zu Ende.
Ich dachte eigentlich immer char * (bzw. vector<char>(DataSize); ) müsste man für Binärdaten verwenden.
Also ich meine wie soll ich z.b. Binärdaten aus einer Datei in einen std::string einlesen soweit ich weiss geht das doch gar nicht oder?
Hier http://www.cplusplus.com/reference/iostream/istream/read/ wird ja auch char* benutzt mit std::string funktioniert die read bzw. write Funktion ja nicht. (Ja, ich weiss vector ist besser nehme ich auch für solche Sachen.)
-
raw** schrieb:
Also ich meine wie soll ich z.b. Binärdaten aus einer Datei in einen std::string einlesen soweit ich weiss geht das doch gar nicht oder?
Hier http://www.cplusplus.com/reference/iostream/istream/read/ wird ja auch char* benutzt mit std::string funktioniert die read bzw. write Funktion ja nicht. (Ja, ich weiss vector ist besser nehme ich auch für solche Sachen.)
Es ist zwar in C++98 streng genommen nicht definiert, dass ein String seine Elemente hintereinander speichert, aber die Implementierung, die das nicht tut, muss erst noch erfunden werden. In C++11 ist sogar garantiert, dass alles hintereinander steht. Daher kannst du die Elemente in den String genau so reinbekommen wie in einen Vector.
Die Frage, die ich mir stelle, ist, was der Vorteil von String gegenüber Vector sein soll, wenn es um Binärdaten geht.
-
Ok, eine letzte Frage hab ich noch:
#include <iostream> #include <fstream> using namespace std; int main() { string abc="\x41\x42\x00\x43"; ofstream f ("file.txt",ios::binary); f.write(abc.c_str(),4); system("PAUSE"); return 0; }Wenn ich die erstellte Datei im Hexeditor anschaue dann steht dort: 41 42 00 00
Wenn ich aber z.b. benutzechar *abc="\x41\x42\x00\x43";dann steht in der Datei 41 42 00 43
Im Debugger sehe ich das der string aber die Binärdaten enthält dann scheint das Problem wohl bei c._str() zu liegen aber das mach auch std::string doch char* oder nicht?
Deshalb denke ich jetzt das char* für Binärdaten doch besser wäre weil Binärdaten natürlich auch Nullbytes enthalten können.
-
edit: Deine Zuweisung am Anfang ist falsch. Das weist dem String einen nullterminierten C-String zu, der hier eben nur zwei Zeichen hat. Guck dir mal die anderen Konstruktoren und Funktionen von String an und was sie genau machen.
Aber: Mich würde immer noch interessieren, warum du String und nicht Vector für Binärdaten nimmst. String ist eigentlich eher auf "normale" Zeichenketten hin designed.
-
anschaue dann steht dort: 41 42 00 00
Die Konvertierung zwischen
char*undstd::stringberuecksichtigt nur 0-terminierte Strings. Wenn du mittelsabc.size()die Laenge vorher pruefst, so wird sie 2 sein. D.h. der Einsatz von 4 beiwriteist falsch.char tmp[] ="\x41\x42\x00\x43"; string abc(tmp, tmp+sizeof(tmp)-1); ofstream f ("file.raw",ios::binary); f.write(abc.data(),abc.size());
-
Ahh, ich glaub jetzt hab ichs, c_str(); dachte wohl mein string wäre schon zu ende als es das Nullbyte gesehen hat.
Ein Nullbyte Kennzeichnet ja eigentlich auch das string ende ...
SeppJ schrieb:
Aber: Mich würde immer noch interessieren, warum du String und nicht Vector für Binärdaten nimmst. String ist eigentlich eher auf "normale" Zeichenketten hin designed
Ja, Vector gefällt mir eigentlich ganz gut.
Aber hier liegt mein Problem:
vector<char*>DBG; DBG.push_back("IRGENDEIN HEADER\r\n");); DBG.push_back("Size: 200\r\n");Ich muss einen request versenden der so aussieht:
Bsp:
IRGENDEIN HEADER
Size: 200Und wenn ich meine Vector so zusammenbau wie in dem Beispiel dann funktioniert das mit dem request nicht mehr.

-
raw** schrieb:
Ahh, ich glaub jetzt hab ichs, c_str(); dachte wohl mein string wäre schon zu ende als es das Nullbyte gesehen hat.
Nein, das überhaupt nichts damit zu tun. Bitte lies die Antworten gründlich.
Ein Nullbyte Kennzeichnet ja eigentlich auch das string ende ...
Für Funktionen aus cstring (bzw. string.h) vielleicht. Nicht bei std::string.
vector<char*>DBG; DBG.push_back("IRGENDEIN HEADER\r\n");); DBG.push_back("Size: 200\r\n");So langsam muss ich sagen: Lern C++. Dein Modell und die technische Umsetzung passen überhaupt nicht zusammen. Da liegt offenbar ein großes Missverständnis von Zeichenketten, Standardcontainern und allgemein der Behandlung von Daten vor.
Du möchtest hier sicherlich einen vector<char> (oder vielleicht doch einen String? Du gibst so wenig Infos und weichst Gegenfragen immer aus). Davon ausgehend gehen die Zuweisungen dann auch komplett anders. Da du vermutlich von C kommst: Ein vector<char*> entspricht einem char**. Dir ist klar, warum das nicht passen kann?
-
raw** schrieb:
Ok, eine letzte Frage hab ich noch:
string abc="\x41\x42\x00\x43";...
Da passiert der Fehler. Eine Konstante "foo" schreibt 4 Bytes in den Speicher. Und zwar die 3 Buchstaben und ein null Byte. Wird damit ein std::string erzeugt, sucht der Konstruktor von std::string nach dem ersten null Byte und übernimmt die Zeichen bis dahin.
Die Konstante "\x41\x42\x00\x43" schreibt eben 5 Bytes in den Speicher. Der Konstruktor sucht hier auch das erste null Byte und findet es aber an der 3. Stelle. Nur die ersten 2 Zeichen \x41 und \x42 werden in den str::string übernommen. Willst Du wirklich alle Zeichen in den std::string übernehmen, geht das mit:
std::string abc("\x41\x42\x00\x43, 4);
-
raw** schrieb:
Ein Nullbyte Kennzeichnet ja eigentlich auch das string ende ...
Bei einem C-String wuerde (die C++-Version von)
strlenso aussehen:template<charT> //Oder so aehnlich. Selbst geschrieben. size_t strlen(charT const* ptr) { size_t rval(0); while( ptr++ ) ++rval; return rval; }Es wird bis zum ersten Terminierungszeichen (0 oder als character-Literal: '\0') gelesen.
wie aber siehtstd::string::length()aus?template< //Oder so aehnlich. Selbst geschrieben. typename CharT, typename Traits, typename Allocator > typename basic_string<CharT, Traits, Allocator>::size_type basic_string::length() const { return mSize;//Oder so aehnlich }Hier wird ein interner, vorzeichenloser Skalar zurueckgegeben. Was heisst das? std::string speichert die Laenge mit! Und fuer den sind damit Terminierungszeichen irrelevant:
std::string a(5, '\0'); // Ein String, der aus 5 Nullbytes besteht std::cout << a.length(); //5Wieso funktioniert dann folgendes nicht:
std::string a = "\0\0\0\0\0"; std::cout << a.length();Das in der ersten Zeile nennt sich copy-initialisation. Hier wird a der Wert "\0\0\0\0\0" zugewiesen; der entsprechende Konstruktor wird aufgerufen.
Allerdings kennt dieser Konstruktor die Laenge des uebergebenen C-Strings nicht; er muss ihn also als Null-terminiert betrachten und hoert damit beim ersten Buchstaben auf. Die Laenge ist dementsprechend 0.
Wie es trotzdem geht?
char const[] meinScheiss = "\0\0\0\0\0"; std::string a(meinScheiss, meinScheiss + sizeof MeinScheiss); //start-end Iteratorenpaar Konstruktor std::cout << a.length();Hier wird 6 herausgegeben. Wieso?
Sehen wir uns an, was da steht:char const[] meinScheiss = "\0\0\0\0\0";Wird vom Compiler zu
char const[6] meinScheiss = {'\0', '\0', '\0', '\0', '\0', '\0'};Geaendert. An die Fuenf Terminierungszeichen wird noch eines rangehaengt (macht der Compiler bei solchen Literalen automatisch).