Effective STL 条款35

Effective C++ 第三版 所有条款总结及对应代码描述(纯干货) Effective C++ 第三版 所有条款总结及对应代码描述(纯干货) 阅读详情

条款35:通过mismatch或lexicographical比较实现简单的大小写无关字符串比较

一个STL菜鸟最常问的问题是“我怎么使用STL来进行大小写无关的字符串比较?”这是一个令人迷惑的简单问题。大小写无关字符串比较要么真的简单要么真的困难,依赖于你要多一般地解决这个问题。如果你忽略国际化问题而且只关注于设计成字符串strcmp那样的类型,这个任务很简单。如果你要有strcmp不具有的按语言处理字符串中的字符的能力(也就是,容纳文本的字符串是除了英语以外的语言)或程序使用一个locale而不是默认的,这个任务很困难。

在本条款,我会作出这个问题的一个简单版本,因为那足以演示STL怎么完成任务。(这个问题一个比较难的版本也能用STL解决。准确地说,它解决了你可以在附录A中看到的locale相关的问题。)为了让简单的问题变得更有挑战性,我会处理两次。想要使用大小写无关比较的程序员通常需要两种不同的调用接口,一种类似strcmp(返回一个负数、零或正数),另一种类似operator(返回true或false)。因此我会演示怎么使用STL算法实现两种调用接口。

但是首先,我们需要一种方法来确定两个字符除了大小写之外是否相等。当需要考虑国际化问题时,这是一复杂的问题。下面的字符比较显然是一个过分简单的解决方案,但它类似strcmp进行的字符串比较,因为本条款我只考虑类似strcmp的字符串比较,不考虑国际化问题,这个函数就够了:

int ciCharCompare(char c1, char c2)   // 大小写无关比较字符
{      // c1和c2,如果c1 < c2返回-1,
      // 如果c1==c2返回0,如果c1 > c2返回1
 int Ic1 = tolower(static_cast<unsigned char>(c1));// 这些语句的解释
 int Ic2 = tolower(static_cast<unsigned char>(c2));// 看下文
 if (Ic1 < Ic2) return -1;
 if (lc1 > Ic2) return 1;
 return 0;
}

这个函数遵循了strcmp,可以返回一个负数、零或正数,依赖于c1和c2之间的关系。与strcmp不同的是,ciCharCompare在进行比较前把两个参数转化为小写。这就产生了大小写无关的字符比较。

正如<cctype>(也是<ctype.h>)里的很多函数,tolower的参数和返回值类型是int,但除非这个int是EOF,它的值必须能表现为一个unsigned char。在C和C++中,char可能或可能不是有符号的(依赖于实现),当char有符号时,唯一确认它的值可以表现为unsigned char的方式是在调用tolower之前转换一下。这就解释了上面代码中的转换。(在char已经是无符号的实现中,这个转换没有作用。)这也解释了保存tolower返回值的是int而不是char。

给定了ciCharCompare,就很容易写出我们的第一个大小写无关的两个字符串比较函数,提供了一个类似strcmp的接口。ciStringCompare这个函数,返回一个负数、零或正数,依赖于要比较的字符串的关系。它基于mismatch算法,因为mismatch确定了两个区间中第一个对应的不相同的值的位置。

在我们可以调用mismatch前,我们必须先满足它的前提。特别是,我们必须确定一个字符串是否比另一个短,短的字符串作为第一个区间传递。因此我们可以把真正的工作放在一个叫做ciStringCompareImpl的函数,然后让ciStringCompare简单地确保传进去的参数顺序正确,如果参数交换了就调整返回值:

int ciStringCompareImpl(const string& s1,  // 实现请看下文
   const string& s2);
int ciStringCompare(const string& s1, const string& s2)
{
 if (s1.size() <= s2.size()) return ciStringCompareImpl(s1, s2);
 else return -ciStringCompareImpl(s2, s1);
}

