当前位置:   article > 正文

C++PrimerPlus 第六章 分支语句和逻辑运算符 - 6.2 逻辑表达式_cout << count;

cout << count;

C++PrimerPlus 第六章 分支语句和逻辑运算符 - 6.2 逻辑表达式

6.2 逻辑表达式

6.2.1 逻辑OR运算符:||

6.2.2 逻辑AND运算符:&&

6.2.3 用&&来设置取值范围

6.2.4 逻辑NOT运算符:!

6.2.5 逻辑运算符细节

6.2.6 其他表示方式


6.2 逻辑表达式

经常需要测试多种条件。例如,字符要是小写,其值就必须大于或等于 ‘a’,且小于或等于 ‘z’。如果要求用户使用y或n进行响应,则希望用户无论输入大写(Y和N)或小写都可以。为满足这种需要,C++提供了3种逻辑运算符,来组合或修改已有的表达式。这些运算符分别是逻辑OR(||)、逻辑AND(&&)和逻辑NOT(!)。下面介绍这些运算符。

6.2.1 逻辑OR运算符:||

在英语中,当两个条件中有一个或全部满足某个要求时,可以用单词or来指明这种情况。例如,如果您或您在配偶在MegaMicro公司工作,您就可以参加MegaMicro公司的野餐会。C++可以采用逻辑OR运算符(||),将两个表达式组合在一起。如果原来表达式中的任何一个或全部都为true(或非零),则得到的表达式的值为true;否则,表达式的值为false。下面是一些例子:

        5 == 5 || 5 == 9         //true because first expression is true

        5 > 3 || 5 > 10          //true because first expression is true

        5 > 8 || 5 < 10         //true because second expression is true

        5 < 8 || 5 > 2         //true because both expressions are true

        5 > 8 || 5 < 2         //false because both expressions are false

由于||的优先级比关系运算符低,因此不需要在这些表达式中使用括号。下表总结了||的工作原理。

 C++规定,||运算符是个顺序点(sequence point)。也是说,先修改左侧的值,再对右侧的值进行判定(C++11的说法是,运算符左边的子表达式先于右边的子表达式)。例如,请看下面的表达式。

        i++ < 6 || i == j

假设i原来的值为10,则在对i和j进行比较时,i的值将为11。另外,如果左侧的表达式为true,则C++将不会去判定右侧的表达式,因为只要一个表达式为true,则整个逻辑表达式为true(读者可能还记得,冒号和逗号运算符也是顺序点)。

程序清单6.4在一条if语句中使用||运算符来检查某个字符的大写或小写。另外,它还使用了C++字符串的拼接特性(参见第4章)将一个字符串分布在3行中。

程序清单6.4 or.cpp

  1. //or.cpp -- using the logical OR operator
  2. #include<iostream>
  3. int main()
  4. {
  5. using namespace std;
  6. cout << "This program may reformat your hard disk\n"
  7. "and destory all your data.\n"
  8. "Do you wish to continue?<y/n>";
  9. char ch;
  10. cin >> ch;
  11. if (ch == 'y' || ch == 'Y')
  12. cout << "You were warned!\a\a\n";
  13. else if (ch == 'n' || ch == 'N')
  14. cout << "A wise choice ... bye\n";
  15. else
  16. cout << "That wasn't a y or n! Apperantly you "
  17. "can't follow\ninstructions, so "
  18. "I'll trash your disk anyway.\a\a\a\n";
  19. return 0;
  20. }

该程序不会带来任何威胁,下面是其运行情况:

        This program may reformat your hard disk

        and destory all your data.

        Do you wish to continue?<y/n>N

        A wise choice ... bye

由于程序只读取一个字符,因此只读取响应的第一个字符。这意味着用户可以用NO!(而不是N)进行回答,程序将只读取N。然而,如果程序后面再读取输入时,将从O开始读取。

6.2.2 逻辑AND运算符:&&

逻辑AND运算符(&&),也是将两个两个表达式组合成一个表达式。仅当原来的两个表达式都为true时,得到的表达式的值才为true。下面是一些例子:

        5 == 5 && 4 == 4         //true because both expressions are true

        5 == 3 && 4 == 4         //false because first expression is false

        5 > 3 && 5 > 10         //false because second expression is false

        5 > 8 && 5 < 10         //false because first expression is false

        5 < 8 && 5 > 2         //true because both expressions are true

        5 > 8 && 5 < 2         //false because both expressions are false

