2012-11-06 12 views
5

Mam funkcję, która działa na 128-bitowych blokach danych z ciągu dowolnej długości. Jeśli łańcuch nie jest równomiernie podzielony na kawałki 128-bitowe, zostanie odpowiednio dopełniony.Jak mogę iterować po ciągu w 128-bitowych porcjach?

Celem jest przekształcenie danych w łańcuchu, który jest wprowadzany do funkcji.

I początkowo myślał o zapętlenie przez String takiego:

//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); 
} 

Myślę, że to będzie działać, ale myślę, że musi być bardziej elegancki sposób to zrobić. Jedną z pomysłów, które przychodziły mi do głowy, było zamknięcie klasy strn i implementacja własnego iteratora, który może odczytać jego zawartość w 128-bitowych porcjach. Jest to atrakcyjne, ponieważ konstruktor może obsłużyć dopełnienie, a niektóre funkcje, z których obecnie korzystam, mogą stać się prywatne, co pozwoli uniknąć potencjalnych nadużyć. Czy wydaje się to owocnym podejściem? Jeśli tak, to w jaki sposób można wdrożyć własny iterator? Szczegółowe wyjaśnienia są mile widziane, ponieważ jestem bardzo niedoświadczony w C++.

Czy istnieją inne, być może lepsze, podejścia?

Dzięki!

Odpowiedz

3

Istnieje wiele podejść. Jednym z prostszych i prostszych będzie: możesz stworzyć swój własny typ, dokładnie o długości 128 bitów; prosty struct wykona zadanie.

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

I użyć go do powtórzenia ciągu znaków. Rzuć początek łańcucha na ten typ struktury: _128bit* start = (_128bit*)buffer; i rozpocznij iterowanie za pomocą zintegrowanej arytmetyki wskaźnika. Wszystkie operacje na start będą działać pod względem wielkości. Na przykład. , start++ przesunie 128 bitów do przodu; start-- przeniesie 128 bitów z powrotem. Gdy znajdziesz się w pożądanej pozycji, przekształć ją na pożądany typ i wykonaj manipulacje.

+0

To brzmi jak proste i eleganckie podejście! Tylko kilka pytań: 1) Czy istnieje powód, dla podkreślenia w "_128bit"? 2) Dlaczego typedef? Zgaduję, że to pozwala mi rzutować inne zmienne i stałe jako typ ... czy moja inuicja jest poprawna? 3) Jak to jest, że operator '++' jest już przeciążony w tym przykładzie? Dlaczego nie muszę tego robić jawnie? Wielkie dzięki i wiele przepraszam za moją niewiedzę o lepszych konstrukcjach C++! =) – blz

+1

1. Jeśli dobrze pamiętam, nazwy zmiennych nie mogą zaczynać się od cyfry. 2. Hmm, nie ma potrzeby w C++, w C może to skrócić kod :). 3. Jest to zaleta arytmetyki wskaźnikowej, działa ona w odniesieniu do wskazanych elementów, zobacz tutaj po więcej szczegółów: http://stackoverflow.com/questions/394767/pointer-arithmetic BTW, to jest czyste rozwiązanie C, bez C++ użyte funkcje – SomeWittyUsername

+0

OK, co ma sens. Wciąż jestem trochę niejasny w kwestii typedefs. Czy słowo kluczowe 'typedef' nie pozwala ci na stworzenie nazwy nowego typu? Czy Twój przykład nie powinien określać nazwy zdefiniowanej struktury? ... coś w stylu 'typedef struct {...}'? – blz

1

I prawdopodobnie to zrobić z iteratorów zamiast indeksowania, nadal używając własnych pętli for:

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); 
} 

Kod boost :: iterator_adaptor będzie wyglądać następująco. Zauważ, że otrzymuję tylko cztery bajty na porcję zamiast 16 dla uproszczenia w przykładzie:

#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

Czy istnieje sposób na podklasę 'std :: string :: const_iterator' tak, że inkrementowanie go za pomocą' ++ 'lub wywołanie' iter.next() 'zwiększy się o 128 bitów? Poza tym jestem nieco zdezorientowany. Myślałem, że 'iter + = 128' przesunie wskaźnik 128 * bajtów * (lub indeksów). czego mi brakuje? – blz

+1

@blz Wierzę, że można użyć 'boost :: iterator_adapter' do utworzenia takiego iteratora, ale mam małe doświadczenie z tą częścią boost. Masz rację, że 'iter + = 128' faktycznie zwiększyłoby się o 128 bajtów. Na szczęście to nie jest to, co robię w moim kodzie: zwiększam o 16 (bajty). Dlatego stworzyłem stałe, aby upewnić się, że nadal działa, nawet na przykład w systemie z 16-bitowym 'char'. –

Powiązane problemy