在ciStringCompareImpl中,大部分工作由mismatch来完成。它返回一对迭代器,表示了区间中第一个对应的字符不相同的位置:

int ciStringCompareImpl(const string& si, const strings s2)
{
 typedef pair<string::const_iterator,   // PSCI = “pair of
   string::const_iterator> PSCI; // string::const_iterator”
 PSCI p = mismatch(     // 下文解释了
   s1.begin(), s1.end(),  // 为什么我们
   s2.begin(),   // 需要not2;参见
   not2(ptr_fun(ciCharCompare))); // 条款41解释了为什么
       // 我们需要ptr_fun
 if (p.first== s1.end()) {    // 如果为真,s1等于
  if (p.second == s2.end()) return 0;  // s2或s1比s2短
  else return -1;
 }
 return ciCharCompare(*p.first, *p.second);  // 两个字符串的关系
}       // 和不匹配的字符一样

幸运的是,注释把所有东西都弄清楚了。基本上,一旦你知道了字符串中第一个不同字符的位置,就可以很容易决定哪个字符串, 如果有的话,在另一个前面。唯一可能感到奇怪的是传给mismatch的判断式,也就是not2(ptr_fun(ciCharCompare))。当字符匹配时这个判断式返回true,因为当判断式返回false时mismatch会停止。我们不能为此使用ciCharCompare,因为它返回-1、1或0,而当字符匹配时它返回0,就像strcmp。如果我们把ciCharCompare作为判断式传给mismatch,C++会把ciCharCompare的返回类型转换为bool,而当然bool中零的等价物是false,正好和我们想要的相反!同样的,当ciCharCompare返回1或–1,那会被解释成true,因为,就像C,所有非零整数值都看作true。这再次和我们想要的相反。要修正这个语义倒置,我们在ciCharCompare前面放上not2和ptr_fun,而且我们都会一直很快乐地生活。

我们的第二个方法ciStringCompare是产生一个合适的STL判断式:可以在关联容器中用作比较函数的函数。这个实现很短也很好,因为我们需要做的是把ciCharCompare修改为一个有判断式接口的字符比较函数,然后把进行字符串比较的工作交给STL中名字第二长的算法——lexicographical_compare:

bool ciCharLess(char c1, char c2)    // 返回在忽略大小写
{        // 的情况下c1是否
        // 在c2前面;
 tolower(static_cast<unsigned char>(c1)) <   // 条款46解释了为什么
  tolower(static_cast<unsigned char>(c2)); // 一个函数对象可能
}        // 比函数好
bool ciStringCompare(const string& s1, const string& s2)
{
 return lexicographical_compare(s1.begin(), s1.end(),  // 关于这个
     s2.begin(), s2.end(), // 算法调用的
     ciCharLess);  // 讨论在下文
}

不,我不会让你再有悬念了。名字最长的算法是set_symmetric_difference。

如果你熟悉lexicographical_compare的行为,上面的代码在清楚不过了。如果你不,可能像隔着一块混凝土一样。幸运的是,要把混凝土换成玻璃并不难。

lexicographical_compare是strcmp的泛型版本。strcmp只对字符数组起作用,但lexicographical_compare对所有任何类型的值的区间都起作用。同时,strcmp总是比较两个字符来看看它们的关系是相等、小于或大于另一个。lexicographical_compare可以传入一个决定两个值是否满足一个用户定义标准的二元判断式。

在上面的调用中,lexicographical_compare用来寻找s1和s2第一个不同的位置,基于调用ciCharLess的结果。如果,使用那个位置的字符,ciCharLess返回true,lexicographical_compare也是;如果,在第一个字符不同的位置,从第一个字符串来的字符先于对应的来自第二个字符串的字符,第一个字符串就先于第二个。就像strcmp,lexicographical_compare认为两个相等值的区间是相等的,因此它对于这样的两个区间返回false:第一个区间不在第二个之前。也像strcmp,如果第一个区间在发现不同的对应值之前就结束了,lexicographical_compare返回true:一个先于任何区间的前缀是一个前缀。

