C++字符串按字典序比较大小后排序

1.综述

这是一个基础问题,也就是说已经被研究透了。

现行环境下最方便的方案还是使用库函数strcmp+qsort


2.strcmp()用法

定义在<string.h> / <cstring>

输入只能是c中的char[]数组,或者c++中的string;

效果为比较两个字符串的字典序大小,如"a"<"A","a123"<"a145";

返回值为负数/0/正数;

负数表示小于;


3.strcmp函数实现方案


①形式简单易懂,输出值-1/0/1更优美

#include <string.h> 
int(strap)(const char *sl,const char *s2)
{
    /*compare unsigned char sl[],s2[]*/
    for(;*sl==*s2;++sl,++s2)
        if(*sl=='\0')
            return(0);
    return((*(unsignedchar*)sl<*(unsignedchar*)s2)?-1:+1);
}


如果不对输出结果进行 01修饰

int strcmp(const char *str1,const char *str2)
{
    while(*str1 == *str2)
    {
        if(*str1 == '\0')
            return0;
        str1++;  str2++;
    }
    return *str1 - *str2;
}


②更简洁效率,缺点是输出值可以为不确定的负数/正数

int strcmp(const char * src, const char * dst)
                                        //字典序比较两字符串大小
{
    int ret = 0 ;
    while(!(ret=*src-*dst)&&*dst)   //相等且没有结束
        ++src; ++dst;
    return( ret );
}


④qsort()函数用法

用以对数组进行排序

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

这个函数的优点在于,其对于顺序的“价值定义”是不确定的。

可以任意给定cmp函数来确定排序的依赖主体。


参数1,开始排序的地址,easy模式下可以采用数组名代替;

参数2 参与排序元素个数(size_t);

参数3  单个元素大小 (size_t);

参数4  cmp函数,确定排序时的价值取向;


qsort会不断调用cmp来比较数组元素的大小。

其中cmp函数在官网手册中特别说明如下

------

return valuemeaning
<0The element pointed to by p1 goes before the element pointed to by p2
0The element pointed to by p1 is equivalent to the element pointed to by p2
>0The element pointed to by p1 goes after the element pointed to by p2
-----


可以任意编纂cmp函数的逻辑,只要返回值<0,则p1会被置于p2前。

同时也实现了,排序逻辑与排序对象的抽象分离。



关于qsort源码请看下面。

两篇内容相近,对照着看理解更好。

https://blog.csdn.net/u011822516/article/details/17059693

https://blog.csdn.net/gen_ye/article/details/52880461


本人阅读以上2篇文章后改写的小作业:

https://blog.csdn.net/w55100/article/details/80516573



5.一个程序案例(strcmp+qsort+结构体)

描述

    给出班里某门课程的成绩单,请你按成绩从高到低对成绩单排序输出,如果有相同分数则名字字典序小的在前。
输入
    第一行为n (0 < n < 20),表示班里的学生数目;
    接下来的n行,每行为每个学生的名字和他的成绩, 中间用单个空格隔开。名字只包含字母且长度不超过20,成绩为一个不大于100的非负整数。
输出
    把成绩单按分数从高到低的顺序进行排序并输出,每行包含名字和分数两项,之间有一个空格。

实例

#include<iostream>
#include<cstdlib>
#include<cstring>

using namespace std;

struct student{
	char name[20];
	int score;
};

//复杂的排序逻辑合并到一个cmp函数内
int cmp(const void *a,const void *b){
    //特别注意,此处形参列表必须使用const void *形式,不然会报错
    student *p1 = (student*)a;
    student *p2 = (student*)b;

    if( p1->score== p2->score){
        //成绩相同时,比较结构体的name大小
        return strcmp( p1->name, p2->name);
    }
    else{
        return p2->score - p1->score; //成绩需要高到低排序
    }
}  


int main(){

	int n;
	int i;
	struct student stus[20];
	
    //输入
	cin>>n;
	for(i= 0;i<n;i++){
		cin>>stus[i].name>>stus[i].score;
	}

	//排序
	qsort(stus,20,sizeof(student),cmp);

    //输出
	for(i= 0;i<n;i++){
		cout<<stus[i].name<<" "<<stus[i].score<<endl;
	}


	system("pause");
	return 0;

}


其他参考

http://www.cplusplus.com/reference/cstdlib/qsort/

https://blog.csdn.net/eapid/article/details/1552310


  • 10
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值