第五天(循环和关系表达式)

来源:互联网 发布:metismenu.js 编辑:程序博客网 时间:2024/05/16 06:10

   昨天晚上做那个概率论与数理统计习题,做到4点多。恩……挺好,就是这种状态


2011-10-03(Loops and Relational Expressions)

1、由于bool型与整形的相互转换性,for循环体中的判断结构可以是整型。如:
for(int i = 5; i; i--)//i = 0时循环停止{    //body... ...}
2、赋值表达式的值是等号左边的值。即:
                         a = (b = 5) + 6;//a = 5 + 6 = 11
是允许的,不过不提倡。这个性质可解释下面的连续赋值语句:
                         a = b = c = 5;
事实上,C++表达式是值或者值与操作符的组合,每个表达式都有值。
3、副作用(side effect)和顺序点(sequence point)。前面提到,表达式是值或者值与操作符的组合,这就意味着,表达式内可以嵌套表达式。所以当计算某一表达式的时候,它的内表达式可能会被修改,这种修改即为副作用,因为这个修改是我们进行主要操作(计算外表达式)是衍生出来的。
程序是一步一步完成的,可以把每一步看作一个顺序点,程序的完成过程即是按顺序到达每个点的过程。顺序点可以是语句中的分号,也可以是一个完整表达式(完整表达式:不是某个表达式的子表达式),其中while循环中的条件表达式是完整表达式。C++遵循一个原则,进入下一个顺序点之前,之前所有的顺序点都要完成(包括完成顺序点时的副作用)。下面来举几例:
                                 int guest = 9;
                                 while(guest++ < 10)
                                 cout << guest << endl;
guest++<10和cout << guest;都是一个顺序点,进入后者之前,之前的顺序点(guest++<10)必须完成,即打印guest值之前,完成:比较、自增1(副作用)。所以程序打印的是10
                                 y = (4 + x++) + (6 + ++x);
x++和++x是表达但不是完整表达式(它是一个更大表达式的子表达),而上面整个语句是顺序点。在完成这个顺序点时,C++不能保证里面的非完整表达式(x++和++x)完成的先后顺序,只能保证的是,完成这个顺序点之后,x已经自增2了。
4、自增自减和解除引用符(*)的优先问题。
①前缀形式和*优先级相同,右往左运算方式
                        * ++p; //等效于*(++p),即将指针移到后解除引用
                        ++ *p; //等效于++ (*p),即解除引用后自增1
②后缀形式优先级高于*
                        *p++; //等效于*(p++),即将指针移到后解除引用
5、逗号(,)操作符。
                               expression1, expression2
是一个表达式,逗号也可以作为一个操作符,任务是将两个表达式按顺序执行,C++保证先计算第一个表达式再计算后一个(即说,逗号是一个顺序点)。既然是表达式,肯定有返回值:C++中规定,返回值为后一个表达式的值。如:
                      cout << (i = 20, j = i * 2) << endl; //打印的是40
既然是操作符,肯定有优先级:逗号操作符的优先级是最低的:
                      int a = 17, 20; //等效于int (a = 17),20;

6、让程序等待。比如某人在编程时想做到一点:执行某段代码后,过5秒甚至更长时间在执行后面的代码。这里提供了一个办法:C++库中有一个名为clock()的函数,它返回的是程序从开始到调用这个函数时候的时间。原理是这样的,完成代码A之后立即调用clock()并记录其值,而后不断使用循环实时比较当前clock()值和刚记录的值,当两者差值为程序员想要时间时,循环停止,继续执行下面代码。

然而,如果要这样做之前,有两个重要问题要解决:clock()返回的单位不一定时秒;记录时间的变量类型不确定。产生两个问题的原因是不同计算机内部记录时间的方式不同。要解决这俩问题,需使用ctime头文件。这个头文件提供一个常量:CLOCKS_PER_SEC表示每秒里包含的系统时间单位数。举例讲,如果CLOCKS_PER_SEC=5,clock()返回的是15,则程序已经执行了3秒。ctime定义了clock_t作为系统时间单位,这样变量类型就确定了。下面是应用:

#include <iostream>#include <ctime> int main(){    using namespace std;    int timeToWait = 5; //Unit: second    cout << "Start to wait... ...\n";    clock_t startTime = clock() / CLOCKS_PER_SEC;    for(; clock() / CLOCKS_PER_SEC - startTime < timeToWait; );    cout << "... ...End\n";    return 0;}
7、循环分入口条件(entry-condition)和出口条件(exit-condition)。区别在于是否先判断条件再执行循环体。for和while属于入口循环,do-while属于出口循环
8、观察下面程序:
#include <iostream>int main(){    using namespace std;    char ch;    while(true)    {        cin.get(ch);        if(ch == '#')break;        cout << ch;    }}
输入输出如下:
                          This is an# apple
                          This is an
注意到,当ch='#'是应该结束循环,而后面却可以继续输入。原因是,数进给cin的字符会被送到缓冲区,按下回车后输入的内容才会被发送到程序,再进行循环。
9、EOF(End-Of-File)。当行首输入Ctrl+Z(用以模拟一个文件的结尾),可以用成员函数eof()或fail()来检测:输入了,两个函数都将返回true,否则为false。例如,上面的程序第10行判断条件改为:if(cin.eof())break;运行结果如下:

                     Time: 19:02<ENTER>
                      Time: 19:02
                      Time: 19:03<ENTER>
                      Time: 19:03
                      <CTRL><Z>

当然,书写可以更紧凑。因为如果读取最后一次成功了,cin会返回true,否则为false,所以上述的程序可以简化为:

                          if(!cin)break; //Line 9
                          cin.get(ch); //Line 10
一样的输入效果。因为cin.get()返回的是cin,可以再次精简,9、10行合并成:
                          if(!cin.get(ch))break;
输入输出效果一致。也可以将EOF视作一个字符,不过它被定义为-1,ASCII没有-1所以如果要储存它,就要使用整型,即将上面程序修改成:
#include <iostream>int main(){    using namespace std;    int ch;    while(true)    {        if((ch = cin.get()) == EOF)break;        cout.put(ch);    }}
原创粉丝点击