每次在 c++ 中输出不同(意外行为)

Different output every time in c++(unexpected behavior)

本文关键字:意外 c++ 输出      更新时间:2023-10-16

这是合并排序的代码,有时它会给出正确的输出,但有时它会给出一个值更改的输出。

#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]超出范围。这意味着未定义的行为。

与其尝试在一个循环中完成所有操作,我会尝试编写干净的代码而不是短代码并使用另一个循环。这个循环将清空你剩下的ab中的任何一个,在你清空另一个循环(或者我写它的方式,它将是两个循环,只有一个会运行(。

这看起来像:

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],有时不。

当然,作为变体。让我们在使用前检查数组大小。