1

NULchar をセパレーターとして使用して、char 配列をトークンに分割したいと考えています。

コマンドからネットワーク経由で受け取った char 配列があるrecvので、char 配列の長さを知っています。そのchar配列には、NULchar(\0)で区切られた一連の文字列があります。

セパレーターはchar であるため、独自の目的で使用されるため、NUL使用できないことを意味します。strtokNULL

したがって、バイト 8 から始まるすべての文字列を反復処理したいと考えています (文字列の前に 2 つの 32 ビット整数が続きます)。

すべてのキャラクターがキャラクターを探してから、これまでに見つけた長さを\0実行できると考えていましたが、これよりも優れた方法があるに違いないと考えました。memcpy

他にどのようなアプローチを取ることができますか?

4

4 に答える 4

1

含まれている文字列を取得する方法を示す簡単なコードを次に示します。

#include <stdio.h>
#include <string.h>

int main(void) {
    char recbuf[7] = {'a', 'b', 'c', '\0', 'd', 'e', '\0'};
    int recbuf_size = 7;
    int j = 0;
    char* p = recbuf;
    while(j < recbuf_size) 
    {
        printf("%s\n", p);  // print the string found
                            // Here you could copy the string if needed, e.g.
                            // strcpy(mySavedStrings[stringCount++], p);

        int t = strlen(p);  // get the length of the string just printed
        p += t + 1;         // move to next string - add 1 to include string termination
        j += t + 1;         // remember how far we are
    }
    return 0;
}

出力:

abc
de

バッファの先頭でいくつかのバイトをスキップする必要がある場合は、次のようにします。

int number_of_bytes_to_skip = 4;
int j = number_of_bytes_to_skip;
char* p = recbuf + number_of_bytes_to_skip;

知らせ:

上記のコードは、受信バッファが常に'\0'. 実際のコードでは、コードを実行する前にそれを確認し、エラー処理を追加する必要があります。次に例を示します。

if (recbuf[recbuf_size-1] != '\0')
{
    // Some error handling...
}
于 2016-05-15T12:36:47.117 に答える
0

次の入力データを想定します。

char input[] = {
  0x01, 0x02, 0x0a, 0x0b,  /* A 32bit integer */
  'h', 'e', 'l', 'l', 'o', 0x00, 
  'w', 'o', 'r', 'l', 'd', 0x00,
  0x00 /* Necessary to make the end of the payload. */
};

先頭の 32 整数は次のようになります。

const size_t header_size = sizeof (uint32_t);

入力の解析は、「文字列」の最初の文字を識別し、それへのポインターを格納してから、見つかった文字列の長さ (1+) と同じだけ移動し、入力の最後に到達するまでやり直すことで実行できます。 .

size_t strings_elements = 1; /* Set this to which ever start size you like. */
size_t delta = 1; /* 1 is conservative and slow for larger input, 
                     increase as needed. */

/* Result as array of pointers to "string": */
char ** strings = malloc(strings_elements * sizeof *strings);

{  
  char * pc = input + header_size;
  size_t strings_found = 0;
  /* Parse input, if necessary increase result array, and populate its elements: */
  while ('\0' != *pc)
  {
    if (strings_found >= strings_elements)
    {
      strings_elements += delta;
      void * pvtmp = realloc(
        strings, 
        (strings_elements + 1) * sizeof *strings /* Allocate one more to have a 
                                        stopper, being set to NULL as a sentinel.*/
      ); 

      if (NULL == pvtmp)
      {
        perror("realloc() failed");
        exit(EXIT_FAILURE);
      }

      strings = pvtmp;
    }

    strings[strings_found] = pc; 
    ++strings_found;

    pc += strlen(pc) + 1;
  }

  strings[strings_found] = NULL; /* Set a stopper element. 
                                    NULL terminate the pointer array. */
}

/* Print result: */
{
  char ** ppc = strings;
  for(; NULL != *ppc; ++ppc)
  {
    printf("%zu: '%s'\n", ppc - strings + 1, *ppc)
  }
}

/* Clean up: */
free(strings);

分割時にコピーする必要がある場合は、この行を置き換えます

  strings[strings_found] = pc; 

  strings[strings_found] = strdup(pc); 

free()使用後およびingの前にクリーンアップ コードを追加しますstrings

{
  char ** ppc = strings;
  for(; NULL != *ppc; ++ppc)
  {
    free(*ppc);
  }
}

上記のコードは、ペイロードの後に​​少なくとも 1文字'\0'(NULヌル文字) が続くことを前提としています。

後者の条件が満たされない場合は、他の終了シーケンスを定義/前後に配置するか、他のソースからの入力のサイズを知る必要があります。そうしないと、問題は解決できません。

上記のコードには、次のヘッダーが必要です。

#include <inttypes.h> /* for int32_t */
#include <stdio.h> /* for printf(), perror() */
#include <string.h>  /* for strlen() */
#include <stdlib.h> /* for realloc(), free(), exit() */

また、次の定義のいずれかが必要になる場合があります。

#define _POSIX_C_SOURCE 200809L

#define _GNU_SOURCE

または、Cコンパイラがstrdup()利用可能にするために他に必要なもの。

于 2016-05-15T12:29:54.637 に答える
0

NUL 分離により、実際に作業が非常に簡単になります。

char* DestStrings[MAX_STRINGS];
int j = 0;
int length = 0; 
inr prevLength =0;
int offset = 8;
for(int i = 0;i<MAX_STRINGS;i++) 
{
     length += strlen(&srcbuffer[j+offset+length]); 
     if(length == prevLength)                          
     { 
       break;
     }
     else
     {

       DestStrings[i] = malloc(length-prevLength+1);
       strcpy(DestStrings[i],&srcbuffer[j+offset+length]);
       prevLength = length;
       j++;
     }

}

潜在的なバッファ オーバーフロー エラーを回避するために、いくつかのチェックを追加する必要があります。このコードで、先に進む方法について少しアイデアが得られることを願っています。

EDIT 1:これは、インデックスを変更する反対票のため、ソリューション全体ではないコードから開始します。

編集 2: 受信データ バッファーの長さは既にわかっているため、受信データに NUL を追加して、このコードがそのまま機能するようにしてください。一方、受信したデータの長さ自体を使用して、コピーされた長さと比較できます。

于 2016-05-15T12:13:14.063 に答える