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

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

时间: 2024-10-19 13:32:41

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

c语言代码编程题汇总 :统计字符串中的大写和小写字母的个数

统计字符串中的大写和小写字母的个数 程序代码如下: 1 /* 2 2017年3月6日19:42:21 3 功能:统计字符串中的大写和小写字母的个数 4 */ 5 6 #include "stdio.h" 7 void fun (char *,int *,int *); 8 9 int main (void) 10 { 11 int m = 0,n = 0; 12 int *Pm = &m, *Pn = &n; 13 char s[100]; 14 printf (&qu

连串字母大写变小写

#include<stdio.h> #include<string.h> int main() { char a[50]; int i,len; i=0; while(gets(a)) { len=strlen(a); for(i=0;i<len;i++) { if(a[i]>='A'&&a[i]<='Z') a[i]=a[i]+32; } puts(a); } return 0; } #include<stdio.h> #includ

word2003字母大写变小写

办法:选中字母区域:然后: 按:shift + F3,可进行大小写切换

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

礼悟:    公恒学思合行悟,尊师重道存感恩.叶见寻根三返一,江河湖海同一体.          虚怀若谷良心主,愿行无悔给最苦.读书锻炼养身心,诚劝且行且珍惜.              ide:visual studio 2017             browser:Firefox / Chrome   bootstrap:3.3.7 代码 <!DOCTYPE html> <html lang="zh-cn"> <head> <meta

MySQL大写和小写问题

近期在将一个windows的mysql数据库转到linux上时,碰到表找不到问题,详细分析了下后发现原来是大写和小写问题. ? 在 MySQL 中,数据库和表对就于那些文件夹下的文件夹和文件. 因而,操作系统的敏感性决定数据库和表命名的大写和小写敏感.这就意味着数据库和表名在 Windows 中是大写和小写不敏感的,而在大多数类型的 Unix 系统中是大写和小写敏感的. ? 奇怪的是列名与列的别名在全部的情况下均是忽略大写和小写的.而表的别名又是区分大写和小写的. ? 要避免这个问题,你最好在定

c语言代码编程题汇总:将字符串中的大写字母转换成小写字母

将字符串中的大写字母转换成小写字母 程序代码如下: 1 /* 2 2017年3月8日21:21:46 3 功能:将字符串中的大写字母转换成小写字母 4 */ 5 /* 6 #include"stdio.h" 7 8 int main() 9 { 10 int n = 0; 11 12 char a[100]; 13 14 printf("please input a string:"); 15 16 gets(a); 17 18 for(int i = 0 ;a[i

在一个字符串中,统计大写字母个数,小写字母个数,其他字符个数的四种算法

题目描述:编写程序,输出字符串中的大写字母.小写小母和其他的个数.如有一个字符串"Helle, This is A test textfile.123456, tannk you!!",则其大写字母个数:3,小写字母个数:29,其他字符个数:18. 这里提供了四种算法,第一种是我们比较好理解的,也属于硬编码问题,其他三种方法要借助JAVA语言的jdk提供的api. 方法一: <!DOCTYPE html> <html lang="en"> &

Css中如何使英文和拼音变成全大写、全小写和首字母大写?

想要实现英文和中文拼音变成全大写.全小写和首个字母大写,需要用到 css中text-transform样式属性,接下来介绍一下 1.text-transform的值 1)Capitalize:英文拼音的首字母大写 2)Uppercase:英文拼音字母全大写 3)Lowercase:英文拼音字母全小写 2.text-transform语法 text-transform:+值类型, 如:text-transform:Capitalize: 3.text-transform的简单使用 1)英文首字母大

传入一个字符串,已知字符串只由字母组成,将其中的大写字母转换为小写,小写转换为大写,返回转换后的字符串

传入一个字符串,已知字符串只由字母组成,将其中的大写字母转换为小写,小写转换为大写,返回转换后的字符串 如传入:@"GOODgoodSTUDY",返回@"goodGOODstudy" */ - (NSString *)upperExchangeLower:(NSString *)str { NSMutableString *str1=[[NSMutableString alloc] initWithString:str]; for (NSUInteger i=0;