for (i = 0; i < t; i++)
{
values.clear();
scanf("%d %d %d", &values[0], &values[1], &values[2]);
printf("%d %d %d\n", values[0], values[1], values[2]);
sort(values.begin(), values.end());
printf("%d %d %d\n", values[0], values[1], values[2]);
printf("Case %d: %d\n", i + 1, values[1]);
}
我有那个小片段。我输入“1200 1500 1800”它应该给我中间值 - 1500.但是,它输出1200,最小值。
我做的是使用STL的sort()对矢量进行排序,然后打印值[1],这是中间值。
但是,sort()似乎根本不起作用,之前和之后的打印矢量是一样的。
我用以下内容声明我的向量:
vector<int> values (3);
我尝试用vector<int> values;
然后push_back(0)
三次声明它。
我想知道为什么它不能以第一种方式工作。
答案 0 :(得分:6)
您的程序有未定义的行为。
要修复它,只需删除此行:
values.clear();
上述行的作用实际上是擦除矢量中的所有元素。然后,这一行:
scanf("%d %d %d", &values[0], &values[1], &values[2]);
^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^
将尝试访问不存在的元素。与关联容器的operator []
不同,向量的operator []
不会创建任何新元素。因此,表达式values[0]
,values[1]
和values[2]
都是尝试访问不存在的元素。
根据C ++ 11标准的表101:
表达式:
a[n]
返回类型:引用;常量
const_reference
a
操作语义:
*(a.begin() + n)
这意味着通过这样做:
values[0]
你实际上是这样做的:
*(values.begin() + 0)
此处对values.begin()
的调用会返回数组中第一个元素的迭代器。由于向量中没有元素(第23.2.1 / 6节),对values.begin()
的调用等同于对values.end()
的调用:
begin()
返回一个迭代器,引用容器中的第一个元素。end()
返回一个迭代器 是容器的过去值。如果容器为空,则为begin() == end()
;
因此,您案例中的values[0]
实际上与此相同:
*(values.end() + 0)
这又相当于:
*(values.end())
换句话说,您正在取消引用指向容器中最后一个元素之外的位置的迭代器。这是未定义的行为,当然同样适用于values[1]
和values[2]
。
答案 1 :(得分:5)
values.clear();
这会清除values
,使其不再包含任何元素。试图访问任何元素将导致未定义的行为,std::sort
将简单地对空数字序列进行排序。
其中a.clear()
是序列容器的a
的定义是:
销毁
a
中的所有元素。使所有引用,指针和迭代器无效,引用a
的元素,并可能使过去的迭代器无效。
帖子:a.empty()
返回true
答案 2 :(得分:1)
我认为&lt; __中位数算法&gt; 标题更容易。
med = __median(a, b, c);
答案 3 :(得分:0)
当您清除vector
时,您将大小设置为0. scanf
行通常不会崩溃,因为vector
通常会预先分配一些存储读取值的存储空间。结果是,当您致电sort
时,begin()
和end()
将是平等的。
您可以尝试将值读入临时值,或在阅读vaules之前调用resize(3)
。
答案 4 :(得分:0)
您尝试使用values.clear();
清除实际现有元素实际上是将它们完全从向量中移除。这会使begin()
和end()
相等,导致排序无效(以及您将各种元素的地址设置为具有未定义行为的输入)。
我认为你真正想要做的是确保向量中没有太多元素,所以不要clear
使用resize
:values.resize(3)
如果它当前较小,则具有去除多余元素或将向量的大小增加到3的效果。