由于&&的优先级低于关系运算符,因此不必在这些表达式中使用括号。和||运算符一样,&&运算符也是顺序点,因此将首先判定左侧,并且在右侧被判定之前产生所有的副作用。如果左侧为false,则整个逻辑表达式必定为false,在这种情况下,C++将不会再对右侧进行判定。下表总结了&&运算符的工作方式。

 程序清单6.5演示了如何用&&来处理一种常见的情况——由于两种不同的原因而结束while循环。在这个程序清单中,一个while循环将值读入到数组。一个测试(j < ArSize)在数组被填满时循环结束,另一个测试(temp >= 0)让用户通过输入一个负值来提前结束循环。该程序使用&&运算符将两个测试组合成一个条件。该程序还使用了两条if语句、一条if else语句和一个for循环,因此它演示了本章和第5章的多个主题。

程序清单6.5 and.cpp

  1. //and.cpp -- using the logical AND operator
  2. #include<iostream>
  3. const int ArSize = 6;
  4. int main()
  5. {
  6. using namespace std;
  7. float naaq[ArSize];
  8. cout << "Enter the NAAQs (New Age Awareness Quotients) "
  9. << "of\nyour neighbors/ Program terminates "
  10. << "when you make\n" << ArSize << " entries "
  11. << "or enter a negative value.\n";
  12. int i = 0;
  13. float temp;
  14. cout << "First value: ";
  15. cin >> temp;
  16. while (i < ArSize && temp >= 0) //2 quitting criteria
  17. {
  18. naaq[i] = temp;
  19. ++i;
  20. if (i < ArSize) //room left in the array,
  21. {
  22. cout << "Next value: ";
  23. cin >> temp; //so get next value
  24. }
  25. }
  26. if (i == 0)
  27. cout << "No data -- bye\n";
  28. else
  29. {
  30. cout << "Enter your NAAQ: ";
  31. float you;
  32. cin >> you;
  33. int count = 0;
  34. for (int j = 0; j < i; j++)
  35. if (naaq[j] > you)
  36. ++count;
  37. cout << count;
  38. cout << " of your neighbors have greater awareness of\n"
  39. << "the New Age than you do.\n";
  40. }
  41. return 0;
  42. }

注意,该程序将输入放在临时变量temp中。在核实输入有效后,程序才将这个值赋给数组。

下面是该程序的两次运行情况。一次在输入6个值后结束:

        Enter the NAAQs (New Age Awareness Quotients) of

        your neighbors/ Program terminates when you make

        6 entries or enter a negative value.

        First value: 28

        Next value: 72

        Next value: 15

        Next value: 6

        Next value: 130

        Next value: 145

        Enter your NAAQ: 50

        3 of your neighbors have greater awareness of

        the New Age than you do.

另一次在输入负值后结束:

        Enter the NAAQs (New Age Awareness Quotients) of

        your neighbors/ Program terminates when you make

        6 entries or enter a negative value.

        First value: 123

        Next value: 119

        Next value: 4

        Next value: 89

        Next value: -1

        Enter your NAAQ: 123.031

        0 of your neighbors have greater awareness of

        the New Age than you do.

程序说明

来看看该程序的输入部分

  1. cin >> temp;
  2. while (i < ArSize && temp >= 0) //2 quitting criteria
  3. {
  4. naaq[i] = temp;
  5. ++i;
  6. if (i < ArSize) //room left in the array,
  7. {
  8. cout << "Next value: ";
  9. cin >> temp; //so get next value
  10. }
  11. }

该程序首先将第一个输入值读入到临时变量(temp)中。然后,while测试条件查看数组中是否还有空间(i < ArSize)以及输入值是否为非负(temp >= 0)。如果满足条件,则将temp的值复制到数组中,并将数组索引加1。此时,由于数组下标从0开始,因此i指示输入了多少个值。也是说,如果i从0开始,则第一轮循环将一个值赋给naaq[0],然后将i设置为1。

当数组被填满或用户输入了负值时,循环将结束。注意,仅当i小于ArSize时,即数组中还有空间时,循环才将另外一个值读入到temp中。

