Поиск 2 последовательных шестнадцатеричных значений в массиве char файла - PullRequest
1 голос
/ 22 мая 2011

Я прочитал файл в массив символов, используя 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, происходит сбой. Когда я не преобразовываю шестнадцатеричные значения в unsigned char, программа не входит в цикл while, когда я делаю это, программа просматривает все символы в массиве и не останавливается, пока не получит ошибку выхода за границы. Я в тупике, пожалуйста, помогите.

Игнорировать счетчик, это просто переменная, которая помогает мне отлаживать.

Заранее спасибо.

Ответы [ 5 ]

2 голосов
/ 22 мая 2011

Почему бы не использовать memchr() для поиска потенциальных совпадений?

Кроме того, убедитесь, что вы имеете дело с рекламными акциями потенциально подписанных типов (char может быть или не быть подписано).Обратите внимание, что хотя 0xff и 0xd9 имеют старший бит, если рассматривать их как 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;
}
1 голос
/ 29 января 2018

use void * memmem (const void * haystack, size_t haystacklen, const void * needle, size_t needlelen);

, который доступен в 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;
}
1 голос
/ 22 мая 2011

4E повысит себя до положительного целого числа, но *p1 будет отрицательным с FF, а затем будет повышено до очень большого значения без знака, которое будет намного больше, чем FF.

Вам необходимо сделатьp1 без знака.

1 голос
/ 22 мая 2011

Вы можете написать код намного короче, как:

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

Также обратите внимание, что функция вызовет ошибку сегментации (или, что еще хуже, вернет неверные результаты), если b фактически не содержит байтовFFD9.

1 голос
/ 22 мая 2011

Вы нарушаете целочисленные акции . Оба операнда для != (и аналогичные) повышаются до 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, и избегать всех приведений.

[Обратите внимание, что помимо всего этого, ваша логика цикла неверна, как указано в различных комментариях.]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...