【问题标题】:Bubble Sort not Sorting and extra elements冒泡排序未排序和额外元素
【发布时间】:2018-02-25 03:14:03
【问题描述】:

我正在尝试按降序进行冒泡排序,但我不断得到奇怪的输出。当我在数组中输入元素时,对于元素 1,它不止一次向我询问元素 1,它会导致一个额外的元素被引入,另一件事是最终元素根本不包含在数组中,我不明白。这是我完整程序的输出,我的代码在它下面:

输入:

How many elements in your array?: 4
Enter elements in your array: 
Element 0: 
97
32
Element 1: 
13
Element 2: 
22
Element 3: 
244
Element 0: 32
Element 1: 13
Element 2: 22
Element 3: 0

我的代码:

#include <stdio.h>

void sort(int array[], int n);

int main() {

    int num = 0;
    printf("How many elements in your array?: ");
    scanf("%d",&num);
    while(num > 9)
        {
        printf("Only enter an array that is size 9 or less.\n");
        printf("Enter a new number: ");
        scanf("%d", &num);
        }
    int array[num];
    printf("Enter elements in your array: \n");
    for(int i = 0; i < num; i++)
    {   
        printf("Element %d: \n",i);
        scanf("%d ",&array[i]);
    }
    sort(array, num);
    for(int j = 0; j < num; j++)
    {
        printf("Element %d: %d\n", j, array[j] );

    }
    return 0;
}

void sort(int array[], int size)
{
    int temp;
    for(int i = 0; i < size; i++)
    {
        /*if(array[i] > array[i+1]) // smallest to biggest
        {
            *temp = array[i];
            array[i] = array[i+1];
            array[i+1] = temp;

        }*/
        if(array[i] > array[i+1]) // 1 2
        {
            temp = array[i];
            array[i] = array[i+1];
            array[i+1] = temp;
        }
    }
}

【问题讨论】:

  • 不要使用scanf 进行用户输入。这是你问题的一半。
  • 如果输入-1会发生什么?
  • 您的sort 溢出缓冲区,因为当isize -1 时,array[i+1] 超出了限制。因此,您正在与一个会影响排序的未定义值进行比较。这也不是冒泡排序,您只是对相邻条目进行排序,而不是全部排序。
  • scanf("%d ",&amp;array[i]); 去掉%d后面的空格。然后注释掉对sort 的调用,并确保您至少从一个好的数组开始。

标签: c arrays sorting scanf


【解决方案1】:

除了 cmets,您的“冒泡排序”永远不会排序,因为它不是冒泡排序。变量的冒泡排序实现类似于:

int i, j, swap;

for (i = 0; i < size - 1; i++) {
    for (j = 0; j < size - i - 1; j++) {
        if (array[j] > array[j + 1]) {  /* For decreasing order use < */
            swap = array[j];
            array[j] = array[j + 1];
            array[j + 1] = swap;
        }
    }
}

话虽如此,您对scanf 的使用充满了陷阱。您必须验证 scanf 的返回以确定 (1) 用户是否通过使用 Ctrl+d(或 Ctrl +z onwindoze)?; (2) 是否有输入匹配失败导致没有发生转换? (3) 如果转换成功,该值是否在可接受的范围内?在你的情况下,这将采取以下形式:

    int num = 0,
        rtn;
    for (;;) {  /* loop continually until valid input received */
        printf ("\nHow many elements in your array?: ");
        rtn = scanf ("%d", &num);
        if (rtn == EOF) {
            fprintf (stderr, "user canceled input.\n");
            return 1;
        }
        else if (rtn == 0) {
            int c;
            fprintf (stderr, "error: invalid input.\n");
            /* discard any characters that remain after input failure */
            for (c = getchar(); c != '\n' && c != EOF; c = getchar()) {}
        }
        else if (num > 9) {
            fprintf (stderr, "error: elements must be 9 or less.\n");
        }
        else
            break;
    }

(注意: 输入失败后,您必须丢弃 stdin 中剩余的所有字符,否则,在下一次迭代中,您的转换将再次失败,导致无限循环——一次使用scanf 进行用户输入的主要缺陷)

您可以对数组值使用缩写检查(而不是循环直到您获得正确的输入,您只是保释,这消除了丢弃字符等)。但是,您没有理由不能在该循环中实现完全稳健的解决方案(实现完整的检查和循环,直到所有数组元素都被填充或用户取消输入)。

    printf("\nEnter elements in your array: \n");
    for (int i = 0; i < num; i++) {   
        printf("Element[%2d]: ", i);
        if (scanf("%d",&array[i]) != 1) {
            fprintf (stderr, "error: invalid input.\n");
            return 1;
        }
    }

将所有部分放在一起,您可以执行类似以下的操作:

#include <stdio.h>

void sort(int *array, int size);

int main (void) {

    int num = 0,
        rtn;
    for (;;) {  /* loop continually until valid input received */
        printf ("\nHow many elements in your array?: ");
        rtn = scanf ("%d", &num);
        if (rtn == EOF) {
            fprintf (stderr, "user canceled input.\n");
            return 1;
        }
        else if (rtn == 0) {
            int c;
            fprintf (stderr, "error: invalid input.\n");
            for (c = getchar(); c != '\n' && c != EOF; c = getchar()) {}
        }
        else if (num > 9) {
            fprintf (stderr, "error: elements must be 9 or less.\n");
        }
        else
            break;
    }

    int array[num];     /* VLA for array */

    printf("\nEnter elements in your array: \n");
    for (int i = 0; i < num; i++) {   
        printf("Element[%2d]: ", i);
        if (scanf("%d",&array[i]) != 1) {
            fprintf (stderr, "error: invalid input.\n");
            return 1;
        }
    }

    sort (array, num);

    putchar ('\n');
    for(int j = 0; j < num; j++)
        printf("Element %d: %d\n", j, array[j]);

    return 0;
}

void sort(int *array, int size)
{
    for (int i = 0; i < size - 1; i++) {
        for (int j = 0; j < size - i - 1; j++) {
            if (array[j] > array[j + 1]) {  /* For decreasing order use < */
                int swap = array[j];
                array[j] = array[j + 1];
                array[j + 1] = swap;
            }
        }
    }
}

使用/输出示例

$ ./bin/bubblesort_input

How many elements in your array?: twenty
error: invalid input.

How many elements in your array?: 12
error: elements must be 9 or less.

How many elements in your array?: 6

Enter elements in your array:
Element[ 0]: 12
Element[ 1]: 2
Element[ 2]: -12
Element[ 3]: -4
Element[ 4]: 5
Element[ 5]: 1

Element 0: -12
Element 1: -4
Element 2: 1
Element 3: 2
Element 4: 5
Element 5: 12

查看一下,如果您有任何其他问题,请告诉我。

【讨论】:

  • 您认为还提及其他问题会更好吗?但是是的......正确的实施。
  • 谢谢你,这个帮助非常大!它消除了我的很多误解。
  • 很高兴它有帮助。学习正确使用scanf 在很大程度上是一个字符统计问题,并且知道哪些转换(数字转换)会消耗前导空格,哪些不会,所以你知道stdin 完成后剩余的内容成功(以及失败后)。这就是为什么fgets(或POSIX getline)——面向行的输入函数是接受用户输入的首选方式——但scanf确实有其有效用途的重要部分对于格式化输入,就像getchar对于面向字符的输入一样。
猜你喜欢
  • 1970-01-01
  • 2016-12-18
  • 2020-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-13
  • 2018-08-19
相关资源
最近更新 更多