P10
赋值运算符、条件运算符以及逗号运算符
逗号表达式又称为“顺序求值运算符”,它是所有运算符中级别最低的,它的作用基本就是连接语句。
条件运算符的表达式如下:
Exp1?Exp2:Exp3;
我们举一个栗子:
max=(ab)?a:b;
相等于
if(ab)max=a;elsemax=b;
需要注意,条件运算符的结合方向与赋值一样是自右至左。
常见的复合赋值运算符:
+=加法赋值-=减法赋值*=乘法赋值/=除法赋值%=模运算赋值=左移赋值=右移赋值=位逻辑与赋值
=位逻辑或赋值^=位逻辑异或赋值[1]
那么以下两端代码b的值会一样吗?
答案是第一段会得到意想不到的结果,而第二段会输出。
为什么呢?第一段中没有对b的类型定义(本来就是不合法的),所以输出的值是一个int的值与short值相加,结果取决于当前计算机的环境。
而第二段的复合赋值运算会将结果强制转换成short,而不会出现错误。
P11
然后我们来讲讲C++中的四大语句(while、for、if和which)
我们借用《算法导论》里的一个例子引入循环的话题:
假设你有一堆无序的扑克牌(可以存在最好和最坏的情况,即已经是自然顺序和完全逆序),你要做的就是将桌面上的排整理成自然顺序,我们采取的是一种叫插入排序的方法:从桌上不断抽取排码在手上,从第二张牌开始,比第一张牌大就放在牌的后面,否则就放在牌的前面。
一个好的编程习惯就是在写一段代码之前写一段伪代码,这个伪代码可以由你自己制定规则,它并不能在计算机上运算,但却能给你提供清晰的思路以便于快速的转换成你需要的语言。
我们发现,每次抽牌这个动作是重复的,我们可以用一个循环来解决它,抽取的牌应该从第二张开始,因为第一张无论是什么牌对最后结果都没有影响。另外,每次抽完牌与手牌(大于两张)比较时会有两种情况,而每次比较的步骤也是重复的,但比较仅在当前牌前后进行,与下一张牌没有关系,我们可以采用一种有别于抽牌的循环完成任务。
以我们上面的背景为例,我们大致可以写出这样的伪代码:
此处的A是一个数组,而A.length与类的概念相似,表示A中数组元素的个数,A[i]表示数组中第i个元素。尽管这是一段伪代码,但已十分接近C的语法。
伪代码中出现了while循环,它的规则是:
while(condition)
{
statement
}
包围statement的花括号不是必须的,当只有一个执行句时可以去掉。
当condition为真,就执行statement,否则就跳出循环,statement中可以包含改变condition的语句,不过我们有时可以用for来代替。另外需要注意的是,condition的条件需要初始化,否则while循环就无效了。
while循环还有三个特殊用法:break、continue和return
break用于中断退出当前循环;contine用于继续接下来的循环;return用于跳出函数体,使函数返回;
break仅仅是结束循环,但循环外的语句会执行,而return连循环外的内容也不执行。
for循环可以说是while循环的加强版,因为statement中带有一个计数器变量的情况非常非常多见。for语句的规则如下:
for(init-statement;condition;expression)
statement
你可能还想起了另一种循环do-while,但它通常可以改写成for的形式,它的规则如下:
do{
statement
}
while(condition);
我们可以来比较一下:
while和for循环还常常用于读取不定的输入数据,有时会用来做数据类型转换(转换为bool型,通常0为flase,非零数为ture),我们可以用文件结束符来结束输入:在Windows为Ctrl+Z,Linux中为Ctrl+D(在Terminal里也一样,万一shell崩掉了可以用结束符停止)
在条件判断上,我们有if和switch,if语句的用法太简单了,所以我就不说了,switch的规则如下:
switch(expression){constantcase1:statement1;constantcase2:statement2;......default:statement;}
要注意的是,switch语句中的分号千万不能漏写,另外break常常与case1:statement1;连用,用于跳出循环。