【问题标题】:parse string input using sscanf iteratively使用 sscanf 迭代解析字符串输入
【发布时间】:2013-05-28 21:33:04
【问题描述】:

我有一个由空格分隔的数字组成的输入字符串,例如“12 23 34”。
输出应该是一个整数数组。

我尝试了以下方法:

while (sscanf(s, "%d", &d) == 1) {
    arr[n++] = d;
}

但我发现,由于我不是从文件中读取(偏移量会自动调整),
我每次都在d 中存储相同的号码。

然后我尝试了这个:

while (sscanf(s, "%d", &d) == 1) {
    arr[n++] = d;
    s = strchr(s, ' ');
}

手动将s 转换为新号码。
我相信应该可以正常工作。我只是不明白为什么它会失败。

【问题讨论】:

  • 如果是常数个数,可以使用macthing格式字符串——“%d %d %d”。如果没有,则每次都可以找到下一个空格,并将传递作为第一个参数传递给scanf

标签: c scanf


【解决方案1】:

scanf 提供了一个优雅的答案:%n 转换,它告诉您到目前为止已经消耗了多少字节。

像这样使用它:

int pos;
while (sscanf(s, "%d%n", &d, &pos) == 1) {
    arr[n++] = d;
    s += pos;
}

【讨论】:

    【解决方案2】:

    第二个技巧确实应该在稍加修改的情况下工作。请参阅代码中的 cmets 了解需要更改的内容:

    while (sscanf(s, "%d", &d) == 1) {
        arr[n++] = d;
        s = strchr(s, ' ');
        // strchr returns NULL on failures. If there's no further space, break
        if (!s) break;
        // Advance one past the space that you detected, otherwise
        // the code will be finding the same space over and over again.
        s++;
    }
    

    标记数字序列的更好方法是strtol,它可以帮助您在读取下一个整数后推进指针:

    while (*s) {
        arr[n++] = strtol(s, &s, 10);
    }
    

    【讨论】:

    • 如果 sscanf 中的 s 为 NULL 会怎样?
    • @mohit 我怀疑这是一种已定义的行为。在我修改代码时没有立即测试NULL 的问题不是你将NULL 传递给sscanf,而是你会在循环的最后一行计算NULL+1,这绝对是错了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-28
    • 1970-01-01
    • 2013-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-20
    相关资源
    最近更新 更多