分支语句和逻辑运算符
6.1 If 语句
两种格式:
- if
- if - else
代码6-1
// if.cpp -- using the if statement
#include <iostream>
using namespace std;
int main()
{
char ch;
int spaces = 0;
int total = 0;
cout << "Enter a sentence :enter . to quit" << endl;
cin.get(ch);// 将空格也输入到输入流中
while (ch != '.')// 结束标志为.
{
if (ch == ' ')
{
++spaces;// 记录空格数
}
++total;// 记录总数
cin.get(ch);// 循环获取输入流中的下一个字符
}
cout << spaces << " spaces \n" << total << " characters total in sentence" << endl;
return 0;
}
如果只加密输出的文本信息,而不改变换行符:
代码6-2
// ifelse.cpp -- using the if else statement
#include <iostream>
int main()
{
char ch;
std::cout << "Type, and I shall repeat." << std::endl;
std::cin.get(ch);
while (ch != '.')// 结束标志为.
{
if (ch == '\n')
{
std::cout << ch;// 如果为换行符,正常输出
}
else
{
std::cout << ++ch;// 否则对ASCII码值加1输出
}
std::cin.get(ch);
}
std::cout << "\nPlease excuse the slight confusion." << std::endl;
return 0;
}
if-else-if-else结构
代码6-3
// ifelseif.cpp -- using the if else if (else) statement
#include <iostream>
using namespace std;
const int Fave = 27;
int main()
{
int n;
cout << "Enter a number in the range 1-100 to find my number." << endl;
do
{
cin >> n;
if (n < Fave)
cout << "Too low -- guess again." << endl;
else if (n > Fave)
cout << "Too high -- guess again." << endl;
else
cout << Fave << " is right." << endl;
} while (n != Fave);
return 0;
}
注意不要将 == 写成 = 运算符
6.2 逻辑表达式
- 逻辑 OR ( || )
仅有一方满足或全满足即为true
5 == 5 || 5 == 9;//true
5 > 3 || 5 > 10;//true
5 > 8 || 5 < 2;//false
// || 运算符优先级低于关系运算符,无需括号区别优先
C++规定 先对 || 左侧判定,再对右边判定,如下:
int i = 10;
int k = 10;
int j = 11;
cout << (i++ < 6 || i == j) << endl;//true
cout << (k == j || k++ < 6) << endl;//false
代码6-4
// or.cpp -- using the Logical OR operator
#include <iostream>
using namespace std;
int main()
{
cout << "This program may reformat your hard disk\n"
"and destroy your database.\n"
"Do you want to continue?<y/n> ";
char ch;
cin >> ch;
if (ch == 'y' || ch == 'Y')
{
cout << "you were warned!\a\a\n";
}
else if (ch == 'n' || ch == 'N')
{
cout << "a wise choice...\n";
}
else
cout << "That wasn't a y or n !\n"
"Apparently you can't follow instructions,so "
"I will trash your disk anyway.\n";
return 0;
}
- 逻辑 AND ( && )
双方全部满足即为true
5 == 5 && 5 == 9;//false
5 > 3 && 5 < 10;//true
5 > 8 && 5 < 2;//false
// && 运算符优先级低于关系运算符,无需括号区别优先,也是先判断左边,再判断右边
代码6-5
// and.cpp -- using the Logical AND operator
#include <iostream>
using namespace std;
const int ArSize = 6;
int main()
{
float naaq[ArSize];
cout << "Enter the NAAQs (New Age Awareness Quotients) "
"of\nyour neighbors. Program 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;
cout << " of your neighbors have greater awareness of \n"
"the New Age than you do." << endl;
}
return 0;
}
设置取值范围
代码6-6
// more_and.cpp -- using the Logical AND operator
#include <iostream>
using namespace std;
const char* quality[4] =
{
"10,000-meter race.\n",
"mud tug-of-war.\n",
"masters canoe jousting.\n",
"pie-throwing festival.\n"
};
int main()
{
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 << "You quality for the " << quality[index] << endl;
return 0;
}
禁止以下写法
if (17 < age < 35)
- 逻辑 NOT( ! )
取反 !true == false
代码6-7
// not.cpp -- using the Logical NOT operator
#include <iostream>
#include <climits>
using namespace std;
bool is_int(double);
int main()
{
double num;
cout << "Yo, dude! Enter an integer value: ";
cin >> num;// 在32位控制台中输入超过int最大值:99999999999
while (!is_int(num))
{
cout << "Out of range -- please enter again.: ";
cin >> num;
}
int val = int (num);
cout << "You hace entered the integer value: " << val << endl;
return 0;
}
bool is_int(double x)
{
if (x <= INT_MAX && x >= INT_MIN)
return true;
else
return false;
}
如果直接读取一个很大的int值,大多数C++只会将其截断为合适的大小,不会通知丢失数据
或将int作为double来读取,或者long long ,其空间长度足以存储典型int值
!优先级高于所有关系和算数运算符
AND 运算符高于 OR 运算符
另外,在包含iso646.h头文件后,可以使用
and表示&&
or表示||
not表示!
6.3 字符函数库 cctype
cctype 函数软件包:简化诸如确定字符是否为大写字母,数字,标点符号等工作
如isalpha(ch)【判断是否为字母】、ispunct(ch)【判断是否为标点符号】,如果是则返回为非零值,否则为0,
这些函数返回值为int类型,可当作bool使用
代码6-8
// cctype.cpp -- using the ctype library
#include <iostream>
#include <cctype>
using namespace std;
int main()
{
cout << "Enter text for analysis, and type @ to terminate input." << endl;
char ch;
int whitespace = 0;
int digits = 0;
int chars = 0;
int puncts = 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)) puncts++;
else others++;
cin.get(ch);
}
cout << chars << " Letters" << endl;
cout << whitespace << " whitespace" << endl;
cout << digits << " digits" << endl;
cout << puncts << " puncts" << endl;
cout << others << " others" << endl;
return 0;
}
主要函数表:
6.4 三目运算符 ? :
代替 if-else 使用,省略代码,不建议嵌套过多层,致使难以理解:
5 > 3 ? 10 : 12;// 如果5 > 3,则选取10,否则选取12
代码6-9
// condit.cpp -- using the conditional operator
#include <iostream>
using namespace std;
int main()
{
int a, b;
cout << "Enter two integers: ";
cin >> a >> b;// 测试数据: 65 45
cout << "The larger of " << a << " and " << b;
int c = a > b ? a : b;
cout << " is " << c << endl;
return 0;
}
6.5 switch 语句
当选择项过多,使用 if-else 过于臃肿,采用 switch 使代码更清晰
代码6-10
// switch.cpp -- using switch statement
#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 is not a valid choice." << endl;
}
showMenu();
cin >> choice;
}
cout << "Bye!" << endl;
return 0;
}
void showMenu()
{
cout << "Please enter 1, 2, 3, 4 or 5:\n"
"1) alarm\t\t\t2) report\n"
"3) alibi\t\t\t4) comfort\n"
"5) quit\n";
}
void report()
{
cout << "It is been an excellent week for business.\n"
"Sales are up 120%. Expenses are down 36%." << endl;
}
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的标签可以自定义,如下:
switch(choice)
{
case 'a' : // 会自动执行下一个选项,因为没有break
case 'A' : cout << "\a\n";
break;// 每一个选项的最后一句,确保只执行特定部分,可删除做对比
case 'r' :
case 'R' : report();
break;
case 'l' :
case 'L' : cout << "The boss was in all day.\n";
break;
case 'c' :
case 'C' : comfort();
break;
default : cout << "That is not a valid choice." << endl;
// 默认句,即输入一个不存在的选项,执行这条语句
}
使用枚举量作标签
代码6-11
// enum.cpp -- using enum
#include <iostream>
#include <cctype>
using namespace std;
enum {red, orange, yellow, green, blue, violent, indigo};
int main()
{
cout << "Enter color code (0-6): ";
int code;
cin >> code;
while (code >= red && code <= indigo)
{
switch (code)
{
case red:
cout << "Her lips were red." << endl;
break;
case orange:
cout << "Her hair was orange." << endl;
break;
case yellow:
cout << "Her shoes was yellow." << endl;
break;
case green:
cout << "Her nails was green." << endl;
break;
case blue:
cout << "Her sweatsuit were blue." << endl;
break;
case violent:
cout << "Her eyes were violet." << endl;
break;
case indigo:
cout << "Her mood were indigo." << endl;
break;
default: // 可以不写,其他输入无法进入循环
cout << "Out of range" << endl;
break;
}
cout << "Enter color code (0-6): ";
cin >> code;
}
cout << "Bye\n";
return 0;
}
6.6 break 和 continue
由于跳过循环
break: 跳出当前循环,即结束循环
continue: 跳过当前循环,进入下一次循环
代码6-12
// jump.cpp -- using continue and break
#include <iostream>
using namespace std;
const int ArSize = 80;
int main()
{
char line[ArSize];
int spaces = 0;
cout << "Enter a line of text" << endl;
cin.get(line, ArSize);
cout << "Complete line:\n" << line << endl;
cout << "Line through first period:\n" << endl;
for (int i = 0; line[i] != '\0'; i++)
{
cout << line[i];
if (line[i] == '.')// 以 . 作为文本结束标志
break;
// goto paries;// 使用goto,需将break注释
if (line[i] != ' ')// 只有是空格,才能使下一步加1
continue;
spaces++;
}
// paries:
cout << "\n" << spaces << " spaces" << endl;
cout << "Done." << endl;
return 0;
}
对于goto语法,不建议使用,可以自行打开注释查看效果
6.7 读取数字循环
将一系列数字读入数组,允许提前结束输入,若发生输入类型不匹配,则会出现以下情况:
- n的值保持不变
- 不匹配的输入被保留在输入队列中
- cin对象的一个错误标记被设置 // clear()方法可以重置标记,同时也重置EOF条件
- 对cin方法的调用将返回false【如果被转换为bool类型】
代码6-13
// cinfish.cpp -- non-numeric input terminates loop
#include <iostream>
using namespace std;
const int MAX = 5;
int main()
{
double fish[MAX];
cout << "Please enter the weights of your fish: " << endl;
cout << "You may enter up to " << MAX << " fish <q to terminate>" << endl;
cout << "fish #1: ";
int i = 0;
while (i < MAX && cin >> fish[i])// 尝试输入非数字,循环会自动退出,cin返回false
// cin放在&&右侧,这样在左边判为false时可直接退出循环,避免多读入一个数据
{
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 found!" << endl;
}
else
{
cout << total/i << " = average weight of " << i << " fish" << endl;
}
cout << "Done!" << endl;
return 0;
}
当输入错误数据类型,且需要继续输入时:
- 重置cin以接收新输入
- 删除错误输入
- 提示再输入
代码6-14
// cingolf.cpp -- non-numeric input skipped
#include <iostream>
using namespace std;
const int MAX = 5;
int main()
{
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]))// 输入类型不匹配,返回false
{
cin.clear();// 重置cin,使其可以重新输入
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" << endl;
cout << "Done!" << endl;
return 0;
}
6.8 简单文件输入/输出
文本 I/O 和文本文件
文本I/O :使用cin输入时,程序将其视为一系列字节,每个字节被解释为字符编码
//控制台输入数据:13.14 6.6
// 对于char
char ch;
cin >> ch;
/*第一个字符 3 被赋给ch ,其二进制字符编码被存储在ch中,输入与目标变量都是字符,无需转换
【!!!这里存储的是字符3的编码,并不是数值3】*/
// 对于int
int n;
cin >> n;
/*cin不断读取,直到遇到非数字字符,即读取 13 ,经过计算知道其为13,将13的二进制编码复制到变量中*/
// 对于double
double x;
cin >> x;
/*cin不断读取,直到遇到第一个非浮点数字符,即读取 13.14 , 使得空格符为输入队列下一个字符
cin经过计算,知道其为13.14,将二进制编码存储到变量中*/
// 对于char数组
char word[50];
cin >> word;
/*cin不断读取,直到遇到空白符,即读取13.14,使得空格符为输入队列下一个字符,
cin将其字符编码存储数组中并在末尾加空字符标志结尾,无需转换*/
// 对于另一种char数组
char word[50];
cin.getline(word, 50);
/*cin不断读取,直到遇到换行符,所有字符存储到数组中,末尾加一个空字符,丢弃换行符
输入队列中的下一个字符为下一行起始字符,无需转换*/
写入文本文件
头文件<fstream>
用于处理输出的类:ofstream 【必须使用这个类创建对象才能使用】
ofstream outFile;// 创建对象outFile,将其与文件对象关联后,可以如同cout一样对其使用【outFile << data】
代码6-15
// outfile.cpp -- writing to a file
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char automobile[50];
int year;
double a_price;
double d_price;
ofstream outFile;
outFile.open("./carinfo.txt");// 此方式打开文件,若不存在即创建,若存在则丢弃原有内容,重新写入新的内容
cout << "Enter the make and model of aotumobile: ";
cin.getline(automobile, 50);
cout << "Enter the model year: ";
cin >> year;
cout << "Enter the original asking price: ";
cin >> a_price;
d_price = a_price * 0.913;
// 控制台输出
cout << fixed;
cout.precision(2);
cout.setf(ios_base::showpoint);
cout << "Make and model: " << automobile << endl;
cout << "Model year: " << year << endl;
cout << "Was asking price: $" << a_price << endl;
cout << "Now asking price: $" << d_price << endl;
// 文件输出
outFile << fixed;
outFile.precision(2);
outFile.setf(ios_base::showpoint);
outFile << "Make and model: " << automobile << endl;
outFile << "Model year: " << year << endl;
outFile << "Was asking price: $" << a_price << endl;
outFile << "Now asking price: $" << d_price << endl;
outFile.close();// 每次打开文件读写操作一定要记得关闭文件
return 0;
}
读取文本文件
头文件<fstream>
用于处理输出的类:ifstream 【必须使用这个类创建对象才能使用】
ifstream inFile;// 创建对象inFile,将其与文件对象关联后,可以如同cin一样对其使用【inFile >> data】
代码6-16
// sumafile.cpp -- functions with an array argument
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
const int SIZE = 60;
int main()
{
char filename[SIZE];
ifstream inFile;
/*
在当前文件夹下新创建scores.txt文件,输入:
18 19 18.5 13.5 14
16 19.5 20 18 12 18.5
17.5
*/
cout << "Enter filename: ";
cin.getline(filename, SIZE);
inFile.open(filename);
if (!inFile.is_open())// 判断文件是否正常打开
{
cout << "Couldn't open file: " << filename << endl;
cout << "Program terminating" << endl;
exit(EXIT_FAILURE);// EXIT_FAILURE = 1 代表带着错误退出程序
}
double value;
double sum = 0.0;
int count = 0;
inFile >> value;
while (inFile.good())// 判断输入正常且不在EOF处
{
++count;
sum += value;
inFile >> value;// 返回一个inFile,类似于cin,可用作判断条件放入if\while等中
}
if (inFile.eof())// 判断是否正确到达EOF
cout << "End of file reached." << endl;
else if (inFile.fail())// 判断类型是否不匹配,不匹配返回true
cout << "Input terminated by data mismatch." << endl;
else
cout << "Input terminated for unknown reason." << endl;
if (count == 0)
cout << "No data processed." << endl;
else{
cout << "Items read: " << count << endl;
cout << "Sum: " << sum << endl;
cout << "Average: " << sum / count << endl;
}
inFile.close();
return 0;
}