0
点赞
收藏
分享

微信扫一扫

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

前行的跋涉者 2022-04-15 阅读 133

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

//or.cpp -- using the logical OR operator
#include<iostream>
int main()
{
	using namespace std;
	cout << "This program may reformat your hard disk\n"
			"and destory all your data.\n"
			"Do you wish 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 ... bye\n";
	else
		cout << "That wasn't a y or n! Apperantly you "
				"can't follow\ninstructions, so "
				"I'll trash your disk anyway.\a\a\a\n";
	return 0;
}

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

        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

//and.cpp -- using the logical AND operator
#include<iostream>
const int ArSize = 6;
int main()
{
	using namespace std;
	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.\n";

	int i = 0;
	float temp;
	cout << "First value: ";
	cin >> temp;
	while (i < ArSize && temp >= 0)	//2 quitting criteria
	{
		naaq[i] = temp;
		++i;
		if (i < ArSize)				//room left in the array,
		{
			cout << "Next value: ";
			cin >> temp;			//so get next value
		}
	}
	if (i == 0)
		cout << "No data -- bye\n";
	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.\n";
	}
	return 0;
}

注意,该程序将输入放在临时变量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.

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

//more_and.cpp -- using the logical AND operator
#include<iostream>
const char* qualify[4] =		//an array of pointers
{								//to strings
	"10,000-meter race,\n",
	"mud tug-of-war.\n",
	"masters canie jousting.\n",
	"pie-throwing festival.\n"
};
int main()
{
	using namespace std;
	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 qualify for the " << qualify[index];
	return 0;
}

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

        Enter your age in years: 87

        You qualify for the pie-throwing festival.

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

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

//not.cpp -- using the not operator
#include<iostream>
#include<climits>
bool is_int(double);
int main()
{
	using namespace std;
	double num;

	cout << "Yo, dude! Enter an integer value: ";
	cin >> num;
	while (!is_int(num))		//continue while num is not int-able
	{
		cout << "Out of range -- please try again: ";
		cin >> num;
	}
	int val = int(num);			//type cast
	cout << "You've entered the integer " << val << "\nBye\n";
	return 0;
}
bool is_int(double x)
{
	if (x <= INT_MAX && x >= INT_MIN)	//use climits values
		return true;
	else
		return false;
}

下面是该程序在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

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++不要求使用头文件。

举报

相关推荐

0 条评论