程序清单6.1
//using if statement 使用 if 语句
#include<iostream>
using namespace std;
void main()
{
char ch;
int spaces = 0, total = 0;
cin.get(ch);
while(ch != '.')
{
if (ch == ' ')
++spaces;
++total;
cin.get(ch);
}
cout << spaces << " spaces, " << total << " characters toal in sentence." << endl;
}
代码运行如下
仅当 ch 为空格时,语句++spaces; 才被执行。因为语句++total;(这里第六版又出现一个印刷错误)位于 if 语句的外面,因此在每轮循环中都将被执行。注意,字符总数中包括按回车键生成的换行符。
程序清单6.2
//using the if else statement 使用if...esle语句
#include<iostream>
void main()
{
char ch;
std :: cout << "Type, and I shall repeat.\n" ;
std :: cin.get(ch);
while(ch != '.')
{
if (ch == '\n')
std :: cout << ch;
else
std :: cout << ++ch;//这里注意ch++ 和++ch 的区别,两种方法的结果是不是同的
std :: cin.get(ch);
}
std :: cout << "\nPlease excuse the slight confusion.\n"; //又有一个印刷错误
}
运行结果:
如果将 ++ch 改成 ch+1; 运行结果则是:
按类型运算规则,ch+1的类型是int型,因此输出的是数值而非字符。最后注意一点,这里 ++ch 是不能改成 ch++ ,效果如下:
根据运算规则,前缀是先运算再赋值,也就是说程序先接收到字符 s, 转换成ASII为115,由于s != \n,于是进入else语句,又因为ch++是后缀,根据运算规则,后缀是先赋值再运算,即 std :: cout << ch++,到这一句的时候,ch被先赋值为s,ASII码为115,而被打印出来 ch = s,此时并未执行++,
当此句执行完成了,到下一句std :: cin.get(ch); 时ch才被赋值为t, ASII码为116, 即15句未尾才执行++,而不是中间就++了,而虽然
的此时ch = t, ASII码为116,但ch的值已经被上一句赋值给s打印出来了,所以虽然这里ch = t, 已经无意义了
程序清单6.3
//using if else if else statement 使用if...else if...else语句
#include<iostream>
using namespace std;
const int Fave = 27;
void main()
{
int n;
cout << "Enter a number in the range 1-100 to find ";
cout << "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!\n:";
}while (n != Fave);
}
程序运行结果:
程序清单6.4
//using the logical or operator 使用逻辑or运算符
#include<iostream>
using namespace std;
void main()
{
cout << "This program may reformat your hard disk\n"
"and destroy 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! Apparently you "
"can't follow\ninstructions, so "
"I'll trash your disk anyway.\a\a\a\n";
}
由于程序只读取一个字符,因此只读取响应的第一个字符,只要第一个字符是n 或者 N都行,然而,如果程序后面再读取输入时,将从刚才输入的第二个字符开始读取,如上面会读取n 字符。6.22 逻辑 AND 运算符: &&
逻辑 AND 运算符(&&),也是将两个表达式组合成一个表达式。仅当原来的两个表达式都为true时,得到的表达式的值才为true.
5 == 5 && 4 == 4 // true(真), 因为两个表达式都为true(真)
5 == 3 && 4 == 4 // false(假), 因为第一个表达式为false(假),红色为假
5 > 3 && 5 > 10 // false(假), 因为第二个表达式为false(假),红色为假
5 > 8 && 5 < 10 // false(假), 因为第二个表达式为false(假),红色为假
5 < 8 && 5 > 2 // true(真), 因为两个表达式都为true(真)
5 > 8 && 5 < 2 // false(假), 因为两个个表达式都为false(假),红色为假
由于 && 的优先级低于关系运算符, 因此不必在这些表达式中使用括号。和 || 运算符一样, && 运算符也是个顺序点,因此将首先判定左侧,并且在右侧被判定之前产生所有的副作用。如果左侧为 fale, 则整个逻辑表达式必定为 false, 在这种情况下, C++ 将不会再对右侧进行判定。
程序清单 6.5演示了如何使用 && 来处理一种常见的情况-------由于两种不同的原因而结束 while 循环。 在这个程序清单中, 一个 while 循环将值读入到数组中。 一个测试 (i < ArSize) 在数组被填满时循环结束, 另一个测试 (temp >= 0) 让用户通过一个负值来提前结束循环。该程序使用 && 运算符瘵两个测试条件组合成一个条件。该程序还使用了两条 if 语句、 一条 if else 语句和一个 for 循环, 因此它演示了本章和第 5 章的多个主题。
程序清单 6.5 and.cpp
#include<iostream>
using namespace std;
const int ArSize = 6;
void 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.\n";
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\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";
}
}
注意: 该程序将输入放在临时变量 temp 中。在核实输入有效后, 程序才将这个值赋给数组。下面是该程序的运行情况。一次在输入6个数值后结束:
另一次在输入负值后结束:
该程序还有另一种情况,就是第一次输入负值,结果如下:
程序说明
来看看该程序的输入部分:
cin >> temp;
while (i < ArSize && temp >= 0)
{
naaq[ i ] = temp;
++i;
if (i < ArSize)
{
cout << "Next value: ";
cin >> temp;
}
}
该程序首先将第一个输入值读入到临时变量(temp)中。然后, while 测试条件查看数组中是否还有空间 (i < ArSize) 以及输入值是否非负 (temp >= 0)。 如果条件满足, 则将temp的值复制到数组中,并将数组索引加1。 此时, 由于数组下标从0开始, 因此 i 指示输入了多少个值。 也是说, 如果i 从0 开始,则第一轮循环将一个值赋给 naaq[ 0 ], 然后将 i 设置为1。
当数组被填满或用户输入了负值时, 循环将结束。注意仅当i 小于ArSize 时, 即数组中还有空间时,循环才将另处一个值读入到temp 中。
获得数据后, 如果没有输入任何数据(即第一次输入的是一个负数), 程序将使用if else 语句指出这一点。这里发现一个问题,程序是说输入一个负数就结束循环,那么if else的条件应该是 temp < 0吧,为何程序清单中使用的代码却是数组下标 i == 0;有些不解,于是我把条件改成temp < 0; 结果和程序清单中运行还是有些不一样,于是继续用F10一步步运行,当输入的temp < 0,则由于while循环测试条件不满足,程度直接来到if else语句,正好满足if (temp < 0), 根据if else规则,将执行if 语句,跳过else语句,因此无论前面输入了多少非负数,只到碰到一个负数,程序就会来到
if (temp < 0)
cout << "No data -- bye\n";
然后程序直接结束;如果是条件改成i == 0; 则当输入一个负数后,程序由于while 测试条件不成立,跳出while循环,来到if else语句,此时,i 应该是大于0,假设前面输入了正数, 再根据if else规则,if 条件不成立,跳过if,执行else语句,因此会执行和自己输入的NAAQ进行比对,并打印出count的值。
我在想程序已经用 while语句设置了条件 while (i < ArSize && temp >= 0), 红色部分, 为何 while 循环体里还要用同样的条件来测试 if (i < ArSize); 于是乎,我把if (i < ArSize) 和大括号去掉,保留中间两句,运行是不会报错,随便输入了几个值,发现和程序清单中情况没什么区别?例子中应该不会出现画蛇添足的情况了,于是输入和清单中同样的数字时,发现了情况,发现了提示虽然只要输入6次,但是实际中输入了7次,而第7次没有参加 if (i < ArSize) 条件测试,通过F10一步步的运行明白,当第 6 次输入,++i = 6, 由于没有测试条件 if (i < ArSize),直接进入了cout << "Next value: "; 并由语句cin >> temp; 将输入的值赋给了 temp, 再由于此时naaq[ 6 ] = 56; 数组的下标6在测试条件 i < ArSize已经不成立,所以for循环中naaq[ 6 ]将不会被参加if(naaq[ j ] > you)比对。
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 mor_and.cpp
//mor_and.cpp -- using the logical AND operator
#include<iostream>
using namespace std;
const char * qualify[ 4 ] =
{
"10,000-meter race.\n",
"mud tug-of-war.\n",
"masters canoe jousting.\n",
"pie-throwing festival.\n"
};
void 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 qualify for the " << qualify[ index ];
}
运行结果如下:
由于输入的年龄不与任何测试取值范围匹配, 因此程序将索引设置为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) //表这样使用!
编译器不会捕获这种错误, 因为它仍然是有效的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
//not.cpp -- using the not operator (使用 not 逻辑运算符)
#include<iostream>
#include<climits>
using namespace std;
bool is_int(double);
void main()
{
double num;
cout << "Yo, dude! Enter an integer value: ";
cin >> num;
while (!is_int(num)) // continue while num is no