谈了很多关于mismatch和lexicographical_compare。虽然我专注于本书的轻便性,但如果我没有提到大小写无关字符串比较函数作为对标准C库的非标准扩展而广泛存在,我可能是玩忽职守的。它们一般有stricmp或strcmpi这样的名字,而且它们一般和我们在本条款开发的函数一样没有提供更多对国际化的支持。如果你想牺牲一些移植性,你知道你的字符串没有包含嵌入的null,而且你不关心国际化,你可以找到实现一个大小写无关字符串比较最简单的方式完全不同STL。取而代之的是,它把两个字符串都转换为const char*指针(参见条款16),然后对指针使用stricmp或strcmpi:

int ciStringCompare(const string& s1, const string& s2)
{
 return stricmp(s1.c_str(),s2.c_str());   // 你的系统上的
}        // 函数名可能
        // 不是stricmp

有的人可能称此为hack,但stricmp/strcmpi被优化为只做一件事情,对长字符串运行起来一般比通用的算法mismatch和lexicographical_compare快得多。如果那对你很重要,你可能不在乎你用非标准C函数完成标准STL算法。有时候最高效地使用STL的方法是认识到其他方法更好。

【绝版C++书籍】《Effective STL》读书笔记 《Effective STL》读书笔记写在前面《Effective STL》中可能过时的内容1 容器第1条:慎重选择容器类型。第2条:不要试图编写独立于容器类型的代码。第3条:确保容器中的对象拷贝正确而高效。第4条:调用empty而不是检查size()是否为0。第5条:区间成员函数优先于与之对应的单元素成员函数。第6条:当心C++编译器最烦人的分析机制。第7条:如果入容器中包含了通过new操作创建的指针,切记在容器对象析构前将delete掉。第8条:切勿创建包含auto_ptr的容器对象。第9条:慎重选择删 阅读详情

相关推荐

Zemax热分析实战:5分钟搞定双胶合透镜温度漂移优化(附操作数详解)

本文详细解析了使用Zemax进行光学系统热分析的全流程,以双胶合透镜为例,重点阐述了如何通过多重结构编辑器模拟温度变化,并利用关键操作数优化系统以抵抗温度漂移。文章提供了从基础设置到高级优化的实战技巧,帮助工程师快速掌握无热化设计方法,确保系统在宽温范围内保持稳定成像性能。

n4o5p6q7r的博客 396

effective stl 第35条:通过mismatch和lexicographical_compare实现简单的忽略大小写的字符串比较

新知识点:not1、not2、not3……not127 not1和not2例子: not1是构造一个与谓词结果相反的一元函数对象,not2是构造一个与谓词结果相反的二元函数对象#include<iostream> #include<algorithm> #include<vector> #include<functional>using namespace std;int ciCharCompar

sun%moon 551

量子通信:初识量子城域网

对量子城域网的概念、作用、拓扑、建设内容等进行了较为全面的初步介绍。

量子领域相关话题 3344

《EfficativeSTL》

定义、使用和扩展STL 没有“STL”的官方定义,在本书中,“STL”的意思是与迭代器合作的C++标准库的一部 分。那包括标准容器(包括string),iostream库的一部分,函数对象和算法。它不包括 标准容器适配器(stack,queue和priority_queue)以及bitset和valarray容器,因为它们 缺乏迭代器支持。它也不包括数据。真的,数组以指针的形式支持迭代器,

JUSTACES 的博客 1306

域控制器开发避坑实录:从硬件设计到软件集成的5个关键挑战

本文深入剖析了域控制器开发中的5大关键挑战,从硬件选型到软件集成,涵盖智能驾驶芯片选择、实时性优化、AUTOSAR架构适配等核心问题。通过实战案例和数据对比,为工程师提供避坑指南,助力提升开发效率和系统可靠性。

