C++高性能转换大小写算法
简述
有一个需求,是需要将URL中的query参数的key全部转换为小写或者大写,键值对的数量有点多,但全部都是英文字母,无需考虑非字母的情况。
实现比较快的做法是使用STL或C标准库中的转换接口,如下:
#include <string>
#include <cctype>
#include <algorithm>
// 字符串中的大写字符转小写
std::string strtolower(std::string s)
{
transform(s.begin(), s.end(), s.begin(), ::tolower);
return s;
}
// 字符串中的小写字符转大写
std::string strtoupper(std::string s)
{
transform(s.begin(), s.end(), s.begin(), ::toupper);
return s;
}
这个方法虽然很好,但是效率不是很高。
分析了一下ascii码的码值,发现大小写字母的ascii码之间是有规律的。
原理
英文字母的ASCII码值表示如下

对比一下其二进制形式

对比使用的是OSChina的在线工具http://tool.oschina.net/diff/
从对比的结果可以看出,大写字母与小写字母的差别仅是一个比特位的不同。
因为它们的这个规律,可以写出下面的转换函数(如果输入不是字母,转出的结果会有错误)
可以查看数字0-9的ascii码值,可以看出它们的第6位都是0,所以转为小写的算法不会影响数字的值。
转小写算法中受到影响的,只有ascii码二进制表示中第六位为0的部分。其中非字母部分如下表

#include <iostream>
#include <string>
#include <stdint.h>
// 更优化
std::string strtoupper(std::string s)
{
if(s.empty()){return s;}
size_t len = s.size() + 1;
size_t alignlen = len + 8 - (len % 8);
s.resize(alignlen);
size_t ec = alignlen / 8;
uint64_t* p8 = (uint64_t*)s.data();
for(size_t i=0;i<ec;++i){
p8[i] &= 0xDFDFDFDFDFDFDFDF;
}
s.resize(len-1);
return s;
}
// 未做进一步优化
std::string strtolower(std::string s)
{
size_t len = s.size();
size_t ec = len /8;
uint64_t* p8 = (uint64_t*)s.data();
for(size_t i=0;i<ec;++i){
p8[i] |= 0x2020202020202020;
}
uint8_t* p1 = (uint8_t*)(p8 + ec);
len %= 8;
for(size_t i=0;i<len;++i){
p1[i] |= 0x20;
}
return s;
}
性能测试
测试代码如下:
int main()
{
//std::cout << "Hello, world!\n";
for(size_t i=0;i<1000000;++i){
std::string s = strtoupper("qwertyuiopasdfghjklzxcvbnm````````QWERTYUIOPASDFGHJKLZXCVBNM");
//std::cout<<s<<std::endl;
s = strtolower("qwertyuiopasdfghjklzxcvbnm\t\t\t\t\t\t\t\tQWERTYUIOPASDFGHJKLZXCVBNM");
//std::cout<<s<<std::endl;
}
return 0;
}
--编译时候请勿优化,否则可能被优化掉!--
测试结果如下:
使用STL算法结果如下
time ./teststl
./teststl 7.88s user 0.03s system 100% cpu 7.904 total
自写代码测试结果如下
time ./test
./test 0.93s user 0.00s system 99% cpu 0.928 total
可以看到,其性能有差异。(应用场景有限)
C++高性能转换大小写算法的更多相关文章
- JS中应用正则表达式转换大小写
JS中应用正则表达式转换大小写,代码很简单,看代码: 以下首字母大写,其它字母小写 <script type="text/javascript"> function r ...
- PHPStorm 使用正则批量查询替换并自动转换大小写的方法
PHPStorm 的项目查询替换功能那是非常非常强大的, 速度也很快, 配合正则更加灵活强大. 一般的正则查询替换没什么太多好说的, 这里主要说说比较少用的 大小写自动转换的问题, 也是比较少用但很有 ...
- 用Java将字符串的首字母转换大小写
在项目开发的时候会需要统一字符串的格式,比如首字母要求统一大写或小写,那用Java如何实现这一功能?下面一起来学习学习. 话不多说,直接上代码 ? 1 2 3 4 5 6 7 8 9 10 11 12 ...
- vscode代码段设置console.log,转换大小写,目录别名
https://blog.csdn.net/gyz718/article/details/71513075 vscode代码段设置console.log https://blog.csdn.net/u ...
- Java 常用知识点汇总(数据类型之间转换、字符串的相关操作-截取、转换大小写等)
1.Java四类八种数据类型 byte:Java中最小的数据类型,在内存中占8位(bit),即1个字节,取值范围-128~127,默认值0 short:短整型,在内存中占16位,即2个字节,取值范围- ...
- golang []byte和string的高性能转换
golang []byte和string的高性能转换 在fasthttp的最佳实践中有这么一句话: Avoid conversion between []byte and string, since ...
- 结合stack数据结构,实现不同进制转换的算法
#!/usr/bin/env python # -*- coding: utf-8 -*- # learn <<Problem Solving with Algorithms and Da ...
- php字符串首字母转换大小写的实例分享
php中对字符串首字母进行大小写转换的例子. in: 后端程序首字母变大写:ucwords() <?php $foo = 'hello world!'; $foo = ucwords($foo) ...
- java代码把字母转换大小写、、、、
总结:从键盘输入多少次,就用for循环控制.这些需要输入的数据都放在循环内部,否则不会执行多次. package com.aaa; import java.util.Scanner; //大小写字母的 ...
随机推荐
- 单元测试利器 JUnit 4
引言 毋庸置疑,程序员要对自己编写的代码负责,您不仅要保证它能通过编译,正常地运行,而且要满足需求和设计预期的效果.单元测试正是验证代码行为是否满足预期的有效手段之一.但不可否认,做测试是件很枯燥无趣 ...
- sklearn中SVM调参说明
写在前面 之前只停留在理论上,没有实际沉下心去调参,实际去做了后,发现调参是个大工程(玄学).于是这篇来总结一下sklearn中svm的参数说明以及调参经验.方便以后查询和回忆. 常用核函数 1.li ...
- 7.3 netty3基本使用
由于dubbo默认使用的是netty3进行通信的,这里简单的列出一个netty3通信的例子. 一 server端 1 Server package com.hulk.netty.server; imp ...
- [置顶] Linux下将Nutch1.3导入eclipse
1.准备工作 首先去官网下载好 apache-nutch-1.3-bin.zip 解压apache-nutch-1.3-bin.zip [pig@CentOs ]$ unzip apache-nu ...
- Java中 CopyOnWriteArrayList 的使用
java中,List在遍历的时候,如果被修改了会抛出java.util.ConcurrentModificationException错误. 看如下代码: import java.util.Array ...
- 自动化打包 Jenkins 持续集成 Git Gradle MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- bash: php: command not found
bash: php: command not found 解决:export PATH=$PATH:/usr/local/php/bin
- 用LSTM生成武侠人名
http://magicly.me/2017/04/07/rnn-lstm-generate-name/?utm_source=tuicool&utm_medium=referral 之前翻译 ...
- Redis集群搭建最佳实践
要搭建Redis集群.首先得考虑以下的几个问题; Redis集群搭建的目的是什么?或者说为什么要搭建Redis集群? Redis集群搭建的目的事实上也就是集群搭建的目的.全部的集群主要都是为了解决一个 ...
- Spring 集成 redistemplate
jar包 <version.clients.jedis>2.7.2</version.clients.jedis><version.data.redis>1.6.2 ...