C++ Primer Plus——第6章 分支语句和逻辑运算符

6.1 if语句

if语句让程序能够决定是否应执行特定的语句。整个if语句被视为一条语句。
在这里插入图片描述

// 程序清单6.1 if.cpp--using the if statement
#include <iostream>

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;
}

在这里插入图片描述

6.1.1 if else语句

if else语句则让程序决定执行两条语句或语句块中的哪一条。整个if else结构被视为一条语句。
在这里插入图片描述

// 程序清单6.2 ifelse.cpp--using the if else statement
#include <iostream>

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;
}

在这里插入图片描述

6.1.2 格式化if else语句

if else中的两种操作都必须是一条语句。如果需要多条语句,需要用大括号将它们括起来,组成一个块语句。

6.1.3 if else if else结构

整个构造仍被视为一条语句。

// 程序清单6.3 ifelseif.cpp--using if else if else
#include <iostream>

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;
}

在这里插入图片描述

6.2 逻辑表达式

3种逻辑运算符:逻辑OR(||)、逻辑AND(&&)、逻辑NOT(!)

6.2.1 逻辑OR运算符:||

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 <iostream>

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?<y/n> ";

    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;
}

在这里插入图片描述

6.2.2 逻辑AND运算符:&&

逻辑AND运算符(&&),也是将两个表达式组合成一个表达式。仅当原来的两个表达式都为true时,得到的表达式的值才为true。
&&运算符也是顺序点,因此将首先判定左侧,并且在右侧被判定之前产生所有的副作用。如果左侧为false,则整个逻辑表达式必定为false,在这种情况下,C++将不会再对右侧进行判定。
在这里插入图片描述

// 程序清单6.5 and.cpp--using the logical AND operator
#include <iostream>

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.2.3 用&&来设置取值范围

// 程序清单6.6 more_and.cpp--using the logical AND operator
#include <iostream>

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.2.4 逻辑NOT运算符:!

!运算符将它后面的表达式的真值取反。

// 程序清单6.7 not.cpp--using the not operator
#include <iostream>
#include <climits>

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;
    }
}

在这里插入图片描述

6.2.5 逻辑运算符细节

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++确保程序从左向右进行计算逻辑表达式,并在知道答案后立刻停止

6.2.6 其他表示方式

标识符and、or和not都是C++保留字,这意味着不能将它们用作变量名等。它们不是C语言的保留字,但C语言程序可以将它们用作运算符,只要在程序中包含头文件iso646.h。
在这里插入图片描述

6.3 字符函数库cctype

// 程序清单6.8 cctypes.cpp--using the ctype.h library
#include <iostream>
#include <cctype>

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;
}

在这里插入图片描述
在这里插入图片描述

6.4 ?:运算符

条件运算符(?:),它是C++中唯一一个需要3个操作数的运算符。
expression1 ? expression2 : expression3
如果expression1为true,则整个条件表达式的值为expression2的值;否则,整个表达式的值为expression3的值。

// 程序清单6.9 condit.cpp--using the conditional operator
#include <iostream>

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;
}

在这里插入图片描述
条件运算符生成一个表达式,因此是一个值,可以将其赋给变量或将其放到一个更大的表达式中。

6.5 switch语句

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 <iostream>

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.5.1 将枚举量用作标签

// 程序清单6.11 enum.cpp-using enum
#include <iostream>

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;
}

在这里插入图片描述

6.5.2 switch和if else

6.6 break和continue语句

break和continue语句都使程序能够跳过部分代码。可以在switch语句或任何循环中使用break语句,使程序跳到switch或循环后面的语句处执行。continue语句用于循环中,让程序跳过循环体中余下的代码,并开始新一轮循环。
在这里插入图片描述

// 程序清单6.12 jump.cpp--using continue and break
#include <iostream>

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."

6.7 读取数字的循环

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 <iostream>

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 <q to terminate>." << 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 <Enter>
// 程序清单6.14 cingolf.cpp--non-numeric input skipped
#include <iostream>

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;
}

在这里插入图片描述

6.8 简单文件输入/输出

6.8.1 文本I/O和文本文件

使用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输出,将执行相反的操作,即整数被转换为数字字符序列,浮点数据被转换为数字字符和其他字符组成的字符序列,字符数据不需要做任何转换。

6.8.2 写入到文本文件中

文件输入:
(1)必须包含头文件fstream
(2)头文件fstream定义了一个用于处理输出的ofstream类
(3)需要声明一个或多个ofstream对象,并以自己喜欢的方式对其进行命名,条件是遵守常用的命名规则(差异:头文件iostream声明了一个名为cout的ostream对象)
(4)必须指明名称空间std
(5)需要将ofstream对象与文件关联起来
(6)使用完文件后,应使用方法close()将其关闭
(7)可结合使用ofstream对象和运算符<<来输出各种类型的数据(就像使用cout那样使用该ofstream对象)

#include <iostream>
#include <fstream>

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;
}

在这里插入图片描述

6.8.3 读取文本文件

文件输出:
(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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值