Ваша процедура сортировки должна работать так, как написано, но вы не можете включить предупреждения в своем коде, и поэтому вы не позволяете компилятору помочь вам исправить предупреждения и ошибки в вашем коде - это само по себе позволило бы вашему коду бежать просто отлично.
Например, ваш компилятор сообщит вам точный номер строки и много раз точный символ в той строке, где была обнаружена ошибка или предупреждение, например,
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
будет порядков величины быстрее, чем сортировка пузырьков (один из самых медленных видов для больших массивов)