0

我见过以下使用自定义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;
}

这个函数究竟是如何工作的?我无法理解其背后的逻辑。如果有人容易解释它会很好。

4

2 回答 2

3

按照ASCII 表,要将字母从小写转换为大写,您需要32从小写字母的 ASCII 值中减去。

对于表示小写字母的 ASCII 值,减去 32 等于 ANDing ~32。这就是正在做的事情

 *(str + index) &= ~32;

它从 中获取index第 th 个成员的值str,减去 32(与 进行按位与~32,清除特定位值)并将其存储回相同的索引。

FWIW,这是“重置”特定位以获得实际减去 32 的结果的特殊情况。这种“减法”在这里基于小写字母 ASCII 值的特定位表示形式起作用。正如评论中提到的,这不是一种通用的减法方式,因为这种“重置”逻辑不适用于任何减法值。

关于使用的运算符

  • &=是按位与赋值
  • ~是按位非。

注意:此自定义函数缺少对str. 你需要照顾好它。

于 2015-06-28T13:37:34.297 回答
2

要理解这一点,我们必须查看字母的 ASCII 表示。在 base 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。请注意,对于同一字母的大写和小写版本,低位都是相同的。

所以:将小写字母转换为相应的大写字母所需要做的就是将 更改011010,或者换句话说,关闭该00100000位。

现在,关闭位的标准方法是对掩码进行按位与运算,在要关闭的位的位置为 0,在其他任何位置为 1。所以我们想要的面具是11011111. 我们可以把它写成,但是这个例子中的0xdf程序员选择强调它是一个补充掩码。二进制的 32 是.00100000~3200100000

这种技术效果很好,除了它会对非字母做一些奇怪的事情。例如,它将'{'变成'['(因为它们分别具有 ASCII 代码01111011001011011)。它会将星号'*'变成换行符'\n'00101010into 00001010)。

在 ASCII 中将大写转换为小写的另一种方法是减去 32。这也将转换'a''A'(97 到 65,十进制),但 if 也会转换为,例如'A''!'。在这种情况下,按位与技术实际上是有利的,因为它转换'A''A'(这是转换为大写的例程应该做的)。

最重要的是,无论您使用 ~32 还是减去 32,在一个适当安全的函数中,您还必须检查被转换的字符是否是正确的字母开头。

此外,值得注意的是,该技术绝对假定为 7 位 ASCII 字符集,并且不适用于其他字符集的重音或非罗马字母,例如 ISO-8859 或 Unicode。(EBCDIC 将是另一回事。)

于 2015-06-28T14:50:22.017 回答