我正在处理C和unix编程的家庭作业问题,老师告诉我们为C中的数组编写排序函数。
我已经从main的一些for循环中进行了排序,但是我们需要的单独的排序功能不起作用。
#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]);
}
我希望Sort(BAT,40)对数组进行排序,然后尝试打印该数组,但是似乎什么也没有发生。
答案 0 :(得分:2)
您的排序例程应该按照编写的方式工作,但是您无法在代码中启用警告,因此您不允许编译器帮助您修复代码中的警告和错误-仅此一项就可以允许您的代码运行得很好。
例如,您的编译器会告诉您确切的行号,并多次告诉您该行中检测到错误或警告的确切字符,例如
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 (在Windows上为cl.exe
),请使用/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);
}
使用/输出示例
$ ./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
进行实际排序
尽管为它的学习方面编写Bubblesort函数没有任何问题,但C库提供了qsort
,它可以而且应该满足您的大多数排序需求。使用qsort
的唯一工作是编写一个简单的compare()
函数来告诉qsort
如何对数组的相邻成员进行排序。 compare()
函数的原型通常会使新的C程序员陷入恐慌状态。原型是:
int compare (const void *a, const void *b)
别让它困扰您。 a
和b
只是指向当前正在比较的数组的两个成员的指针。您的工作是编写函数的其余部分,以便于a
指向的值:
b
所指向的值之前排序,返回负数; b
指向的值,返回零,最后b
之后返回strcmp
一样。)要处理a
和b
是空指针的事实,只需在取消引用以使用它们的值之前将它们强制转换为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
会很容易导致整数溢出和< em>未定义的行为。通过使用两个不等式,而不是直接相减,可以消除溢出的机会,同时提供所需的回报。想一想:
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
的速度要比气泡排序(大型数组中最慢的排序之一)快 Magnitudes