sscanf - чтение шестнадцатеричных значений не будет работать с запятой - PullRequest
2 голосов
/ 26 марта 2020

Я пытаюсь пропустить строку и проанализировать два значения, как в коде ниже:

int main()
{
    char format[] = "%*s HEX_DATA:%04x, NEGATIVE_VAL:%d";
    char str[] = "text_to_be_skipped, HEX_DATA:d800, NEGATIVE_VAL:-20";

    uint16_t hex_data = 0;
    int8_t neg_val = 0;

    int status = sscanf(str, format, &hex_data, &neg_val);

    printf("Status: %d, HEX_DATA: %04x, NEGATIVE_VAL: %d", status, hex_data, neg_val);

    return 0;
}

Возвращает следующий вывод:

Status: 2, HEX_DATA: ffff, NEGATIVE_VAL: -20

Неверное шестнадцатеричное значение. Когда , in format[] удаляется, вывод будет следующим:

Status: 1, HEX_DATA: d800, NEGATIVE_VAL: 0

Теперь значение hex_data анализируется правильно, но neg_val не анализируется. Как их все разобрать?

Ответы [ 2 ]

3 голосов
/ 26 марта 2020

Вместо использования %*s следует использовать %*[^,],, чтобы игнорировать все символы (включая пробелы) вплоть до первой запятой до HEX_DATA.

Кроме того, %04x для записи требуется (un)signed int, а не uint16_t (также ведущий 0 не требуется). И %d нужен (signed) int для записи, а не int8_t. Используйте модификаторы типа h и hh для записи в меньшие типы соответственно.

См. эту ссылку для получения более подробной информации.

Попробуйте вместо этого:

int main()
{
    char format[] = "%*[^,], HEX_DATA:%4hx, NEGATIVE_VAL:%hhd";
    char str[] = "text_to_be_skipped, HEX_DATA:d800, NEGATIVE_VAL:-20";

    uint16_t hex_data = 0;
    int8_t neg_val = 0;

    int status = sscanf(str, format, &hex_data, &neg_val);

    printf("Status: %d, HEX_DATA: %04x, NEGATIVE_VAL: %d", status, hex_data, neg_val);

    return 0;
}

Вывод:

Status: 2, HEX_DATA: d800, NEGATIVE_VAL: -20

Live Demo

UPDATE : или лучше использовать SCNd8, * Вспомогательные макросы формата 1034 *, PRId8 и PRIx16 из <inttypes.h>, например:

#include <inttypes.h>

int main()
{
    char format[] = "%*[^,], HEX_DATA:%4" SCNx16 ", NEGATIVE_VAL:%" SCNd8;
    char str[] = "text_to_be_skipped, HEX_DATA:d800, NEGATIVE_VAL:-20";

    uint16_t hex_data = 0;
    int8_t neg_val = 0;

    int status = sscanf(str, format, &hex_data, &neg_val);

    printf("Status: %d, HEX_DATA: %04" PRIx16 ", NEGATIVE_VAL: %" PRId8, status, hex_data, neg_val);

    return 0;
}

Вывод:

Status: 2, HEX_DATA: d800, NEGATIVE_VAL: -20

Live Demo

1 голос
/ 26 марта 2020

Проблема в том, что ваши типы данных не соответствуют вашей строке формата - x для чтения беззнакового целого, а не uint16_t, а d для целого, а не int8_t. Попробуйте

char format[] = "%*s HEX_DATA:%04"SCNx16", NEGATIVE_VAL:%"SCNd8;
...