【问题标题】:Implementing RLE algorithm in C++ meta programming style以 C++ 元编程风格实现 RLE 算法
【发布时间】:2019-03-04 01:51:09
【问题描述】:

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

【问题讨论】:

  • 该代码使用 gcc 生成 6m5a4t1s。请确保您拥有准确的代码、准确的输出,并告诉我们您的编译器。 minimal reproducible example 为必填项。
  • @Yakk - Adam Nevrsumont 我已经在 Cxxdroid 移动编译器上编译了代码并得到了我在帖子中提到的结果,但是当我尝试使用在线编译器时,我得到了你提到的结果,可能我需要更改我的编译器。附带问题,是否由于不完整、不可验证和/或问题不符合 StackOverflow 的标准而投反对票
  • 我用过 c4droid。并阅读代码,它应该按照 c4dtoid 所说的去做。
  • @Yakk-AdamNevraumont 我的手机上没有 C4Droid 应用程序。 Cxxdroid 是免费的,所以我正在使用它。

标签: c++ templates recursion template-meta-programming


【解决方案1】:

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

问题是你初始化静态成员cnt如下

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

size_t RLE<0>::cnt = 0;

所以你得到cnt == N,当编译器使用RLE&lt;N - 1&gt;::cnt 值初始化(g++ 情况),cnt == 1N &gt; 0,当编译器使用零作为RLE&lt;N - 1&gt;::cnt(clang++ 情况)。

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

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

您在RLE&lt;N&gt; 中打印cnt - 所以N1,根据情况 - 并且您将cnt 中的cnt 设置为零RLE&lt;N&gt;

但是,当您将RLE&lt;N&gt; 中的cnt 设置为零时,RLE&lt;N-1&gt; 中的cnt 保持不变(因此N-11,视情况而定)。

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

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

size_t RLE<0>::cnt = 1;

并将RNE&lt;N-1&gt;::cnt 设置为cnt + 1 in 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);
}

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

【讨论】:

  • @ma66,感谢您浏览代码。我想知道如何使用元程序来完成。我同意普通的递归版本更清晰,更容易理解。问候
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-25
  • 1970-01-01
  • 2011-02-12
  • 1970-01-01
相关资源
最近更新 更多