这个自定义的 toupper() 函数是如何工作的?

How this custom toupper() function works?

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

这个函数具体是怎么工作的?我无法理解其背后的逻辑。如果有人简单地解释它会很好。

ASCII table 之后,要将字母从小写转换为大写,您需要从小写字母的 ASCII 值中减去 32

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

中所做的
 *(str + index) &= ~32;

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

FWIW,这是 "resetting" 一个特定位的特例,用于获得实际减去 32 的结果。这个 "subtraction" 在这里工作基于小写字母 ASCII 值的特定位表示.如评论中所述,这不是一般的减法方式,因为此 "resetting" 逻辑不适用于 any 减法值。

关于使用的operators

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

注意:此自定义函数缺少对 str 中存在的(无效)有效值的错误检查。你需要照顾好它。

要理解这一点,我们必须查看字母的 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,也就是关掉00100000位。

现在,关闭某个位的标准方法是对一个掩码进行按位与操作,其中在您要关闭的位的位置为 0,在其他位置为 1。所以我们要的mask是11011111。我们可以将其写为 0xdf,但本例中的程序员选择通过编写 ~32 来强调它是 00100000 的补充掩码。 32 的二进制是 00100000.

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

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

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

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