Реализация алгоритма RLE в стиле метапрограммирования C ++ - PullRequest
0 голосов
/ 04 марта 2019

Я реализовал простой рекурсивный алгоритм для RLE (кодирование длины выполнения).

Код:

#include <iostream>
using namespace std;

template <size_t N>
struct RLE {
    static size_t cnt;

    static void Compress(char const p[]) {                
        // Check current char with next char. If they are not same then print the current character and its count. Then reset the counter to 0 for next itetation.
        if (!(*p == *(p + 1))) {
            cout << cnt << *p;
            cnt = 0;
        }
        // Call the function again with new character
        RLE<N - 1>::Compress(p + 1);
    }
};

template <size_t N>
size_t RLE<N>::cnt = 1 + RLE<N - 1>::cnt;

template <>
struct RLE<0> {
    static size_t cnt;
    static void Compress(char const[]) {
    }
};;

//template<>  // On uncomenting this like why do I get a error "extraneous template<>, in declaration of variable cnt."
size_t RLE<0>::cnt = 0;

int main(void) {
    char const str[]{"mmatsss"};

    // -1 since sizeof includes terminating null char.
    RLE<sizeof(str) - 1>::Compress(str);
}

Для входа типа «mmatsss» ожидаемый результат равен «2m1a1t3s», но я получаю «1m1a1t1s», то есть код печатает только первый символ группы.Я не могу выяснить ошибку в коде.Может кто-нибудь, пожалуйста, взгляните на это и помогите мне понять, что я здесь делаю неправильно.

1 Ответ

0 голосов
/ 04 марта 2019

Я не могу выяснить ошибку в коде, может кто-нибудь, пожалуйста, взгляните на нее и помогите мне понять, что я здесь делаю неправильно.

Проблемаявляется то, что вы инициализируете статический член cnt следующим образом

template <size_t N>
size_t RLE<N>::cnt = 1 + RLE<N - 1>::cnt;

size_t RLE<0>::cnt = 0;

, поэтому вы получаете cnt == N, когда компилятор использует инициализированное значение RLE<N - 1>::cnt (случай g ++), cnt == 1 при N > 0когда компилятор использует ноль для RLE<N - 1>::cnt (случай clang ++).

Я не знаю, кто прав, но дело в том, что когда вы пишете

        cout << cnt << *p;
        cnt = 0;

, вы печатаете cntв RLE<N> - то есть N или 1, в зависимости от случая - и вы устанавливаете в ноль cnt в RLE<N>.

Но когда вы устанавливаете в ноль cntв RLE<N>, cnt в RLE<N-1> остаются неизменными (поэтому N-1 или 1, в зависимости от случая).

Я не вижу много метапрограммирования в вашем коде, но мне кажется,что возможная коррекция установлена ​​для всех cnt на 1

template <size_t N>
size_t RLE<N>::cnt = 1;

size_t RLE<0>::cnt = 1;

и для RNE<N-1>::cnt как cnt + 1 в Compress()

static void Compress(char const p[])
{                
    if (!(*p == *(p + 1)))
    {
        cout << cnt << *p;
        cnt = 0u;
    }

    RLE<N - 1>::cnt = cnt+1u;  <---  add this line

    RLE<N - 1>::Compress(p + 1);
}

Но, честно говоря, я предпочитаю вашоригинал (не метапрограммирование) код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...