【问题标题】:Wierd output after sorting排序后的奇怪输出
【发布时间】:2015-05-18 08:41:15
【问题描述】:

排序后我得到奇怪的输出

如果使用scanf 提供输入,则该行会导致错误。输出有一些奇怪的排列。 (我已评论该行)

如果我使用cin,输出就可以了。在线编译器中也不存在此问题。同样的事情发生在不同的计算机上。

例如,如果我输入

5
23 44 32 2 233

输出是

32 23 233 2 44

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iomanip>


using namespace std;

int main()
{
    unsigned long long int n=0,i=0;

    // cin>>n;
    scanf("%llu",&n);

    unsigned long long int arr[n];

    for(i=0;i<n;i++)
    {
        // cin>>arr[i]; //if use this no error but if use next line it is
        scanf("%llu",&arr[i]); //causing error
    }

    sort(arr,arr+n);

    for(i=0;i<n;i++)
    {
        // cout<<arr[i]<<" ";
        printf("%llu ",arr[i]);
    }
    return 0;
}

【问题讨论】:

  • 您是否尝试在调试器中单步执行代码?
  • 看看 Michael Burr 对Strange “unsigned long long int” behaviour的回答
  • @swapnilansh 就我而言,如果编译器支持可变长度数组,它会很好地工作。
  • @swapnilansh 另外我确信这个问题与 scanf 没有什么共同点,因为输出显示了正确的值,尽管它们没有在您的帖子中排序。
  • 您使用的是什么编译器/环境?

标签: c++ sorting


【解决方案1】:

如果使用cin 有帮助,那么%llu 可能是给定指针的错误标志。检查您的编译器的文档并查看 long long 的含义并检查您的库的 printf/scanf 文档。

【讨论】:

    【解决方案2】:

    有各种可能的解释。很可能是一个编译器(或库或运行时),其中scanf() 不能正确支持%llu 格式和long long unsigned 类型。

    long long 类型在 1999 年标准之前不是 C 的正式组成部分,在 2011 年标准之前(从内存中)不是 C++ 的一部分。结果是,根据您的编译器的年龄,支持从不存在到部分(您所看到的)到完成。

    实际上,由于 C++ 流函数(operator&gt;&gt;() 等)的组织方式,可以说更改 C++ 流以支持新类型(如 long long unsigned)比更改 C I/O 更容易。 C++ 流在设计上更加模块化(operator&gt;&gt;() 是为每种类型重载的函数,因此更容易添加对新类型的支持,而不会破坏处理现有类型的现有代码)。 C I/O 函数(如scanf())以允许更多单一实现的方式指定 - 这意味着,要添加对新类型和格式说明符的支持,有必要更改/调试/验证/验证更多现有代码。这意味着与 C++ I/O 相比,更改 C I/O 可以合理地花费更多的精力,因此也需要更多的时间。自然地,YMMV 在这个论点 - 取决于库开发人员的技能。但是,在实践中,通过各种措施,标准 C++ 流的实现比 C I/O 函数更模块化,因此更易于维护,这是一个公平的赌注。

    另外,虽然你没有问,构造 unsigned long long int arr[n] 其中n 是一个变量是无效的 C++。你最好使用标准容器,比如std::vector

    【讨论】:

      【解决方案3】:

      可能发生的情况是 %llu 对于您的编译器来说是错误的。
      例如,如果您使用 -Wall 标志在 MinGW 中使用 g++ 编译程序以获取所有警告,您会得到:

      a.cpp: In function 'int main()':
      a.cpp:16:20: warning: unknown conversion type character 'l' in format [-Wformat=]
           scanf("%llu",&n);
      

      因此编译器将忽略额外的l 并将输入扫描为%lu。 如果您在 32 位系统上编译,长整数很可能是 32 位长,即 4 个字节。
      因此扫描的数字将在您的内存中占用 4 个字节,并且由于 arr[n] 数组是一个 long long 数组,即每个元素是 64 位 - 8 个字节,scanf 只会写入每个元素的前 4 个字节。
      假设您使用的是 little endian 系统,这 4 个字节将是 long long 元素中最不重要的部分。最重要的部分不会被写入,并且可能包含垃圾。 不过,排序算法将使用每个元素的完整 8 个字节进行排序,因此将使用每个元素最重要部分的垃圾对数组进行排序。

      由于您在 Windows 32 位系统上使用代码块,请尝试将所有出现的 "%llu" 替换为 "%I64u"

      【讨论】:

        猜你喜欢
        • 2011-09-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-29
        • 2013-10-04
        • 1970-01-01
        • 2014-06-15
        • 1970-01-01
        • 2021-03-08
        相关资源
        最近更新 更多