operator拓展
前言
优化一下之前重载的时候 +
就是让hstring + 1234也能实现,不过要对后面的数进行转换,且在不使用三方函数。
正文
正常的一串数字123456
跟char之间的联系,其实就要看ASCII码了。
可以看到字符0的二进制数是48,其它都是在48基础上+
那么转换的思路就明确了。
1 | int a = 12345; |
再然后肯定要通过循环,for和while其实都差不多,但是都有一个痛点
1 | while (a!=0){ |
一开始傻瓜式写法,都不知道自己怎么想的。。。。
- int i=0;放在循环里面,每次都是从0开始覆盖,没有意义
- 不一定要强转,编译器有隐转
- while的条件倒也惨白,里面a%=10,如果最后一位是1,就死循环了。
所以有的时候脑子真的晕乎乎,修改一下
1 | int i = 0; |
这样就行了。强转之类的不是必要的问题不大啊。
负数的问题
无非就是前面多个-
号
而且我们这里本身最后还要倒转,所以在循环结束的时候判断一下是否小于0,
1 | if (a < 0) str[i++] = '-'; |
加上这个就完事。
但是运行的时候就会发现毛病。因为负数,取模运算就搞事情了,+48也得不到那个字符。
所以要先给他反转。
然后 a<0这个预计要用两次,而且第二次的时候a已经反转成正数了。
所以可能要提前放在一个布尔变量里。
1 | int a = -12345; |
跑了一遍也没啥问题,ok。
然后反转一下。
也需要额外定义一个变量。
1 | int a = -12345; |
这个i下面又用到了,所以改了下名字。
也是成功反转了。
不过依照优化而言,他还是有很多地方
1 | int a = -1225475; |
这种倒写倒是省了一个变量和循环。
抛开if,有些地方优化其实都是数学上的优化,需要逻辑思维比较好的。if (flag) a = -1 * a;
像这个用负负得正的思想,但其实a的值无外乎 -1 /0 1 ,
flag这个a < 0;人的思维更偏向于 a >= 0;
布尔值在c/c++也就是0 和 1;
那么不使用if,让负数变成正数,就要a*-1,但是正数不变,或者就是*1
a是输入项,关键就在于-1和1怎么来的。
前面的布尔值0 1,要转变成1 -1,让这个值*2 - 1, 当布尔值为1时,1*2-1还是1,当布尔值为0时,0*2 - 1就等于-1了。
1 | bool flag = a >= 0; |
这样第一个if就省掉了。
1 | if (flag) str[--len] = '-'; |
像第二个if就不是很好省略啊。按我个人肯定做不出来了。
套用老师的做法
目前flag就两种情况,0 1
0的时候 len的长度肯定因为没有符号位-1,去放这个符号位
1的时候 len不变,
0的时候 要加上-
1的时候 不需要
0的时候 ‘-‘ * (flag+1)*(1-flag) + str[len] * flag
1的时候 ‘-‘ * (flag+1)*(1-flag) + str[len] * flag
这种操作,就是负数的时候1-0=1 保住前面的’-‘
而正数的时候1-1=0 前面的’-‘就被舍弃了。
转换成代码
1 | str[len = len - 1 * (1 - flag)] = '-' * (flag + 1) * (1 - flag) + str[len] * flag; |
u1s1,这个逻辑我要理好久。。。。
不过效果是ok的
不过在测试的时候发现了个问题,是我之前测试的时候都没注意的就是a=0的时候
因为while的条件就是a,当a=0的时候,他压根没进去。
所以按照必定先执行一次的惯例,就要使用dowhile。
这样的话a=0的时候就也能够输出了。
1 | int a = 0; |
后面的处理真的不是我这个二愣子看得明白的。。。
封装到我们的类里面
1 | hstring &hstring::operator+(int _val){ |
如果要扩充长度记得修改str的长度,还有最后memcpy的时候的长度-len
有效长度就是在12以内含符号。
long 在win下也就是四字节范围跟int差不多
longlong的范围9223372036854775807,反正在这里也就是修改一下str的长度和len的长度。
浮点数先不考虑,因为存在精度缺失的问题。后面的位数算多了不一定是对的。
反正这种重写操作,要么挨个类型写,要么用模板。这里暂时不搞了,先抓紧复习完进度。
结语
数学。。太弱了,在这方面不占优势。纯纯码农了属于是。