五. 分支语句和逻辑运算符
5.1 if语句
if.cpp
#include <iostream>
int main() {
using std::cin;
using std::cout;
char ch;
int spaces = 0;
int total = 0;
cin.get(ch);
while (ch != '.')
{
if (ch == ' ')
++spaces;
++total;
cin.get(ch);
}
cout << spaces << " spaces, " << total;
cout << " characters total in sentence\n";
return 0;
}
5.1.1 if else语句
5.1.2 格式化if else语句
格式1:
if (ch == 'Z')
{
zorro++;
cout << "Another Zorro cadidate\n";
}
else
{
dull++;
cout << "Not a Zorro candidate\n";
}
格式2:
if (ch == 'Z') {
zorro++;
cout << "Another Zorro cadidate\n";
}
else {
dull++;
cout << "Not a Zorro candidate\n";
}
第一种格式强调的是语句的块结构,第二种格式则将语句块与关键字if和else更紧密地结合在一起。
5.1.3 if else if else结构
if (ch == 'A')
a_grade++;
else if (ch == 'B')
b_grade++;
else
soso++;
ifelseif.cpp
#include <iostream>
const int Fave = 27;
int main() {
using namespace std;
int n;
cout << "Enter a number in the range 1-100 to find ";
cout << "my favorite number: ";
do
{
cin >> n;
if (n < Fave)
cout << "Too low -- guess again: ";
else if (n > Fave)
cout << "Too high -- guess again: ";
else
cout << Fave << " is right!\n";
} while (n != Fave);
return 0;
}
5.2 逻辑表达式
逻辑表达式有三种,分别是:逻辑OR(||)、逻辑AND(&&)、逻辑NOT(!)。
C++逻辑OR和逻辑AND运算符地优先级都低于关系运算符:
x > 5 && x < 10等价于(x > 5) && (x < 10)
!运算符的优先级高于所有的关系运算符和算数运算符。因此,要对表达式求反,必须用括号将其括起。逻辑AND运算符的优先级高于逻辑OR运算符。
5.3 字符函数库cctype
cctype.cpp
#include <iostream>
#include <cctype>
int main() {
using namespace std;
cout << "Enter text for analysis, and type @"
" to terminate input.\n";
char ch;
int whitespace = 0;
int digits = 0;
int chars = 0;
int punct = 0;
int others = 0;
cin.get(ch);
while (ch != '@') {
if (isalpha(ch))
chars++;
else if (isspace(ch))
whitespace++;
else if (isdigit(ch))
digits++;
else if (ispunct(ch))
punct++;
else
others++;
cin.get(ch);
}
cout << chars << " letters, "
<< whitespace << " whitespace, "
<< digits << " digits, "
<< punct << " punctuations, "
<< others << " others.\n";
return 0;
}
5.4 ?:运算符
C++有一个常被用来代替if else语句的运算符,这个运算符被称为条件运算符(?:),它是C++中唯一一个需要三个操作数的运算符。该运算符的通用格式如下:
expression1 ? expression2 : expression3;
如果expression1为true,则整个条件表达式的值为expression2的值;否则,整个表达式的值为expression3的值。示例:
5 > 3 ? 10 : 12; //表达式的值为10
3 == 9 ? 25 : 18; //表达式的值为18
condit.cpp
#include <iostream>
int main() {
using namespace std;
int a, b;
cout << "Enter two integers: ";
cin >> a >> b;
cout << "The larger of " << a << " and " << b;
int c = a > b ? a : b;
cout << " is " << c << endl;
return 0;
}
5.5 switch语句
通用格式:
switch (intger expression)
{
case label1: statment(s)
case label2: statment(s)
...
default: statment(s)
}
switch.cpp
#include <iostream>
using namespace std;
void showmenu();
void report();
void comfort();
int main() {
showmenu();
int choice;
cin >> choice;
while (choice != 5)
{
switch (choice)
{
case 1: cout << "a\n";
break;
case 2: report();
break;
case 3: cout << "The boss was in all day.\n";
break;
case 4: comfort();
break;
default: cout << "That's not a choice.\n";
}
showmenu();
cin >> choice;
}
cout << "Bye!\n";
return 0;
}
void showmenu()
{
cout << "Please enter 1, 2, 3, 4, or 5:\n"
"1) alarm 2) report\n"
"3) alibi 4) comfort\n"
"5) quit\n";
}
void report()
{
cout << "It's been an excellent week for business.\n"
"Sales are 120$. Expreses are down 35$.\n";
}
void comfort()
{
cout << "Your employees think you are the finest CEO\n"
"in the industy. The board of directors think\n"
"you are the finest CEO in the industry.\n";
}
使用字符(而不是整数)作为菜单选项和switch标签,可以为大写标签和小写标签提供相同的语句:
char choice;
cin >> choice;
while (choice != 'Q' && choice != 'q')
{
switch (choice)
{
case 'a':
case 'A': cout << "a\n";
break;
case 'r':
case 'R': report();
break;
case 'l':
case 'L': cout << "The boos was in all day.\n";
break;
case 'c':
case 'C': comfort();
break;
default: cout << "That's not a choice.\n";
}
showmenu();
cin >> choice;
}
5.5.1 将枚举量用作标签
通常,cin无法识别枚举类型(它不知道程序员是如何定义他们的),因此该程序要求用户选择选项时输入一个整数。当switch语句将int值和枚举量标签进行比较时,将枚举量提升为int。另外,在while循环测试条件中,也会将枚举量提升为int类型。
enum.cpp
#include <iostream>
enum {red, orange, yellow, green, blue, violet, indigo};
int main() {
using namespace std;
cout << "Enter color code (0-6): ";
int code;
cin >> code;
while (code >= red && code <= indigo)
{
switch (code)
{
case red: cout << "Her lips were red.\n"; break;
case orange: cout << "Her hair was orange.\n"; break;
case yellow: cout << "Her shoes were yellow.\n"; break;
case green: cout << "Her nails were green.\n"; break;
case blue: cout << "Her sweatsuit was blue.\n"; break;
case violet: cout << "Her eyes were violet.\n"; break;
case indigo: cout << "Her mood was indigo.\n"; break;
}
cout << "Enter color code(0-6): ";
cin >> code;
}
cout << "Bye\n";
return 0;
}
5.5.2 switch和if else
如果既可以使用if else if语句,也可以使用switch语句,则当选项不少于3个时,应使用switch语句。
5.6 break和continue语句
break和continue语句都能使程序跳过部分代码。可以在switch语句或任何循环中使用break语句,使程序跳到switch或循环后面的语句处执行。continue语句用于循环中,让程序跳过循环体中余下的代码,并开始新一轮循环。
5.7 读取数字的循环
输入类型不匹配时,将发生四种情况:
· n的值保持不变;
· 不匹配的输入将保留在输入队列中;
· cin对象中的一个错误标记被设置;
· 对cin方法的调用将返回false。
cinfish.cpp
#include <iostream>
const int Max = 5;
int main() {
using namespace std;
double fish[Max];
cout << "Please enter the weights of your fish.\n";
cout << "You may enter up to " << Max
<< " fish <q to terminate>.\n";
cout << "fish #1: ";
int i = 0;
while (i < Max && cin >> fish[i])
{
if (++i < Max)
cout << "fish #" << i + 1 << "; ";
}
double total = 0.0;
for (int j = 0; j < i; j++)
total += fish[j];
if (i == 0)
cout << "No fish\n";
else
cout << total / i << " = average weight of "
<< i << " fish\n";
cout << "Done.\n";
return 0;
}
如果需要继续读取,应采取3个步骤:
· 重置cin以接受新的输入
· 删除错误输入
· 提示用户再输入
cingolf.cpp
#include <iostream>
const int Max = 5;
int main() {
using namespace std;
int golf[Max];
cout << "Please enter your golf scores:\n";
cout << "You must enter " << Max << " rounds.\n";
int i;
for (i = 0; i < Max; i++)
{
cout << "round #" << i + 1 << ": ";
while (!(cin >> golf[i]))
{
cin.clear(); //重置输入
while (cin.get() != '\n')
continue;
cout << "Please enter a number: ";
}
}
double total = 0.0;
for (i = 0; i < Max; i++)
total += golf[i];
cout << total / Max << " = average score "
<< Max << " rounds\n";
return 0;
}
5.8 简单文件输入/输出
5.8.1 文本I/O和文本文件
使用cin进行输入时,程序将输入视为一系列的字节,其中每个字节都被解释为字符编码。不管目标数据类型是什么,输入一开始都是字符数据——文本数据。然后,cin对象负责将文本转换为其他类型。
5.8.2 写入到文本文件中
首先总结控制台输入的多个方面:
· 必须包含头文件iostream。
· 头文件iostream定义了一个用处理输入的istream类。
· 头文件iostream声明了一个名为cin的istream变量(对象)。
· 必须指明名称空间 std;例如,为引用元素 cin,必须使用编译指令using 或前缀std::。
· 可以结合使用 cin 和运算符>>来读取各种类型的数据。
· 可以使用cin和get()方法来读取一个字符,使用cin和getline()来读取一行字符。
· 可以结合使用cin和eof)fail()方法来判断输入是否成功
· 对象 cin 本身被用作测试条件时,如果最后一个读取操作成功,它将被转换为布尔值 true,否则
被转换为 false。
文件输出与此极其相似:
· 必须包含头文件fstream。
· 头文件fstream 定义了一个用于处理输入的ifstream类。
· 需要声明一个或多个ifstream 变量(对象),并以自己喜欢的方式对其进行命名,条件是遵守常用
的命名规则。
· 必须指明名称空间std;例如,为引用元素ifstream,必须使用编译指令using 或前缀std
· 需要将ifstream 对象与文件关联起来。为此,方法之一是使用open()方法。
· 使用完文件后,应使用 close()方法将其关闭。
· 可结合使用ifstream对象和运算符>>来读取各种类型的数据。
· 可以使用 ifstream 对象和get()方法来读取一个字符使用 ifstream 对象和 getline()来读取一行字符
· 可以结合使用ifstream和eof()fil()等方法来判断输入是否成功。
· ifstream 对象本身被用作测试条件时,如果最后一个读取操作成功,它将被转换为布尔值 truc, 否则被转换为false。
sumafile.cpp
#include <iostream>
#include <fstream>
#include <cstdlib>
const int SIZE = 60;
int main() {
using namespace std;
char filename[SIZE];
ifstream infile;
cout << "Enter name of data file: ";
cin.getline(filename, SIZE);
infile.open(filename);
if (!infile.is_open())
{
cout << "Could not open the file " << filename << endl;
cout << "Program terminating.\n";
exit(EXIT_FAILURE);
}
double value;
double sum = 0.0;
int count = 0;
infile >> value;
while (infile.good())
{
++count;
sum += value;
infile >> value;
}
if (infile.eof())
cout << "End of file reached.\n";
else if (infile.fail())
cout << "Input terminated by data mismatch.\n";
else
cout << "Input terminated for unknown reason.\n";
if (count == 0)
cout << "No data processed.\n";
else
{
cout << "Ttems read: " << count << endl;
cout << "Sum: " << sum << endl;
cout << "Average: " << sum / count << endl;
}
infile.close();
return 0;
}
检查文件是否被成功打开至关重要。下面是一些可能出问题的地方: 指定的文件可能不存在; 文件可能位于另一个目录(文件夹)中;访问可能被拒绝:用户可能输错了文件名或省略了文件扩展名。
需要特别注意的是文件读取循环的正确设计。读取文件时,有几点需要检查。首先,程序读取件时不应超过 EOF。如果最后一次读取数据时遇到 EOF,方法 eof( )将返回 true。其次,程序可能遇到型不匹配的情况。如果最后一次读取操作中发生了类型不匹配的情况,方法 fail()将返回true(如果遇到了EOF,该方法也将返回true)。最后,可能出现意外的问题如文件受损或硬件故障。如果最后一次读取文件时发生了这样的问题,方法 bad()将返回 true。不要分别检查这些情况,一种更简单的方法是使用 good()方法,该方法在没有发生任何错误时返回 true。
5.9 总结
C++提供了if语句、ifelse 语和 switch 语句来管理选项,if语句使程序有条件地执行语句或语句块,也就是说,如果满足特定的条件,程序将执行特定的语句或语句块。if else 语句程序选择执行
两个语句或语句块之一。可以在这条语句后再加上 if else,以提供一系列的选项。switch 语句引导程序执行一系列选项之一。
C++还提供了帮助决策的运算符,这种表达式对两个值进行比较f和ifelse语句通常使用关系表达式作为测试条件。通过使用逻辑运算符(&&、||和!),可以组合或修改关系表达式创建更细致的测试。条件运算符(?:提供了一种选择两个值之一的简洁方式。
cctype字符函数库提供了一组方便的、功能强大的工具,可用于分析字符输入。
对于文件I/0来说,循环和选择语句是很有用的工具:文件I/0与控制台I/0极其相似。声明ifstream和ofstream对象,并将它们同文件关联起来后,便可以像使用cin和cout 那样使用这些对象。