C++中字母大写和小写转换实现的优化
C++中字母大写和小写转换实现的优化
write by 九天雁翎(JTianLing) --
blog.csdn.net/vagrxie
在本文中所有以转换为小写为例。
从推荐复用代码的角度来看,用库函数是不错的办法:
方案一:
char gc1[53] = "abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ";
void wayOne()
{
strlwr(gc1);
}
长处是使用方便,别人看着也easy理解,可是效率慢的让人吐血。
extern "C" char * __cdecl _strlwr (
char * string
)
{
if (__locale_changed == 0)
{
char * cp;
/* validation
section */
_VALIDATE_RETURN(string != NULL,
EINVAL, NULL);
for (cp=string; *cp; ++cp)
{
if
('A' <= *cp
&& *cp <= 'Z')
*cp
+= 'a' - 'A';
}
return(string);
}
else
{
_strlwr_s_l(string, (size_t)(-1),
NULL);
return string;
}
}
循环中平均2.5次的推断,(*cp一次,if的’A’<=一次,*cp<=版次)加平均每次0.5次的加法,尽管这种转换O(n)是不可缺少的,可是对于这样多的操作还是慢的可怕。
例2:
char gc2[53]
= "abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ";
namespace MYTEST
{
inline char*
strlwr(char
*asz)
{
for(char*
lp = gc2;
*lp != 0; ++lp)
{
*lp |= 0x20;
}
return asz;
}
}
void wayTwo()
{
MYTEST::strlwr(gc2);
}
此例中利用了ASCII字母值的特点,一共仅仅有一次推断(*lp!=0),一次位或操作。算法上提高了非常多:)事实上已经达到了1/3的效率提升。。。。。
将原来一大堆的代码,转化成了反汇编仅仅有4句的程序:
00401020 80 08 20 or byte ptr [eax],20h
00401023 83 C0 01 add eax,1
00401026 80 38 00 cmp byte ptr [eax],0
00401029 75 F5 jne wayTwo+10h (401020h)
可是考虑到char仅仅是1个字节,看到
00401020 80 08 20 or byte ptr [eax],20h
一句都感觉不爽,白白浪费了eax 这样4个字节的寄存器,于是能够这样优化:
namespace MYTEST2
{
inline char*
strlwr(char
*asz)
{
long* lp
= (long*)gc3;
for(; *((char*)lp) != 0; ++lp)
{
(long)(*lp) |= 0x20202020;
}
for(char*
lpc = (char*)lp;*lpc!=0; ++lpc)
{
*lpc |= 0x20;
}
return asz;
}
}
说实话,。。。。。。。。。。。没有不论什么清晰性可言,没有不论什么可读性可言,可是优化的思想就是充分的利用4个字节的寄存器,而且以DWORD来读取内存,这是非常有效率的方式。汇编代码事实上比C语言代码更加清晰,原因在于C语言代码还须要处理大量与类型相关的事情,汇编代码不须要。
第一个循环汇编代码例如以下:
00401040 81 08 20 20 20 20 or dword ptr [eax],20202020h
00401046 83 C0 04 add eax,4
00401049 80 38 00 cmp byte ptr [eax],0
0040104C 75 F2 jne wayThree+10h (401040h)
将循环次数降低了3/4。。。。所以效率的优化还是非常明显的。单指令多数据操作的思想只是就是这样的思想的延生罢了。。。呵呵,可是说在前面,如此影响可读性的效率优化,除非在非常必要的情况下,不然慎用。。。。。
为了证实效率的优化,起码也得给出一个測试结果给大家看看吧,不然还以为我胡扯了。
void wayOne()
// Hit Count : 1
// Time : 5553.00
// Time with Children : 5553.00
{
strlwr(gc1);
}
void wayTwo()
// Hit Count : 1
// Time : 247.00
// Time with Children : 247.00
{
MYTEST::strlwr(gc2);
}
void wayThree()
// Hit Count : 1
// Time : 180.00
// Time with Children : 180.00
{
MYTEST2::strlwr(gc3);
}
int _tmain(int argc, _TCHAR* argv[])
// Hit Count : 1
// Time : 6836996435.00
// Time with Children : 6837002415.00
{
wayThree();
wayTwo();
wayOne();
}
測试结果为AQtime5測试数据,单位为机器周期,由于结果已经非常明显了,所以没有进行多次循环的測试。而且为了排除缓存的影响,将最快的放在了最前面,那么哪怕有缓存的影响,对于wayThree也是最不利的才对。库函数的5000多的结果,说慢的可怕并不为过。在数据量非常大的时候,这样的优化的差异可不是一点点而已。
C++中字母大写和小写转换实现的优化的更多相关文章
- eclipse字母大写和小写转换的快捷键
大写转换小写 ctrl+shift+y 小写转换大写 ctrl+shift+x
- Excel大写和小写转换函数
Excel中的大写和小写转换函数 (1).转换为所有小写字母:lower函数 (2).转换为所有大写字母:upper函数 (3).转换为首字母大写,其余小写字母:proper函数 三种函数的使用方式. ...
- php实现兼容Unicode文字的字符串大写和小写转换strtolower()和strtoupper()
前言 网上流传着这么一个腾讯笔试题: PHP的strtolower()和strtoupper()函数在安装非中文系统的server下可能会导致将汉字转换为乱码,请写两个替代的函数实现兼容Unicode ...
- 如何将js字符串变成首字母大写其余小写
有时候会接收到一些大小写不规则的字符串,如"JAMES"."alice"."Amy"等,如何将他们统一的变成首字母大写其余小写的形式呢? 思 ...
- double中首字母大写与小写的区别
Double 是类 double是基础数据类型.Double类型是double的包装类.Double 和double之间的相互转化称为自动拆箱和自动装箱.如果从对象角度理解,那么Double就是对象, ...
- Bootstrap3基础 text-uppercase/lowercase/capitalize 字母大写、小写和首字母大写
内容 参数 OS Windows 10 x64 browser Firefox 65.0.2 framework Bootstrap 3.3.7 editor ...
- shell中把大写字母转换成小写字母
shell中把大写字母转换成小写字母 参考:http://www.jb51.net/article/40257.htm echo "AABBCC" | tr "[:upp ...
- python 练习题:将列表中的大写字母转换成小写
将列表中的大写字母转换成小写如果list中既包含字符串,又包含整数,由于非字符串类型没有lower()方法,L1 = ['Hello', 'World', 18, 'Apple', None]请修改列 ...
- 【转载】C#将字符串中字母全部转换为大写或者小写
在C#的编程开发过程中,有时候判断字符串是否相等时,并不关注字母的大小写,此时在C#中可以使用ToUpper方法将字符串中所有的字母转换为大写,使用ToLower方法可以将字符串中所有字母转换为小写. ...
随机推荐
- docker学习笔记13:Dockerfile 指令 WORKDIR介绍
Dockerfile中的WORKDIR指令用于指定容器的一个目录, 容器启动时执行的命令会在该目录下执行. 相当于设置容器的工作目录了.我们来看一个dockerfile文件 #test FROM ub ...
- 查看死锁原因 /data/anr/traces.txt
Android ANR这个错误大家并不陌生,但是从Android 2.2开始出错的ANR信息会自动上传给Google进行系统分析改进,当然了你的应用ANR错误其实保存在一个文件中,在/data/anr ...
- WebView使用详解
一.用WebView处理页面导航 可以加载本地资源也可以加载web资源,区别是我们要加载本地资源要实现在assets文件夹里添加一个.html资源.调取网页的时候可以用loadUrl方法把网址添加进去 ...
- c: c代码书写规范
排版: 较长的语句或函数过程参数(>80字符)要分成多行书写, 长表达式要在低优先级操作符处划分新行,操作符放在新行之首, 划分出的新行要进行适当的缩进,使排版整齐,语句可读 参考: 1. 运算 ...
- Source Insight使用技巧
1. source insight必设: option-->key assignments--> Edit: Delete Line ---- Assign New Key: Ctr ...
- mysql设置root密码
1.停止mysql服务.可以在windows服务管理器设置,运行->services.msc->停止mysql服务 2.跳过权限验证: mysqld -nt --skip-grant-ta ...
- android APP 中微信分享功能实现 的总结
//花了很长时间最终完成了微信分享功能,中间走了很多弯路,在此做一下小结,希望对在应用中使用到微信分享的朋友有所帮助. 主要问题就是下面两个: 1.为什么运行了项目之后,微信分享只是闪了一下就没有了? ...
- Win8.1应用开发之动态磁贴
using demo02.Common; using System; using System.Collections.Generic; using System.IO; using System.L ...
- WM_PAINT消息在窗口重绘的时候产生,那什么时候窗口会重绘(异步工作方式效率高、灵活性强,还有UpdateWindow和RedrawWindow帮忙)
Q:wm_paint消息在窗口重绘的时候产生,那什么时候窗口会重绘?? A: 严格地说,只有当收到WM_PAINT消息后窗口会重绘 但是引起这个消息的事件有很多, 比如:1.首次创建 2.移动 3.改 ...
- 【linux】UBUNTU 12.04下傻瓜式简单安装arm-linux-gcc等gnu arm toolchain交叉编译工具
欢迎转载,转载时请保留作者信息,谢谢. 邮箱:tangzhongp@163.com 博客园地址:http://www.cnblogs.com/embedded-tzp Csdn博客地址:http:// ...