导图社区 C++第5章循环和关系表达式
for循环的组成部分、回到for循环、修改步长、使用for循环访问字符串、基于范围的for循环、do while循环、循环和文本输入等。
编辑于2021-11-02 15:13:44循环和关系表达式
for循环
for循环的组成部分
概述
for(initialization; test-expression; update-expression) body 循环只进行依次初始化(initialization),test-expression(测试表达式)决定循环体是否被执行。update-expression(更新表达式)在每轮循环结束时执行,此时循环体已经执行完毕。
1. 表达式和语句
(1)C++将赋值表达式的值定义为左侧成员的值,因此下面的表达式值为20: x = 20 由于赋值表达式有值,因此可以写下面的语句: madis = (cooks = 4) + 3; 表达式cooks = 4的值为4,因此madis的值为7。然而,我们不鼓励这种做法。但是可以写出下面的语句: x = y = z = 0; 这种方法可以快速的将若干个变量设为相同的值。
(2)像x < y这样的关系表达式将被判定为bool值true或false。下面代码指出了一些有关的重要方面,同时注意到<<运算符的优先级比表达式中使用的运算符高,因此代码中使用括号来调整优先次序: #include<iostream> int main() { using namespace std; int x = 100; cout << (x < 3) << endl; cout.setf(ios_base::boolalpha);// a newer C++ feature cout << (x > 3) << endl; return 0; } 下面是该程序的输出: 0 true 通常,cout在显示bool值之前将他们转换为int,但cout.setf(ios_base::boolalpha)函数调用设置了一个标记,命令cout显示true和false。
(3)从表达式到语句的转变很容易,只要加分号即可。因此下面是一个表达式: age = 100 而下面是一个语句: age = 100; 更准确的说,这是一条表达式语句。只要加上分号,所有的表达式都可以成为语句,但不一定都有意义。例如,如果rodents是个变量,则下面就是一条有效的C++语句: rodents + 6; 编译器允许这样的语句,但它没有完成任何有用的工作(智能编译器甚至可能跳过这语句)。
2. 非表达式和语句
语句 = 表达式 + 分号; 但语句 - 分号 != 表达式。 例如: int a; 这是一条语句,但是 int a 却不是表达式。
3. 修改规则
C++允许这样做: for(int i = 0; i < 5; i++); 也就是说,可以在for循环的初始化部分声明变量。因此for循环的语法也可以修改成这样: for(for-init-statement condition; expression) statement 乍一看这很奇怪,因为只有一个分号,但这是允许的。对于for-init-statement来说,它既可以是表达式语句,又可以是声明。这种语法规则用语句替换了后面跟分好的表达式,语句本身有自己的分号。 在for-init-statement中声明变量还有实用的一面,这种变量只存在于for语句当中,也就是说,离开for语句后,这种变量将消失。
回到for循环
修改步长
使用for循环访问字符串
递增运算符(++)和递减运算符(--)
副作用和顺序点(++和--不要混杂使用)
前缀格式和后缀格式
下面的语句有何不同? x++和++x for(n = lim; n > 0; n--)和for(n = lim; n > 0; --n) 从逻辑上说,在上述两种情况下,使用前缀格式和后缀格式并没有任何区别。它们都是将x加1和n减1,对程序的行为没有任何影响。 但是格式的选择不同,对执行速度可能有细微的差别。对于内置类型和当代的编译器而言,这看似不是什么问题。然而,C++允许针对类定义这些运算符,在这种情况下,用户这样定义前缀函数,将值加1,然后返回结果;但后缀版本首先复制一个副本,将其加1,然后将副本的值返回。因此,对于类而言,前缀版本的效率比后缀版本的效率高。
递增/递减运算符和指针
组合赋值运算符
+= -= *= /= %=
复合语句(语句块)
(1)用两个花括号{}来构造一条复合语句(代码块),它们被共同视为一条语句。
(2)如果在语句块里定义一个新的变量,则仅当程序执行时该语句块中的语句时,该变量才存在。执行完该语句块后,变量将被释放。
其他语法技巧——逗号运算符
使用逗号运算符将两个表达式合并为一个: ++j, --i; // two expressions count as one for syntax purpose
1. 程序说明
2. 逗号运算花絮符
C++的逗号运算符特性
(1)确保先计算第一个表达式,然后计算第二个表达式: i = 20, j = 2 * i; // i set to 20, then j set to 40
(2)逗号表达式的值是第二部分的值。例如,上述语句的值就是40
(3)在所有运算符中,逗号运算符的优先级是最低的: cats = 17, 240; 被解释为: (cats = 17), 240; 也就是说,将cats设置为17,而240不起作用。当然,也可以通过以下方法将cats设置为240: cats = (17, 240);
关系表达式
< <= == > >= !=
赋值、比较和可能犯的错误
musicians == 4的值为true或false,musicians = 4的值为4(for循环中尤为注意)
C-风格字符串的比较
比较string类字符串
循环和文本输入
使用原始的cin进行输入
在读取字符时,cin也与读取其他类型一样,自动忽略空格和换行符。
使用cin.get(char)进行补救
成员函数cin.get(ch)读取输入中的下一个字符(即使它是空格),并将其赋给变量ch
使用哪一个cin.get()
cin.get(name, ArSize); cin.get(ch); ch = cin.get();
文件尾条件(EOF)
使用符号来表示输入结束难以令人满意,因为这些符号可能原本就是输入的合法字符。因此我们可以通过模拟文件输入结束的文件尾条件(EOF,全称end of file)来控制输入结束。 一般来说,键盘上通过Ctrl+Z来模拟EOF,cin一旦读到EOF 便自动结束。但是在有些实现中还需要按下回车键才能终止输入(例如VS、VC等)。 在检测到EOF后,cin将两位(eofbit和failbit)都设置为1.可以通过成员函数eof()来查看eofbit是否被设置;如果检测到EOF,则cin.eof()将返回bool值true,否则返回false。同样,如果eofbit或failbit被设置为1,则fail()成员函数返回true,否则返回false。
1. EOF结束输入
cin.clear()方法可以清除EOF标记,使输入继续执行
2.常见的字符输入做法
基本设计: cin.get(ch); while (cin.fail() == false) { ... cin.get(ch); }
简化判断条件: cin.get(ch); while (!cin.fail()) { ... cin.get(ch); }
方法cin.get(ch)返回的是一个cin对象。istream类中提供了一个将istream对象转换为bool值的函数。当cin出现在一个需要bool值的地方,这个函数将被调用。若最后一次读取成功,则返回true,否则返回false cin.get(ch); while (cin) { ... cin.get(ch); } 这比!cin.fail()或!cin.eof()更通用,因为它可以检测到其他失败的原因,如磁盘故障。
最后,由于cin.get(ch)返回对象为cin,因此可以直接写成这种形式: while (cin.get(ch)) { ... }
另一个cin.get()版本
cin.get() 返回输入中的下一个字符,因此可以这样使用: ch = cin.get(); 当该函数到达EOF时,将没有可以返回的字符。但cin.get()将返回一个用符号常量EOF表示的特殊值。该常量是在头文件<iostream>定义的。EOF值必须不同于任何有效的字符,通常被定义为-1,但不需要知道其具体的值,只用EOF即可。通常可以用以下方法进行输入: while ((ch = cin.get()) != EOF) 这里注意用括号改变优先级次序
嵌套循环和二维数组
初始化二维数组
使用二维数组
基于范围的for循环
C++11新增了一种循环:基于范围(range-based)的for循环:对数组(或容器类,如vector和array)的每个元素执行相同的操作,如: double prices[5] = {4.99, 10.99, 6.87, 7.99, 8.49}; for (double x : prices) cout << x << std::endl; 要修改数组的元素,需要使用以下语句: for (double& x : prices) x = x * 0.80; // 20% off sale 还可以结合使用基于范围的for循环和列表初始化: for (int x : {1, 2, 3, 4, 5}) cout << x * x << " ";
do while循环
语法: do body while(test-expression);
while循环
for与while
for (init-expression; test-expression; update-expression) { statements(s) } for循环改成while循环: init-expression; while (test-expression) { statement(s) update-expression }
while (test-expression) body while循环改成for循环: for (; test-expression; ) body
等待一段时间:编写延时循环
(1)早期方法
long wait = 0; while (wait < 10000) wait++; // counting silently
(2)现用方法
引用头文件<ctime>,它定义了一个符号常量:CLOCKS_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 *CLOCK_PER_SEC; // convert to clock ticks cout << "starting\a\n"; clock_t start = clock(); while (clock() - start < delay); // wait cout <<"Done\n"; return 0; }
(3)类型别名(2种建立方式)
(1)预处理器 #define BYTE char
(2)关键字typedef typedef char byte;