Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 切换到新编译器后,sscanf的工作方式不同_C++_Visual Studio_Scanf - Fatal编程技术网

C++ 切换到新编译器后,sscanf的工作方式不同

C++ 切换到新编译器后,sscanf的工作方式不同,c++,visual-studio,scanf,C++,Visual Studio,Scanf,我在两个不同版本的编译器中有不同的scanf函数行为 int number; int offset = 0; const char* ref = "123456"; sscanf(ref, "%d %n", &number, &offset); 我不明白为什么Visual Studio 2013版本12.0的偏移量==4,而Visual Studio 2017版本15.9的偏移量==6。这是旧版本的错误吗? 当我删除空格时,两个版本都显示正确的数

我在两个不同版本的编译器中有不同的scanf函数行为

    int number;
    int offset = 0;
    const char* ref = "123456";
    sscanf(ref, "%d %n", &number, &offset);

我不明白为什么Visual Studio 2013版本12.0的偏移量==4,而Visual Studio 2017版本15.9的偏移量==6。这是旧版本的错误吗? 当我删除空格时,两个版本都显示正确的数字:

    sscanf(ref, "%d%n", &number, &offset);
%d%n与%d%n有何不同

%d%n
%d%n
有何不同

第一个仅统计
%d
所使用的字符,而后面的另一个也统计任何可能的空白字符

#include <cstdio>
#include <iostream>


void test(const char * ref, const char * fmt)
{
    std::cout << "fmt: \"" << fmt << "\"  ref: \"" << ref << "\"" << std::endl;
    int number;
    int offset = 0;
    int ret = std::sscanf(ref, fmt, &number, &offset);
    std::cout << " - Returned: " << ret << "  Offset: " << offset << "  Number: " << number << std::endl;
}


int main(int argc, char* argv[])
{
    test("123456", "%d %n");
    test("123456", "%d%n");
    test("123456  ", "%d %n"); // case 3
    test("123456  ", "%d%n");  // case 4
}
请注意,在案例3中,附加的2个空白字符是如何计数的(因此偏移量=8),而在案例4中,它们是如何不计数的(因此偏移量=6)



我不明白为什么Visual Studio 2013版本12.0的偏移量==4,而Visual Studio 2017版本15.9的偏移量==6。这是旧版本的错误吗

这看起来确实像一个bug。可能性:

  • %d%n
    被解释为需要在数字后加空格,才能使
    %n
    生效。您的输入“123456”没有后面的空白,因此它未定义偏移量。这违反了标准,因为它清楚地表明格式字符串中的空白字符与输入字符串中的零个或多个空白字符相匹配。确切措辞:“由空白字符组成的指令是通过读取输入直到第一个非空白字符(未读)来执行的,[…]此指令永远不会失败。”()

  • 旧平台上的
    sizeof(int)
    太小,无法表示数字
    123456

    有符号整数的最小允许最大值是
    32767
    (谢谢@MartinYork)

    这意味着带有
    %d
    sscanf
    只能读取
    12345
    ,而不能读取
    123456
    ,从而将
    6
    保留在输入中。这将导致偏移量为5,而不是4



解决方案:首先决定您是否需要
%d%n
%d%n
的语义,然后将测试用例添加到您的测试套件中(您有一个,不是吗?),以确保提供的功能符合您的期望。如果需要,请提供自己的实现。

这只是猜测,但您应该检查
sscanf
的返回值:两个编译器是否都返回2?每台机器上
int
的大小是多少
std::cout格式字符串中的“空格”将读取零个或多个空格字符。“为什么Visual Studio 2013 12.0版的偏移量==4”-->其错误。user7242858建议您再次尝试编写代码,并从
sscanf()
发布返回值,在这两种情况下,返回值都应为1。
fmt: "%d %n"  ref: "123456"
 - Returned: 1  Offset: 6  Number: 123456
fmt: "%d%n"  ref: "123456"
 - Returned: 1  Offset: 6  Number: 123456
fmt: "%d %n"  ref: "123456  "
 - Returned: 1  Offset: 8  Number: 123456
fmt: "%d%n"  ref: "123456  "
 - Returned: 1  Offset: 6  Number: 123456