Chapter 6分支语句和逻辑运算符
- 6.1 if语句
- 6.2 逻辑表达式
- 6.2.4 逻辑NOT运算符:!
- 6.3 字符函数库cctype
- 6.4 ?:运算符
- 6.5 switch语句
- 6.6 break 和 continue语句
- 6.7 读取数字的循环
- 6.8 简单文件输入/输出
- 6.9 复习题
- 1. 请看下面两个计算空格和换行符数目的代码片段:
- 2. 在程序清单6.2中,用ch+1替换++ch将发生什么情况呢?
- 3. 请认真考虑下面的程序:
- 4. 创建下述条件的逻辑表达式:
- 5. 在英语中,“I will not not speak”的意思与“I will speak”相同,在C++中, !!x 是否与x相同呢。
- 6. 创建一个条件表达式,其值为变量的绝对值。也就是说,如果变量x为正,则表达式x的值为x;但如果x的值为负,则表达式的值为-x——这是一个正值。
- 7. 用switch修改下面的代码片段:
- 8. 对于程序清单6.10,与使用数字相比,使用字符(如a和c)表示菜单选项和case标签有何优点呢?(提示:想想用户输入q和输入5的情况)
- 9. 请看下面的代码片段:
6.1 if语句
语法:
if(test-conditon)
statement
6.1.1 if else 语句
通用格式:
if(test-condition)
statement
else
statement
6.1.2 格式化if else语句
if else的操作都是一条语句,如果需要多条语句,需要{}括起来
6.1.3 if else if else结构
猜数游戏,程序如下:
// ifelseif.cpp
#include<iostream>
const int Fave = 32;
int main()
{
using namespace std;
int n;
cout << "Enter an number in the rang 1-100 to find ";
cout << "my favourite number: ";
do
{
cin >> n;
if(n > Fave)
cout << "Too high. -- guess again";
else if(n < Fave)
cout << "Too Low. -- guess again";
else
cout << n << " is right.\n";
} while (n != Fave);
return 0;
}
- 条件运算符和错误防范
将variable == value 写成 value == variable
6.2 逻辑表达式
测试多种条件。逻辑OR(||),逻辑AND(&&),逻辑NOT(!)。
6.2.1 逻辑OR运算符:||
C++规定,||运算符是个顺序点,可以先修改左侧的值进行判定,不满足在对右侧的值进行判定。
6.2.2 逻辑AND运算符:&&
将两个测试条件组合成一个条件。
6.2.3 用&&来设置取值范围
- 取值范围测试
if(age > 17 && age <35)
是对的。
if(17<age<35)
,无编译错误,但会计算(17<age)<35
6.2.4 逻辑NOT运算符:!
!运算符对于返回true-false值或可以被解释为true-false值的函数来说很有用。
下面代码实现了筛选可赋值给变量int的数字输入:
// not.cpp -- using the not operator
#include<iostream>
#include<climits>
bool is_int(double);
int main()
{
using namespace std;
double num;
cout << "Yo, dude! Enter an integer value: ";
cin >> num;
while (!is_int(num))
{
cout << "Out of range -- please try again: ";
cin >> num;
}
int val = int (num);
cout << "You have enter the integer " << val << " \nBye\n";
return 0;
}
bool is_int(double x)
{
if(x <= INT_MAX && x >= INT_MIN)
return true;
else
return false;
}
bool is_int()函数限制了取值范围,确定输入有效后,程序将其赋给一个int变量。
6.2.5 逻辑运算符细节
- C++逻辑OR和逻辑AND运算符的优先级都低于关系运算符。
- !运算符的优先级高于所有的关系运算符和算数运算符。
- 逻辑运算符AND的优先级高于逻辑OR运算符
6.3 字符函数库cctype
-
isalpha(ch)
,是字母返回一个非零值,不是返回零,注意不是bool值 -
ispunct(ch)
,是标点符号将返回true, -
isspace()
,是否是空格 -
isdigits()
,是否是数字
6.4 ?:运算符
?:运算符常被用来代替if else语句的运算符,它是C++中唯一需要三个操作数的运算符。
expression1 ? expression2 : expression3
6.5 switch语句
switch 适合从大型列表中选择:
switch(integer-expression)
{
case1 label : statement(s)
case2 label : statement(s)
case3 label : statement(s)
...
default : statement(s)
}
在执行玩一个标签的语句后,因该添加break;否则会继续执行下一个标签的语句,知道遇到break;。
6.5.1 将枚举量用作标签
cin无法识别枚举类型,因此在输入选项时会要求用户输入一个整数。
当switch语句将int和枚举量标签进行比较是,会将枚举量提升为int型。
6.5.2 switch和if else
if else:
- 可以处理取值范围
- 适合选项较少<3使用
switch:
- 每一个标签是一个单独的值
- 适合处理多个选项>=3
- 就代码长度和效率而言,switch语句的效率更高
6.6 break 和 continue语句
break: 跳过循环;
continue: 跳过循环体剩下的代码,开始新一轮循环。
goto: goto paris: 该语句将跳到paris:作为标签的位置
6.7 读取数字的循环
定义一个数字,用户输入一个单词,将发生4种情况:
- n的值保持不变
- 不匹配的输入将被保留在输入队列中;
- cin对象中的一个错误标记被设置
- 对cin方法的调用将返回fasle(如果被转换成bool类型)
输入字符后,想继续输入内容:
if(!cin)
{
cin.clear(); //reset input
cin.get(); // read q
}
cin.get(); //read end of line after last input
cin.get(); //wait for user to press<Enter>
当输入的不是数字时,应采取三个步骤
- 重置cin以接受新的输入
- 删除错误输入
- 提示用户在输入
实现的代码如下:
while(!(cin >> num))
{
cin.clear();
while(cin.get() != '\n')
{
continue;
}
cout << "Please enter a numebr";
}
6.8 简单文件输入/输出
6.8.1 文本I/O和文本文件
如下输入行:
38.5 19.2
不同数据类型的变量存储时,cin如何处理该输入行。
- char ch; cin >> ch;
输入行第一个字符被赋给ch,在这里第一个字符是数字3,其字符编码(二进制)存储在变量ch中,注,存储的不是数值,而是3的编码。
执行完上述语句后,输入队列的下一个字符为8,下一个输入操作对其进行处理。 - int n; cin >> n;
在该情况下,cin将不断读取,直到遇到非数字字符。也就是说,它将读取3和8,这样句点将成为输入队列的下一个字符。cin通过计算发现,两个字符对应数值38,因此将38的二进制编码复制到变量n中。 - double x; cin >> x;
在该情况下,cin将不断读取,直到遇到非浮点数字符。空格成为输入队列的下一个字符。cin通过计算发现,两个字符对应数值38.5,因此将38.5的二进制编码(浮点格式)复制到变量n中。 - char word[50]; cin >> word;
在该情况下,cin将不断读取,直到遇到空白字符。空格成为输入队列的下一个字符。然后cin将这4个字符的字符编码存储到word中,并在末尾加上一个空字符。这里不需要进行任何转换。 - char word[50]; cin.getline(word,50);
在这种情况下,cin将不断读取,直到遇到换行符。所有字符被存储到数组word中,并在末尾加上一个空字符。换行符被丢弃,输入队列中下一个字符是下一行的第一个字符。
6.8.2 写入到文本文件中
文件写入准备:
- 必须包含头文件fstream。
- 头文件fstream定义了一个用于处理输出的ofstream类。
- 需要声明一个或多个ofstream变量(对象),并以自己喜欢的方式对其进行命名,条件是遵守常用的命名规则。
- 必须知名名称空间std;
- 需要将ofstream对象与文件关联起来,方法是使用open()方法。
- 使用完文件后,应使用方法close()将其关闭。
- 可结合使用ofstream对象和运算符<<来输出各种类型的数据。
注:运行open()时,如果文件不存在,将会创建一个文件;如果文件存在,默认会丢失文件原有的内容,然后添加新的输出。
6.8.3 读取文本文件
文件读取准备:
- 必须包含头文件fstream。
- 头文件fstream定义了一个用于处理输出的ifstream类。
- 需要声明一个或多个ifstream变量(对象),并以自己喜欢的方式对其进行命名,条件是遵守常用的命名规则。
- 必须知名名称空间std;
- 需要将ifstream对象与文件关联起来,方法是使用open()方法。
- 使用完文件后,应使用方法close()将其关闭。
- 可结合使用ifstream对象和运算符>>来输出各种类型的数据。
检查文件是否被成功打开的代码:
inFile.open("bowling.txt");
if(!inFile.open())
{
exit(EXIT_FAILUTE);
}
检测文件尾:inFile.eof();
检测输入是否正确,到达文件尾inFile.good();
6.9 复习题
1. 请看下面两个计算空格和换行符数目的代码片段:
// Version 1
while (cin.get(ch))
{
if(ch == ' ')
spaces++;
if(ch == '\n')
newlines++;
}
// Version 2
while (cin.get(ch))
{
if (ch == ' ')
spaces++;
else if(ch == '\n')
newlines++;
}
第二种格式比第一种格式好在哪里?
两个版本给出的答案下同,if else的效率更高。考虑ch为空格的情况,版本1还需要查看ch是不是换行符,而版本2不需要,效率更高。
2. 在程序清单6.2中,用ch+1替换++ch将发生什么情况呢?
替换之后会发生输出的字符与输入的字符一样。
本题考虑的不是运算优先级的问题,而是ch + 1将改变字符的数据类型,变为int将作为int打印。
3. 请认真考虑下面的程序:
#include<iostream>
using namespace std;
int main()
{
char ch;
int ct1,ct2;
ct1 = ct2 = 0;
while((ch = cin.get()) != '$')
{
cout << ch;
ct1++;
if(ch = '$')
ct2++;
cout << ch;
}
cout << "ct1 = " << ct1 << ", ct2 = " << ct2 << "\n";
return 0;
}
假设输入如下(请在每行末尾按回车键):
Hi!
Send $10 or \(20 now!
则输出将是什么(还记得吗,输入被缓冲)?
H\)i\(!\)
\(S\)e\(n\)d$ $ct1 = 9, ct2 = 9
4. 创建下述条件的逻辑表达式:
- a.weight大于或等于115,但小于125
weight >= 115 && weight <125
- b.ch为q或Q
ch == 'q' or ch == 'Q'
- c.x为偶数,但不是26
(x % 2) == 0 && 26 != x
- d.x为偶数,但不是26的倍数
(x % 2) == 0 && (x % 26) != 0
- e.donation 为1000-2000或guest为1
(donation >= 1000 && donation <= 2000) or 1 == guest
- f.ch是小写字母或大写字母(假设小写字母是依次编码的,大写字母也是依此编码的,但在大小写字母间编码不是连续的)
((ch >= 'a' && ch <= 'z') or (ch >= 'A' && ch <= 'Z'))
;
5. 在英语中,“I will not not speak”的意思与“I will speak”相同,在C++中, !!x 是否与x相同呢。
不相同,不一定 x = 5,!!x = 1.;x为bool变量,则!!x = x。
6. 创建一个条件表达式,其值为变量的绝对值。也就是说,如果变量x为正,则表达式x的值为x;但如果x的值为负,则表达式的值为-x——这是一个正值。
x > 0 ? x:-x
(x >= 0)?x:-x
7. 用switch修改下面的代码片段:
if(ch == 'A')
a_grade++;
else if(ch == 'B')
b_grade++;
else if(ch == 'C')
c_grade++;
else if(ch == 'D')
d_grade++;
else
f_grade++;
switch代码如下:
switch(ch)
case 'A' : a_grade++;break;
case 'B' : b_grade++;break;
case 'C' : c_grade++;break;
case 'D' : d_grade++;break;
default: f_grade++;//break;
default需要加break;
8. 对于程序清单6.10,与使用数字相比,使用字符(如a和c)表示菜单选项和case标签有何优点呢?(提示:想想用户输入q和输入5的情况)
- 使用字符,当输入数字时,可以提醒用于错了,重新输入,而使用数字,输入字符会使程序陷入死循环(挂起)。
9. 请看下面的代码片段:
int line = 0;
char ch;
while (cin.get(ch))
{
if(ch == 'Q')
break;
if(ch != '\n')
coutinue;
line++;
}
请重写该代码片段,不要使用break和continue语句。
int line = 0;
char ch;
while (cin.get(ch)&& (ch != 'Q'))
{
if(ch == '\n')
line++;
}