qsort 函数的使用——对普通数组、指针数组、二维数组中的元素进行排序

在ANSI C中,qsort函数的原型是

#include <stdlib.h>

void qsort(void *base, size_t nmemb, size_t size, int (*compar) (const void *, const void *));

解释:qsort函数对含有nmemb个元素的数组进行排序,而base指针指向数组的第一个元素。这个数组的元素个数由size指定。

compar函数对qsort的比较操作进行定义,所以可以定制数字的比较,字符串的比较,甚至结构体的比较,等等。compar的写法见下面几个例子。

一、使用qsort函数对普通数组进行排序。

代码如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3
 4 int compare(const void *arg1, const void *arg2);
 5
 6 int
 7 main(int argc, char** argv)
 8 {
 9     int i;
10
11     int arr[5] = { 13, 17, 2, 7, 71 };
12
13     qsort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(int), compare);
14
15     for (i = 0; i < 5; i++) {
16         printf("%d ", arr[i]);
17     }
18     printf("\n");
19 }
20
21
22 int compare(const void *arg1, const void *arg2) {
23     int a = *(int*)arg1;
24     int b = *(int*)arg2;
25     if (a > b) {
26         return 1;
27     }
28     else if (a < b) {
29         return -1;
30     }
31     else {
32         return 0;
33     }
34 }

讲一下参数compar的定义,由于qsort要求传入一个函数指针,所以这个函数的名字我们可以自己设置,就跟其他形参的名字一样,一般用cmp或者compare。

qsort函数把我们传入的arr当做指向数组第一个元素的指针,所以相应地,在代码第22行,形参表中的arg1和arg2,就是指向数组某个元素的指针

在第23行和第24行,我们将void*转换为int*,并且将指针解引用之后的值赋予a和b,进行比较。

如果a>b返回1,a<b返回-1,就意味着我们进行元素的升序排序,将元素从小到大进行排序。

二、使用qsort函数对指针数组进行排序。

代码如下:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4
 5 int compare(const void *arg1, const void *arg2);
 6
 7 int
 8 main(int argc, char** argv)
 9 {
10     int i;
11
12     char *arr[5] = { "i", "love", "c", "programming", "language" };
13
14     qsort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(char *), compare);
15
16     for (i = 0; i < 5; i++) {
17         printf("%s ", arr[i]);
18     }
19     printf("\n");
20     /* getchar(); */
21 }
22
23 int compare(const void *arg1, const void *arg2) {
24     char *a = *(char**)arg1;
25     char *b = *(char**)arg2;
26     int result = strcmp(a, b);
27     if (result > 0) {
28         return 1;
29     }
30     else if (result < 0) {
31         return -1;
32     }
33     else {
34         return 0;
35     }
36 }

与平常我们所用的数组相比,指针数组有些难理解,其实第12行的arr数组,它就是存放着5个指针,第1个元素存放指向常量字符串"i"的地址,第2个元素存放指向常量字符串"love"的地址,依此类推。

那么我们向qsort传入arr之后,qsort将arr理解为指向数组中第一个元素的指针,所以第23行形参表中,arg1和arg2其实是指向指向常量字符串的指针的指针,是char**。而我们需要传给strcmp这个字符串比较函数的,是“指向字符串的指针”,是char*,所以我们将void*转换为char**,然后解引用,得到char*,赋予a和b。接下来使用strcmp对a和b进行比较。

三、使用qsort函数对指针数组进行排序。

代码如下:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4
 5 int compare(const void *arg1, const void *arg2);
 6
 7 int
 8 main(int argc, char** argv)
 9 {
10     int i;
11
12     char arr[5][16] = { "i", "love", "c", "programming", "language" };
13
14     qsort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(arr[0]), compare);
15     printf("%s\n", arr[0]);
16     for (i = 0; i < 5; i++) {
17         printf("%s ", arr[i]);
18     }
19     printf("\n");
20     /* getchar(); */
21 }
22
23 int compare(const void *arg1, const void *arg2) {
24     char *a = (char*)arg1;
25     char *b = (char*)arg2;
26     int result = strcmp(a, b);
27     if (result > 0) {
28         return 1;
29     }
30     else if (result < 0) {
31         return -1;
32     }
33     else {
34         return 0;
35     }
36 }

二维数组比较常见,但是在qsort函数中要对这个数组中的元素进行排序,理解起来稍微有些难度。不过一步一步分析,思路也就自然了。

这里对二维数组进行排序,其实是对二维数组的第二维中存放的字符串进行排序。所以在第14行对qsort函数的调用中,第二个参数是待排元素的个数(5个),第三个参数是待排元素的大小(16)。

我们将arr传入qsort函数,qsort函数将arr理解为指向数组第一个元素的指针,arr的第一个元素是arr[0][0],所以参数arg1和arg2指的是指向"a[i][0]"的指针,我们知道,a[i][0]是字符,就是char,所以arg1和arg2指的是char *。我们将void*转换为char*,赋予a和b,调用strcmp函数对a和b进行比较。

就是这样。

时间: 2024-12-26 16:31:34

