今天跟大家分享的小技巧是关于英文字母的大小写转换的。有时候我们会遇到一些关于字母大小写转换的问题,比如将某一个字符串中的字母转为大写,或转为小写,将Hello World转为HELLO WORLD或是转为hello world。那么我们需要如何来设计程序呢?说到大小写转换,我们自然就想到了将'a'转为'A';将'b'转为'B';将'c'转为'C'……也就是说我们可以遍历字符串中所有的字符,并判断当前字符是'a'、'b'、'c'……的哪一个,然后再把它们转为对应的大写字母'A'、'B'、'C'……具体的程序如下:
char toUpperCase(char ch)
{
if (ch == 'a')
{
return 'A';
}
if (ch == 'b')
{
return 'B';
}
if (ch == 'c')
{
return 'C';
}
......
if (ch == 'z')
{
return 'Z';
}
return ch;
}
我们来这样编写程序从结果上看没有任何问题,但这段程序的运行效率实在太低了,而且26个字母就需要编写26个判断条件,这样的程序过于笨拙。我们换一个角度思考这个问题,先来回顾一下英文字母在ASCII码表中的编码和位置:
|
|
我们注意到A-Z和a-z这些字母都是按顺序编码的,并且同一个字母的大小写编号都差32,也就是说'a'-'A' == 32;'b'-'B' == 32;'c'-'C' == 32; ... 'z'-'Z' == 32。当我们看到这个规律时,大小写转换的问题就变的简单明了了:
于是我们的程序就可以这样来编写:
void toUpperCase(char *p)
{
while (*p != '\0')
{
if (*p >= 'a' && *p <= 'z')
{
*p -= 32;
}
}
}
上面程序是将字符串中的小写字母转为大写字母,对于大写转小写的情况只需要将条件判断处修改成A到Z并将*p -= 32;这里的减号修改成加号修改*p += 32;即可。
这样的程序就比较美观并且高效了,但还有没有更好的办法来解决这个问题呢?我们继续来观察ASCII码表中的编码,可以看到任意一个字母的大写字符和小字符的二进制编码中只有第5个bit位(从右向左依次为第0位、第1位、第2位、第3位、第4位、第5位、第6位、第7位)不同,其它bit位上的数值都是相同的,例如:
0100 0001 A 0110 0001 a
0100 0010 B 0110 0010 b
0100 0011 C 0110 0011 c
也就是说所有大写字母的第5个bit位上都是0,而所有小写字母的第5个bit位上都是1(当初American National Standard Institute制定ASCII码时就是这样巧妙的设计),所以:
于是我们的程序就可以这样来编写:
char toUpperCase(char *p)
{
while (*p != '\0')
{
if (*p >= 'a' && *p <= 'z')
{
*p &= 0xdf;
}
}
}
上面程序是将字符串中的小写字母转为大写字母,对于大写转小写的情况只需要将条件判断处修改成A到Z并将*p &= 0xdf;这里修改成*p |= 0x20;即可。
但是这样的程序看起来还是有一点奇怪:0xdf和0x20不是那么人性化,读起来也不是很好懂,我们可以将其修改为以下形式:
//小写转大写
if (*p >= 'a' && *p <= 'z')
{
//第5个bit位变为0
*p &= ~(1 << 5);
}
//大写转小写
if (*p >= 'A' && *p <= 'Z')
{
//第5个bit位变为1
*p |= (1 << 5);
}
今天的小技巧你学会了吗?
Copyright © 2015-2023 问渠网 辽ICP备15013245号