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多的结果,说慢的可怕并不为过。在数据量非常大的时候,这样的优化的差异可不是一点点而已。

write by 九天雁翎(JTianLing)
-- blog.csdn.net/vagrxie

C++中字母大写和小写转换实现的优化的更多相关文章

  1. eclipse字母大写和小写转换的快捷键

    大写转换小写 ctrl+shift+y        小写转换大写 ctrl+shift+x   

  2. Excel大写和小写转换函数

    Excel中的大写和小写转换函数 (1).转换为所有小写字母:lower函数 (2).转换为所有大写字母:upper函数 (3).转换为首字母大写,其余小写字母:proper函数 三种函数的使用方式. ...

  3. php实现兼容Unicode文字的字符串大写和小写转换strtolower()和strtoupper()

    前言 网上流传着这么一个腾讯笔试题: PHP的strtolower()和strtoupper()函数在安装非中文系统的server下可能会导致将汉字转换为乱码,请写两个替代的函数实现兼容Unicode ...

  4. 如何将js字符串变成首字母大写其余小写

    有时候会接收到一些大小写不规则的字符串,如"JAMES"."alice"."Amy"等,如何将他们统一的变成首字母大写其余小写的形式呢? 思 ...

  5. double中首字母大写与小写的区别

    Double 是类 double是基础数据类型.Double类型是double的包装类.Double 和double之间的相互转化称为自动拆箱和自动装箱.如果从对象角度理解,那么Double就是对象, ...

  6. Bootstrap3基础 text-uppercase/lowercase/capitalize 字母大写、小写和首字母大写

      内容 参数   OS   Windows 10 x64   browser   Firefox 65.0.2   framework     Bootstrap 3.3.7   editor    ...

  7. shell中把大写字母转换成小写字母

    shell中把大写字母转换成小写字母 参考:http://www.jb51.net/article/40257.htm echo "AABBCC" | tr "[:upp ...

  8. python 练习题:将列表中的大写字母转换成小写

    将列表中的大写字母转换成小写如果list中既包含字符串,又包含整数,由于非字符串类型没有lower()方法,L1 = ['Hello', 'World', 18, 'Apple', None]请修改列 ...

  9. 【转载】C#将字符串中字母全部转换为大写或者小写

    在C#的编程开发过程中,有时候判断字符串是否相等时,并不关注字母的大小写,此时在C#中可以使用ToUpper方法将字符串中所有的字母转换为大写,使用ToLower方法可以将字符串中所有字母转换为小写. ...

随机推荐

  1. 基于Sql Server 2008的分布式数据库的实践(四)

    原文 基于Sql Server 2008的分布式数据库的实践(四) 数据库设计 1.E-R图 2.数据库创建 Win 7 1 create database V3 Win 2003 1 create  ...

  2. maven仓库--私服(Nexus的配置使用)

    maven--私服的搭建(Nexus的使用)和注意的问题 私服是什么 私服,私有服务器,是公司内部Maven项目经常需要的东东,不总结一下,不足以体现出重视.Nexus是常用的私用Maven服务器,一 ...

  3. Android中的Audio播放:控制Audio输出通道切换

    Audio 输出通道有很多,Speaker.headset.bluetooth A2DP等.通话或播放音乐等使用Audio输出过程中,可能发生Audio输出通道的切换.比如,插入有线耳机播放音乐时,声 ...

  4. eclipse上 安装php插件

    首先在安装之前需要有eclipse   以及SDK环境已经搭建好 eclipse开发工具下载路径: http://dl.oschina.net/soft/eclipse java sdk下载路径: h ...

  5. Python3 正则表达式特殊符号及用法(详细列表) http://bbs.fishc.com/thread-57691-1-1.html (出处: 鱼C论坛)

    http://bbs.fishc.com/thread-57691-1-1.html 留待查询用

  6. 【译】在ASP.NET中创建PDF-iTextSharp起步

    原文 [译]在ASP.NET中创建PDF-iTextSharp起步 .Net framework 中自身并不包含可以和pdf打交道的方法.所以,当你需要你的ASP.Net Web应用程序中包含创建或与 ...

  7. perl 面向对象 new方法

    [root@wx03 test]# cat Scan.pm package Scan; sub new{ my $class = shift; my $self={ 'a'=>11, 'b'=& ...

  8. linux查看接口连接状态

    ethtool # ethtool em1 Settings for em1: Supported ports: [ TP ] Supported link modes: 10baseT/Half 1 ...

  9. Deamon Thread 讲解

    The daemon thread's life cycle is same with the life cycle of the application which starts this daem ...

  10. 【剑指offer】字符串转整数

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/28015693 题目描写叙述: 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函 ...