《C++ Primer》第4章 表达式
4.7节 条件运算符
练习4.21:编写一段程序,使用条件运算符从vector<int>中找到哪些元素的值是奇数,然后将这些奇数值翻倍。
【出题思路】
条件运算符使得我们可以把简单的if-else结构嵌入到表达式中,条件表达式可以作为赋值运算符的右侧运算对象。
【解答】
满足题意的程序如下所示:
#include <iostream>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;
int main()
{
vector<int> vInt;
const int sz = 10; //使用sz作为数组的维度
srand((unsigned)time(NULL)); //生成随机数种子
//使用for循环为数组赋初值
cout << "数组的初始值是:" << endl;
for(int i = 0; i != sz; ++i)
{
vInt.push_back(rand() % 100); //生成100以内的随机数
cout << vInt[i] << " ";
}
cout << endl;
//使用范围for循环把数组中的奇数翻倍
for(auto &val: vInt)
{
val = (val % 2 != 0) ? val * 2 : val; //条件表达式
}
//使用范围for循环和迭代器输出数组的当前值
cout << "调整后的数组值是:" << endl;
for(auto it = vInt.cbegin(); it != vInt.cend(); ++it)
{
cout << *it << " ";
}
cout << endl;
return 0;
}
运行结果:
练习4.22:本节的示例程序将成绩划分成high pass、pass和fail三种,扩展该程序使其进一步将60分到75分之间的成绩设定为low pass。要求程序包含两个版本:一个版本只使用条件运算符;另外一个版本使用1个或多个if语句。哪个版本的程序更容易理解呢?为什么?
【出题思路】
条件表达式的作用与if-else语句类似。条件表达式可以嵌套,但是嵌套的层数越少越好,如果嵌套层数过多,则代码的可读性会变得非常差。
【解答】
使用条件运算符实现的程序如下所示:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string finalgrade;
int grade;
cout << "请输入您要检查的成绩:" << endl;
//确保输入的成绩合法
while(cin >> grade && grade >= 0 && grade <= 100)
{
//使用三层嵌套的条件表达式
finalgrade = (grade > 90) ? "high pass"
: (grade > 75) ? "pass"
: (grade > 60) ? "low pass" : "fail";
cout << "该成绩所处的档次是:" << finalgrade << endl;
cout << "请输入您要检查的成绩:" << endl;
}
return 0;
}
运行结果:
练习4.23:因为运算符的优先级问题,下面这条表达式无法通过编译。根据4.12节中的表(第147页)指出它的问题在哪里?应该如何修改?
string s = "word";
string p1 = s + s[s.size() - 1] == 's'?"":"s";
【出题思路】
条件运算符的优先级非常低,因此在使用条件运算符构成复合表达式时必须在适当的地方添加括号。
【解答】
题目中的几个运算符的优先级次序从高到低是加法运算符、相等运算符、条件运算符和赋值运算符,因此式子的求值过程是先把s和s[s.size()- 1]相加得到一个新字符串,然后该字符串与字符's'比较是否相等,这是一个非法操作,并且与程序的原意不符。
要想实现程序的原意,即先判断字符串s的最后一个字符是否是's',如果是,什么也不做;如果不是,在s的末尾添加一个字符's',我们应该添加括号强制限定运算符的执行顺序。
string p1 = s + (s[s.size() - 1] == 's'?"":"s");
练习4.24:本节的示例程序将成绩划分成high pass、pass和fail三种,它的依据是条件运算符满足右结合律。假如条件运算符满足的是左结合律,求值过程将是怎样的?
【出题思路】
假设条件运算符满足的是左结合律,即嵌套的条件运算符从左向右求值。
【解答】
原文的程序是:
finalgrade = (grade > 90) ? "high pass" : (grade < 60)?"fail":"pass";
根据左结合律的含义,该式等价于:
finalgrade = ((grade > 90) ? "high pass" : (grade < 60))?"fail":"pass";
先考查grade > 90是否成立,如果成立,第一个条件表达式的值为"highpass";如果不成立,第一个条件表达式的值为grade < 60。这条语句是无法编译通过的,因为条件运算符要求两个结果表达式的类型相同或者可以互相转化。即使假设语法上通过,也就是说,第一个条件表达式的求值结果分为3种,分别是"high pass"、1和0。接下来根据第一个条件表达式的值求解第二个条件表达式,求值结果是"fail"或"pass"。上述求值过程显然与我们的期望是不符的。