0

我有两个分别实现编码和解码的函数:

void
delta_encode (char *buffer, const unsigned int length)
{
 char delta = 0;
 char original;
 unsigned int i;
 for (i = 0; i < length; ++i)
 {
  original = buffer[i];
  buffer[i] -= delta;
  delta = original;
 }
}

void
delta_decode (char *buffer, const unsigned int length)
{
 char delta = 0;
 unsigned int i;
 for (i = 0; i < length; ++i)
 {
  buffer[i] += delta;
  delta = buffer[i];
 }
}

我不喜欢这些的是它们非常相似,除了 += 与 -= 部分。有没有办法将它们组合成一个函数,它会询问用户是要编码还是解码,并分别选择 -= 或 += 版本。如果有,它的代码会是什么样子?如果有几种方法可以做到这一点,哪种方法最好?

4

5 回答 5

2

如果您有相同的代码但对于符号,您可以在函数调用中添加一个参数,如果您有编码版本,则将您encode/decode添加的内容乘以。-1因此:

typedef enum {ENCODE = -1; DECODE = 1;} CODE_TYPE;

void delta_code(char *buffer, const unsigned int length, CODE_TYPE e);

void delta_code(char *buffer, const unsigned int length, CODE_TYPE e) 
  {
  char delta = 0;
  char original;
  unsigned int i;
  for (i = 0; i < length; ++i)
    {
    original = buffer[i];
    buffer[i] += delta*e;
    delta = (e<0)?original:buffer[i];
    }
  }
于 2013-04-15T04:44:33.030 回答
2

只要这是一个“智力练习”,我还不如发布这个,它捕获了编码/解码的对称性:

#include <stdbool.h>

void delta_code(char *buffer, const unsigned int length, bool encode) 
{
    char delta = 0;
    unsigned int i;
    for (i = 0; i < length; ++i)
    {
        char next_delta;
        if (encode)
        {
            next_delta = buffer[i];
            buffer[i] -= delta;
        }
        else
        {
            buffer[i] += delta;
            next_delta = buffer[i];
        }
        delta = next_delta;
    }
}

编辑: OP 提到了语言功能。如果 C 有一个广义的后缀减法,比如说=-它像后缀一样工作,因为它在减法之前--返回左侧的值,那么你可以这样做:

   for (i = 0; i < length; ++i)
       delta = encode? (buffer[i] =- delta) : (buffer[i] += delta);

当然,在真正的 C 中你可以做

      char temp;
      for (i = 0; i < length; ++i)
          delta = encode? (temp = buffer[i], buffer[i] -= delta, temp) : (buffer[i] += delta);
于 2013-04-15T05:19:24.453 回答
1

我同意所有说这样做不好的人的观点。它使您的程序效率降低,代码更笨拙(从而降低了可读性)。如果您在实施设计时遇到这样的障碍,您可能需要重新考虑您的设计以及为什么会存在这样的要求。

说了这么多,你可以做这样的事情:

typedef enum
{
    ENCODE,
    DECODE
} CONTEXT;

void
delta_operation (char *buffer, const unsigned int length, CONTEXT context)
{
    if(context == ENCODE)
    {
        char delta = 0;
        char original;
        unsigned int i;
        for (i = 0; i < length; ++i)
        {
            original = buffer[i];
            buffer[i] -= delta;
            delta = original;
        }
    }
    else if(context == DECODE)
    {
        char delta = 0;
        unsigned int i;
        for (i = 0; i < length; ++i)
        {
            buffer[i] += delta;
            delta = buffer[i];
        }
    }
}

并称它为:

char buffer[] = "Whatever your buffer is supposed to be";
delta_operation (buffer, strlen(buffer), ENCODE);
于 2013-04-15T04:37:36.940 回答
1

我个人同意@paddy。您不应该仅仅为了减少代码行而使您的代码不可读。

一般来说,如果你想在 += 和 -= 之间切换,你可以使用 (+/-1) 乘数。对于 += 你应该使用 multiplier = 1 然后你会得到:

buffer[i] = buffer[i] + multiplier * delta ==> buffer[i] = buffer[i] + delta

对于 -= 你可以使用 multiplier = -1 然后你会得到:

buffer[i] = buffer[i] + multiplier * delta ==> buffer[i] = buffer[i] - delta

特别是对于您的代码,它可能看起来像这样(您可以使用 boolean 而不是 int 并在函数中分配值):

void
delta_encode_decode (char *buffer, const unsigned int length, int shouldDecode)
{
 char delta = 0;
 char original;
 unsigned int i;
 for (i = 0; i < length; ++i)
 {
  original = buffer[i];
  buffer[i] = buffer[i] + shouldDecode * delta;

  if (shouldDecode == 1)
    delta = buffer[i];
  else
    delta = original;

 }
}

或更“优雅”的解决方案(Anish Ram 的贡献):

typedef enum
{
    ENCODE = -1,
    DECODE = 1
} eOperation;

并使用 eOperation 而不是 -1/+1 的硬编码值和 int 参数

于 2013-04-15T04:44:18.540 回答
0

这是其他人似乎还没有建议的东西。您可以制作一个内核函数来对单个字符进行操作并将其传入。

typedef void (*delta_op)( char *value, char *delta );

void encode( char *value, char *delta )
{
    char prev = *value;
    *value += *delta;
    *delta = prev;
}

void decode( char *value, char *delta )
{
    *value -= *delta;
    *delta = *value;
}

然后你只需将你的内核函数传递给主要部分。

void encode_decode( char *buffer, unsigned int length, encode_op operation )
{
    char delta = 0;
    unsigned int i;
    for (i = 0; i < length; ++i)
    {
        operation( &buffer[i], &delta );
    }
}

所以你这样打电话:

encode_decode( buffer, length, encode );
encode_decode( buffer, length, decode );

不过它会很笨重而且很慢......就像qsort. 因为所有的函数调用。

于 2013-04-15T05:44:43.107 回答