【问题标题】:sscanf - read hex values won't work with commasscanf - 读取十六进制值不适用于逗号
【发布时间】:2020-03-25 21:20:50
【问题描述】:

我正在尝试跳过字符串并解析两个值,如下面的代码所示:

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

十六进制值错误。当format[]中的,被删除后,输出如下:

Status: 1, HEX_DATA: d800, NEGATIVE_VAL: 0

现在 hex_data 值已正确解析,但 neg_val 未解析。如何全部解析?

【问题讨论】:

    标签: c scanf


    【解决方案1】:

    您应该使用%*[^,], 来忽略直到HEX_DATA 之前的第一个逗号(包括空格)在内的所有字符(包括空格),而不是使用%*s

    另外,%04x 需要 (un)signed int 来写入,而不是 uint16_t(另外,不需要前导 0)。而%d 需要(signed) int 来写信,而不是int8_t。使用hhh 类型修饰符分别写入更小的类型。

    更多详情请见this reference

    试试这个:

    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

    更新:或者更好的是,使用来自<inttypes.h>SCNd8SCNx16PRId8PRIx16 格式帮助宏,例如:

    #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

    【讨论】:

    • 逗号是 rad-herring - 它与问题无关。你可以将scanf规范改成使用%*[^,]而不是%*s,但这确实与问题或问题无关。
    • @ChrisDodd "逗号是 rad-herring" - 这取决于 text_to_be_skipped 是否包含空格。显然在给出的示例中,它没有,但我们显然不知道 OP 的生产代码中 text_to_be_skippedreal 内容。 %*s 如果遇到逗号前的空格 (ideone.com/g8pCvo) 将停止解析,而 %*[^,], 将仅在遇到逗号 (ideone.com/iTtw98) 时停止解析。由于HEX_DATA 之前显然有一个逗号,我会选择后者以确保安全。
    • 我会说它可能包含一个逗号(或不以逗号结尾),因为它包含一个空格 - 任何比示例更复杂的东西都可能是一个问题,并且真的什么都没有与变量中的无效数据的 sscanf 返回明显成功 (2) 的问题有关。
    【解决方案2】:

    问题在于您的数据类型与格式字符串不匹配——x 用于读取无符号整数,而不是 uint16_t,d 用于读取 int,而不是 int8_t。试试

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

    【讨论】:

    • 同样把%04改成%40是没用的和混乱的
    • @chqrlieforyellowblockquotes: true 它没有效果,但它无害——它没有效果
    猜你喜欢
    • 2012-04-29
    • 2019-09-19
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    • 2019-07-28
    • 1970-01-01
    相关资源
    最近更新 更多