C语言中qsort函数的使用,对结构体和字符串数组进行排序

qsort 函数是C语言提供的库排序函数,除了解决传统的int数组排序以外,还可以对字符串、结构体等进行排序。这里qsort函数也体现了之前说过的回调函数的机制

在库中长这么个样子:

void qsort ( void * base, 
					 size_t num,
					 size_t size,
int ( * comparator ) ( const void *, const void * ) );

先简单了解一波qsort函数

1)qsort函数包含在 stdlib.h中。

2) 函数参数,对照上述结构来看:

void *base

表示待排序序列的地址。void * 类型的指针变量意味着可以针对 int、char、struct 等各种类型序列。

size_t num

表示待排序列中关键字的个数。常用sizeof(a)/sizeof(a[0])的形式确定。

size_t size

表示待排序列中关键字的大小,单位为字节。 常用sizeof(a[0])确定。

int ( * comparator ) ( const void *, const void * )

表示 函数指针,该函数指针指向一个返回值为int 参数为两个指针常量的的函数
而这两个指针常量就是待比较的两个关键字。

------------------------------------------分割线-------------------------------------------------------

就使用来说最关键的是要自写一个“比较函数”作为第四个参数传入qsort函数。其中函数对应上述qsort中的形参,返回值必须是int 参数必须是两个指向关键字的指针
而函数返回值需要满足以下特性:

》当前一个关键字比后一个关键字小的时候 return 值 <0;
》当前一个关键字与后一个关键字相等的时候 return 值=0;
》当前一个关键字比后一个关键字大的时候 return 值>0;

注意点:void * 指针有两个典型的特性:

1)可以指向任何类型的变量。
2)void *类型的的指针不能进行解引用操作,因为无法确定类型就无法确定每个单元的字节数,当然也就不能对该指针变量进行偏移操作。因此对这种类型指针要解引用的时候需要强转类型。

上例子:

1)排序int数组

结果默认按照关键字升序排列。

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

//自写一个比较int类型序列的比较函数
int int_cmp(const void* p1,const void* p2)
{
	//比较函数返回值要满足上述要求,这里直接返回两个关键字的差值即可
	//但是如果直接写: return *p1-*p2; 这个写法是错误的无法通过编译,因为p1,p2是void*类型的指针是不可以直接解引用的!这里需要强转一下写成下面的代码:
	return *((int *)p1)-*((int*)p2);//若是 return *((int*)p2)- *((int *)p1);则降序
}

int main()
{
	//声明i用于控制遍历数组
	int i=0;
	//初始化int数组
	int Arr[]={5,6,7,4,3,1}
	//定义整型变量方便管理数组的元素个数
	int sz=sizeof(Arr)/sizeof(Arr[0]);
	qsort(Arr,sz,sizeof(Arr[0],int_cmp);//待排序列地址、待排关键字个数、关键字大小、比较函数地址 四个参数都准备完毕,已经可以开始排序。
	for(i=0;i<sz;++i)
	{
		printf("%d",Arr[i]);
	}
}

运行结果:
升序排列

2)排序字符串数组

还是首先要处理好比较函数,与int_cmp函数相类似,定义char_cmp比较函数:

#include <stdio.h>
#include <stdlib.h>  //因为要用到qsort 函数
#include <string.h>  //因为要用到strcmp函数
int char_cmp(const void* p1, const void* p2)
{
	return strcmp(*(char**)p1,*(char**)p2);
	//先用(char**)强转,再用*解引用一层
}
int main()
{
	int i=0;
	//定义字符串指针数组
	 char* p[]={"xiongda","gtqiang","xionger"};
	 int sz=sizeof(p)/sizeof(p[0]);
	 qsort(p,sz,sizeof[p[0]),char_cmp);
	 for(i=0;i<sz;++i)
	 {
	 		printf("%s\n",*p[i]);
	 }
	return 0;
}

字符串是不可以直接相加减的,需要利用一个库函数strcmp函数,它在string.h中
strcmp函数返回值刚好满足比较函数返回值要求,因此直接返回strcmp函数即可

运行结果:
按照降序
可知是按照字符串依次对比字符,字符默认按照降序排列。

3)排序结构体

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//定义结构体,取别名STU
typedef struct stu
{
	int age;
	char* name;
} STU;
int cmp_by_name(const void* p1,const void* p2)
{
	return strcmp((STU*)p1->name,(STU*)p2->name);
}
int main()
{
	int i=0;// 用于遍历结构体数组
	//定义结构体数组
	STU stu[]={{20,"zhangmazi"},{40,"tangshiye"},{32,"huangsilang"}};
	int sz=sizeof(stu)/sizeof(stu[0]);
	qsort(stu,sz,sizeof(stu[0]),cmp_by_name);
	for(i=0;i<sz;++i)
	{
		printf("%d %s\n",stu[i].age,stu[i].name);
	}
	return 0;
}

运行结果:
按照名字排序
结果按照名字排名。

当然你还可以设计一个按照年龄排名的比较函数,这里不多说。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值