2012-11-06 7 views
5

Ich habe eine Funktion, die auf 128-Bit-Datenblöcke aus einer Zeichenfolge beliebiger Länge arbeitet. Wenn die Zeichenfolge nicht gleichmäßig in 128-Bit-Teile unterteilt werden kann, wird sie entsprechend aufgefüllt.Wie kann ich über eine Zeichenfolge in 128-Bit-Blöcken iterieren?

Der Zweck besteht darin, die Daten in der Zeichenfolge zu transformieren, die in die Funktion eingegeben wird.

Ich dachte zunächst eine solche durch den Strang von looping:

//This might have stupid errors. Hopefully it stillg gets the point across. 
for (int i = 0; i < strn.size(); i += 16) 
{ 
    string block = strn.substr(i, i + 15); 
    strn.replace(i, i + 15, block); 
} 

ich dies funktionieren würde erraten, aber ich denke, es muss eine elegantere Art und Weise, dies zu tun. Eine Idee, die mir in den Sinn kam, war, in eine Klasse zu kapseln und meinen eigenen Iterator zu implementieren, der seinen Inhalt in 128-Bit-Blöcken lesen kann. Das ist ansprechend, weil der Konstruktor mit Padding umgehen kann und einige der Funktionen, die ich gerade nutze, privat gemacht werden könnten, um möglichen Missbrauch zu vermeiden. Scheint dies ein fruchtbarer Ansatz? Wenn ja, wie geht man bei der Implementierung eines eigenen Iterators vor? Ausführliche Erklärungen sind sehr willkommen, da ich mit C++ sehr wenig Erfahrung habe.

Gibt es andere, vielleicht bessere Ansätze?

Danke!

Antwort

3

Es gibt viele Ansätze. Einer der einfacheren und geradlinigeren wäre wie folgt: Sie können Ihren eigenen Typ genau 128 Bit erstellen; einfach struct wird den Job erledigen.

typedef struct 
{ 
    char buf[16]; 
} _128bit; 

Und verwenden Sie es, um über Ihre Zeichenfolge zu iterieren. Legen Sie den Anfang der Zeichenfolge in diesen Strukturtyp: _128bit* start = (_128bit*)buffer;, und starten Sie die Iteration mit der integrierten Zeigerarithmetik. Alle Operationen auf start funktionieren in Bezug auf seine Größe. Z.B. , start++ wird 128 Bits vorwärts bewegen; start-- verschiebt 128 Bit zurück. Sobald Sie an der gewünschten Position sind, konvertieren Sie sie zum gewünschten Typ und führen Sie Ihre Manipulationen durch.

+0

, der wie ein einfacher und eleganter Ansatz klingt! Nur ein paar Fragen: 1) Gibt es einen Grund für den Unterstrich in '_128bit'? 2) Warum der Typdef? Ich schätze, das erlaubt mir, andere Variablen und Konstanten als seinen Typ zu werfen ... ist meine Inuition korrekt? 3) Wie kommt es, dass der Operator '++' in diesem Beispiel bereits überladen ist? Warum muss ich das nicht explizit machen? Vielen Dank und viele Entschuldigungen für meine Unkenntnis der feineren C++ Konstrukte! =) – blz

+1

1. Wenn ich mich richtig erinnere, können Variablennamen nicht mit einer Ziffer beginnen. 2. Hmm, brauche eigentlich nicht in C++, in C kann das den Code verkürzen :). 3. Das ist der Vorteil der Zeigerarithmetik, es arbeitet in Bezug auf die spitzen Elemente, siehe hier für weitere Details: http://stackoverflow.com/questions/394767/pointer-arithmetik BTW, das ist eine reine C-Lösung, kein C++ Funktionen verwendet – SomeWittyUsername

+0

Ok, das macht Sinn. Ich bin jedoch immer noch etwas unklar über Typdefs. Ist es nicht möglich, mit dem Schlüsselwort 'typedef 'einen neuen Typnamen zu erstellen? Sollte Ihr Beispiel also keinen Namen für die von Ihnen definierte Struktur angeben? ... etwas wie 'typedef struct {...}'? – blz

1

würde ich wahrscheinlich mit Iteratoren tut dies eher als Indizierung, noch Ihre eigenen for-Schleife:

const int NUM_BITS_IN_CHUNK = 128; 
const int CHUNK_SIZE = NUM_BITS_IN_CHUNK/CHAR_BIT; 

for(std::string::const_iterator iter = str.begin(); iter < str.end(); iter += CHUNK_SIZE) 
{ 
    your_func(iter, iter + CHUNK_SIZE); 
} 

Der boost :: iterator_adaptor Code würde wie folgt aussehen. Beachten Sie, dass ich nur vier Bytes pro Chunk bekommen statt 16 der Einfachheit halber im Beispiel .:

#include <iostream> 
#include <string> 

#include <boost/iterator_adaptors.hpp> 

struct string_chunk_iterator : public boost::iterator_adaptor<string_chunk_iterator, std::string::const_iterator> 
{ 
    string_chunk_iterator(const std::string::const_iterator& base) : iterator_adaptor(base) { } 

private: 
    friend class boost::iterator_core_access; 
    void increment() { this->base_reference() = this->base() + 4; } 
    void advance(typename iterator_adaptor::difference_type n) 
    { 
     this->base_reference() = this->base() + (4 * n); 
    } 
}; 

int main() 
{ 
    const std::string tester(20, 'A'); 

    string_chunk_iterator iter(tester.begin()); 
    string_chunk_iterator str_end(tester.end()); 

    for(; iter != str_end; ++iter) 
    { 
     std::string chunk(&*iter, &*(iter + 1)); 

     std::cout << chunk << std::endl; 
    } 

    return 0; 
} 
+0

Gibt es eine Möglichkeit, 'std :: string :: const_iterator' abzuleiten, so dass das Inkrementieren mit' ++ 'oder das Aufrufen von' iter.next() 'um 128 Bits erhöht wird? Außerdem bin ich ein bisschen verwirrt. Ich hätte gedacht, dass 'iter + = 128 'den Zeiger 128 * Bytes * (oder Indizes) bewegen würde. Was vermisse ich? – blz

+1

@blz Ich glaube, Sie könnten 'boost :: iterator_adapter' verwenden, um einen solchen Iterator zu erstellen, aber ich habe wenig Erfahrung mit diesem Teil von Boost. Sie haben Recht, dass 'iter + = 128' tatsächlich um 128 Bytes erhöht wird. Glücklicherweise tue ich das nicht in meinem Code: Ich erhöhe um 16 (Bytes). Deshalb habe ich die Konstanten erstellt, um sicherzustellen, dass es auch auf einem System mit 16 Bit 'char' funktioniert. –