weixin_29258297的博客 394

【图神经网络】从0到1使用PyG手把手创建异构图

异构图的准确定义如下:异构图(Heterogeneous Graphs):一个异构图GGG有一组节点V=v1,v2,...,vnV=v_1,v_2,...,v_nV=v1​,v2​,...,vn​和一组边E=e1,e2,...,emE=e_1,e_2,...,e_mE=e1​,e2​,...,em​组成,其中每个节点和每条边都对应着一种类型,用TvT_vTv​表示节点类型的集合,TeT_eTe​表示边类型的集合,一个异构图有两个映射函数,分别将每个节点映射到其对应的类型ϕv:V→Tv\phi_v:V\rig

小哲的博客 7833

lexicographical_compare()按字典序比较函数用法示例(字符串排序)

#include "algostuff.hpp" using namespace std; void printCollection(const list& l) { PRINT_ELEMENTS(l); } bool lessForCollection(const list& l1,const list& l2) { return lexicographical_compare(l1.begin(),l1.end(),l2.begin(),l2.end()); } int m

自由时间 1659

Android音频子系统分析-car_audio_configuration.xml

先附上一个例子,再逐一解释。概括来说,该文件描述了车里有哪些区域,每个区域划分了多少组,每个组包含了哪些设备,每个设备接收哪些类型的音频流。

不定时记录分享一些有用没用的东西 988

Effective STL 中文版(大全)

候捷说,对于STL,程序员有三个境界,开始是使用STL,然后是理解STL,最后是补充STL。EffectiveSTL是一本非常好的书,帮助你更好的理解STL,其作者就是《EffectiveC++》一书的作者。如果你已经初步了解了STL的容器、迭代器、算法和函数,而又想更好的了解STL,那么《EffectiveSTL》是你的最佳选择。 还有一部分没有找到链接,如果再找不到我会自己试着翻译

幸福村的人 1139

音视频开发—H264相关概念和压缩原理详解(GOP、宏块、帧内压缩、帧间压缩)

本文讲述了H264相关概念和原理——GOP概念,SPS与PPS,帧内压缩原理,帧间压缩原理,解释了什么是运动补偿,什么运动矢量等等概念

weixin_46999174的博客 3976

Oracle EBS 寄销/VMI(2)-->采购篇

上篇有一部分设置需要建BPA后,将BPA编号与批准的供应商相关联.     本篇主要是讲的内容:一揽子采购协议-->准标采购订单-->收接入库-->子库转移-->创建冲减通知-->'按接收开票' 自动开票程序 1. PO-->采购订单à采购订单 创建一揽子采购协议,确定物料

陈显平的专栏-Oracle EBS 1万+

2 Studying《Effective STL》

《Effective STL》摘要 STL是C++标准库的重要组成部分,涵盖容器、迭代器、算法和函数对象等。本文总结了STL使用中的关键要点: 容器选择: 根据插入删除位置选择序列容器(vector、list、deque) 考虑查找效率选择关联容器(set、map)或哈希容器 指针容器需注意资源管理,建议使用智能指针 容器操作优化: 优先使用empty()而非size()==0 区间操作比单元素操作更高效 使用reserve避免频繁重新分配内存 注意string实现的多样性 算法使用: 确保目标区间足够大

u012906122的专栏 753

ARM系统控制和管理接口System Control and Management Interface

本文档描述了一个可扩展的独立于操作系统的软件接口,用于执行各种系统控制和管理任务,包括电源和性能管理。 本文档描述了系统控制和管理接口(SCMI),它是一组操作系统无关的软件接口,用于系统管理。

AI-安全-功耗 1913

Effective STL 目录

