编码
在计算机中,任何东西都是二进制数据,那么,我们在屏幕上看见的字符是怎么被识别的呢?
这要依托于一套特定的编码,将二进制数据映射成字符
ascll编码是目前应用比较广泛的,所以这里我们讨论的大小写转换基于ascll编码体系(事实上后面大多数编码都是兼容ascll编码的)
ASCLL编码
ASCII 码表
ASCII 值 | 控制字符 | ASCII 值 | 控制字符 | ASCII 值 | 控制字符 | ASCII 值 | 控制字符 |
0 | NUL | 32 | (space) | 64 | @ | 96 | 、 |
1 | SOH | 33 | ! | 65 | A | 97 | a |
2 | STX | 34 | ” | 66 | B | 98 | b |
3 | ETX | 35 | # | 67 | C | 99 | c |
4 | EOT | 36 | $ | 68 | D | 100 | d |
5 | ENQ | 37 | % | 69 | E | 101 | e |
6 | ACK | 38 | & | 70 | F | 102 | f |
7 | BEL | 39 | ' | 71 | G | 103 | g |
8 | BS | 40 | ( | 72 | H | 104 | h |
9 | HT | 41 | ) | 73 | I | 105 | i |
10 | LF | 42 | * | 74 | J | 106 | j |
11 | VT | 43 | + | 75 | K | 107 | k |
12 | FF | 44 | , | 76 | L | 108 | l |
13 | CR | 45 | - | 77 | M | 109 | m |
14 | SO | 46 | . | 78 | N | 110 | n |
15 | SI | 47 | / | 79 | O | 111 | o |
16 | DLE | 48 | 0 | 80 | P | 112 | p |
17 | DCI | 49 | 1 | 81 | Q | 113 | q |
18 | DC2 | 50 | 2 | 82 | R | 114 | r |
19 | DC3 | 51 | 3 | 83 | S | 115 | s |
20 | DC4 | 52 | 4 | 84 | T | 116 | t |
21 | NAK | 53 | 5 | 85 | U | 117 | u |
22 | SYN | 54 | 6 | 86 | V | 118 | v |
23 | TB | 55 | 7 | 87 | W | 119 | w |
24 | CAN | 56 | 8 | 88 | X | 120 | x |
25 | EM | 57 | 9 | 89 | Y | 121 | y |
26 | SUB | 58 | : | 90 | Z | 122 | z |
27 | ESC | 59 | ; | 91 | [ | 123 | {undefined |
28 | FS | 60 | < | 92 | \ | 124 | | |
29 | GS | 61 | = | 93 | ] | 125 | } |
30 | RS | 62 | > | 94 | ^ | 126 | ~ |
31 | US | 63 | ? | 95 | — | 127 | DEL |
字母编码之间的关系
十进制关系
看到上面的编码表之后,发现a-z与A-Z之间分别是连续的,编码值是递增的
所以实际上会存在这种关系:
1 | 'a'+1 == 'b' |
嗯,这很容易就能看出来
然后比较大小写字母
我们很容易就会以为,大写字母的值会要比小写字母的值大,其实并不是,从上表就可以看出
‘A’ = 65 a=’97’
很明显,大写字母的值要小于小写字母的值,而且上面提到过,大小写字母的编码值是连续的,且排序在后面要大于排序在前面的
所以:
每个大写字母总是比相对应的小写字母要小‘a’ - ‘A’的值,也就是32
自然,我们在转换的时候就可以通过加减32来实现大小写转换
1 | char a = 'a'; |
1 | ➜ cpp .\a.exe |
或者说加减(‘a’-‘A’)
1 | char g = 'g'; |
1 | ➜ cpp .\a.exe |
tip:’b’ - ‘B’ ‘c’ - ‘c’ 之类的也是可以的,就不再细说举例了
当然,这么做还有个缺点,我们不能盲目地加减,我们必须还要判断其为大写还是小写,因为大写减去32将不再是字母,同理,小写加上32也不再是字母
二进制关系
那么大小写字母为什么不编码在连续的位置的呢,谁知道呢,我只知道这么编码可以为我们进行大小写转换提供捷径,你不信?来看看
我们来列举几个大小写的二进制值看看(你可以对照上面的表自己算一下,或者用win系统自带计算器的程序员模式)
字母 | 十进制 | 二进制 |
---|---|---|
A | 65 | 01000001 |
a | 97 | 01100001 |
B | 66 | 01000010 |
b | 98 | 01100010 |
Z | 90 | 01011010 |
z | 122 | 01111010 |
眼睛尖一点,你会发现对应的大小写字母,只是从左向右看第3位不同,其他位完全相同。大写字母这一位是0,小写字母这一位是1,而这一位正好是第6位,所以大小写之间差了32($2^5=32$)
这有用吗?非常有用!他们只有一位不同,我们完全可以利用位运算符来对这一位进行操作来达到大小写转换的目的
&,|
先提一下&,|的小性质
每一位&1,结果不变,&0则为0
每一位|0,结果不变,|1则为1
小写转大写
对于小写字母,我们可以用”&”将第5位变成0:
1 | char a = 'a'; |
1 | ➜ cpp .\a.exe |
大写转小写
对于大写字母,我们可以用”|”将第5位变成1
1 | char A = 'A'; |
1 | ➜ cpp .\a.exe |
这么做很快捷,简单,相比于上面的方法还不用判断大小写,为什么这么说?
一个字符转大写的时候,就算它本身已经是大写了,它的第5位是0,0&0会怎么样,还不是0,等于说没有变
小写类似,1|1也是1,并没有改变
大小写互转
那如果要大小写互转呢?那就使用异或操作符^
^执行半加操作,怎么理解?就是在那一位执行加法,但是不进位。
也就是说,0^0=0,0^1=1,1^0=1,1^1=0
再直白一点,^0就是不变,^1就是取反
只要在那一位^1,就能实现将0变为1,1变为0,从而实现大小写转换
1 | char A = 'A'; |
1 | ➜ cpp .\a.exe |
应用
可以用宏定义封装一下(不封装也行,只是可读性会变差),进行快速转换,可以简化代码结构,提高效率
1 |
|
1 | ➜ cpp .\a.exe |
- 本文作者: 汤圆
- 本文链接: https://littlesun.cloud/2022/01/01/位运算实现字母的大小写转换/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!