获得数据后,如果没有输入任何数据(即第一次输入的是一个负数),程序将使用if else语句指出这一点,如果存在数据,就对数据进行处理。

6.2.3 用&&来设置取值范围

&&运算符还允许建立一系列if else if else语句,其中每种选择都对应于一个特定的取值范围。程序清单6.6演示了这种方法。另外,它还演示了一种用于处理一系列消息的技术。与char指针变量可以通过指向一个字符串的开始位置来标识该字符串一样,char指针数组也可以标识一系列字符串,只要将每一个字符串的地址赋给各个数组元素即可。程序清单6.6使用qualify数组来存储4个字符串的地址,例如,qualify[1]存储字符串“mud tug-of-war\n”的地址。然后,程序便能够将cout、strlen()或strcmp()用于qualify[1],就像用于其他字符串指针一样。使用const限定符可以避免无意间修改这些字符串。

程序清单6.6 more_and.cpp

  1. //more_and.cpp -- using the logical AND operator
  2. #include<iostream>
  3. const char* qualify[4] = //an array of pointers
  4. { //to strings
  5. "10,000-meter race,\n",
  6. "mud tug-of-war.\n",
  7. "masters canie jousting.\n",
  8. "pie-throwing festival.\n"
  9. };
  10. int main()
  11. {
  12. using namespace std;
  13. int age;
  14. cout << "Enter your age in years: ";
  15. cin >> age;
  16. int index;
  17. if (age > 17 && age < 35)
  18. index = 0;
  19. else if (age >= 35 && age < 50)
  20. index = 1;
  21. else if (age >= 50 && age < 65)
  22. index = 2;
  23. else
  24. index = 3;
  25. cout << "You qualify for the " << qualify[index];
  26. return 0;
  27. }

下面是该程序的运行情况:

        Enter your age in years: 87

        You qualify for the pie-throwing festival.

由于输入的年龄不与任何测试取值范围匹配,因此程序将索引设置为3,然后打印相应的字符串。

程序说明

在程序清单6.6中,表达式age > 17 && age < 35测试年龄是否位于两个值之间,即年龄是否在18岁到34岁之间。表达式age >= 35 && age < 50运算符<=运算符将35包括在取值范围内。如果程序使用age > 35 && age < 50,则35将被所有的测试忽略。在使用取值范围测试时,应确保取值范围之间既没有缝隙,又没有重叠。另外,应确保正确设置每个取值范围(参加本节后面的旁注“取值范围测试”)。

if else语句用来选择数组索引,而索引则标识特定的字符串。

取值范围测试

取值范围测试的每一部分都使用AND运算符将两个完整的关系表达式组合起来:

        if (age > 17 && age < 35) //OK

不要使用数学符号将其表示为:

        if (17 < age < 35) //Don’t do this!

编译器不会捕捉这种错误,因为它仍然是有效的C++语法。<运算符从左向右结合,因此上述表达式的含义如下:

        if ((17 < age) < 35)

但17 < age的值要么为true(1),要么为false(0)。不管是哪种情况,表达式17 < age的值都小于35,因此整个测试的结果总是true!

6.2.4 逻辑NOT运算符:!

!运算符将它后面的表达式的真值取反。也是说,如果expression为true,则!expression是false;如果expression为false,则!expression是true。更准确地说,如果expression为true或非零,则!expression为false。

通常,不使用这个运算符可以更清楚地表示关系:

        if (!(x > 5)) //if (x <= 5) is clearer

然而,!运算符对于返回true-false值或可以被解释为true-false值的函数来说很有用。例如,如果C-风格字符串s1和s2不同,则strcmp(s1, s2)将返回非零(true)值,否则返回0。这意味着如果这两个字符串相同,则!strcmp(s1, s2)为true。

程序清单6.7使用这种技术(将!运算符用于函数返回值)来筛选可赋给int变量的数字输入。如果用户定义的函数is_int()(稍后将详细介绍)的参数位于int类型的取值范围内,则它将返回true。然后,程序使用while(!is_int(num))测试来拒绝不在该取值范围内的值。

