每次在 c++ 中输出不同(意外行为)
Different output every time in c++(unexpected behavior)
这是合并排序的代码,有时它会给出正确的输出,但有时它会给出一个值更改的输出。
#include "bits/stdc++.h"
using namespace std;
//function to merge two array
vector<int> merging(vector<int> a,vector<int> b){
int x = (int)a.size() + (int)b.size();
vector<int> v(x);
int p = 0;
int q = 0;
for(int i=0;i<x;++i){
if((q<(int)b.size())?a[p]<b[q]:true && p<(int)a.size()){
v[i] = a[p];
p++;
}else{
v[i] = b[q];
q++;
}
}
return v;
}
//splitting the array and then merging the array
vector<int> mergeSort(vector<int> k){
int x = (int)k.size();
if(x<2){
return k;
}
vector<int> a(k.begin(),k.begin()+(x/2));
vector<int> b(k.begin()+(x/2),k.end());
return merging(mergeSort(a),mergeSort(b));
}
int main(){
vector<int> v = {3,5,34,11,32,7,35,54,67,89,23,4,3};
//calling the merge function
vector<int> b = mergeSort(v);
for(int i=0;i<(int)b.size();++i){
cout << b[i] << "n";
}
return 0;
}
有时预期输出3 3 4 5 7 11 23 32 34 35 54 67 89
有时输出为3 3 4 5 7 11 23 32 34 -423887504 35 54 67
好的,首先关闭
if((q<(int)b.size())?a[p]<b[q]:true && p<(int)a.size()){
伊克斯。
这是一些真正令人费解的逻辑。你在 if 中有一个三元,你有true && ...
(这与那里的...
相同(,而且任何地方绝对没有间距,使整个事情更加不可读。这不会通过发生在我 100 英尺范围内的任何代码审查。甚至在我深入研究您的代码之前,我就猜这就是问题所在。
因此,在您的示例中,当您尝试最后一次合并时,您将具有以下值:
a = {35, 54, 67}
b = {3, 4, 23, 89}
让我们通过您的合并来演练它...前几个循环一切正常,直到您有:
p = 3
q = 3
x = 7
i = 6
v = {3, 4, 23, 35, 54, 67, 0}
现在,我们正在进入循环,i < x
是真的,所以我们仍然在继续。我们得到你有趣的如果。
q < b.size()
是真的,3 < 4
.所以我们看看a[p] < b[q]
或a[3] < b[3]
.呃哦!你看到问题了吗?a[3]
超出范围。这意味着未定义的行为。
与其尝试在一个循环中完成所有操作,我会尝试编写干净的代码而不是短代码并使用另一个循环。这个循环将清空你剩下的a
或b
中的任何一个,在你清空另一个循环(或者我写它的方式,它将是两个循环,只有一个会运行(。
这看起来像:
size_t p = 0, q = 0, i = 0;
while(p < a.size() && q < b.size()) {
if(a[p] < b[q]) {
v[i++] = a[p++];
} else {
v[i++] = b[q++];
}
}
while(p < a.size()) {
v[i++] = a[p++];
}
while(q < b.size()) {
v[i++] = b[q++];
}
你会注意到我在这里更改的几件事:
- 我已经从
int
移动到size_t
,所以你可以避免所有这些丑陋的强制转换,因为你的变量已经与向量大小的类型相匹配。 - 我已经拆分了两个循环来清空两个向量中的任何一个仍然有值。
- 我已经搬到了
while
,因为我认为它们在这里看起来更好。
需要注意的几点:
操作员感知 -((q < b.size()) ? a[p] < b[q] : true && p < a.size())
相当于:(q < b.size() ? a[p] < b[q] : p < a.size())
。 请注意,您不考虑 p,不幸的是,它可能已经结束(未定义的行为( - 请注意,这是您的错误。 修复相当简单 -
(q < b.size() && p < a.size() ? a[p] < b[q] : p < a.size())
仅当两个数组上都剩下任何元素时,才应用比较。
此外,您的代码中有许多不良模式:
首先,你有很多多余的C风格演员表。这很糟糕,原因有两个: 1.你写C++,使用C++演员表!(static_cast在您的情况下( 2.你无缘无故地选角。向量(通常在C++中(的大小类型是std::size_t
的,这是有充分理由的。用它!
代码中的另一件事是将参数作为值而不是 const-ref 传递,这是一种非常糟糕的做法,会导致到处发生不必要的复制。
第三,你的变量名毫无意义。
第四,你使用命名空间std,这是强烈建议的。
可能是这一行的麻烦:
if((q<(int)b.size())?a[p]<b[q]:true && p<(int)a.size()){
在使用 A[P] 之前,您不会检查数组 'A' 的大小。因此,有时(由于内存浪费(,a[p]可以小于b[q],有时不。
当然,作为变体。让我们在使用前检查数组大小。
- 在C++中对T*类型执行std::move的意外行为
- 使用取消引用的指针的多态性会产生意外的结果.为什么?
- 处理除以零会导致<csignal>意外行为
- vscode下的Arduino代码出现意外编译错误
- 使用++运算符会导致意外的结果
- 套接字读取后,我在缓冲区中看到意外输入
- 更改.cpp程序的输入文件中数据的位置会意外更改输出
- 使用vscode调试时,GDB意外退出
- 此测试()中发生了什么意外过程?为什么总是覆盖 ch[0 1 2..]?
- 尝试将字符串/字符转换为整数会产生意外结果
- 错误 C2760:语法错误:映射迭代器上意外的标记"标识符",预期的";"
- C++标头错误 C2238 意外标记";"
- C++中意外的多头值
- vector.size() 在比较中意外工作
- 使用 malloc() 时出现意外大小
- 多线程程序中出现意外的内存泄漏
- 为什么static_cast基础类型的枚举类int8_t获得意外值?
- 字符串比较中的意外输出
- 我的代码中的意外价值以及我如何修复它
- C++ 编译错误:意外的类型名称"字符串":预期的表达式