【问题标题】:What does the n stand for in `sscanf(s, "%d %n", &i, &n)`?`sscanf(s, "%d %n", &i, &n)` 中的 n 代表什么?
【发布时间】:2012-11-02 16:51:24
【问题描述】:

手册页指出sscanf的签名是

sscanf(const char *restrict s, const char *restrict format, ...);

我见过answer on SO,其中使用sscanf 的函数来检查输入是否为整数。

bool is_int(char const* s) {
    int n;
    int i;
    return sscanf(s, "%d %n", &i, &n) == 1 && !s[n];
}

查看!s[n] 似乎建议我们检查sscanf 是否扫描字符序列直到终止字符\0。所以我假设n 代表函数结束时sscanf 将在字符串s 中的索引。

但是变量i 呢?这是什么意思?

编辑:

更明确地说:我看到sscanf 的签名想要一个char * 类型的指针作为第一个参数。格式说明符作为 seconf 参数,因此它知道如何解析字符序列以及与转换说明符一样多的变量作为下一个参数。我现在明白i 是用于保存解析的整数。

由于格式说明符只有一个,我试着推导出n的功能。

我对@9​​87654336@ 的上述假设是否正确?

【问题讨论】:

  • int变量sscanf存储解析后的值。
  • 整数 (i) 的地址 (&)。
  • 进一步阅读手册页。
  • i 表示 iNeedABetterName

标签: c


【解决方案1】:

看起来操作员已经有了答案,但是因为我费心自己查找并运行代码...

来自“C The Pocket Reference”(Herbert Shildt 的第二版)scanf() 部分:

%n 接收一个整数值,等于目前读取的字符数

对于返回值:

scanf()函数返回一个等于字段数的数字 已成功赋值

sscanf() 函数的工作原理相同,它只是从提供的缓冲区参数(在本例中为 s )获取输入。 "== 1" 测试确保只解析了一个整数,!s[n] 确保输入缓冲区在解析整数之后很好地终止和/或字符串中实际上只有一个整数。

运行此代码,像“32”这样的 s 值给出了“真”值(我们没有将 bool 定义为系统上的类型),但 s 作为“3 2”给出“假”值,因为 s [n] 在这种情况下是“2”,并且 n 的值为 2(在这种情况下,“3”被解析以创建 int)。如果 s 为“3”,则此函数仍将返回 true,因为所有空格都已输入,并且 n 的值为 3。

另一个示例输入“3m”给出了一个“假”值,如您所料。

【讨论】:

  • 我认为允许将已经很好的答案换成更详细的答案,这样遇到相同问题的其他人可以更快地找到答案。非常感谢你的努力,伙计!
【解决方案2】:

来自sscanf() 的手册页的逐字记录:

转化次数

[...]

n

没有任何期望;相反,字符数 距离输入远的消耗通过下一个指针存储, 它必须是指向 int 的指针。这不是一个 转换,尽管它可以用 * 赋值抑制字符来抑制。 C 标准说:“执行 %n 指令不会增加在完成时返回的赋值计数 执行”,但更正似乎与此相矛盾。可能不明智 对 %n 次转换对返回值的影响做出任何假设。

【讨论】:

  • 谢谢,这正是我需要的。既然您指出了相关立场,我就明白这是什么意思了。
  • 是的,需要消耗很多东西——尤其是对于刚接触 c 概念的初学者来说。 :-)
  • 我换了答案,因为答案更详细,无意冒犯。只是试图确保其他有相同问题的人可以更快地找到最佳答案。但我并不比以前更感激,你已经得到了我的 +1。 ;-)
【解决方案3】:

我想指出原始代码有问题:

bool is_int(char const* s) {
    int n;
    int i;
    return sscanf(s, "%d %n", &i, &n) == 1 && !s[n];
} 

我会解释原因。并且我会解释 sscanf 格式的字符串。

首先,越野车:

给定输入“1”,即整数 1,sscanf 会将 1 存储到 i 中。那么,由于后面没有空格,sscanf就不会碰n了。并且 n 未初始化。因为 sscanf 将 i 设置为 1,所以 sscanf 返回的值将是 1,表示扫描了 1 个字段。由于 sscanf 返回 1,所以表达式的部分

sscanf(s, "%d %n", &i, &n) == 1

会是真的。因此 && 表达式的另一部分将执行。并且 s[n] 将访问内存中的某个随机位置,因为 n 未初始化。

解释格式:

"%d %n"

尝试扫描可能是十进制数或整数或科学计数法数字的数字。该数字是一个整数,它后面必须至少有一个空格。空白可以是空格、\n、\t 和某些其他不可打印的字符。只有在后面跟着空格时,它才会将 n 设置为扫描到该点的字符数,包括空格。

此代码可能是预期的:

    static bool is_int(char const* s) 
    {
        int i;
        int fld;
        return (fld = sscanf(s, "%i", &i)) == 1;
    }

    int main(int argc, char * argv[])
    {
        bool ans = false;

        ans = is_int("1");
        ans = is_int("m");

        return 0;
    }

此代码基于,如果 s 是整数,则 sscanf 将扫描它,而 fld 将恰好是一。如果 s 不是整数,则 fld 将为零或 -1。如果有其他东西,比如一个词,则为零;如果只有一个空字符串,则为 -1。

【讨论】:

  • 更正:上面的代码应该使用 %d 而不是 %i。我把这两个弄糊涂了。
  • 肯定since there is no white space after, sscanf will not touch n.不完全正确"%d %n" 格式不强制空格,它实际上允许它,如果您需要严格验证,这可能仍然是一个问题。使用"%d %n" 解析"123 "(带有尾随空格)将使其通过测试,而%d%n 则不会。
【解决方案4】:

变量i 表示直到它读取一个整数值。

你想问什么?不是太清楚!代码将(尝试)从字符串中读取一个整数到 'i'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-11
    • 2020-12-28
    • 1970-01-01
    • 2017-07-27
    • 2022-01-13
    • 2021-09-23
    • 1970-01-01
    • 2018-03-04
    相关资源
    最近更新 更多