项目场景:
while作为以条件真假来判断循环主题是否进行的函数常在不知道循环次数时使用,通常和字符串函数一起出现,本篇试图通过返回值和符号优先级实现“此时无声胜有声”
char* my_strcpy(char* dest,const char* stc)
{
assert(stc&&dest);
char* ret = dest;
while (++*dest!= 0);
while (*dest++ = *stc++);
return ret;
}
以上是strcpy的实现,孤独的while已经实现了所有事情,小问号你是否有很多朋友?
下面将介绍while语句的一些简(tou)洁(懒)写法,最后我们将分析上面的代码。
材料补充
1.优先级
第1优先级:各种括号,成员运算符 . ;
第2优先级:所有单目运算符,如++、–、!、~等;
第3优先级:乘法运算符*、除法运算符/、求余运算符%;
第4优先级:加法运算符+、减法运算符-;
第5优先级:移位运算符<<、>>;
第6优先级:大于运算符>、大于等于运算符>=、小于运算符<、小于等于运算符<=;
第7优先级:等于运算符==、不等于运算符!=;
第8优先级:按位与运算符&;
第9优先级:按位异或运算符^;
第10优先级:按位或运算符|;
第11优先级:逻辑与运算符&&;
第12优先级:逻辑或运算符||;
第13优先级:三目条件运算符 ?: ;
第14优先级:各种赋值运算符,如=、+=、-=、*=、/= 等;
第15优先级:逗号运算,
同一优先级一般采用从右到左(有例外)
2.返回值(博大精深不全部列举了)
a,b----->返回a
逗号运算符只返回逗号前的数
a=b----->返回b
赋值运算返回的赋值
......
while的缩短
第一阶段:空字符串,‘\0’和布尔值中的假等价。涉及到判断非空,判断是否为0,判断字符串是否结束都可以应用。
//一代代码 while(m==0); while(*p=='\0'); while(pi!=NULL); while(*p!='\0') //简化后如下 while(!m); while(!(*p)); while(pi); while(*p);
这种形式大多数人都已经了解,并且适用面广,在if,assert语句中,用‘0’,‘ ’来代替布尔值的情况也很常见。
步骤1:判断变量值为0或空时()内式子的真假性
步骤2:若为假则在括号中直接放入变量,若为真则需要用“!”或是“not”进行转换
第二阶段:与返回值、优先级结合的while语句
//原版 while(*str) { str++; count++; } while(*dest==*src) { *dest++; *src++; } //改版 while(*(str++),count++){;}//返回“,”前的值 while(*dest++==*str++){;}//赋值运算返回*str的值
这里需要注意一个点,*和++的优先级在不同编译器里面有所不同,最好用()明确运算的顺序,以免产生歧义报错
那么整这些幺蛾子有什么用呢,本文给出的例子循环结构比较简单,看上去并没有必要用这种方法,似乎还一定程度上减少了可读性。但这种写法的关键在于:方便查看循环中数值变化。如果在上百行的循环体中藏有一个a++,当有一天你需要将其修改成a+=2时就需要用到查找,如果是将a++,b++,c++,d++......,大面积的替换将更加麻烦。实际上,这种写法就是将循环中的数值变化放在最前面的while条件判断语句中,实现更加简洁的效果。
分析strcpy
char* my_strcpy(char* dest,const char* stc)
{
int count = 0;
assert(stc&&dest);//判断字符串是否存在
char* ret = dest
while (++*dest!= 0);//字符串前的空格(代码健壮性)
while (*dest++ = *stc++);(不断的copy直到赋值“\0”)
return ret;
}
最后的最后我们就可以来看看它了,解析在上面啦。特别提一句,为什么最后需要return ret而不直接return dest呢,因为在dest++的过程中dest指向的已经是字符串末端了,我们需要返回原来字符串开始时的地址!
OK!债见!