qsort 函数的使用——对普通数组、指针数组、二维数组中的元素进行排序的相关文章

数组指针与二维数组的寻址

引例:已知如下程序 1 #include <stdio.h> 2 main() 3 { 4 int x[3][4] = {1,3,5,7,9,11,2,4,6,8,10,12} ; 5 int (*p)[4] = x, k = 1, m, n = 0; 6 for(m=0; m < 2; m++) 7 n += *(*(p+m)+k); 8 printf("%d\n",n); 9 } 试写出程序的输出值.(虽然我很讨厌做这种笔头功夫的题,我也坚信编程语言是在实践中练出

指针与数组--指针与二维数组2

指向一维数组的指针   char (*p)[10] ;指向一维数组的指针类型 typedef  char(*TYPE_P2ARRAY)[10]  ;   该指针可以指向数组 ,且使用起来效果节本相同,但指针与数组并不等价.{sizeof结果不同  , 且该指针还可以指向除此之外其他类型的数据. } #include <stdio.h> typedef int (*TP_PARRY1)[3] ; #define Uart_Printf printf void f1(void) { int a[2

数组指针(二维数组的指针)

1 #include <iostream> 2 3 using namespace std; 4 5 6 int main() 7 { 8 int v[2][2]={{1,2},{3,4}}; 9 cout<<"v = "<<v<<endl; 10 cout<<"*v = "<<*v<<" &v = "<<&v<<endl;

例看二维数组,指针,二维数组指针

例程: /****************************************************** * * 文件名:例程 * * 文件描述:例看二维数组,指针,二维数组指针 * * 创建人:Jesse * * 版本号: * * 修改记录: * ******************************************************/ #include <stdio.h> #define ROW 3 #define LINE 3 void main(voi

二级指针与二维数组

最近看<Linux C程序设计大全>这本书,虽然书中有一些错误,但整体来说,书写得还算可以. 当看到网络编程[第23.2.4小节 获得主机信息]时,遇到了一段代码,原文如下: “一台主机有许多和网络相关的信息,例如,主机名称.IP地址.主机提供的服务等.这些信息一般都保存在系统中的某个文件里(例如/etc/hosts等),用户程序可以通过系统提供的函数读取这些文件上的内容.Linux环境下使用gethostent函数读取和主机有关的信息,该函数的原型如下: 1 #include <net

指针和二维数组

指针和二维数组 首先定义一个数组: 1 int a[5][3] = { {1,6,11}, 2 {2,7,12}, 3 { 3,8,13 }, 4 { 4,9,14 }, 5 { 5,10,15 } 6 }; 随便定义的一个二维数组i = 5, j = 3 然后看下面3种方式: 1 int *b = a[0]; 2 int *c = *a; 3 int &d = **a; 其实上面的三种方式的效果是一样的,大牛一看就知道,这不是废话么.我们还是输出下 1 //value 2 std::cout

指针与二维数组间的关系

1.四种表示a[i][j]的形式是等价的: a[i][j]==*(a[i]+j)==*(*(a+i)+j)==(*(a+i))[j] 2.通过行指针p引用二维数组a的元素a[i][j]的方法可用以下4种等价形式: p[i][j]==*(p[i]+j)==*(*(p+i)+j)==(*(p+i))[j] 3.对指向二维数组的行指针p进行初始化的方法: p=a 或p=&a[0] 4.对指向二维数组的列指针进行初始化的方法(以下三种方法等价): p=a[0] 或 p=*a 或 p=&a[0][0

二维数组指针及二维动态数组的分配问题

在我以前的文章中都有讲过关于数组指针及指针数组的相关问题,但是讲得不够深入,我后来后了别人写的博客后觉得人家的确实写得好, 也学到了不少东西,对以前的问题有深的领悟了,于是准备结合这些博客和文章再稍微深入一点讲讲这些问题.这些指针的问题是C语言中的基础与关键 而且一旦出现这些问题,不太好找bug的来源,有时候不得不借助反汇编. 参考文章: http://c.biancheng.net/cpp/html/476.html       C语言指针数组和数组指针 http://blog.csdn.ne

关于理解指针数组,数组指针,数组名,二维数组的一些技巧。

/*************关于数组名***************/ int a[3] = {1, 2, 3} 1.数组名代表数组第一个元素的地址,注意,不是数组地址(虽然值相等),是数组第一个元素地址,a 等同于 &a[0]; a+1是第二个元素的地址.比第一个元素地址a(或者&a[0])超出了一个整型指针的大小,在这里是4个字节(byte) cout << a << endl;会输出数组第一个元素地址. 2.取址符号&. &a是数组的地址,注意

PHP如何判断一个数组是一维数组或者是二维数组?用什么函数?

如题:如何判断一个数组是一维数组或者是二维数组?用什么函数? 判断数量即可 <?php if (count($array) == count($array, 1)) { echo '是一维数组'; } else { echo '不是一维数组'; } PHP手册: int count ( mixed $var [, int $mode ] )  --  计算数组中的单元数目或对象中的属性个数  如果可选的 mode 参数设为 COUNT_RECURSIVE(或 1),count() 将递归地对数组