2012-04-11 15 views
4

Ist es möglich, eine std :: string für read() zu verwenden?Ist es möglich, eine std :: string für read() zu verwenden?

Beispiel:

std::string data; 

read(fd, data, 42); 

Normaly, haben wir char * verwenden, aber ist es möglich, eine std :: string direkt zu benutzen? (Ich ziehe es keinen char * für speichere das Ergebnis erstellen)

Dankten

+0

Wenn zero-copy Ihr Ziel ist, würde es Ihnen helfen, "read" durch "mmap" zu ersetzen und dann einen fest zugewiesenen std :: string darum zu legen? – user1202136

+0

Gibt es Leerzeichen in der Zeichenfolge, die Sie gerade lesen? –

Antwort

7

Nun, Sie müssen eine char* irgendwie erstellen, da das ist, was die Funktion erfordert. (BTW: Sie sprechen über die Posix-Funktion read, nicht wahr, und nicht std::istream::read?) Das Problem ist nicht die char*, ist es, was die char* Punkte (was ich vermute, ist das, was Sie eigentlich gemeint ist).

Die einfachste und übliche Lösung hier ein lokales Array zu verwenden wäre:

char buffer[43]; 
int len = read(fd, buffer, 42); 
if (len < 0) { 
    // read error... 
} else if (len == 0) { 
    // eof... 
} else { 
    std::string data(buffer, len); 
} 

Wenn Sie direkt in eine std::string jedoch erfassen möchten, dann ist dies möglich (wenn auch nicht unbedingt eine gute Idee):

std::string data; 
data.resize(42); 
int len = read(fd, &data[0], data.size()); 
// error handling as above... 
data.resize(len); // If no error... 

Dies vermeidet die Kopie, sondern ganz offen ... die Kopie ist unbedeutend Vergleich zu der Zeit, die für die tatsächliche Lese- und für die Zuteilung o f der Speicher in der Zeichenfolge. Dies hat auch den (wahrscheinlich vernachlässigbaren) Nachteil der resultierenden Zeichenkette mit einem tatsächlichen Puffer von von 42 Bytes (aufgerundet auf was auch immer), anstatt nur das Minimum , das für die tatsächlich gelesenen Zeichen notwendig ist.

(Und da die Menschen manchmal die Frage aufwerfen, in Bezug auf die Kontiguität des Speichers in std:;string: Das war ein Problem, zehn oder mehr Jahre Die ursprünglichen Spezifikationen für std::string wurden expressedly von nicht zusammenhängenden zu ermöglichen. Implementierungen, entlang der Linien von der damals populären rope Klasse.In der Praxis fand kein Hersteller diese als nützlich, und die Leute begannen, Kontiguität anzunehmen.An diesem Punkt, der Normungsausschuss beschlossen, den Standard mit bestehenden Praxis auszurichten und Kontiguität erfordern. Also ... keine Implementierung überhaupt nicht hat zusammenhängenden gewesen, und keine zukünftige Umsetzung wird contiguity verzichten, die Anforderungen in C++ gegeben. 11)

+0

"Dies vermeidet die Kopie, aber ganz ehrlich ... Die Kopie ist unbedeutend im Vergleich zu der Zeit, die für das tatsächliche Lesen und für die Zuweisung der benötigt wird Speicher in der Zeichenfolge. " Dies hängt von der Größe der gelesenen Daten ab. Die Leute haben viel Aufwand investiert, um den Linux-Kernel auf mehreren Datenübertragungswegen zu zerlegen. – user1202136

+0

@ user1202136 In diesem Fall beträgt die Größe der Kopie 42 Byte. Und es gibt eine dynamische Zuweisung und eine Übertragung von Bytes aus dem System. Die Situation ist im Kernel anders, zumindest wenn es um Dinge wie Puffer geht (die wahrscheinlich in der Größenordnung von 4 KB oder mehr liegen und aus Pools zugewiesen werden). –

0

Wenn die Lesefunktion ein char * erfordert, dann nicht. Sie können die Adresse des ersten Elements eines std :: vectors von char verwenden, solange es zuerst in der Größe geändert wurde. Ich glaube nicht, dass alte (vor C++ 11) Zeichenketten garantiert zusammenhängende Speicher haben, ansonsten könnten Sie etwas Ähnliches mit der Zeichenkette machen.

0

Nein, Sie können nicht und Sie sollten nicht. In der Regel speichern std :: string-Implementierungen intern andere Informationen wie die Größe des zugewiesenen Speichers und die Länge der tatsächlichen Zeichenfolge. In der C++ - Dokumentation wird explizit angegeben, dass das Ändern von Werten, die von c_str() oder data() zurückgegeben werden, zu undefiniertem Verhalten führt. Kein

0

, aber

std::string data; 
cin >> data; 

funktioniert gut. Wenn Sie das Verhalten von read(2) wirklich wollen, dann müssen Sie Ihren eigenen Puffer von Zeichen zuweisen und verwalten.

+0

Dies wird auf Leerzeichen zu brechen. –

+2

Welches, für alles, was wir von der Frage sagen können, kann gewünscht werden ... – DRVic

0

Da read() für Rohdateneingang vorgesehen ist, std :: string ist eigentlich eine schlechte Wahl, weil std :: string Text behandelt. std :: vector scheint die richtige Wahl für die Verarbeitung von Rohdaten zu sein.

-1

Mit std :: getline aus der Strings-Bibliothek - siehe cplusplus.com - kann aus einem Stream lesen und direkt in ein String-Objekt schreiben. Beispiel (wieder aus cplusplus.com riss - 1. Hit auf Google für getline):

int main() { 
    string str; 
    cout << "Please enter full name: "; 
    getline (cin,str); 
    cout << "Thank you, " << str << ".\n"; 
} 

So funktionieren, wenn sie von stdin lesen (cin) und aus einer Datei (ifstream).

+0

Warum ist das relevant? read ist ein Systemaufruf bei posix und bezieht sich nicht auf die Konsole. –

Verwandte Themen