由leetcode “转换小写字母”引发的思考(位运算符转换字母大小写)

有关于练习题

转换小写字母链接

普通方法

  1. 开始想把字符串给dst
    竟然用了 char* dst=str;
    …给是给了,但是不能对字符串进行操作。因为dst指向常量区。str在形参里是char*,
    但是在main函数里是数组形式,因为测试代码的时候他可以改变。

  2. 然后我想了创建一个字符串数组,用了这样的代码

char dst[100] = "";
	strcpy(dst, str);
	int n = strlen(str);
	for (int i = 0; i < n; i++)
	{
		*str = *str + 32;
//A B C D E
		str++;
//B C D E
//C D E
....
//E
	}

脑子又抽了,那你str走到最后,你返回了个啥。返回了个空

  1. 为什么不直接用这个数组进行解决
char * toLowerCase(char* str){
int n=strlen(str);
for(int i =0;i<n;i++)
{
    //必须是A到Z之间才转换小写
    if(str[i]<='Z'&&str[i]>='A')
    {
     str[i]=str[i]+32;
     }
 
}

return str;
}

必须要经常回忆,不然忘光了

位运算方法

在这里插入图片描述

大写转小写,小写转大写

每个字母的大小写相差32,就是 2 5 2^5 25用二进制表示是0100000

那么A的ASCII值为65, 2 6 + 1 2^6+1 26+1
二进制为1000001
a的ASII值为97, 2 6 2^6 26+1+ 2 5 2^5 25
二进制为:1000001(65) + 0100000(32)=1100001 (97)
A与a,二进制只有第6位不一样,可以用异或运算符。
A的第一位是1,32的第一位是0,A的第6位是0,32的第6位是1,A的最高位是1,32最高位是0。相异为真,A的第一位本来就是1,第6位变成1,最高位本来就是1。A变成a。 (因为32的二进制只有第6位是1)。
所以A转换成a,还可以用A=A^(1<<5)=a
同理a转换成A,可以用a=a^(1<<5)=A,与上面的原理一样

题解:由于是一个字符串,先求出长度,然后循环长度次,对每一个字符进行操作。对于本题只需要大写字符转换小写,写一个if条件判断就好了。大写进行操作,小写就不动

char * toLowerCase(char* str){
int n=strlen(str);
for(int i =0;i<n;i++)
{
   
     if(str[i]<='Z'&&str[i]>='A')
    {
     str[i]^=32;
     }
    
}

return str;
}

大写转小写,小写转小写

还是以A与a为例。
A:1000001
a: 1100001
32: 0100000

A=A | 32 =a;
a=a | 32 =a;

这样写的好处是,不需要写if语句进行判断,统一处理,小写不变,大写变小写。

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

return str;
}

练习题变形

假如有道题,让小写变成大写。还是一样三种方法:

普通方法

if语句变成在小写字母的范围内

for(int i =0;i<n;i++)
{
if(str[i]<='z'&&str[i]>='a')
    {
     str[i]=str[i]-32;
     }
}

位运算方法

大写转小写,小写转大写

A=A^32=a
a=a^32=A

for(int i =0;i<n;i++)
{
if(str[i]<='z'&&str[i]>='a')
    {
     str[i]^=32;
     }
}

小写变大写、大写变大写

还是以A与a为例。
A:01000001
a: 01100001
-33: 10100001

负数必须和他的补码进行运算

-33(取反):11011110(除符号位之外逐位取反)
-33(补码):11011111(+1)
&:全1则1。
A&-33(补码)=01000001
A=A&-33(原码)=01000001=A
晕了,已经是正数了,还在求人家的原码
A&-33(取反)=00111110
A&-33(原码)=00111111

前面算了-33补码,这里直接用

a=a&-33(补码)=01000001=A
所以
A=A&-33=A
a=a&-33=A

for(int i =0;i<n;i++)
{
  str[i]&=-33;
}

返回局部变量的地址,回忆并对比引用做返回值

在vs 2013编一个代码时,最后失误返回了一个数组名,这个数组是在函数里开的一个局部变量,相当于我返回了数组第一个变量的地址。所以编译器发出警告。
在这里插入图片描述
我们知道实际返回是这样一个过程,临时变量在中间做值拷贝.p出了函数所指向的地址被释放掉了,临时变量的指针还在指,就成了悬空指针。
在这里插入图片描述
那么如果p是malloc出来的变量,我返回p,就是返回堆上的地址,是可以的,不过需要你自己用完之后释放内存,指针不用还要置空。

C++引用做返回值的话p到临时变量不用拷贝)突然想起来C++中引用,
点这个链接,目录里有个引用做返回值可以详细回忆

点这 二级指针也可以在看看

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楠c

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值