if语句让程序能够决定是否应执行特定的语句。整个if语句被视为一条语句。
// 程序清单6.1 if.cpp--using the if statement
#include
using namespace std;
int main(void)
{
char ch;
int spaces = 0;
int total = 0;
cin.get(ch);
while (ch != '.') {
if (ch == ' ') {
++spaces;
}
++total;
cin.get(ch);
}
// 若在输入字符中包含回车,则字符总数中包括回车键生成的换行符
cout << spaces << " spaces, " << total << " characters total in sentence." << endl;
return 0;
}
if else语句则让程序决定执行两条语句或语句块中的哪一条。整个if else结构被视为一条语句。
// 程序清单6.2 ifelse.cpp--using the if else statement
#include
using namespace std;
int main(void)
{
char ch;
cout << "Type, and I shall repeat." << endl;
cin.get(ch);
while (ch != '.') {
if (ch == '\n') {
cout << ch;
} else {
cout << ++ch;
// cout << ch + 1; 此情况cout将显示int值,不是char字符
}
cin.get(ch);
}
cout << endl << "Please excuse the slight confusion." << endl;
return 0;
}
if else中的两种操作都必须是一条语句。如果需要多条语句,需要用大括号将它们括起来,组成一个块语句。
整个构造仍被视为一条语句。
// 程序清单6.3 ifelseif.cpp--using if else if else
#include
using namespace std;
int main(void)
{
const int Fave = 27;
int n;
cout << "Enter a number in the range 1-100 to find 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!" << endl;
}
} while (n != Fave);
return 0;
}
3种逻辑运算符:逻辑OR(||)、逻辑AND(&&)、逻辑NOT(!)
C++可以采用逻辑OR运算符(||),将两个表达式组合在一起。如果原来表达式中的任何一个或全部都为true,则得到的表达式的值为true;否则,表达式的值为false。
C++规定,||运算符是个顺序点。也就是说,先修改左侧的值,再对右侧的值进行判定(C++11的说法是,运算符左边的子表达式先于右边的子表达式)
i++ < 6 || i == j
// 假设i原来的值为10,则在对i和j进行比较时,i的值将为11
// 如果左侧的表达式为true,则C++将不会去判定右侧的表达式,因为只要一个表达式为true,则整个逻辑表达式为true
// 程序清单6.4 or.cpp--using the logical OR operator
#include
using namespace std;
int main(void)
{
cout << "This program may reformat your hard disk and destroy all your data." << endl;
cout << "Do you wish to continue? " ;
char ch;
cin >> ch;
if (ch == 'y' || ch == 'Y') {
cout << "Your were warned!\a\a" << endl;
} else if (ch == 'n' || ch == 'N') {
cout << "A wise choise ... bye" << endl;
} else {
cout << "That wasn't a y or n! Apparently you can't follow\ninstructions, so I'll trash your disk anyway.\a\a\a" << endl;
}
return 0;
}
逻辑AND运算符(&&),也是将两个表达式组合成一个表达式。仅当原来的两个表达式都为true时,得到的表达式的值才为true。
&&运算符也是顺序点,因此将首先判定左侧,并且在右侧被判定之前产生所有的副作用。如果左侧为false,则整个逻辑表达式必定为false,在这种情况下,C++将不会再对右侧进行判定。
// 程序清单6.5 and.cpp--using the logical AND operator
#include
using namespace std;
int main(void)
{
const int Arsize = 6;
float naaq[Arsize];
cout << "Enter the NAAQs (New Age Awareness Quotients) of\n"
<< "your neighbors. Pragram terminates when you make\n"
<< Arsize << " entries or enter a negative value." << endl;
int i = 0;
float temp;
cout << "First value: ";
cin >> temp;
while (i < Arsize && temp >= 0) {
naaq[i] = temp;
++i;
if (i < Arsize) {
cout << "Next value: ";
cin >> temp;
}
}
if (i == 0) {
cout << "No data--bye" << endl;
} else {
cout << "Enter your NAAQ: ";
float you;
cin >> you;
int count = 0;
for (int j = 0; j < i; j++) {
if (naaq[j] > you) {
++count;
}
}
cout << count << " of your neighbors have greater awareness of the New Age than you do." << endl;
}
return 0;
}
// 程序清单6.6 more_and.cpp--using the logical AND operator
#include
using namespace std;
int main(void)
{
const char *qualify[4] = {
"10,000-meter race.\n",
"mud tug-of-war.\n",
"masters canoe jousting.\n",
"pie-throwing festival.\n"
};
int age;
cout << "Enter your age in years: ";
cin >> age;
int index;
if (age > 17 && age < 35) {
index = 0;
} else if (age >=35 && age < 50) {
index = 1;
} else if (age >=50 && age < 65) {
index = 2;
} else {
index = 3;
}
cout << "Your qualify for the " << qualify[index];
return 0;
}
在使用取值范围测试时,应确保取值范围之间既没有缝隙,又没有重叠。
取值范围测试的每一部分都使用AND运算符将两个完整的关系表达式组合起来:
if (age > 17 && age < 35) // OK
不要使用数学符号将其表示为:
if (17 < age < 35)
编译器不会捕获这种错误,因为它仍然是有效的C++语法。
<运算符从左向右结合,因此上述表达式的含义如下:
if ((17 < age) < 35)
但17 < age的值要么为true(1),要么为false(0)。不管是哪种情况,表达式17 < age的值都小于35,因此整个测试的结果总是true!
!运算符将它后面的表达式的真值取反。
// 程序清单6.7 not.cpp--using the not operator
#include
#include
using namespace std;
bool is_int(double x);
int main(void)
{
double num; // 首先将可能的int值作为double值来读取,double类型的精度足以存储典型的int值,且取值范围更大
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've entered the integer " << val << "\nBye\n";
return 0;
}
bool is_int(double x)
{
if (x <= INT_MAX && x >= INT_MIN) {
return true;
} else {
return false;
}
}
1、逻辑OR和逻辑AND运算符的优先级低于关系运算符
x > 5 && x < 10将被解释为(x > 5)&&(x < 10)
2、!运算符的优先级高于所有的关系运算符和算术运算符
!x > 5将被解释为(!x) > 5,将永远为false
3、逻辑AND运算符的优先级高于逻辑OR运算符
age > 30 && age < 45 || weight > 300被解释为(age > 30 && age < 45) || weight > 300
4、C++确保程序从左向右进行计算逻辑表达式,并在知道答案后立刻停止
标识符and、or和not都是C++保留字,这意味着不能将它们用作变量名等。它们不是C语言的保留字,但C语言程序可以将它们用作运算符,只要在程序中包含头文件iso646.h。
// 程序清单6.8 cctypes.cpp--using the ctype.h library
#include
#include
using namespace std;
int main(void)
{
cout << "Enter text for analysis, and type @ to terminate input." << endl;
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." << endl;
return 0;
}
条件运算符(?:),它是C++中唯一一个需要3个操作数的运算符。
expression1 ? expression2 : expression3
如果expression1为true,则整个条件表达式的值为expression2的值;否则,整个表达式的值为expression3的值。
// 程序清单6.9 condit.cpp--using the conditional operator
#include
using namespace std;
int main(void)
{
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;
}
条件运算符生成一个表达式,因此是一个值,可以将其赋给变量或将其放到一个更大的表达式中。
switch (integer-expression)
{
case label1 : statement(s)
case label2 : statement(s)
...
default : statement(s)
}
integer-expression必须是一个结果为整数值的表达式。
每个标签都必须是整数常量表达式。
最常见的标签是int或char常量,也可以是枚举量。
如果integer-expression不与任何标签匹配,则程序将跳到标签为default的那一行。
default标签是可选的,如果被省略,而又没有匹配的标签,则程序将跳到switch后面的语句执行。
C++中的case标签只是行标签,而不是选项之间的界线。
程序跳到switch中特定代码行后,将依次执行之后的所有语句,除非有明确的其他指示。
程序不会在执行到下一个case处自动停止,要让程序执行完一组特定语句后停止,必须使用break语句。
这将导致程序跳到switch后面的语句处执行。
// 程序清单6.10 switch.cpp--using the switch statement
#include
using namespace std;
void showenum();
void report();
void comfort();
int main(void)
{
showenum();
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";
}
showenum();
cin >> choice;
}
cout << "Bye!\n";
return 0;
}
void showenum()
{
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 up 120%. Expenses are down 35%.\n";
}
void comfort()
{
cout << "Your employees think you are the finest CEO in the industry."
<< "The board of directors think you are the inest CEO in the industry.\n";
}
// 程序清单6.11 enum.cpp-using enum
#include
using namespace std;
enum {red, orange, yellow, green, blue, violet, indigo};
int main(void)
{
cout << "Enter color code (0-6): ";
int code;
cin >> code;
// cin无法识别枚举类型,因此该程序要求用户选择选项时输入一个整数
// 当switch语句将int值和枚举量标签进行比较时或在while循环测试条件中,将枚举量提升为int
while (code >= red && code <= indigo) {
switch (code) {
case red : cout << "Her lips were red.\n";
break;
case orange : cout << "Her hear 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;
}
break和continue语句都使程序能够跳过部分代码。可以在switch语句或任何循环中使用break语句,使程序跳到switch或循环后面的语句处执行。continue语句用于循环中,让程序跳过循环体中余下的代码,并开始新一轮循环。
// 程序清单6.12 jump.cpp--using continue and break
#include
using namespace std;
int main(void)
{
cout << "Enter s line of text:" << endl;
const int Arsize = 80;
char line[Arsize];
cin.get(line, Arsize);
int spaces = 0;
cout << "Complete line:" << endl << line << endl;
cout << "Line through first period:" << endl;
for (int i = 0; line[i] != '\0'; i++) {
cout << line[i];
if (line[i] == '.')
break;
if (line[i] != ' ')
continue;
spaces++;
}
cout << endl << spaces << " spaces" << endl;
cout << "Done." << endl;
return 0;
}
在for循环中,continue语句使程序直接跳到更新表达式处,然后跳到测试表达式处。对于while循环来说,continue将使程序直接跳到测试表达式处,因此while循环体中位于continue之后的更新表达式都将被跳过。
// C++也有goto语句
char ch;
cin >> ch;
if (ch == 'P')
goto paris;
cout << ...
...
paris: cout << "You've just arrived at Paris."
int n;
cin >> n;
当cin发现输入类型不匹配时,将发生4种情况:
(1)n的值保持不变
(2)不匹配的输入将被留在输入队列中
(3)cin对象中的一个错误标记被设置(clear()方法重置错误输入标记,同时也重置文件尾)
(4)对cin方法的调用将返回false(输入错误和EOF都将导致cin返回false)
程序发现用户输入了错误内容时,应采取3个步骤:
1、重置cin以接受新的输入
2、删除错误输入
3、提示用户再输入
// 程序清单6.13 cinfish.cpp--non-numeric input terminates loop
#include
using namespace std;
int main(void)
{
const int Max = 5;
double fish[Max];
cout << "Please enter the weights of your fish." << endl;
cout << "You may enter up to " << Max << " fish ."
<< endl;
cout << "fish #1: ";
int i = 0;
// 如果i等于Max,则循环将结束,而不会将一个值读入到数组后面的位置
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" << endl;
} else {
cout << total / i << " = average weight of " << i << " fish" << endl;
}
cout << "Done." << endl;
return 0;
}
// 为了让窗口打开以便能看到输出,需要添加额外代码
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
// 程序清单6.14 cingolf.cpp--non-numeric input skipped
#include
using namespace std;
int main(void)
{
const int Max = 5;
int golf[Max];
cout << "Please enter your golf scores." << endl;
cout << "You must enter " << Max << " rounds." << endl;
int i;
for (i = 0; i < Max; i++) {
cout << "round # " << i + 1 << ": ";
while (!(cin >> golf[i])) {
cin.clear();
while (cin.get() != '\n'); // get rid of bad input
cout << "Please enter a number: ";
}
}
double total = 0.0;
for (int j = 0; j < Max; j++) {
total += golf[j];
}
cout << total / Max << " = average score " << Max << " rounds." << endl;
return 0;
}
使用cin进行输入时,程序将输入视为一系列的字节,其中每个字节都被解释为字符编码。
不管目标数据类型是什么,输入一开始都是字符数据——文本数据。然后,cin对象负责将文本转换为其他类型。
例:输入行:38.5 19.2
(1)
char ch;
cin >> ch;
输入行的第一个字符被赋给ch。其字符编码被存储在变量ch中。
(2)
int n;
cin >> n;
cin将不断读取,直到遇到非数字字符。将38的二进制编码复制到变量n中。
(3)
double x;
cin >> x;
cin将不断读取,直到遇到第一个不属于浮点数的字符。将38.5的二进制编码复制到变量x中。
(4)
char word[50];
cin >> word;
cin将不断读取,直到遇到空白字符。cin将3、8、句点和5这4个字符的字符编码存储到数组word中,并在末尾加上一个空字符。
(5)
char word[50];
cin.getline(word, 50);
cin将不断读取,直到遇到换行符。所有字符都被存储到数组word中,并在末尾加上一个空字符。换行符被丢弃。
对于cout输出,将执行相反的操作,即整数被转换为数字字符序列,浮点数据被转换为数字字符和其他字符组成的字符序列,字符数据不需要做任何转换。
文件输入:
(1)必须包含头文件fstream
(2)头文件fstream定义了一个用于处理输出的ofstream类
(3)需要声明一个或多个ofstream对象,并以自己喜欢的方式对其进行命名,条件是遵守常用的命名规则(差异:头文件iostream声明了一个名为cout的ostream对象)
(4)必须指明名称空间std
(5)需要将ofstream对象与文件关联起来
(6)使用完文件后,应使用方法close()将其关闭
(7)可结合使用ofstream对象和运算符<<来输出各种类型的数据(就像使用cout那样使用该ofstream对象)
#include
#include
using namespace std;
int main(void)
{
char automobile[50];
int year;
double a_price;
double d_price;
cout << "Enter the make and model of automobile: ";
cin.getline(automobile, 50);
cout << "Enter the model year: ";
cin >> year;
cout << "Enter the original asking price: ";
cin >> a_price;
d_price = 0.913 * a_price;
cout << fixed;
cout.precision(2);
cout.setf(ios_base::showpoint);
cout << "Make and model: " << automobile << endl;
cout << "Year: " << year << endl;
cout << "Was asking $" << a_price << endl;
cout << "Now asking $" << d_price << endl;
ofstream outFile;
// 使用方法open()将该对象与特定文件关联起来
// 方法open()接受一个C-风格字符串作为参数,这可以是一个字面字符串,也可以是存储在数组中的字符串
outFile.open("carinfo.txt");
// 若文件carinfo.txt不存在,open()将新建一个名为carinfo.txt的文件
// 若文件carinfo.txt已存在,默认情况下将丢弃原有内容,将新的输出加入到该文件中
outFile << fixed;
outFile.precision(2);
outFile.setf(ios_base::showpoint);
outFile << "Make and model: " << automobile << endl;
outFile << "Year: " << year << endl;
outFile << "Was asking $" << a_price << endl;
outFile << "Now asjing $" << d_price << endl;
outFile.close(); // 方法close()不需要使用文件名作为参数
// 如果忘记关闭文件,程序正常终止时将自动关闭它
return 0;
}
文件输出:
(1)必须包含头文件fstream
(2)头文件fstream定义了一个用于处理输出的ifstream类
(3)需要声明一个或多个ifstream对象,并以自己喜欢的方式对其进行命名,条件是遵守常用的命名规则(差异:头文件iostream声明了一个名为cin的istream对象)
(4)必须指明名称空间std
(5)需要将ifstream对象与文件关联起来(使用方法open())
(6)使用完文件后,应使用方法close()将其关闭
(7)可结合使用ifstream对象和运算符>>来输出各种类型的数据(就像使用cin那样使用该ifstream对象)
(8)可以使用ifstream对象和get()方法来读取一个字符,使用ifstream对象和getline()来读取一行字符
(9)可以结合使用ifstream和eof()、fail()等方法来判断输入是否成功
(10)ifstream对象本身被用作测试条件时,如果最后一个读取操作成功,它将被转换为布尔值true,否则被转换为false