由于没有看内容,有些翻译可能不准确,请见谅:)容器条款1: 仔细选择你要的容器 条款2: 小心对“容器无关代码”的幻想 条款3: 使容器里对象的拷贝操作轻量而正确 条款4: 用empty来代替检查size是否为0 条款5: 尽量使用范围成员函数代替他们的单元素兄弟 条款6: 警惕C++的及其令人恼怒的分析 条款7: 当使用new得指针的容器时,切记在容器销毁前d

AMin2001的专栏 1483

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Effective STL目录

    从去年12月开始,我花了40天看了《Effective STL》这本书,并写了相关的读书笔记,我在考虑是否将这部分笔记在BLOG上贴出来。在此之前,先贴上Effective STL目录,并且强烈推荐这本书。如果想加深对STL的了解,这本书必不可少。同时还需要参考的书是《STL源代码剖析》。这篇目录上带有了相关链接。前言致谢导读容器条款1:仔细选择你的容器条款2:小心对“容器无关代码”的幻想

李永亮的专栏 1861

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

More Effective C++ 条款35:让自己熟悉C++标准库

More_Effective_C++35——让自己熟悉C++标准库

君鼎的博客 392

Effective C++ 条款总结

Effective C++ 条款总结一、让自己习惯C++1 视C++为一个语言联邦2 尽量使用const等替换#define3 尽可能使用const4 确定对象使用前被初始化 自己在看这本书的时候,回去翻看目录的时候,有些规则会被遗忘,因此做个简单的小总结供自己和其他人参考,没读过的还是要先去读一遍的 一、让自己习惯C++ 1 视C++为一个语言联邦 C++是一种包含许多特性的语言,因而不要把它视为一个单一语言。理解C++至少需要学习一下4个部分: C语言。C++仍以C为基础 objected-ori

catkin_ws的博客 1177

【C++】万字详解Effective C++

本文为前段时间读《Effective C++》(侯捷译)时做的个人笔记。

Friday 4289

More Effective C++ 条款18

 条款18:分期摊还期望的计算在条款17中,我极力称赞懒惰的优点,尽可能地拖延时间,并且我解释说懒惰如何提高程序的运行效率。在这个条款里我将采用一种不同的态度。这里将不存在懒惰。我鼓励你让程序做的事情比被要求的还要多,通过这种方式来提高软件的性能。这个条款的核心就是over-eager evaluation(过度热情计算法):在要求你做某些事情以前就完成它们。例如下面这个模板类,用来表示放有大

追随技术的梦想 1088

More Effective C++ 条款35 让自己习惯于标准C++ 语言

(由于本书出版于1996年,因此当时的新特性现在来说可能已经习以为常,但现在重新了解反而会起到了解C++变迁的作用) 1. 1990年后C++的重要改变 1). 增加了新的语言特性:RTTI,namespaces,bool,关键词mutable和explicit,enums作为重载函数之自变量所引发的类型晋升转换,以及"在class 定义区内直接为整数型(intergral)...

ddzai7557的博客 231

【一文读懂】《Effective STL》50条有效使用STL的经验

本文按 Scott Meyers《Effective STL》(2001)原书 8 章顺序,系统梳理全部 50 条条款,覆盖容器选型、vector/string、关联容器、迭代器、算法、函数子、STL 实战与其他议题。对初学者易混淆处配代码示例,并在关键处标注 C++11/20 的现代等价写法(如 unordered_map、std::erase_if、lambda 取代 bind1st)。

码工许师傅 366

Effective STL笔记

#estl 第50条:熟悉与STL相关的web站点。三个:www.sgi.com/tech/stl、www.stlport.org 和 www.boost.org。 #estl 第49条:学会分析与STL相关的编译器诊断信息。嗯,第一招是替换大法,然后介绍了一下与容器、插入迭代器、绑定器、输出迭代器或算法相关的错误大概有什么套路看。 #estl 第48条:总是包含(#include)正确 的头文件...

weixin_34015566的博客 164
上一篇: Effective STL 条款28
下一篇: Effective STL 条款37
AMin2001
博客等级 码龄26年 7粉丝 35原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值