0

エンコードとデコードをそれぞれ実装する 2 つの関数があります。

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

それらについて私が気に入らない点は、+= と -= の部分を除いて、それらが非常に似ているということです。それらを 1 つの関数に統合する方法はありますか?ユーザーにエンコードまたはデコードのどちらを行うかを尋ね、それぞれ -= または += バージョンを選択します。存在する場合、そのコードはどのようになりますか? これを行う方法がいくつかある場合、どれが最適ですか?

4

5 に答える 5

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 に答える
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 に答える
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) 乗数を使用できます。+= の場合、乗数 = 1 を使用する必要があり、次のようになります。

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

-= の場合、乗数 = -1 を使用すると、次のようになります。

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

具体的には、コードの場合、次のようになります (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;

-1/+1 および int パラメータのハードコードされた値の代わりに eOperation を使用します。

于 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 に答える