C++ primer plus 第五章:循环和关系表达式
目录
一、for循环
- for循环的组成:for(initialization;test-expression;update-expression)
如:for (i = 1 ; i < 10 ; i++){body}
- i 的声明可以在for中进行:for (int i = 1 ; i < 10 ; i++)
这样声明的 i 是一个局部变量,只在for循环体内有效,后文会详述局部变量。
- 赋值表达式有值,值为左边成员的值:
22 + 27 的值是49
x = 20 的值是20
maids = (cooks = 4) + 3的值为7
- <<运算符的优先级比算数运算符高,因此要使用括号:cout << (x = 4) << endl;
- 修改步长:i ++ 和 i -- 的步长都是1,for允许用户使用其他表达式来代表步长,如
int by = 2;
for (int i =1; i < 10 ; i = i + by)
- 递增运算符(++)和递减运算符(--)
- 前缀格式和后缀格式(以++为例,--同理): ++ i 和 i ++
一般来说,前缀格式意味着先对 i 加 1 ,再参与运算,
如:int i = 10;
cout << ++ i;
输出值为11。
后缀格式意味着先让 i 参与运算,再对 i 加 1。
如:int i = 10;
cout << i ++;
cout << i;
输出值为10和11.
优先级:前缀递增(递减)和指针解除引用运算符优先级相同,以从右到左的方式进行结合;后缀递增(递减)比前缀运算符优先级高。
例,声明:
double arr[3] = [21.1,22.3,23.5];
double *pt = arr;
对于:*++pt; 先对pt递增一次,再将*运用于pt,值为22.3
对于:++*pt; 先将*运用于pt,再对*pt递增一次,值为22.1
对于:*pt++; 先对pt递增一次,再将*运用于pt,值为22.3
- 副作用和顺序点
副作用指表达式对变量做出了修改的行为,顺序点是程序执行时的一个点,要确保在每个顺序点前的副作用都发生了才能继续执行。
如:int i = 9;
while (i++ < 10)
cout << i ;
在这里,while语句的末尾就是一个顺序点,在此之前i ++ 的副作用要确保发生了才会继续执行,因此 i 先以值 9 通过while循环条件判定,再执行 i ++让 i 加 1,然后才进入循环体,输出值为10。
而对于这个例子:y = (4 + x--) + (6 + x++);
顺序点在末尾,x将以当前值执行完这条语句后,先递减一次,再递增一次。所以也可以这么说,后缀格式的递增(递减)运算符将在顺序点之前的其他语句执行完后再依次执行。
- 组合赋值运算符(略)
- 复合语句块和局部变量
复合语句块:for循环体内可以包含多条语句,用花括号包起来。
在复合语句块中定义的变量有以下特点:
- 只在语句块内生效,循环结束后释放
- 若定义的变量名在之前已经使用了,那么在循环执行过程中将发生隐藏(新变量将旧变量藏起来),循环结束后还原。
- 逗号运算符:允许将两条表达式放在同一位置
如:for (i = 0,j = 99 ; i < j ; i ++,j++)
ps : 逗号运算符是一个顺序点
- 关系表达式(略)
二、while循环
- while循环是没有初始化和更新部分的for循环,只有测试条件和循环体。
详细的说它们之间存在三个差别:
- 在for循环中,可使用初始化语句声明一个局部变量,但在while中不可以
- 在for循环中省略的测试条件时,将认为条件是true
- 如果循环体中包括continue,情况会有所不同。(看完第六章后回来补充)
- 编写延时循环:函数clock()可返回程序开始执行后所用的系统时间。头文件ctime定义了一个符号常量CLOCK_PER_SEC,该常量为每秒钟包含的系统时间单位数。ctime将clock_t作为clock()返回类型的别名,这意味着可以将变量声明为clock_t类型。
#include<iostream>
#include<ctime>
int main()
{
using namespace std;
cout << "Enter the delay time,in seconds: ";
float secs;
cin >> secs;
clock_t delay = secs * CLOCKS_PER_SEC; //将延迟时间秒数转换为系统时间
cout << "starting\a\n";
clock_t start = clock(); //开始循环时的时间
while(clock() - start < delay)
; //就算循环体为空也要写上分号
cout << "done \a\n";
return 0;
}
该程序以系统时间单位为单位(而不是以秒为单位)计算延迟时间,避免了在每轮循环中将系统时间转换为秒。
三、do while循环
- do while循环是出口条件循环,至少会执行一次,其他地方与while循环一致
格式为:do
{
body;
}while(test-expression);
四、基于范围的for循环(C++ 11)
- C++ 11新增了一种基于范围的for循环,这简化了一类常见循环问题:对数组(或者容器类,如vector、array)的每个元素执行相同操作。如:
int prices[5] = {1,2,3,4,5};
for (int x : prices)
cout << x << std::endl;
x表示数组prices的第一个元素,之后每执行一次循环体x将表示后一位的元素。
- 如果要修改数组的元素,则应使用以下形式:
for (int &x : prices)
x = x*2;
- 还可以与初始化列表结合:
for (int x : {1,2,3,4,5})
cout << x << " ";
这种循环将在16章中用于讨论各种模板容器类。
五、嵌套循环和二维数组
- 二维数组:int maxtemps[4][5]; //表示一个具有4个元素的二维数组,每个元素都是一个具有5个整数的一维数组
- 二维数组的初始化:
int maxtemps[3][4] =
{
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
- 指针数组:char* cities[2] = {"china city","america city"};
这样声明使得该数组中的每一个元素都是一个char指针,指向一个字符串的首地址。
- 嵌套循环
for (int i = 0; i < m ; i ++)
{
for (int j = 0;j < n ; j ++)
{
body;
}
}
六、循环和文本输入
本节讨论循环完成的最常见的一项任务:逐字符地读取来自文件或者键盘的文本。在C++中cin对象支持3中不同模式的单字符输入,其用户接口各不相同。
- 使用原始的cin进行输入
#include<iostream>
int main()
{
using namespace std;
char ch;
int count = 0;
cout << "Enter characters;enter # to quit:\n";
cin >> ch;
while(ch != '#')
{
cout << ch << endl;
++count;
cin >> ch;
}
cout << count << " characters read";
}
这段代码实现一个这样的功能:从用户端得到输入字符,并回显在屏幕上,直到读取到'#'字符(这种字符称为哨兵字符)停止。这种方式有两个特点:
- cin会忽略空格和换行符,且不会将二者计数。
- 发送给cin的输入会被缓冲,只有按下回车之后才会将输入的内容发送给程序。
- 使用cin.get(char)对上述第一点改进
#include<iostream>
int main()
{
using namespace std;
char ch;
int count = 0;
cout << "Enter characterslenter # to quit:\n";
cin.get(ch);
while(ch != '#')
{
cout << ch << endl;
++count;
cin.get(ch);
}
cout << count << " characters read";
}
cin.get(ch)将会读取输入的下一个字符,包括空格。
- 文件尾条件
上述两种输入方式都存在一个问题,就是哨兵字符可能本身就是输入的一部分。若输入来自于文件,C++提供了一种功能更为强大的技术——检测文件尾(EOF)。
#include<iostream>
int main()
{
using namespace std;
char ch;
int count = 0;
cout << "Enter characters:\n";
cin.get(ch);
while (cin.fail()== false)
{
cout << ch;
++count;
cin.get(ch);
}
cout << endl << count << "characters read\n" ;
return 0;
}
当cin识别到文件尾EOF后,eofbit位和failbit位将被设置为1,通过函数eof()和fail()可以判断这两位是否被设置,若被设置为1,则函数返回true,否则返回false。