首页 > 解决方案 > sscanf() 通过更改 for 循环的索引值导致无限循环

问题描述

功能:

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.

出于好奇,我在循环中放了一个ind++,它在顶部是 2,在底部是 1。如果我sscanf()取出它就会终止。

标签: clinuxgcc

解决方案


格式对应的变量%x必须是int,不是char。使用错误的类型会导致未定义的行为;在您的程序中,它正在写入0ind因此循环永远不会停止。

to的size参数fgets()应该是缓冲区的大小,不加 1。fgets()将减去 1 以获得它在 null 之前可以读取的字符数。您应该将 1 的大小加 1 input_string,而不是 的参数fgets()

fgets()还包括它返回的输入中的换行符,您还需要为此添加空间input_string

如果要转换输入中的所有字节,则需要在input_string每次循环中从不同的索引进行扫描。

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设置为字符长,而无需为换行符和 null 添加空间。而不是使用fgets(),使用fread()来准确读取您想要的字符数:

fread(input_string, CHAR_PER_BYTE, num_bytes, stdin);

推荐阅读