【问题标题】:searching an unsigned char array for characters在无符号字符数组中搜索字符
【发布时间】:2014-05-01 20:05:53
【问题描述】:

我有一个要读取的二进制数据文件。文件中的值是 8 位无符号整数,“记录”分隔符是 ASCII 文本(例如$MSG$GRP)。我把数据读成一大块,如下:

unsigned char *inBuff = (unsigned char*)malloc(file_size*sizeof(unsigned char));  
result = fread(inBuff, sizeof(unsigned char), file_size, pFile);

我需要搜索这个数组以找到以$GRP 开头的记录(这样我就可以读取后面的数据),有人可以提出一个好的方法吗?我尝试了几件事,但都没有奏效。例如,我最近的尝试是:

std::stringstream str1;
str1 << inBuff;
std::string strTxt = str1.str();

但是,当我检查它的长度时,它只有 5。我在记事本中查看了文件,注意到第六个字符是 NULL。所以它似乎因为NULL而被切断了。有什么想法吗?

【问题讨论】:

  • 不要混合使用 C 和 C++。使用fstream 并将您的文件直接读入std::string。如果你仍然想要/需要坚持使用你的 C 代码,don't cast the result of malloc
  • 不要混合使用 C 和 C++。去for (i=0; i&lt;file_size-4; i++) if (strncmp(&amp;inBuff[i], "$MSG", 4) printf( "Found $MSG at %d\n", i );
  • 能否提供一些示例代码和示例文件?听起来很容易通过strstr()sscanf() 实现。
  • @Dogbert 鉴于该文件包含 8 位无符号整数,其中一些为 0(又名 NULL),我很确定 strstr 不是一个可行的解决方案,我怀疑 @ 987654333@ 也可以。从问题描述来看,OP是二进制文件,而不是简单的文本文件。
  • @user3386109 它实际上是一个二进制文件,包含二进制和 ASCII 值(实际上是混合的)。不过划界并不难,如果我们把 is 当作 ASCII,我们可以找到边界。

标签: c++ arrays string


【解决方案1】:

假设 fread 不返回 -1,其中的值会告诉您有多少字节可供搜索。

期望能够对二进制数据进行字符串搜索是不合理的,因为二进制数据中可能存在 NUL 字符,这将导致长度函数提前终止。

一种可能的方法是搜索数据是在缓冲区上使用memcmp,以及您的搜索键和搜索键的长度。

【讨论】:

    【解决方案2】:

    (根据我的评论)

    C str 函数假定以零结尾的字符串。任何 C 字符串函数都会在第一个二进制 0 处停止。使用memchr 定位$,然后使用strncmpmemcmp。特别是,不要假设紧跟在 4 字节标识符之后的字节是二进制 0

    在代码中(C,未测试):

    /* recordId should point to a simple string such as "$GRP" */
    unsigned char *find_record (unsigned char *data, size_t max_length, char *recordId)
    {
        unsigned char *ptr;
        size_t remaining_length;
        ptr = startOfData;
    
        if (strlen(recordId) > max_length)
            return NULL;
    
        remaining_length = max_length;
        do
        {
           /* fast scan for the first character only */
           ptr = memchr (ptr, recordId[0], remaining_length);
           if (!ptr)
              return NULL;
    
           /* first character matches, test entire string */
           if (!memcmp (ptr, recordId, strlen(recordId))
              return ptr;
    
           /* no match; test onwards from the next possible position */
           ptr++;
    
           /* take care not to overrun end of data */
           /* It's tempting to test
              remaining_length = ptr - startOfData;
              but there is a chance this will end up negative, and
              size_t does not like to be negative.
            */
           if (ptr >= startOfData+max_length)
               break;
    
           remaining_length = ptr-startOfData;
        } while (1);
    
        return NULL;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-04
      • 2020-08-04
      • 2016-11-29
      • 2011-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多