以C++元编程风格实现 RLE 算法



我已经为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",即代码只打印组的第一个字符。我无法找出代码中的错误。有人可以看看它,并帮助我了解我在这里做错了什么。

我无法找出代码中的错误,有人可以看看它,并帮助我了解我在这里做错了什么。

问题是您初始化静态成员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 == 1N > 0时,当编译器使用零表示RLE<N - 1>::cnt(CLak++大小写)。

我不知道谁是对的,但关键是当你写的时候

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

你用RLE<N>打印cnt- 所以N1,根据情况 - 你RLE<N>cnt设置为零。

但是当你在RLE<N>中将cnt设置为零时,RLE<N-1>中的cnt保持不变(所以N-11,根据情况)。

我在您的代码中没有看到太多元编程,但在我看来,可能的更正cnt设置为 1

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

并将RNE<N-1>::cnt设置为Compress()中的cnt + 1

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

但是,坦率地说,我更喜欢您的原始(不是元编程)代码。

最新更新