• 《C++ Primer plus 》第六章:分支语句和逻辑运算符


    if语句

    1. if (test-condition)
      statement

    2. if
      else

    3. if
      else if
      else

    逻辑表达式

    1. 逻辑OR运算符:||

      C++规定,||运算符是个顺序点(sequence point)。也是说,先修改左侧的值,再对右侧的值进行判定。例如,如下表达式
      i++ < 6 || i == j
      假设 i 原来的值为10,在将i++与6进行比较时,i++的值为10,但在将i与j进行比较时,i的值为11;

      另外,如果左侧的表达式为true,则C++将不会去判定右侧的表达式,因为只要一个表达式为 true,则整个逻辑表达式为 true(冒号和逗号运算符也是顺序点)

    2. 逻辑AND运算符:&&

    3. 逻辑NOT运算符:!

      一些细节:

      C++逻辑OR和逻辑AND运算符的优先级都低于关系运算符。
      这意味着下面的表达式:
      x > 5 && x < 10
      将被解释为:
      (x>5) && (x<10)
      另一方面,!运算符的优先级高于所有的关系运算符和算术运算符。因此,要对表达式求反,必须用括号将其括起,如下所示:
      !(x>5)
      而!x > 5 的值总是false,因为!x的值只能为true或false,而它们将被转换为 1 或 0.

      逻辑 AND 运算符的优先级高于逻辑 OR 运算符。因此,表达式:

      age > 30 && age < 45 || weight > 300
      会被解释为 :(age > 30 && age < 45) || (weight > 300)
      如果这两个条件中的一个或全部都为 true,则整个表达式为true。

      但最简单的方法就是用括号,这样代码容易阅读,避免读者查看不常使用的优先级规则,并减少由于没有准确记住所使用的规则而出错的可能性。

      C++提供了逻辑运算符的另一种表示方式:
      && ----- and
      || ------ or
      ! ----- not
      这意味着 and、or、not 都是C++保留字,不能用作变量名。它们并不是C语言的保留字,但是在程序中包含了iso646.h头文件,C程序也可以将它们用作运算符。

    字符函数库 cctype

    C++从C语言继承了一个与字符相关的、非常方便的函数软件包,它可以简化诸如确定字符是否为大写字母、数字、标点符号等工作,这些函数的原型是在头文件cctype(老式风格为ctype.h)中定义的。例如,如果ch是一个字母,则 isalpha(ch) 函数返回一个非零值,否则返回0。同样,如果 ch 是标点符号(如逗号或句号),函数 ispunct(ch) 将返回 true。(这些函数的返回类型为 int,而不是 bool,但通常 bool 转换 可以让程序员把它们当作 bool 类型。)

    函数名称返回值
    isalnum()如果参数是字母数字,即字母或数字,该函数返回true
    isalpha()如果参数是字母,该函数返回 true
    iscntrl()如果参数是控制字符,该函数返回 true
    isdigit()如果参数是数字(0~9),返回 true
    isgraph()如果参数是除空格之外的打印字符,返回true
    islower()如果参数是小写字母,返回true
    isprint()如果参数是打印字符(包括空格),返回true
    ispunct()如果参数是标点符号,返回 true
    isspace()如果参数是标准空白字符,如空格、进纸、换行符、回车、水平制表符或者垂直制表符,返回true
    isupper()如果参数是大写字母,返回 true
    isxdigit()如果参数是十六进制数字,即 0~ 9、a~ f或 A ~ F,返回 true
    tolower()如果参数是大写字符,则返回其小写,否则返回该参数
    toupper()如果参数是小写字符,则返回其大写,否则返回该参数

    条件运算符 ?:

    C++有一个常被用来代替 if else 语句的运算符,这个运算符被称为条件运算符(?:),条件运算符(?:)是 C++ 中唯一一个需要 3 个操作数的运算符。该运算符的通用格式如下:
    expression1 ? expression2 : expression3
    如果 expression1 为 true,则整个表达式的值为 expression2 的值;否则,整个表达式的值为 expression3 的值。下面的两个示例演示了该运算符是如何工作的:

    5 > 3 ? 10 : 12  		// 5>3 is true, so expression value is 10
    3 ==  9 ? 25 : 18     	// 3 == 9 is false, so expression value is 18
    
    • 1
    • 2

    用一句话概括就是:真前假后

    switch 语句

    switch (integer-expression){
    	case label1 : statement(s)
    	case label2 : statement(s)
    	case label3 : statement(s)
    	...
    	default		: statement(s)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    顾名思义,interger-expression 必须是一个结果为整数值的表达式相应的,每个标签都必须是整数常量表达式

    最常见的标签是 int 或 char 常量,也可以是枚举量。
    如果 integer-expression 不与任何标签匹配,则程序将跳到标签为 default 的那一行。
    Default 标签是可选的,如果被省略,而又没有匹配的标签,则程序将跳到 switch 后面的语句处执行。

    C++ 中的 case 标签只是行标签,而不是选项之间的界限。也就是说,程序跳到switch中特定代码行之后,将依次执行之后的所有语句,除非有明确的其它指示。程序不会在执行到下一个case处自动停止,要让程序执行完一组特定语句后停止,必须使用 break 语句,这将导致程序跳到 switch 后面的语句处执行。switch语句会执行第一次进入case之后的所有语句,包括在那之后的其它case的语句

    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 'c':
    		case 'C': comfort();
    					break;
    		default : cout << "That's not a choice.\n"
    	}
    	showmenu();
    	cin >> choice;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    由于case ‘a’ 后面没有 break 语句,因此程序将接着执行下一行——case ‘A’ 后面的语句。

    switch 语句 和 if else 语句都允许程序从选项中进行选择。相比之下,if else 更通用。例如,它可以处理取值范围,如下所示:

    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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    然而,switch并不是为处理取值范围而设计的。switch语句中的每一个case标签都必须是一个单独的值。另外,这个值必须是整数(包括 char),因此 switch 无法处理浮点测试。另外 case 标签值还必须是常量。如果选项设计取值范围、浮点测试或两个变量的比较,则应使用 if else 语句。

    然而,如果所有的选项都可以使用整数常量来标识,则可以使用 switch 语句 或 if else 语句。由于switch语句是专门为这种情况设计的,因此,如果选项超过了两个,则就代码长度和执行速度而言,switch语句的效率更高。

    break 和 continue 语句

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

    虽然 continue 语句会跳过循环体的剩余部分,但不会跳过循环的更新表达式。在for循环中,continue 语句使程序直接跳到更新表达式处,然后跳到测试表达式处。
    然而,对于while循环来说,continue 将使程序直接跳到测试表达式处,这意味着位于continue之后的更新表达式都将被跳过。在某些情况下,这可能是一个问题。

    和 C 语言一样, C++ 也有goto语句。下面的语句将跳到使用 paris: 作为标签的位置:
    goto paris;
    也就是说,可以有下面这样的代码:

    char ch;
    cin >> ch;
    if(ch == 'P')
    	goto paris;
    cout << ...
    ...
    paris: cout << "You've just arrived at Paris.\n";
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在大多数情况下(有些人认为,在任何情况下),使用 goto 语句不好,而应使用结构化控制语句(如 if else、switch、continue 等)来控制程序的流程。

    读取数字的循环

    int n;
    cin >> n
    如果用户输入一个单词,而不是一个数字,情况将如何呢?发生这种类型不匹配的情况时,将发生4种情况:

    • n的值保持不变
    • 不匹配的输入将被留在输入队列中
    • cin对象中的一个错误标记被设置
    • 对cin方法的调用将返回false(如果被转换为bool类型)
      方法返回false意味着可以用非数字输入来结束读取数字的循环。非数字输入设置错误标记意味着必须重置该标记,程序才能继续读取输入。clear()方法重置错误输入标记,同时也重置文件尾。输入错误和EOF都将导致cin返回false。
    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: ";
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    简单的文件输入/输出

    C++使得将读取键盘输入和在屏幕上显示输出(统称为控制台输入/输出、控制台I/O)的技巧用于文件输入/输出(文件I/O)非常简单。

    这里讨论文本文件,即每个字节都存储了一个字符编码的文件。

    先总结一下有关将cout用于控制台输出的基本事实,为文件输出做准备:

    • 必须包含头文件 iostream
    • 头文件iostream定义了一个用来处理输出的 ostream 类
    • 头文件iostream声明了一个名为cout的ostream变量(对象)
    • 必须指明名称空间std;例如,为引用元素cout和endl,必须使用编译指令using或者前缀std::。
    • 可以结合使用cout和运算符<<来显示各种类型的数据

    文件输出与此极其相似

    • 必须包含头文件 fstream
    • 头文件 fstream定义了一个用于处理输出的 ofstream 类
    • 需要声明一个或多个ofstream变量(对象),并以自己喜欢的方式命名,但要遵守命名规则
    • 必须指明名称空间std;例如,为引用元素 ofstream,必须使用编译指令 using 或前缀 std::
    • 需要将 ofstream 对象与文件关联起来。为此,方法之一是使用 open() 方法
    • 使用完文件后,应使用方法 close() 将其关闭
    • 可结合使用 ofstream 对象和运算符<<来输出各种类型的数据

    注意,虽然头文件iostream提供了一个预先定义好的名为cout的ostream对象,但您必须声明自己的ofstream对象,为其命名,并将其同文件关联起来。

    下面演示了如何声明这种对象:
    ofstream outFile;
    ofstream fout;

    下面演示了如何将这种对象与特定的文件关联起来:
    outFile.open(“fish.txt”);
    char filename[50];
    cin >> filename;
    fout.open(filename)
    方法open()接受一个C-风格字符串作为参数,这可以是一个字面字符串,也可以是存储在数组中的字符串。
    下面演示了如何使用这种对象:
    double wt = 125.8;
    outFile << wt;
    char line[81] = “Objects are closer than they appear.”;
    fout << line << endl; // write a line of text

    重要的是,声明一个 ofstream 对象并将其同文件关联起来后,便可以像使用 cout 那样使用它。所有可用于 cout 的操作和方法(如 <<、endl 和 setf())都可用于 ofstream 对象(如前述示例中的 outFile 和 fout)。

    总之,使用文件输出的主要步骤如下:

    1. 包含头文件 fstream
    2. 创建一个 ofstream 对象
    3. 将该 ofstream 对象同一个文件关联起来
    4. 就像使用 cout 那样使用该 ofstream 对象

    默认情况下,open()将首先截断该文件,即将其长度截短到零——丢其原有的内容,然后将新的输出加入到该文件中。
    打开文件用于接受输入时可能失败。例如,指定的文件可能已经存在,但是禁止对其进行访问。因此细心的程序员将检查打开文件的操作是否成功,这将在下一个例子中介绍。

    接下来介绍文本文件输入,它是基于控制台输入的。控制台输入涉及多个方面,下面首先总结这些方面:

    • 必须包含头文件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 对象和运算符 >> 来读取各种类型的数据
    • 可以使用ifstream对象和get()方法来读取一个字符,使用 ifstream 对象和getline() 来读取一行字符
    • 可以结合使用 ifstream 和 eof()、fail()等方法来判断输入是否成功
    • ifstream对象本身被用作测试条件时,如果最后一个读取操作成功,它将被转换为布尔值true,否则被转换为false

    如果试图打开一个不存在的文件用于输入,情况将如何呢?这种错误将导致后面使用 ifstream 对象进行输入时失败。检查文件是否被成功打开的首先方法是使用方法 is_open(),为此,可以使用类似于下面的代码:

    inFile.open("bowling.txt");
    if ( !inFile.is_open()){
    	exit(EXIT_FAILURE);
    }
    
    inFile >> value;
    while(inFile.good()){
    	...
    }
    if(inFile.eof()){
    }
    else if (inFile.fail()){
    }
    else{
    
    }
    inFile.close();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    注意,good()方法指出最后一次读取输入的操作是否成功,这一点至关重要。为此,一种标准的方法是,在循环之前(首次执行循环测试之前)放置一条输入语句,并在循环的末尾(下次执行循环测试之前)放置另一条输入语句:

    inFile >> value;
    while(inFile.good()){
    	...
    	inFile >> value;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    或者,直接改为
    while(inFile >> value){

    }

  • 相关阅读:
    Grafana Prometheus 监控JVM进程
    undefined reference to `timersub‘ 错误处理
    UE5 官方案例Lyra 全特性详解 9.蓝图消息系统
    聚乙烯亚胺偶联乳清白蛋白/肌白蛋白/豆清白蛋白/蓖麻蛋白/豌豆白蛋白1b ( PA1b)科研试剂
    计算机毕设 大数据工作岗位数据分析与可视化 - python flask
    磁盘性能测试
    分析Java中 CharSequence源码
    css3中有哪些伪选择器?
    ant design ant design Pro 中的table横向与纵向合并问题
    学习-Java继承和多态之对象类型的转换
  • 原文地址:https://blog.csdn.net/weixin_40064300/article/details/127966049