程序清单6.7 not.cpp

  1. //not.cpp -- using the not operator
  2. #include<iostream>
  3. #include<climits>
  4. bool is_int(double);
  5. int main()
  6. {
  7. using namespace std;
  8. double num;
  9. cout << "Yo, dude! Enter an integer value: ";
  10. cin >> num;
  11. while (!is_int(num)) //continue while num is not int-able
  12. {
  13. cout << "Out of range -- please try again: ";
  14. cin >> num;
  15. }
  16. int val = int(num); //type cast
  17. cout << "You've entered the integer " << val << "\nBye\n";
  18. return 0;
  19. }
  20. bool is_int(double x)
  21. {
  22. if (x <= INT_MAX && x >= INT_MIN) //use climits values
  23. return true;
  24. else
  25. return false;
  26. }

下面是该程序在int占32位的系统上的运行情况:

        Yo, dude! Enter an integer value: 6234128679

        Out of range -- please try again: -8000222333

        Out of range -- please try again: 99999

        You've entered the integer 99999

        Bye

程序说明

如果给读取int值的程序输入一个过大的值,很多C++实现只是将这个值截短为合适的大小,并不会通知丢失了数据。程序清单6.7中的程序避免了这样的问题,它首先将可能的int值作为double值来读取。double类型的精度足以存储典型的int值,且取值范围更大。另一种选择是,使用long long来存储输入的值,因为其取值范围比int大。

布尔函数is_int()使用了climits文件(第3章讨论过)中定义的两个符号常量(INT_MAX和INT_MIN)来确定其参数是否位于适当的范围内。如果是,该函数将返回true,否则返回false。

main()程序使用while循环来拒绝无效输入,直到用户输入有效的值为止。可以在输入超出取值范围时显示int的界限,这样程序将更为友好。确认输入有效后,程序将其赋给一个int变量。

6.2.5 逻辑运算符细节

正如本章前面指出的,C++逻辑OR和逻辑AND运算符的优先级都低于关系运算符。这意味着下面的表达式

        x > 5 && x < 10

将被解释为:

        (x > 5) && (x < 10)

另一方面,!运算符的优先级高于所有的关系运算符和算术运算符。因此,要对表达式求反,必须用括号将其括起,如下所示:

        !(x > 5)         //is it false that x is greater than 5

        !x > 5         //is !x greater than 5

第二个表达式总是为false,因为!x的值只能为true或false,而它们将被转换为1或0。

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

        age > 30 && age < 45 || weight > 300

被解释为:

        (age > 30 && age < 45) || weight > 300

也是说,一个条件是age位于31~44,另一个条件是weight大于300。如果这两个条件中的一个或全部都为true,则整个表达式为true。

当然,还可以用括号将所希望的解释告诉程序。例如,假设要用&&将age大于50或weight大于300的条件与donation大于1000的条件组合在一起,则必须使用括号将OR部分括起:

        (age > 50 || weight > 300) && donation > 1000

否则,编译器将把weight条件与donation条件(而不是age条件)组合在一起。

虽然C++运算符的优先级规则常可能不使用括号便可以编写复合比较的语句,但最简单的方法还是用括号将测试进行分组,而不管是否需要括号。这样代码容易阅读,避免读者查看不常使用的优先级规则,并减少由于没有准确记住所使用的规则而出错的可能性。

C++确保程序从左向右进行计算逻辑表达式,并在知道答案后立刻停止。假如,假设有下面的条件:

        x != 0 && 1.0 / x > 100.0

如果第一个条件为false,则整个表达式肯定为false。这是因为要使整个表达式为true,每个条件都必须为true。知道第一个条件为false后,程序将不判定为第二个条件。这个例子非常幸运,因为计算第二个条件将导致被0除,这是计算机没有定义的操作。

6.2.6 其他表示方式

并不是所有的键盘都提供了用作逻辑运算符的符号,因此C++标准提供了另一种表示方式,如下表所示。标识符and、or和not都是C++保留字,这意味着不能将它们用作变量名等。它们不是关键字,因为它们都是已有语言特性的另一种表示方式。另外,它们并不是C语言中的保留字,但C语言程序可以将它们用作运算符,只要在程序中包含了头文件iso646.h。C++不要求使用头文件。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/781007
推荐阅读
相关标签
  

闽ICP备14008679号