简述

有一个需求,是需要将URL中的query参数的key全部转换为小写或者大写,键值对的数量有点多,但全部都是英文字母,无需考虑非字母的情况。

实现比较快的做法是使用STL或C标准库中的转换接口,如下:

  1. #include <string>
  2. #include <cctype>
  3. #include <algorithm>
  4. // 字符串中的大写字符转小写
  5. std::string strtolower(std::string s)
  6. {
  7. transform(s.begin(), s.end(), s.begin(), ::tolower);
  8. return s;
  9. }
  10. // 字符串中的小写字符转大写
  11. std::string strtoupper(std::string s)
  12. {
  13. transform(s.begin(), s.end(), s.begin(), ::toupper);
  14. return s;
  15. }

这个方法虽然很好,但是效率不是很高。

分析了一下ascii码的码值,发现大小写字母的ascii码之间是有规律的。

原理

英文字母的ASCII码值表示如下



对比一下其二进制形式



对比使用的是OSChina的在线工具http://tool.oschina.net/diff/

从对比的结果可以看出,大写字母与小写字母的差别仅是一个比特位的不同

因为它们的这个规律,可以写出下面的转换函数(如果输入不是字母,转出的结果会有错误)

可以查看数字0-9的ascii码值,可以看出它们的第6位都是0,所以转为小写的算法不会影响数字的值。

转小写算法中受到影响的,只有ascii码二进制表示中第六位为0的部分。其中非字母部分如下表

  1. #include <iostream>
  2. #include <string>
  3. #include <stdint.h>
  4. // 更优化
  5. std::string strtoupper(std::string s)
  6. {
  7. if(s.empty()){return s;}
  8. size_t len = s.size() + 1;
  9. size_t alignlen = len + 8 - (len % 8);
  10. s.resize(alignlen);
  11. size_t ec = alignlen / 8;
  12. uint64_t* p8 = (uint64_t*)s.data();
  13. for(size_t i=0;i<ec;++i){
  14. p8[i] &= 0xDFDFDFDFDFDFDFDF;
  15. }
  16. s.resize(len-1);
  17. return s;
  18. }
  19. // 未做进一步优化
  20. std::string strtolower(std::string s)
  21. {
  22. size_t len = s.size();
  23. size_t ec = len /8;
  24. uint64_t* p8 = (uint64_t*)s.data();
  25. for(size_t i=0;i<ec;++i){
  26. p8[i] |= 0x2020202020202020;
  27. }
  28. uint8_t* p1 = (uint8_t*)(p8 + ec);
  29. len %= 8;
  30. for(size_t i=0;i<len;++i){
  31. p1[i] |= 0x20;
  32. }
  33. return s;
  34. }

性能测试

测试代码如下:

  1. int main()
  2. {
  3. //std::cout << "Hello, world!\n";
  4. for(size_t i=0;i<1000000;++i){
  5. std::string s = strtoupper("qwertyuiopasdfghjklzxcvbnm````````QWERTYUIOPASDFGHJKLZXCVBNM");
  6. //std::cout<<s<<std::endl;
  7. s = strtolower("qwertyuiopasdfghjklzxcvbnm\t\t\t\t\t\t\t\tQWERTYUIOPASDFGHJKLZXCVBNM");
  8. //std::cout<<s<<std::endl;
  9. }
  10. return 0;
  11. }

--编译时候请勿优化,否则可能被优化掉!--

测试结果如下:

使用STL算法结果如下

  1. time ./teststl
  2. ./teststl 7.88s user 0.03s system 100% cpu 7.904 total

自写代码测试结果如下

  1. time ./test
  2. ./test 0.93s user 0.00s system 99% cpu 0.928 total

可以看到,其性能有差异。(应用场景有限)

