2012-03-30 9 views
3

Ich versuche, den Inhalt einer Karte effizient in eine Zeichenfolge zu konvertieren, um über Socket zu senden. Ich habe dies so weit ...Anhängen an Puffer in C++

char buffer[1024]; 
for (iter = my_mapy.begin(); iter != my_map.end();iter++) 
{ 
    sprintf(buffer, "%s|%ld|%d", buffer, iter->first, iter->second); 
} 

Während dies funktioniert, ich habe mich gefragt, ob es ineffizient ist. Google sucht nach dem effizientesten Weg, um int/long/doubles in string zu konvertieren, was in sprintf resultiert, weshalb ich es verwende. Aber ich bin besorgt, dass der Inhalt des Puffers immer wieder kopiert wird, während ich nur bis zum Ende anhängen möchte. Ist das richtig, und wenn ja, gibt es einen besseren Weg, dies zu tun? Leistung und Geschwindigkeit haben Priorität 1.

Danke!

+0

Verwenden von '% s', um einen Puffer zu sich selbst zu kopieren? Das ist * hässlich * und ich bin überrascht, dass es funktioniert. –

Antwort

5

Sie haben Recht; Die hier vorgeschlagene Lösung kopiert den Puffer jedes Mal. Um es besser zu machen, müssen Sie den Rückgabewert von sprintf verwenden.

char buffer[1024]; 
char* end_of_buffer = buffer; 
std::size_t remaining_space = sizeof(buffer); 

for (auto iter = my_map.begin(); iter != my_map.end(); iter++) 
{ 
    int written_bytes = snprintf(end_of_buffer, remaining_space, "|%ld|%d", iter->first, iter->second); 

    if (written_bytes > 0) { 
     end_of_buffer += written_bytes; 
     remaining_space -= written_bytes; 
    } else { 
     perror("Something is wrong with the buffer"); 
    } 
} 

Hinweis, nebenbei gesagt, dass ich snprintf verwendet, die Spur des Puffers des Restlänge hält. Sie sollten immer anstelle der unsicheren Version verwenden. Ihre Anwendung wird sich weiterentwickeln, und durch große Kreativität finden Sie einen Weg, diesen Puffer überlaufen. Inzwischen kommt die Sicherheit ohne zusätzliche Kosten.

(Ich meine nichts für ungut, natürlich.)

+0

Ich ging durch die Antworten und testete alle verschiedenen Methoden. Jede Methode wurde 10.000.000 Mal ausgeführt. Meine ursprüngliche Methode (zusammen mit dem, was ich gelernt habe Tücken zu sein) nahm: 35,96 sec Stream-Methode nahm: 30,27 sec Andres' Methode nahm: 27.98 sec ich jetzt den Streams verwenden, aber ich werde definitiv später zu Andres 'Methode wechseln. Danke! – Joshua

+1

"Ich werde definitiv später wechseln" passiert fast nie in der realen Welt. Entweder wechseln Sie jetzt, oder stellen Sie sicher, dass Sie für Ihre aktuelle Wahl glücklich sind, ihre unbegrenzte Zeit zu bleiben. – Steve314

+0

Was @ Steve314 sagte. Wenn ich nicht auf dem kritischen Pfad bin oder Feldbreiten kontrolliere, bevorzuge ich auch Stringstreams. Diese Wahl könnte völlig legitim sein. –

5

Sie std::ostringstream s verwenden sollten, sind sie effizienter und C++ - ish:

#include <sstream> 

std::ostringstream oss; 
for (iter = my_mapy.begin(); iter != my_map.end();iter++) 
{ 
    oss << iter->first << "|" << iter->second; 
    //oss.str() returns the string in which everything was stored. 
} 

Danach werden Sie noch operator<< Sachen am Ende des ostringstream anhängen können.

+2

+1 - sie entfernen auch ein potenzielles Pufferüberlaufproblem. – Steve314

+0

Das war mein ursprünglicher Gedanke, aber fast jeder Artikel, den ich las, sagte, Streams seien langsamer, aber sicherer. Mein Puffer sollte nie mehr als 1024 wachsen, darum mache ich mir keine Sorgen. – Joshua

+0

Benötigen Sie diesen Code, um * effizient * zu sein? ostringstreams könnte% 10 ~ 15 langsamer sein als sprintf. Ich würde mich trotzdem für diesen Ansatz entscheiden. – mfontanini

0

Sie sollten wahrscheinlich stattdessen stringstream verwenden, aber wenn Sie mehr Effizienz wollen, dann nehme ich an, Sie können gerade char * für Ihren Puffer verwenden, müssen Sie nur sicherstellen, dass Sie es wachsen, es sei denn Sie wissen, es wird nicht über 1024 Bytes.

+0

Das war mein ursprünglicher Gedanke, aber fast jeder Artikel, den ich las, sagte, Streams seien langsamer, aber sicherer. Mein Puffer sollte nie mehr als 1024 wachsen, darum mache ich mir keine Sorgen. – Joshua

+0

Ja, sie werden nicht so schnell sein, aber sie sollten nicht SO viel langsamer sein und sie sind viel sicherer. –

2

Sie haben den Puffer an sprintf als Eingabe und Ausgabe übergeben. Das ist undefiniertes Verhalten.

+0

-1 richtig, aber nicht hilfreich. –

+0

@AndresJaanTack: eigentlich war die Frage "ist das korrekt, und wenn ja ...?" Es ist also eine korrekte und hilfreiche Antwort. – KillianDS