Сортировка работает в main (), но не в отдельной функции - PullRequest
0 голосов
/ 09 апреля 2019

Я работаю над проблемой домашней работы для программирования на C и Unix, и учитель сказал нам написать функцию сортировки для массива на C.

У меня работает сортировка из некоторых циклов for в main, но необходимая нам отдельная функция сортировки не работает.

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

int Sort(int arr[], int size){

    int i,j,a;
    for(i = 0; i < size; i++){
        for(j = i+1; j < size; j++){
            if(arr[i] > arr[j]){
                a = arr[i];
                arr[i] = arr[j];
                arr[j] = a;
            }
        }
    return arr;
    }
}

int main(){
    int a;
    int BAT[40];
    for(int i=0; i < 40; i++){
       BAT[i] = (float)(599)* ( (float)rand() / (float)RAND_MAX );
       printf("%d \n", BAT[i]);
    }
    printf(" the array should now be sorted \n"); 
    //Sort(BAT, 40); THIS IS THE FUNCTION CALL THAT DIDNT SEEM TO WORK SO I COPIED THE SORT OUT OF THE SORT FUNCTION TO TEST

    //THIS IS THE SORT CODE AND WHILE IT IS IN THE MAIN IT WORKS
    for(int i = 0; i < 40; i++){
        for(int j = i+1; j < 40; j++){
            if(BAT[i] > BAT[j]){
                a = BAT[i];
                BAT[i] = BAT[j];
                BAT[j] = a;
            }
        }
    }
    //END OF SORTING TEST
        for(int j=0; j < 40; j++){
            printf("%d \n", BAT[j]);
        }

Я ожидаю, что сортировка (BAT, 40) отсортирует массив, который я затем пытаюсь распечатать, но вместо этого, похоже, ничего не происходит.

1 Ответ

2 голосов
/ 09 апреля 2019

Ваша процедура сортировки должна работать так, как написано, но вы не можете включить предупреждения в своем коде, и поэтому вы не позволяете компилятору помочь вам исправить предупреждения и ошибки в вашем коде - это само по себе позволило бы вашему коду бежать просто отлично.

Например, ваш компилятор сообщит вам точный номер строки и много раз точный символ в той строке, где была обнаружена ошибка или предупреждение, например,

bubblesortfn.c: In function ‘Sort’:
bubblesortfn.c:21:5: warning: return makes integer from pointer without a cast 
[enabled by default]
     return arr;
     ^

Как возврат может сделать целое число из указателя ?? Проще говоря, ваша функция пытается вернуть массив целых чисел (int *), и ваша функция объявлена ​​int Sort. (вам не нужно ничего возвращать, но вы можете просто исправить это, изменив декларацию на int *Sort (....)).

Остальные проблемы - это простые синтаксические проблемы и неиспользуемые переменные (например, a в main()), которые будут немедленно помечены вашим компилятором - послушайте его. Пусть это поможет вам написать лучший код.

Всегда компилировать с включенными предупреждениями , а не принимать код, пока он не скомпилируется без предупреждения . Чтобы включить предупреждения, добавьте -Wall -Wextra -pedantic в строку компиляции gcc/clang. Для clang вместо этого вы можете использовать -Weverything. Для VS (cl.exe в Windows) используйте /W3 (или /Wall, но вы получите довольно много посторонних предупреждений, не связанных с кодом). Прочитайте и поймите каждое предупреждение, а затем исправьте его.

Как уже упоминалось в моем комментарии, не используйте магические числа в своем коде (кроме случаев, когда это абсолютно необходимо, например, с модификатором fscanf field-width ). Вместо этого, если вам нужна константа, #define один (или больше) или используйте глобальный enum, чтобы сделать то же самое. Таким образом, у вас есть единственное место в верхней части вашего кода, чтобы изменить вещи, если это необходимо, и вам не нужно переходить к декларациям или ограничениям цикла, чтобы что-то изменить.

Буквально, исправление выявленных предупреждений и приведение в порядок вещей - это все, что нужно для работы вашего кода, и правильная сортировка массива в вашей функции Sort (я также добавил функцию prnintarray() для печати вашего массива в во избежание повторяющихся циклов в main(). Если положить его целиком и заполнить генератор случайных чисел, вызвав srand() перед использованием rand(), вы можете сделать:

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

/* if you need a constant, define one (or more) - avoid magic numbers */
#define ROWSZ   10      /* max integers to print per-row */
#define MAXB    40      /* max integers in BAT */
#define MULTP  599      /* multiplier constant */

int *Sort (int arr[], int size)
{
    int i, j, a;
    for (i = 0; i < size; i++) {
        for (j = i + 1; j < size; j++) {
            if (arr[i] > arr[j]){
                a = arr[i];
                arr[i] = arr[j];
                arr[j] = a;
            }
        }
    }
    return arr;
}

/* simple print function to output arr of sz with rowsz int per-row */
void prnintarray (int *arr, size_t sz, size_t rowsz)
{
    for (size_t i = 0; i < sz; i++) {
        if (i && i % rowsz == 0)
            putchar ('\n');
        printf (" %4d", arr[i]);
    }
    putchar ('\n');
}

int main (void) {

    int BAT[MAXB] = {0};    /* initialize all arrays - good practice */

    srand (time(NULL));     /* seed the random number generator */

    for (int i = 0; i < MAXB; i++)      /* fill array */
        BAT[i] = MULTP * ( (float)rand() / (float)RAND_MAX );

    puts ("\nunsorted array:\n");
    prnintarray (BAT, MAXB, ROWSZ); 

    Sort (BAT, MAXB);

    puts ("\nsorted array:\n");
    prnintarray (BAT, MAXB, ROWSZ); 
}

Пример использования / OUtput

$ ./bin/bubblesortfn

unsorted array:

  461  519  346  508  265   93  358  407  278  151
  465  531  430  148  181  227  452  206  401  202
  103  518  259  267  342  495  570  431  477  455
  164  339  375  511  248   42    6    8  450  284

sorted array:

    6    8   42   93  103  148  151  164  181  202
  206  227  248  259  265  267  278  284  339  342
  346  358  375  401  407  430  431  450  452  455
  461  465  477  495  508  511  518  519  531  570

Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.

Использование qsort Для сортировки в реальном мире

Хотя в написании функции пузырьковой сортировки для ее аспекта обучения нет ничего плохого, библиотека C предоставляет qsort, которая может и должна покрывать большинство ваших потребностей в сортировке. Ваша единственная задача при использовании qsort - написать простую функцию compare(), которая скажет qsort, как сортировать соседние элементы массива. Прототип функции compare() обычно отправляет новых программистов на C в состояние паники. Прототип:

int compare (const void *a, const void *b)

Не позволяйте этому беспокоить вас. a и b - это просто указатели на два члена вашего массива, которые в настоящее время сравниваются Ваша задача - написать оставшуюся часть функции, чтобы, если значение указывало на a:

  • сортирует перед значением, на которое указывает b, возвращается отрицательное число;
  • равно значению, указанному b, возвращается ноль и, наконец,
  • сортирует после b возвращается положительное значение. (все как у strcmp).

Чтобы справиться с тем фактом, что a и b являются указателями void, вы просто приводите их к int указателям перед разыменованием, чтобы использовать их значения, например,

int compare (const void *a, const void *b)
{
    const int *pa = a,    /* a and b are pointers to elements being compared*/
              *pb = b;    /* in array, cast as required to proper type */

Поскольку ваш массив int, a и b будут указателями на int, вы просто приводите их к int *. Теперь вы можете получить доступ к значениям через указатели (например, разыменование *pa, чтобы получить значение по адресу, который хранится в pa).

Теперь, чтобы удовлетворить требования возврата, тривиальное решение будет:

     return *pa - *pb;

Однако, если *pa - большое отрицательное значение, а *pb - большое положительное значение, вычитание *pa - *pb может легко привести к целочисленному переполнению и неопределенному поведению ,Вместо прямого вычитания, используя два неравенства, можно исключить вероятность переполнения, обеспечивая при этом необходимый возврат.Продумайте:

    return (*pa > *pb) - (*pa < *pb);

Поэтому, сложив вместе функцию qsort и заменив свой вызов на Sort на вызов qsort, вы переписали бы свой код как:

int compare (const void *a, const void *b)
{
    const int *pa = a,    /* a and b are pointers to elements being compared */
              *pb = b;    /* in array, cast as required to proper type */

    /*  inequality avoids overflow from subtracting 2 large values
     *  (x > y) - (x < y) , returns -1, 0, 1 (like strcmp) for 
     *  -1 -> x sorts before y,  0 -> x equals y,  1 -> x sorts after y
     */
    return (*pa > *pb) - (*pa < *pb);
}

Тогда

    qsort (BAT, MAXB, sizeof *BAT, compare);

Попробуйте.В качестве бонуса для больших массивов qsort будет порядков величины быстрее, чем сортировка пузырьков (один из самых медленных видов для больших массивов)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...