繁体   English   中英

在文件的char数组中搜索2个连续的十六进制值

[英]Searching for 2 consecutive hex values in a char array of a file

我已经使用fread将文件读入字符数组。 现在,我想在该数组中搜索两个连续的十六进制值,即FF后跟D9(其jpeg标记表示文件结尾)。 这是我用来执行此操作的代码:

char* searchBuffer(char* b) {
    char* p1 = b;
    char* p2 = ++b;
    int count = 0;

    while (*p1 != (unsigned char)0xFF && *p2 != (unsigned char)0xD9) {
        p1++;
        p2++;
        count++;
    }

    count = count;
    return p1;
}

现在,我知道如果搜索不包含0xFF的十六进制值(例如4E后跟46),则此代码有效,但是每次尝试搜索0xFF时,它都会失败。 当我不将十六进制值转换为无符号字符时,程序不会进入while循环,当我这样做时,程序会遍历数组中的所有字符,并且直到出现超出范围的错误才会停止。 我很困惑,请帮忙。

忽略计数,它只是一个可以帮助我调试的变量。

提前致谢。

为什么不使用memchr()查找潜在的匹配项?

另外,请确保您要处理的潜在签名类型的促销活动( char可能签名也可能未签名)。 请注意,虽然将0xff0xd9视为8位值时已将其高位设置,但它们是非负整数常量,因此不会发生“符号扩展”:

char* searchBuffer(char* b) {
    unsigned char* p1 = (unsigned char*) b;
    int count = 0;

    for (;;) {
        /* find the next 0xff char */
        /* note - this highlights that we really should know the size   */
        /* of the buffer we're searching, in case we don't find a match */
        /* at the moment we're making it up to be some large number     */
        p1 = memchr(p1, 0xff, UINT_MAX);
        if (p1 && (*(p1 + 1) == 0xd9)) {
            /* found the 0xff 0xd9 sequence */
            break;
        }

        p1 += 1;
    }

    return (char *) p1;
}

另外,请注意,如果没有找到目标,您实际上应该传递一些有关正在搜索的缓冲区大小的概念。

这是一个采用缓冲区大小参数的版本:

char* searchBuffer(char* b, size_t siz) {
    unsigned char* p1 = (unsigned char*) b;
    unsigned char* end = p1 + siz;

    for (;;) {
        /* find the next 0xff char */
        p1 = memchr(p1, 0xff, end - p1);
        if (!p1) {
            /* sequnce not found, return NULL */
            break;
        }


        if (((p1 + 1) != end) && (*(p1 + 1) == 0xd9)) {
            /* found the 0xff 0xd9 sequence */
            break;
        }

        p1 += 1;
    }

    return (char *) p1;
}

使用void * memmem(const void * haystack,size_t haystacklen,const void * needle,size_tneedlelen);

在string.h中可用,并且易于使用。

char* searchBuffer(char* b, int len) 
{
    unsigned char needle[2] = {0xFF, 0XD9};
    char * c;
    c = memmem(b, len, needle, sizeof(needle));
    return c;
}

您正在整数促销中犯规。 != (和类似的)的两个操作数都提升为int 并且,如果其中至少有一个是unsigned ,那么它们都将被视为unsigned (实际上不是100%准确,但是对于这种特殊情况,就足够了)。 所以这:

*p1 != (unsigned char)0xFF

等效于:

(unsigned int)*p1 != (unsigned int)(unsigned char)0xFF

在您的平台上, char显然是带signed ,在这种情况下,它永远不能采用(unsigned int)0xFF的值。

因此,尝试按以下方式投射*p1

(unsigned char)*p1 != 0xFF

或者,您可以让函数采用unsigned char参数而不是char ,并避免进行所有强制转换。

[请注意,最重要的是,您的循环逻辑是不正确的,正如各种注释所指出的。]

4E将提升自己为正整数,但是*p1对于FF将为负,然后将提升为非常大的无符号值,该值将远大于FF。

您需要使p1 无符号。

您可以将代码编写得更短:

char* searchBuffer(const char* b) {
    while (*b != '\xff' || *(b+1) != '\xd9') b++;
    return b;
}

还要注意,如果b实际上不包含字节FFD9,则该函数将导致分段错误(或更糟糕的是,返回无效结果)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM