2009-02-15 15 views
6

-edit- Ich bin binäre und keine Zeichenfolge senden. Mein Test verwendet HTML-Seiten, also verwende ich in diesem Beispiel nur eine Zeichenkette, aber meine Frage betrifft binäre Vektoren und Debugging mit ostream. Ich mache das ein wenig Verwirrung.Gibt es eine bessere Möglichkeit, eine Zeichenfolge mit Cout bis zu N Zeichen zu drucken?

Ich habe den folgenden Code:

cout << string(&v[0]).substr(0, len); 

Gibt es einen besseren Weg, um die Zeichenfolge v mit cout bis die Länge len zu drucken? Ich dachte an v tun [len] = 0, aber ich ist eine Behauptung, mit einer Größe von 1 Mein Code geworfen ist:

vector<char> v; 
v.reserve(1024*16); //required 
v.resize(1); //so we can do &v[0] 
recv(sockfd, &v[0], v.capacity(), 0); 
while (l > 0) 
{ 
    cout << string(&v[0]).substr(0, l); 
    recv(sockfd, &v[0], v.capacity(), 0); 
} 
cout << "the size is " << v.size(); 
+0

Dieser Code ist beschädigt. Schrecklich so. Die Verwendung eines Vektors zur Zuweisung eines Arrays (was im Wesentlichen dort passiert) ist nicht nur gefährlich (Vektoren sind wichtig, um ihre internen Arrays neu zuzuordnen!), Sondern auch sinnlos. –

+0

Verwenden Sie v.resize (1024 * 16), wenn Sie * einen Vektor verwenden müssen, aber wie von dionadar erwähnt, ist es keine gute Idee, dies zu tun und schützt Sie im Grunde nicht davor und könnte auch dazu führen einige interessante Nächte, die diesen Code debuggen. –

+0

Was ist falsch an seiner Verwendung von Vektor? Wenn die Größe ist dynamisch, ich sehe nichts schlechtes mit ihm –

Antwort

7

können Sie die Methode Ostream verwenden :: Schreiben auf dem cout Objekt:

#include <iostream> 
#include <vector> 

using namespace std; 

int main() 
{ 
    vector<char> test; 
    test.push_back('a'); 
    test.push_back('b'); 
    test.push_back('c'); 

    cout.write(&test[0], 3); 
    cout << endl; 
} 

Ausgänge:

abc

Seit ostream :: schreiben Ostream kehrt & enthält * Dies können Sie auch tun

cout.write(&test[0], 3) << endl; 

aber ich bin mir nicht sicher, ob das tatsächlich besser (oder klarer) ist.

5
vector<char> v; 
v.reserve(1024*16); //required 
v.resize(1); //so we can do &v[0] 
recv(sockfd, &v[0], v.capacity(), 0); 

Dieser Code hat einen Fehler. Der Aufruf reserve garantiert Ihnen nur, dass Sie push_back mindestens so viele Elemente zurückgeben können, bis Verweise und Iteratoren auf den Vektor wieder ungültig gemacht werden (durch eine mögliche Neuzuweisung des verwendeten Puffers). Es wird nicht können Sie in v [0..1024 * 16-1] schreiben, wie Sie es mit recv tun. Sie haben

v.resize(1024*16); //required 

tatsächlich haben, dass viele Elemente zur Verfügung und übergeben tatsächlich v.size() statt v.capacity() zu tun.

Für Ihre Teilzeichenfolge Betrieb würde ich wahrscheinlich tun

std::string str(&v[0], n); 
std::cout << str; 

Wo n im Bereich von 0 bis(), um V.SIZE. Sie können std::min(n, v.size()) verwenden, um sicherzustellen, dass, wenn n in Ihrem Fall größer sein könnte und Sie eine obere Grenze benötigen.

(auf einer Seite Knoten, ich würde vermeiden, eine Variable namens "l" (ell) dort, weil es kann sehr ähnlich wie eine "1" (eins), die die Hölle aus Menschen verwirren)

+0

von dem, was ich lese, können Sie tatsächlich in 0-1024 * 16-1 Elemente schreiben, und es ist garantiert kontinuierlich, jedoch Elemente von Größe zu Kapazität sind nicht konstruiert/initialisiert. –

+0

ist es nicht richtig, weil der Vektor nicht so viele Elemente hat. Sie können natürlich nur bis zu v [0..v.size() - 1] schreiben/lesen. –

+0

BTW, wenn Sie einen Puffer mit konstanter Größe benötigen, ist es besser boost :: array v; Übergeben Sie dann v.data() und v.size(). oder ein Array auf dem Stack - obwohl rohe Arrays sollten vermieden werden ... du weißt, Gefahr um die Ecke –

-2

Siehe Kommentare: Ich stehe korrigiert. Ich wurde informiert. Aber ich denke immer noch, es ist verrückt, sich auf solche Interna zu verlassen. Der letzte Microsoft Compiler, den ich verwendet habe, hat die C99-Standards verletzt, was mir kein Ende der Trauer beschert hat. Wenn sie keine Rückgabewerte direkt auf vsnprinf() oder neue erhalten können, wollen Sie wirklich auf Errata wie folgt verlassen?

Sie machen Annahmen hinsichtlich der Implementierung von Vektoren. Sie nehmen an, dass v [1] direkt nach v [0] im Speicher kommt.

