第6章 分支语句和逻辑运算符
文章目录
逻辑表达式
逻辑运算符OR(||)、AND(&&)、NOT(!)
运算符左边的子表达式先于右边的子表达式,例如:
i++<6||i==j //假设i=10,则在i和j比较时,i的值将为11.
另外,如果左侧的表达式为True,则c++不会去判定右边的表达式。
逻辑运算符细节
-
c++逻辑OR和AND的优先级都低于关系运算符。
-
而!的优先级高于所有的关系运算符和算术运算符,因此,要对表达式求反,要用括号括起来:
!(x>6)
!x>5 //表达式总是为false,因为!x的值只能是true或false,而它们将被转化为1或0.
-
逻辑AND的优先级高于OR:age>30&&age<45||weight>300
-
and、or、not是它们的另一种表现方式,因为并不是所有的键盘都提供了用作逻辑运算符的符号。
字符函数库cctype
可以简化诸如确定字符是否为大写字母、数字、标点符号等工作,在头文件cctype中定义。例如:
如果ch是一个字母,函数isalpha(ch)函数返回一个非零值,否则返回0。
如果ch是一个标点符号,函数ispunct(ch)将返回true。
#include <iostream>
#include <cctype>
int main(){
using namespace std;
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))
digits++;
else if(ispunct(ch))
punct++;
else
others++;
cin.get(ch);
}
cout<<chars<<"letters,"
<<whitespace<<"whitespace,"
<<digits<<"digits,"
<<punct<<"punct,"
<<others<<"other.\n";
return 0;
}
?:运算符
c++有一个被用来代替if else语句的运算符——条件运算符(?:),它是c++中唯一一个需要3个操作数的运算符。通用格式如下:
expression1 ? expression2:expression3
如果expression1的值为true,则整个表达式的值为expression2的值;否则为expression3的值。
5>3 ? 10:12 //表达式的值为10
#include <iostream>
int main(){
using namespace std;
int a,b;
cout<<"enter: ";
cin>>a>>b;
cout<<"the larger is ";
int c=a>b ?a:b;
cout<<c<<endl;
return 0;
}
上面的程序用来确定两个数中较大的一个。与if else的区别是,条件运算符生成一个表达式,因此是一个值,可以将其赋给变量或将其放到一个更大的表达式中。
switch语句
通用格式:
switch(inter-expression)
{
case label1:statement(s)
case label1:statement(s)
…
default :statement(s)
}
switch语句就像是指路牌。执行到switch语句时,程序将跳到使用inter-expression的值标记的哪一行,例如,如果inter-expression的值为4,则程序将执行标签为case4:那一行。
- inter-expression必须是一个结果为整数值的表达式。
- 每个标签都必须是整数常量表达式,最常见的标签是int或char常量,也可以是枚举量。
- 如果 inter-expression不与任何标签匹配,则程序将跳到标签为default的那一行。
- default标签是可选的,如果被省略,而又没有匹配的标签,则程序将跳到switch后面的语句处执行。
- 要让程序执行完一组特定语句后停止,必须使用break语句。否则将接着执行下一条case语句。
将枚举量用作标签
#include <iostream>
enum{red,orange,yellow,green};
int main(){
using namespace std;
cout<<"enter color code: ";
int code;
cin>>code;
while(code>=red && code<=green)
{
switch(code){
case red:cout<<"red\n";break;
case orange:cout<<"orange\n";break;
case yellow:cout<<"yellow\n";break;
case green:cout<<"green\n";break;
}
cout<<"enter color : ";
cin>>code;
}
cout<<"Bye\n";
return 0;
}
上述程序使用enum定义了一组常量,通常,cin无法识别枚举类型(它不知道程序员是如何定义它们的),因此该程序要求用户选择选项使输入一个整数。当switch语句将int值和枚举量标签进行比较时,将枚举量提升为int。在while循环测试中,也会将枚举量提升为int。
switch和if else
switch语句中的每一个case标签都必须是一个单独的值,而且这个值必须是整数(包括char),因此switch无法处理浮点测试。另外,case标签值还必须是常量。
如果涉及取值范围、浮点测试或两个变量的比较,则应使用if else语句。
break和continue语句
都使程序能够跳过部分代码。可以在switch语句和任何循环中使用break语句。continue用于循环中
#include <iostream>
const int Arsize=80;
int main(){
using namespace std;
char line[Arsize];
int spaces=0;
cout<<"enter a line of text:\n";
cin.get(line,Arsize);
cout<<"Complete line:\n"<<line<<endl;
cout<<"LIne through first period:\n";
for(int i=0;line[i]!='\0';i++)
{
cout<<line[i];
if (line[i]=='.')
break;
if (line[i]!=' ')
continue;
spaces++;
}
cout<<"\n"<<spaces<<"space\n";
return 0;
}
在该程序中,满足某条件时,使用break来结束循环。接下来,程序计算空格数,但不计算其他字符。当字符不为空格时,循环使用continue语句跳过计数部分。
continue导致程序跳过循环体的剩余部分,但不会跳过循环的更新表达式。
在for循环中,continue语句使程序直接跳到更新表达式处,然后跳到测试表达式处。
在while循环中,continue将使程序直接跳到测试表达式处,因此while循环体中位于continue之后的更新表达式都将被跳过。
当continue之后有多条语句时,可以提高程序的可读性,这样就不必将所有的语句放在if中。
c++也有goto语句。下面的语句将跳到使用paris:作为标签的位置
读取数字的循环
假设要编写一个将一系列数字读入到数组中的程序,并允许用户在数组填满之前结束输入。一种方法是利用cin。
如果用户输入一个单词,而不是一个数字。这种类型不匹配的现象将导致对cin的调用将返回false(如果被转换为bool类型)
方法返回false意味着可以用非数字输入来结束读取数字的循环,非数字输入设置错误标记意味着必须重置该标记,程序才能继续读取输入。clear()方法重置错误输入标记,同时也重置文件尾。错误输入和EOF都将导致cin返回false。
编写一个程序,计算平均每天捕获的鱼的重量。这里假设每天最多捕获5条鱼,因此一个包含5个元素的数组将足以存储所有的数据,但也可能没有捕获这么多鱼。
#include <iostream>
const int Max=5;
int main(){
using namespace std;
double fish[Max];
cout<<"enter weight: \n";
cout<<"you may enter up to "<<Max<<" fish<q to terminate>.\n";
cout<<"fish #1: ";
int i=0;
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\n";
else
cout<<total/i<<"=average weight of ";
cout<<"done.\n";
return 0;
}
这个程序输入’q’结束输入。
如果逻辑AND的左边为false,则c++不会判断右侧的表达式。从而不会再将一个值读入到数组后面的位置中。
假设程序要求用户提供5个高尔夫得分,以计算平均成绩。如果用户输入非数字输入,程序将拒绝,并要求用户继续输入数字。
#include <iostream>
const int Max=5;
int main(){
using namespace std;
int golf[Max];
cout<<"enter weight: \n";
cout<<"you may enter up to "<<Max<<" rounds.\n";
int i=0;
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: ";
}
}
double total=0.0;
for (i=0;i<Max;i++)
total+=golf[i];
cout<<total/i<<"=average weight of ";
cout<<"done.\n";
return 0;
}
如果输入数字,则cin表达式为true,把一个值放到数组中;而 !(cin>>golf[i])为false,因此结束内部循环。
如果输入非数字,则cin表达式将为false,因此不会把任何值放到数组中,而表达式!(cin>>golf[i])为true,进入内部循环。
循环的第一句使用clear()方法重置输入,如果省略这条语句,程序将拒绝继续读取输入。接下来,程序在while循环中使用cin.get()来读取行尾之前的所有输入,从而删除这一行中的错误输入。
简单文本输入/输出
有时,通过键盘输入并非最好的选择。例如,假设编写了一个股票分析程序,并下载了一个文件,其中包含1000种股票的价格。在这种情况下,让程序直接读取文件,而不是手工输入文件中的所有值所方便的多。
文本I/O和文本文件
使用cin进行输入时,程序将输入视为一系列的字节,其中每个字节都被解释为字符编码。不管目标数据类型是什么,输入一开始都是字符数据——文本数据。然后,cin对象负责将文本转换为其他类型。
假设有如下输入行:38.5、19.2
-
首先来看char数据类型的情况:
char ch;
cin>>ch;
输入行中的第一个字符被赋给ch。在这里,第一个字符是数字3,其字符编码被存储在变量ch中。输入和目标变量都是字符,因此无需转换。
-
int n;
cin>>n;
cin将不断读取,直到遇到非数字字符,即读取3和8,句点成为输入队列中的下一个字符
cin通过计算发现,这两个字符对应数值是38,因此将38的二进制编码复制到变量n中。
-
double x;
cin>>x;
cin不断读取,直到遇到第一个不属于浮点数的字符。cin将读取3、8、句点和5。空格成为输入队列的下一个字符。