leetcode入门刷题笔记(3)-C/C++ | ASCII

转换成小写字母-ASCII码

来源:力扣(LeetCode)[题源链接]
题目:给你一个字符串 s ,将该字符串中的大写字母转换成相同的小写字母,返回新的字符串。

示例 :
输入:s = “Hello”
输出:“hello”

我们先提前预知一下,ASCII码大写字母转小写字母可以用或与 |=32来转化,后面会解释。

小白尝试1(不通过):

char* toLowerCase(char* s) {
    int len = strlen(s);
    for(int i=0;i<len;i++)
    {
        *s |= 32;
        s++;
    }
    return s;
}

*s |= 32;
这行代码只能让s字符串的第一个字符大小写转化
s++
s++,是自加sizeof(s)的大小,执行完s++之后,指向的是s所占大小的下一个字节,而不是s的下一个字符,所以不能直接s++来修改下一个字符

尝试2(通过):

char* toLowerCase(char* s) {
    int len = strlen(s);
    char *p = s;
    for(int i=0;i<len;i++)
    {
        *p |= 32;
        p++;
    }
    return s;
}

char *p = s;
定义了一个char类型指针*p指向s字符串的地址s
p++
自加一个char类型大小,每次自加后依次指向下一个字符的地址

不另外定义一个指针也可以,用数组来表示
尝试3(通过):

char* toLowerCase(char* s) {
    int len = strlen(s);
    for(int i=0;i<len;i++)
    {
        s[i] |= 32;
    }
    return s;
}

或是用语言的API
官方解答:

char * toLowerCase(char * s){
    int len = strlen(s);
    for (int i = 0; i < len; ++i) {
        s[i] = tolower(s[i]);
    }
    return s;
}

ASCII字母位运算技巧

在ASCII码中,A-Z对应65-90(十进制),a-z对应97-122,其大小写之间刚好相差32,即相差10 0000(二进制)
手推一下A、Z、a、z的二进制,可以发现因为刚好相差32,他们大小写之间的(二进制),只有第六位是0和1的差别!
运行以下代码

#include <stdio.h>
int main() {
	char string[] = "ABCabc";
	string[0] += 32;
	string[1] |= 32;
	string[2] ^= 32;
	string[3] -= 32;
	string[4] &= -33;
	string[5] ^= 32;
	for(int i=0; i<6; i++)
		printf("%c",string[i]);
    return 0;
}

输出打印结果为

abcABC

经过推理,可以得知

大写变小写、小写变大写:字符 ^= 32
大写变小写、小写变小写:字符 |= 32
大写变大写、小写变大写:字符 &= -33

关于&=-33,涉及到补码,其二进制同~32

只有26字母,为什么大小之间的ASCII差值是32,而不是26?

转载于力扣@疯子 跳转链接
因为字母大小之间的切换是一个很高频的行为,在设计ASCII表时,出于效率的考量,把大小之间的转换需要的 算力 压缩到最小。(关健词:算力)
也就是只需要对一个bit位操作就可以实现大小写之间的切换。
如何压缩算力

如:

int n = 0b100;
n ^= 0b011;

n 最终等于 0b111。虽然只进行了一次 异或 操作,但是对于最底层的 异或 逻辑,是需要对各个bit分别进行一次 异或运算 最终把 3次 的异或累加返回。

同样的逻辑,对应到字母大小之间的切换,每次只需要 1次位操作 就可以得做到大小写切换。(关键词:1次)
从而把大小之间转换的代价压缩到最小。
是的,ASCII里面的字母序是经过细心设计出来的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值