【问题标题】:Function sscanf not respecting width field函数 sscanf 不考虑宽度字段
【发布时间】:2014-09-15 05:26:11
【问题描述】:

我正在尝试使用 sscanf 解析 mac 地址。这是我的尝试:

uint8_t mac[6];

//string version of mac address stored in s
if(strlen(s) == 17 && sscanf(s, 
    "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", 
    &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) == 6)
{ /*the mac address was parsed correctly*/ }

这适用于00:00:00:00:00:00 之类的常见情况,但它将地址00:00:00:00:0:123 解析为00:00:00:00:00:12

sscanf 可以处理这种情况,还是我必须手动解析字符串?

编辑:格式应该完全是“xx:xx:xx:xx:xx:xx”。如果一个字节只能容纳一个字符,则必须使用前导零写入。

【问题讨论】:

  • 由于您为每个组件指定 2 个字符,因此每个组件最多扫描 2 个字符。您希望它在输入更多字符时做什么?
  • 我希望它准确读取 2 个字符,必要时以 0 开头。
  • 如果您希望它最多读取两个字符,那么00:00:00:00:0:123 会不会不正确?确实,我马上就知道这是一个不正确的 MAC 地址。
  • 正如您现在发现的那样,scanf(和家人)并不适合解析和验证字符串,仅用于从字符串中提取值。您需要想出另一种解析和验证字符串的方法,例如带有strtoulstrtok 循环来解析和检查数字。

标签: c parsing scanf


【解决方案1】:

scanf 格式中给出的字段宽度是 最大 字段宽度——无法指定最小字段宽度(因此最小值始终为 1)。因此,如果您想读取固定宽度的字段并拒绝较短的字段,则需要直接检查所有字段分隔符。如果您还想拒绝带有空格的字符串(scanf 会忽略除cn[ 之外的所有转换类型的空格),则需要使用其他内容。

int check_mac(const char *s, uint8_t *mac) {
    for (int i = 0; i < 6; i++, s += 3) {
        if (!isxdigit(s[0]) || !isxdigit(s[1]) || s[2] != ":::::"[i])
            return -1;
        sscanf(s, "%hhx", &mac[i]); }
    return 0; }

【讨论】:

    【解决方案2】:

    如果使用strtok,我会感觉好多了。

    unsigned char mac[6];
    const char * s = "00:00:00:00:0:12";
    const char * delims = ":";
    
    char temp[100];
    strcpy(temp, s);
    
    char * str = strtok(temp, delims);
    int i = 0;
    do
    {
        if (sscanf(str, "%hhx", &mac[i++]) < 1)
            break;
    } while ((i < 6) && ((str = strtok(NULL, delims)) != NULL));
    

    【讨论】:

    • 希望没有人输入额外的:
    • sscanf 会捕捉到它,但如果有人输入了额外的 :00 ,那么你会说得很好。我昨晚很晚才写的——经过编辑修复。
    • 这似乎无法正确检测到每个 OP 的 "0:00:00:00:0:12" 的故障“如果一个字节只能容纳一个字符,则必须用前导零写入。”
    • 我认为这是对输入的要求,即我们可以对输入做出的假设。我并不认为这意味着代码必须强制执行该规则,所以因为不这样做很方便,所以我没有。
    猜你喜欢
    • 2017-05-26
    • 1970-01-01
    • 1970-01-01
    • 2013-12-22
    • 1970-01-01
    • 2012-04-21
    • 2021-08-13
    • 2019-07-27
    • 1970-01-01
    相关资源
    最近更新 更多