2009-03-12 3 views
3

Given (in C++)einfachste Weg, eine Folge von Bytes in einen größeren Puffer in C++

char * byte_sequence; 
size_t byte_sequence_length; 
char * buffer; 
size_t N; 

Angenommen byte_sequence und byte_sequence_length initialisiert zu wiederholen, bis zu einem gewissen beliebigen Länge Bytefolge (und seine Länge) und buffer wird initialisiert, um auf N * byte_sequence_length Bytes zu zeigen, was wäre der einfachste Weg, die byte_sequence in bufferN mal zu replizieren? Gibt es etwas in STL/BOOST, das schon so etwas macht?

Zum Beispiel, wenn die Sequenz "abcd" wäre und N 3 wäre, dann würde buffer am Ende "abcdabcdabcd" enthalten.

Antwort

11

würde ich wahrscheinlich gehen mit diesem gerade:

for (int i=0; i < N; ++i) 
    memcpy(buffer + i * byte_sequence_length, byte_sequence, byte_sequence_length); 

Dies vorausgesetzt, dass Sie mit binären Daten handelt und verfolgen die Länge, nicht mit '\0' Terminierung.

Wenn Sie möchten, dass diese C-Strings sind, müssen Sie ein zusätzliches Byte zuweisen und in das '\0' ein Ende hinzufügen.Bei einem c-string und eine ganze Zahl, dann würden Sie es wie folgt zu tun:

char *RepeatN(char *source, size_t n) 
{ 
    assert(n >= 0 && source != NULL);    
    size_t length = strlen(source) - 1; 
    char *buffer = new char[length*n + 1]; 
    for (int i=0; i < n; ++i) 
     memcpy(buffer + i * length, source, length); 
    buffer[n * length] = '\0'; 
} 
7

Wiederholung des Puffers während Zeigerarithmetik zu vermeiden:

Sie std :: vector können < char> oder std :: string die Dinge einfacher für Sie. Beide Container können auch binäre Daten enthalten.

Diese Lösung hat die schönen Eigenschaften, die:

  • Sie brauchen nicht über Speicherzugriffsverletzungen zu befürchten
  • Sie brauchen nicht darum, die Größe Ihres Puffer sorgen korrekte
  • ohne manuelle Umschichtungen

  • Sie können Sequenzen jederzeit an Ihre Puffer anhängen.

    //Note this works even for binary data. 
    void appendSequenceToMyBuffer(std::string &sBuffer 
         , const char *byte_sequence 
         , int byte_sequence_length 
         , int N) 
    { 
        for(int i = 0; i < N; ++i) 
         sBuffer.append(byte_sequence, byte_sequence_length); 
    } 
    
    //Note: buffer == sBuffer.c_str() 
    

    Alternative: Für binäre Daten mit Hilfe von memcpy:

    buffer = new char[byte_sequence_length*N]; 
    for (int i=0; i < N; ++i) 
        memcpy(buffer+i*byte_sequence_length, byte_sequence, byte_sequence_length); 
    //... 
    delete[] buffer; 
    

    Alternative: Für null beendet Datenstring mit strcpy:

    buffer = new char[byte_sequence_length*N+1]; 
    int byte_sequence_length = strlen(byte_sequence); 
    for (int i=0; i < N; ++i) 
        strcpy(buffer+i*byte_sequence_length, byte_sequence, byte_sequence_length); 
    //... 
    delete[] buffer; 
    

    Alternative: Wenn Sie den Puffer mit einem einzigen Wert füllen:

    buffer = new char[N]; 
    memset(buffer, byte_value, N); 
    //... 
    delete[] buffer; 
    
  • +0

    Ein Kommentar zur ersten Lösung - wenn Sie sBuffer.reserve (byte_sequence_length * N) aufrufen, bevor Sie die Anhänge ausführen, können Sie mehrfache Neuzuweisungen verhindern. – Eclipse

    2

    Wenn N a zu sein ist bekannt, Potenz von 2, können Sie aus dem ersten Teil des Puffers auf nachfolgende Teile kopieren, die Menge jedes Mal kopiert steigen:

    assert((N > 0) && ((N & (N-1)) == 0)); 
    memcpy(buffer, byte_sequence, byte_sequence_length); 
    for (size_t i = 1; i < N; i *= 2) 
        memcpy(buffer + i * byte_sequence_length, buffer, i * byte_sequence_length); 
    

    Edit: Es ist trivial, dies auf Arbeit auszudehnen, wenn N nicht eine Potenz von 2 ist. Hier ist eine verbesserte Version, die alle Einschränkungen für N entfernt und auch die ungerade für Anweisung mit einer Weile ersetzt.

    if (N > 0) 
        memcpy(buffer, byte_sequence, byte_sequence_length); 
    size_t copied = 1; 
    while (copied < N) 
    { 
        size_t tocopy = min(copied, N - copied); 
        memcpy(buffer + copied * byte_sequence_length, buffer, tocopy * byte_sequence_length); 
        copied += tocopy; 
    } 
    
    Verwandte Themen