C++高性能转换大小写算法的更多相关文章

  1. JS中应用正则表达式转换大小写

    JS中应用正则表达式转换大小写,代码很简单,看代码: 以下首字母大写,其它字母小写 <script type="text/javascript"> function r ...

  2. PHPStorm 使用正则批量查询替换并自动转换大小写的方法

    PHPStorm 的项目查询替换功能那是非常非常强大的, 速度也很快, 配合正则更加灵活强大. 一般的正则查询替换没什么太多好说的, 这里主要说说比较少用的 大小写自动转换的问题, 也是比较少用但很有 ...

  3. 用Java将字符串的首字母转换大小写

    在项目开发的时候会需要统一字符串的格式,比如首字母要求统一大写或小写,那用Java如何实现这一功能?下面一起来学习学习. 话不多说,直接上代码 ? 1 2 3 4 5 6 7 8 9 10 11 12 ...

  4. vscode代码段设置console.log,转换大小写,目录别名

    https://blog.csdn.net/gyz718/article/details/71513075 vscode代码段设置console.log https://blog.csdn.net/u ...

  5. Java 常用知识点汇总(数据类型之间转换、字符串的相关操作-截取、转换大小写等)

    1.Java四类八种数据类型 byte:Java中最小的数据类型,在内存中占8位(bit),即1个字节,取值范围-128~127,默认值0 short:短整型,在内存中占16位,即2个字节,取值范围- ...

  6. golang []byte和string的高性能转换

    golang []byte和string的高性能转换 在fasthttp的最佳实践中有这么一句话: Avoid conversion between []byte and string, since ...

  7. 结合stack数据结构,实现不同进制转换的算法

    #!/usr/bin/env python # -*- coding: utf-8 -*- # learn <<Problem Solving with Algorithms and Da ...

  8. php字符串首字母转换大小写的实例分享

    php中对字符串首字母进行大小写转换的例子. in: 后端程序首字母变大写:ucwords() <?php $foo = 'hello world!'; $foo = ucwords($foo) ...

  9. java代码把字母转换大小写、、、、

    总结:从键盘输入多少次,就用for循环控制.这些需要输入的数据都放在循环内部,否则不会执行多次. package com.aaa; import java.util.Scanner; //大小写字母的 ...

随机推荐

  1. sqlserver 临时表、表变量、CTE的比较

    原文地址:  sqlserver 临时表.表变量.CTE的比较 1.临时表 1.1 临时表包括:以#开头的局部临时表,以##开头的全局临时表. 1.2 存储 不管是局部临时表,还是全局临时表,都会放存 ...

  2. 「BZOJ」「3262」陌上花开

    CDQ分治 WA :在solve时,对y.z排序以后,没有处理「y.z相同」的情况,也就是说可能(1,2,3)这个点被放到了(2,2,3)的后面,也就是统计答案在前,插入该点在后……也就没有统计到! ...

  3. 移动前端调试工具-Weinre真机调试

    之前做移动前端调试页面的时候就是简单的使用Chrome模拟器调试,能满足基本基本的需求,后来发现了基于Web Inspector(Webkit)的远程调试工具Weinre,可以在PC端直接调试运行在移 ...

  4. javascript 的面向对象特性参考

    最近在看用javascript+css实现rich client.javascript 也是一个蛮有意思的语言.特别是其面向对象的实现和其他“标准”的OO launguage有很大的不同.但是,都是动 ...

  5. distinct 多列详解

    1.distinct单列 select distinct(a) from tableA; 2.distinct多列 select distinct a,b,c from tableA; 注意此时是将a ...

  6. iOS中的时钟动画

    iOS 动画效果非常多,我们在开发中可能会遇到很多动画特效,我们就会用到核心动画框架CoreAnimation,核心动画里面的动画效果有很多,都是在QuartzCore.framework框架里面,今 ...

  7. 让App中增加LruCache缓存,轻松解决图片过多造成的OOM

    上次有过电话面试中问到Android中的缓存策略,当时模糊不清的回答,如今好好理一下吧. Android中普通情况下採取的缓存策略是使用二级缓存.即内存缓存+硬盘缓存->LruCache+Dis ...

  8. win10安装jdk以及配置环境变量

    本人使用的jdk版本:jdk-8u171-windows-x64.exe, 1.安装jdk: 双击 jdk-8u171-windows-x64.exe ,然后就是简单的安装流程,安装文件位置建议保持默 ...

  9. 【Spark】SparkStreaming-高可用-HA-Master

    SparkStreaming-高可用-HA-Master sparkstreaming master 高可用_百度搜索 Spark:Master High Availability(HA)高可用配置的 ...

  10. NLP系列(4)_朴素贝叶斯实战与进阶(转)

    http://blog.csdn.net/han_xiaoyang/article/details/50629608 作者: 寒小阳 && 龙心尘 时间:2016年2月. 出处:htt ...