Es gibt einen Unterschied zwischen char buf []; & buf [1] == & buf [0] + 1 und vektor v; & v [1] == & v [0] + 1. Das Char-Array verwendet Zeigerarithmetik. Der Vektor verwendet den Operator []. Wie der Vektor Daten intern speichert, ob er benachbart ist oder nicht, hängt von dieser Vektorklasse ab.

Während Ihr Code noch funktioniert, ist dies immer noch eine BAD Sache! Es macht Ihre Software spröde, was dazu führt, dass sie auf seltsame und erwartete Weise bricht, wenn Sie es am wenigsten erwarten!

Dies ist eine ideale Situation für ein temporäres Char-Array auf dem lokalen Stack. Die Größe ist klein. Sie haben eine fest codierte maximale Größe.

Wenn die Größe nicht konstant war, würde ich immer noch einen kleinen lokalen Char-Array-Puffer auf dem Stapel verwenden. Ich würde es einfach nach jeder Iteration an eine C++ std :: string anhängen. (Ja, std :: strings kann Binärwerte einschließlich mehrerer Nullzeichen speichern.)

recv() gibt zurück, wie viele Bytes es gelesen hat. Vektor v nimmt das nicht automatisch auf. Sie müssen diesen Wert also speichern und verwenden.

Ich schlage vor:

#define BUFFER_SIZE (1024*16) 
#define FLAGS  0 

int received = 0; 
int total = 0; 
char buffer [ BUFFER_SIZE + 1 ]; 

memset(buffer, 0, BUFFER_SIZE + 1); 

received = recv(sockfd, buffer, BUFFER_SIZE, FLAGS); 

if (received > 0) 
{ 
    copy(buffer + total, 
     buffer + total + received, 
     ostream_iterator<char>(cout)); 

    total += received; 
} 

while((received > 0) && (total < BUFFER_SIZE)) 
{ 
    received = recv(sockfd, buffer + total, BUFFER_SIZE - total, FLAGS); 

    if (received > 0) 
    { 
    copy(buffer + total, 
      buffer + total + received, 
      ostream_iterator<char>(cout)); 

    total += received; 
    } 
} 

buffer [ total ] = '\0'; 
buffer [ BUFFER_SIZE ] = '\0'; 

cout << "The total size is " << total << endl; 
+0

gut. eigentlich ist der Vektor zusammenhängend, eines seiner Hauptmerkmale. Sie haben garantiert, dass & v [1] == & v [0] + 1 wahr ist, wenn der Vektor mindestens 2 Elemente enthält. –

+0

es war nicht so in C++ 98. aber es wurde in C++ 03 behoben. Lesen Sie http://herbsutter.wordpress.com/2008/04/07/cringe-not-vectors-are-guaranteed-to-be-contiguous/ –

+0

Ich stehe behoben. Ursprüngliches Posting aktualisiert. Aber ich denke immer noch, es ist verrückt, sich auf solche Interna zu verlassen. Der letzte Microsoft Compiler, den ich verwendet habe, hat die C99-Standards verletzt, was mir kein Ende der Trauer beschert hat. Wollen Sie sich wirklich so auf Errata verlassen? Vor allem, wenn es nicht nötig ist? –

0

Warum Sie die Größe auf 1 setzen?
Wenn Sie den Speicherplatz reservieren, ist der Speicherplatz verfügbar, in den der Vektor hineinwachsen kann (ohne Neuzuordnung). Aber wer hat gesagt, dass es sicher ist, es direkt zu benutzen? Ich habe gesehen (debuggen) Implementierungen, die einen Warnungspuffer hinzufügen, gerade nachdem size() diese Bits ändert, und es würde eine Bestätigung erzeugen, wenn es das nächste Mal überprüft wird. Sie sollten nur von 0 -> size() lesen/schreiben.

Hinweis: Mit dieser Option können Sie auch v [len] = '\ 0';

vector<char> v(1024*16); 

std::size_t len = recv(sockfd, &v[0], v.size(), 0); 
while (len > 0) 
{ 
    v[len] = '\0'; 
    cout << &v[0]; 
    len = recv(sockfd, &v[0], v.size(), 0); 
} 

Beachten Sie, dass dies wahrscheinlich nicht der beste Weg ist, eine Zeichenfolge zu lesen.
Ich würde Länge Informationen über den Stream übergeben, so dass Sie wissen, wenn es nicht mehr Informationen zu lesen gibt dann lesen Sie nur so viel wie erforderlich ist.

+0

Wenn ich do v.clear() verwende; v.push_back (Daten) ein paar Mal. Ich müsste die Kapazität erneut anpassen? was würde alle meine Zeichen und in Zeichen Fall keine ctor, aber initial zu fillData? das ist nervig, besonders wenn ich viele 128bytes schreibe/sende und einen buf von mindestens 16k benötige. Gibt es eine Möglichkeit, ... –

+0

gibt es eine Möglichkeit, die Größe zu ändern, ohne die Daten in fillValue zu initialisieren? Wenn nicht, dass Debug-Impl würde mich in diesem Prj nerven und es sein, debug imple vs vermeiden möglicherweise viel Aufwand mit der Größenanpassung. auch, ostream.write (ptr, len); löst meine Frage. –

Verwandte Themen