功能sscanf不尊重宽度字段

时间:2014-09-15 05:26:12

标签: c parsing scanf

我正在尝试使用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 个答案:

答案 0 :(得分:3)

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; }

答案 1 :(得分:0)

使用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));