我见过以下使用自定义toupper()
功能的程序。
#include <stdio.h>
void my_toUpper(char* str, int index)
{
*(str + index) &= ~32;
}
int main()
{
char arr[] = "geeksquiz";
my_toUpper(arr, 0);
my_toUpper(arr, 5);
printf("%s", arr);
return 0;
}
这个功能究竟如何运作?我无法理解它背后的逻辑。如果有人轻易解释它会很好。
答案 0 :(得分:3)
在ASCII table之后,要将字母从小写转换为大写,您需要从小写字母的ASCII值中减去32
。
对于表示小写字母的ASCII值,减去32,等于ANDing ~32
。这就是在
*(str + index) &= ~32;
从index
获取str
成员的值,减去32(按位与~32
,清除特定位值)并将其存储回相同的索引
FWIW,这是&#34;重置&#34;的一个特例。一个特定的位来得到实际减去32的结果。这个&#34;减法&#34;这里基于小写字母ASCII值的特定位表示。正如评论中所提到的,这不是一种通用的减法方法,因为这将重置&#34;逻辑不会对减法的任何值起作用。
关于使用的operators,
&=
是按位AND ~
是按位NOT。注意:此自定义函数缺少str
中存在的(有效)值的错误检查。你需要照顾它。
答案 1 :(得分:1)
要理解这一点,我们必须查看字母的ASCII表示。在2号基地最容易做到这一点。
A 01000001 a 01100001
B 01000010 b 01100010
C 01000011 c 01100011
D 01000100 d 01100100
... ...
X 01011000 x 01111000
Y 01011001 y 01111001
Z 01011010 z 01111010
请注意,大写字母均以010
开头,小写字母均以011
开头。请注意,对于相同字母的大写和小写版本,低位位都是相同的。
所以:我们需要做的就是将小写字母转换为相应的大写字母,将011
更改为010
,换句话说,关闭{{ 1}}位。
现在,关闭一点的标准方法是对要关闭的位的位置为0的掩码进行按位AND,其他地方为1。所以我们想要的面具是00100000
。我们可以将其写为11011111
,但本例中的程序员选择通过编写0xdf
来强调它是00100000
的补充掩码。二进制32是~32
。
这种技术很好,除了它会用非字母做奇怪的事情。例如,它会将00100000
变为'{'
(因为它们分别具有ASCII代码'['
和01111011
)。它会将星号001011011
转换为换行符'*'
('\n'
转换为00101010
)。
在ASCII中将大小写转换为小写的另一种方法是减去32.这也会将00001010
转换为'a'
(97到65,十进制),但是如果还要转换例如,'A'
到'A'
。在这种情况下,按位AND技术实际上是有利的,因为它将'!'
转换为'A'
(这是转换为大写例程应该执行的操作)。
最重要的是,无论你是和~32还是减去32,在正确安全的功能中,你还必须检查被转换的字符是否是正确的字母开头。
此外,值得注意的是,此技术绝对采用7位ASCII字符集,并且不适用于其他字符集的重音或非罗马字母,例如ISO-8859或Unicode。 (EBCDIC将是另一回事。)