使用printf时,Mergesort输出会发生变化

时间:2014-03-03 01:05:32

标签: c debugging printf output mergesort

在尝试用C语言编写一个mergesort作为练习时,我遇到了一个奇怪的问题,即算法的输出随着printf的存在而改变。让我进一步阐述。我有一个“MergeSort.h”文件,其中我的mergesort算法如下:

#ifndef _MSORT_H_
#define _MSORT_H_

void merge(int a[],int lo,int mi,int hi){
    int n1 = (mi - lo) +1;
    int n2 = hi - mi;
    int left[n1];
    int right[n2];
    int i;
    int j;
    int k;
    for(i = 0;i < n1;i++){
        left[i] = a[lo+i];
    }
    for(j = 0;j < n2;j++){
        right[j] = a[mi+j+1];
    }
    i = 0;
    j = 0;
    for(k = lo;k <= hi;k++){
        if(left[i] < right[j]){
            a[k] = left[i];
            i = i + 1;
        }else{
            a[k] = right[j];
            j = j+1;
        }
    }

}

void msorthelper(int a[],int p,int r){
    if(p < r){
        int mid = (p + r)/2;
        msorthelper(a,0,mid);
        msorthelper(a,mid+1,r);
        merge(a,p,mid,r);
    }
}

void msortex(int a[],int size){
    msorthelper(a,0,size-1);
    int counter;
    for(counter = 0;counter < size;counter++){
        printf(" %d ",a[counter]);
    }
}
#endif

我在sorttester.c中有相应的排序测试器:

#include <stdio.h>
#include "mergesort.h"

int main(){

    int out[] = {8,1,6};
    msortex(out,3);

}

运行sorttester的输出如下:

  

1 0 0

现在这是有趣的部分,当我将任何printf语句放到合并的开头时,会生成正确的输出。这是一个例子:

    #ifndef _MSORT_H_
    #define _MSORT_H_

    void merge(int a[],int lo,int mi,int hi){
        printf("Hello\n"); 
        int n1 = (mi - lo) +1;
        int n2 = hi - mi;
        int left[n1];
        int right[n2];
        .................Rest of the code.....

现在的输出是:

  

HelloHello 1 6 8

这是数组8 6 1的正确排序顺序。

有人可以告诉我这里我可能做错了什么导致输出因printf的存在而大幅增加?

由于

1 个答案:

答案 0 :(得分:2)

查看代码的合并部分:

for(k = lo;k <= hi;k++){
    if(left[i] < right[j]){
        a[k] = left[i];
        i = i + 1;
    }else{
        a[k] = right[j];
        j = j+1;
    }
}

让我们假设

left[] = {1, 2}
right[] = {3, 4, 5}

在合并循环(k)的2次迭代之后,“i”的值将为2.从现在开始,您将尝试比较

left[2] < right[j]

哪个是无效的,因为左[2]会引用一些随机存储器(左数组大小只有2,因此索引2的元素不存在,只有0和1)

因此,如果您为i和j值添加保护,例如首先将条件更改为:

if(i != n1 && (j == n2 || left[i] < right[j])){

你应该没事。

无论如何,我还应该告诉你,你不应该用不是const的值来声明数组大小,例如:

int left[n1];
int right[n2];

它实际上是被标准禁止的。您应该动态分配它,使用向量(如果是c ++)或jus声明它们是全局的,具有足够大的大小(最大n值)