【问题标题】:Array stores same number form a list of numbers twice数组从数字列表中存储相同的数字两次
【发布时间】:2017-09-11 23:31:53
【问题描述】:

我的程序所做的是,它采用从文件中读取的数字数组,并使用选择排序和冒泡排序方法对它们进行排序。当它通过冒泡排序方法排序时,该数组连续两次列出一个数字。它也总是被复制的第二个数字。我检查了是否由于某种原因该数字实际上被传递给新数组两次,但事实并非如此。我也尝试了不同的输入文件,同样的事情发生在同一个地方。这也切断了列表中的最后一个数字。我在我的代码中没有看到任何明显的原因导致这种情况发生。

程序调用的列表如下:

10

50

78

83

92

100

0

4

72

3

19

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int findMin(int arr[], int start, int size);
void printArr(int arr[], int size);
void selectionSort(int arr[], int size);
void bubbleSort(int arr[], int size);

int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        printf("Syntax Error: ./<exec> <infile>\n");
        exit(1);
    }

    FILE *ifp = NULL;
    ifp = fopen(argv[1], "r");

    if(ifp == NULL)
    {
        printf("Could not open %s for reading\n", argv[1]);
        exit(1);
    }

    int counter;
    int j = 0;

    fscanf(ifp, "%d", &counter);

    int array[counter];
    int arrB[counter];
    for(j = 0; j < counter; ++j)
    {
        fscanf(ifp, "%d", &array[j]);
    }

    for(j = 0; j < counter; j++)
    {
        arrB[j] = array[j];
    }
    int size = sizeof(array) / sizeof(int);

    printf("Before: ");
    printArr(array, size);

    selectionSort(array, size);
    bubbleSort(arrB, size);

    fclose(ifp);

    return 0;
}
int findMin(int arr[], int start, int size)
{
    int i = 0;
    int minLoc = start;
    int minVal = arr[minLoc];

    for ( i = start + 1; i < size; ++i)
    {
        if (arr[i] < minVal)
        {
            minVal = arr[i];
            minLoc = i;
        }
    }

    return minLoc;
}

void printArr(int arr[], int size)
{
    int i = 0;

    for(i = 0; i < size; ++i)
        printf("%3d ", arr[i]);
    printf("\n");
}
void selectionSort(int arr[], int size)
{
    int i = 0;
    int minLoc = 0;
    int tmp = 0;
    for(i = 0; i < size; ++i)
    {
        minLoc = findMin(arr, i, size);
        tmp = arr[i];
        arr[i] = arr[minLoc];
        arr[minLoc] = tmp;
    }

    printf("** Selection Sort **\n After: ");
    printArr(arr, size);

}
void bubbleSort(int arr[], int size)
{
    int i = 0;
    int j = 0;
    int tmp = 0;

    for(j = 0; j < size; j++)
    {
        for(i = 0; i < size; ++i)
        {
            if(arr[i] > arr[i+1])
            {
                tmp = arr[i];
                arr[i] = arr[i+1];
                arr[i+1] = tmp;
            }
        }
    }
    printf("** Bubble Sort **\n After: ");
    printArr(arr, size);

}

【问题讨论】:

  • for(i = 0; i &lt; size; ++i) { if(arr[i] &gt; arr[i+1]) 是可疑的,因为 arr[size] 被访问 - 传递了数组边界。建议尝试for(i = 1; i &lt; size; ++i) { if(arr[i-1] &gt; arr[i]) 并调整swap。
  • 刚刚运行了您的代码。输出似乎没问题。这就是我得到的:之前:50 78 83 92 100 0 4 72 3 19 ** 选择排序 ** 之后:0 3 4 19 50 72 78 83 92 100 ** 冒泡排序 ** 之后:0 3 4 19 50 72 78 83 92 100
  • @chux 解决了!谢谢!

标签: c arrays bubble-sort selection-sort


【解决方案1】:

bubbleSort() 访问数组边界外。因此未定义的行为 (UB)。

for(j = 0; j < size; j++) {
    for(i = 0; i < size; ++i) {
        if(arr[i] > arr[i+1]) {   // Here code access outside bounds when i = size - 1
            ... Code swaps arr[i], arr[i+1];
        }
    }
}

相反

for(j = 0; j < size; j++) {
    for(i = 1; i < size; ++i) {
        if(arr[i-1] > arr[i]) {
            ... Code swaps arr[i-1], arr[i];
        }
    }
}

【讨论】:

  • for(i = 0; i &lt; size-1; ++i) { if(arr[i] &gt; arr[i+1]) { ...
  • @AlexLop。我更喜欢if(arr[i-1] &gt; arr[i]) 来应对极端情况:当使用size_t 作为unsigned 类型进行索引/调整大小时,数组索引的最佳类型int 可能太窄,你的@当size == 0SIZE_MAX 时,987654328@ 是一个问题。当然这是极端考虑。
猜你喜欢
  • 2017-04-27
  • 1970-01-01
  • 2020-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-03
  • 2022-07-19
  • 1970-01-01
相关资源
最近更新 更多