0

私がする必要があるのは、次のようなテキストまたは文字列が与えられたときです

\0abc\n\0Def\n\0Heel\n\0Jijer\n\tlkjer

qsort を使用して、rot エンコーディングの比較に基づいて、この文字列をソートする必要があります。

int my_rot_conv(int c) {
  if ('a' <= tolower(c) && tolower(c) <= 'z')
    return tolower(c)+13 <= 'z' ? c+13 : c-13;
  return c;
}

int my_rot_comparison(const void *a, const void *b) {
  char* ia = (char*) a;
  char* ib = (char*) b;
  int i=0;
  ia++, ib++;
  while (i<strlen(ia)) {
    if (ia[i] == '\0' || ia[i] == '\n' || ia[i] == '\t' || ib[i] == '\0' || ib[i] == '\n' || ib[i] == '\t') {
      i++;
    }
    if (my_rot_conv(ia[i]) > my_rot_conv(ib[i])) {
      return 1;
    } else if (my_rot_conv(ia[i]) < my_rot_conv(ib[i]))
      return -1;
  }
  return 0;
}

次の例では、\0 で始まる 2 つの文字列を比較して -1 を取得しています。

printf("%d \n", my_rot_comparison("\0Abbsdf\n", "\0Csdf\n"));

ただし、これは qsort を使用した文字列では機能しません。これはia++, ib++;、1 つの単語の比較でしか機能しないためです。

char *my_arr;
my_arr = malloc(sizeof(\0abc\n\0Def\n\0Heel\n\0Jijer\n\tlkjer));
strcpy(my_arr, \0abc\n\0Def\n\0Heel\n\0Jijer\n\tlkjer);
qsort(my_arr, sizeof(my_arr), sizeof(char), my_rot_comparison);

配列は次のようにソートする必要があります\0Def\n\0Heel\n\0Jijer\n\0\n\tlkjer

私の質問は、文字\0と文字を含む文字列に対して機能する比較関数をどのように定義すればよいですか?\t\n

4

3 に答える 3

3

strlen関数の定義により、文字列の末尾は、文字列の先頭またはその後で最初に検出されたバイトであると見なされる\0ため、バイトが埋め込まれた文字列では正しく動作しません。 strlen\0

残りの標準 C 文字列関数は、同じ方法で定義されます。

\0これは、バイトを含む可能性のある文字列 (のような) データを操作するには、別の関数セットを使用する必要があることを意味します。おそらく、これらの関数を自分で作成する必要があります。

文字列の末尾をマークするためlengthに特定の番兵バイト ( など) に依存できないため、おそらくメンバーを含む構造体を定義する必要があることに注意してください。\0例えば:

typedef struct {
    unsigned int length;
    char bytes[];
}
MyString;

入力文字列で禁止されている他のバイト ( 以外\0) がある場合は、(コメンター @Sinn ごとに) と交換してから\0、通常の C 文字列関数を使用できます。ただし、これがうまくいくかどうかは明らかではありません。

于 2013-10-31T00:33:43.167 に答える
0

\0最後にエクストラを使用して終了すると仮定します

int strlenzz(char*s)
{
  int length =0;
  while(!(*s==0 && *(s+1) == 0))
  {
   s++;
   length++;
  }
  return length+1
} 
于 2013-10-31T00:46:29.310 に答える
0

個人的には、danfuzz の提案のようなものが好きですが、代替案をリストするために...

エスケープ規則を使用して、関数を次のように記述できます。

  • 「エスケープ」/エンコード、埋め込み (ただし終端ではない) '\0'/NUL を展開して「\」と「0」を表示 (C ソース コード文字列リテラルを記述するときに使用される規則を採用)、および
  • 別のエスケープする。

そうすれば、それらを C 文字列として渡すことができます。上記の qsort/rot 比較コードはそのまま機能しstrlen(escaped_value)ますが、エスケープされた表現のバイト数を返すことを十分に意識する必要があります。その値に NUL が埋め込まれている場合、エスケープされていない値のバイト。

たとえば、次のようなものです。

void unescape(char* p)
{
    char* escaped_p = p;
    for ( ; *escaped_p; ++escaped_p)
    {
        if (*escaped_p == '\\')
            if (*++escaped_p == '0')
            {
               *p++ = '\0';
               continue;
            }
        *p++ = *escaped_p;
    }
    *escaped_p = '\0'; // terminate
}

バッファに十分なメモリがあることを確認するか、新しいバッファをmallocする何らかの方法が必要なため、エスケープはよりトリッキーです-計算しやすい最悪の場合のサイズとして、unescaped_value * 2 + 1 の論理サイズのいずれかの長さ、またはエスケープが必要な NUL を数えて、logical-size + #NULs + 1.... に厳密にサイズ変更します。

于 2013-10-31T01:29:36.430 に答える