在行尾有奇怪的sscanf行为

时间:2018-01-08 02:40:15

标签: c scanf

为学校做一些项目,我遇到了以下问题:

<link data-require="bootstrap-css" data-semver="4.0.0-alpha.4" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.4/css/bootstrap.min.css" /> <link data-require="bootstrap@*" data-semver="4.0.5" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" /> 读取与预期值不同的值。

我想读这样的东西:

sscanf

这是我目前使用的代码:

1 0 185336079 0 0 168231418 -256 0 255 1
2 0 185336079 -256 0 168231418 -256 0 255 2
3 0 185336079 -256 0 168231418 -256 0 255 3
4 0 185336079 0 0 0 0 0 255 4

以上代码生成的输出如下:

FILE *fd = open_fd("/proc/firewall", "r");

while ((read = getline(&line, &len, fd)) != -1) {
    sscanf(line, "%d %c %d %d %d %d %d %d %c %c\n", &num,
        &rule_u.inbound_outbound,
        &rule_u.source_ip,
        &rule_u.source_netmask,
        &rule_u.source_port,
        &rule_u.destination_ip,
        &rule_u.destination_netmask,
        &rule_u.destination_port,
        &rule_u.protocol,
        &rule_u.action);

    printf("scanf read rule action : %c\n", rule_u.action);
    printf("sscanf whole line:\n%s\n",line);
    convert_rule_from_u();
    print_rule();
}

预期输出应如下:

scanf read rule action : 5
sscanf whole line:
1 0 185336079 0 0 168231418 -256 0 255 1

scanf read rule action : 5
sscanf whole line:
2 0 185336079 -256 0 168231418 -256 0 255 2

scanf read rule action : 5
sscanf whole line:
3 0 185336079 -256 0 168231418 -256 0 255 3

scanf read rule action : 5
sscanf whole line:
4 0 185336079 0 0 0 0 0 255 4

scanf read rule action : 1 sscanf whole line: 1 0 185336079 0 0 168231418 -256 0 255 1 scanf read rule action : 2 sscanf whole line: 2 0 185336079 -256 0 168231418 -256 0 255 2 scanf read rule action : 3 sscanf whole line: 3 0 185336079 -256 0 168231418 -256 0 255 3 scanf read rule action : 4 sscanf whole line: 4 0 185336079 0 0 0 0 0 255 4

rule_u struct

我做错了什么?

3 个答案:

答案 0 :(得分:2)

在尝试使用格式说明符"255 0"阅读"%c %c"时,代码在每行末尾都有问题。

这会扫描并保存字符'2'和第一个'5'。 OP希望将整数保存为255和0的所需结果。

使用"%hhu %hhu"读取数字文本并将其整数另存为unsigned char

答案 1 :(得分:1)

通常,在scanf()系列函数的格式字符串中使用尾随空格是一个坏主意 - 有关详细信息,请参阅Trailing blank in scanf() format string。如果函数是sscanf()或其中一个亲戚,从字符串而不是文件流中读取,那么它不是灾难。

但是,您还遇到了问题,即最后的第二个%c未读取所有255 - 您需要%d(或者{最后一列的{1}}或%hhd),应该审核所有其他%c列;也许他们也应该是数字?

  

所以你说它应该是这样的:%hhu - 可以吗?我认为它之前阅读了整个sscanf(line, "%d%hhu%d%d%d%d%d%d%hhu%hhu",...;我正在玩它,它正在工作,或者至少看起来像它。

转换规范之间的空格是可以的;它们使它更具可读性。字符串末尾的换行符意味着&#34;读取空白区域,直到找到不是空格&#34;的东西,如果输入来自(磁盘)文件或字符串,则可以。如果输入来自终端,管道,FIFO,套接字,那将是一场灾难。 对255的调用不会返回,直到输入中出现下一条消息为止;它需要除换行符或空格或制表符之外的其他内容来表示&#34;全部&#34;。那可能不是你想要的。

示例数据中的最后一个字段显然不是单个字符。您可能需要一个适合无符号字符的数字,因此scanf()是合适的。其他两个%hhu列仅在数据中保留零,但如果它们可以包含大于9的数字,则需要%c

&#39;入站/出站&#39;列可能是0或1,因此%hhu可能就行了(但请注意,值为%c'0',而不是'1'和{{ 1}}!)。您知道数据(或需要知道数据) - 您的电话。

我注意到你的结构浪费了相当多的空间。开头的一个字节字段后面有3个字节的填充,最后还有两个字节的填充。考虑移动彼此相邻的三个无符号字符字段以保存每个结构4个字节(您仍然有1个填充字节,但这是5的改进)。想一想这是否重要(可能性并不重要)。

此外,您应该测试0 - 或1的返回值,以确保输入正确。

sscanf()

答案 2 :(得分:0)

你的倒数第二个转换说明符是%c,它只需要一个字符。您的输入有3:"255"(或某些此类内容)。

因此,您正在偏离轨道,并且每一行都是从最后一行读取的项目,而不是之前的迭代。