sscanf () вызывает бесконечное l oop путем изменения значения индекса цикла for - PullRequest
1 голос
/ 29 мая 2020

Функция:

void input_bytes(unsigned char bytes[], int num_bytes)
{
    const int CHAR_PER_BYTE = 2; /* expects hex input */
    const int STRING_SIZE = num_bytes * CHAR_PER_BYTE;

    char input_string[STRING_SIZE + 1];  /* + 1 for null char */
    int ind;
    unsigned char byte;

    fgets(input_string, STRING_SIZE + 1, stdin);

    printf("after fgets\n");

    for (ind = 0; ind < num_bytes; ind++)
    {
        printf("top of loop, ind: %d\n", ind);

        sscanf(input_string, "%2x", &byte);
        bytes[ind] = byte;

        printf("bottom of loop, ind: %d\n", ind);
    }

    printf("\n\n");
}

Драйвер:

int main()
{
    unsigned char bytes[5];

    input_bytes(bytes, 5);
}

Вывод:

after fgets
top of loop, ind: 0
bottom of loop, ind: 0
top of loop, ind: 1
bottom of loop, ind: 0
top of loop, ind: 1
bottom of loop, ind: 0
top of loop, ind: 1
bottom of loop, ind: 0
top of loop, ind: 1
bottom of loop, ind: 0
top of loop, ind: 1
bottom of loop, ind: 0
top of loop, ind: 1
bottom of loop, ind: 0
top of loop, ind: 1
bottom of loop, ind: 0
top of loop, ind: 1
bottom of loop, ind: 0
...

Компиляция с gcc driver.c -o driver.

Я поставил an ind++ в l oop из любопытства, и он идет на 2 вверху и 1 внизу. Если я возьму sscanf(), он отключится.

1 Ответ

2 голосов
/ 29 мая 2020

Переменная, соответствующая формату %x, должна быть int, а не char. Использование неправильного типа приводит к неопределенному поведению; в вашей программе 0 записывается в ind, поэтому l oop никогда не останавливается.

Аргумент size для fgets() должен быть размером буфера без добавления 1. fgets() вычитает 1, чтобы получить количество символов, которое он может прочитать перед нулем. Вы должны добавить 1 к размеру input_string, а не аргументу fgets().

fgets() также включает новую строку во входных данных, которые он возвращает, вам нужно добавить место для этого в input_string также.

Если вы хотите преобразовать все байты на входе, вам нужно сканировать каждый раз с другого индекса в input_string через l oop.

void input_bytes(unsigned char bytes[], int num_bytes)
{
    const int CHAR_PER_BYTE = 2; /* expects hex input */
    const int STRING_SIZE = num_bytes * CHAR_PER_BYTE + 2; // + 2 for newline and null byte

    char input_string[STRING_SIZE];
    int ind;
    unsigned int byte;

    fgets(input_string, STRING_SIZE, stdin); /* + 1 for null char */

    printf("after fgets\n");

    for (ind = 0; ind < num_bytes; ind++)
    {
        printf("top of loop, ind: %d\n", ind);

        sscanf(&input_string[2*ind], "%2x", &byte);
        bytes[ind] = byte;

        printf("bottom of loop, ind: %d\n", ind);
    }

    printf("\n\n");
}

Поскольку на самом деле вы не выполняете никаких строковых операций с input_string. Вы можете сделать его длиной точно num_bytes * CHAR_PER_BYTE символа, не добавляя пробела для новой строки и нуля. Вместо fgets() используйте fread(), чтобы прочитать точное количество символов, которое вы хотите:

fread(input_string, CHAR_PER_BYTE, num_bytes, stdin);
...