首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

如果给定的条件是true,基本的if语句允许程序执行一个语句或一个包含在花括号中的语句块。如图4-1所示。

图4-1 简单if语句的逻辑

下面是if语句的一个简单例子,它测试类型为char的变量letter的值:

if(letter == 'A')

std::cout << "The first capital, alphabetically speaking.\n";

std::cout << "This statement always executes.\n";

如果letter的值是'A',条件就为true,这些语句就输出下面的结果:

The first capital, alphabetically speaking.

This statement always executes.

如果letter的值不是'A',就只输出第二行语句。要测试的条件放在关键字if后面的括号中。注意分号的位置,它位于if和括号中的条件后面的语句之后。在括号中的条件的后面不能有分号,因为if和条件是和后面的语句或语句块绑定在一起的。它们本身是不能单独存在的。

if之后的语句只有在条件为true时才执行。对于程序的编译来说,语句的缩进是不必要的,但这种缩进有助于理解if条件和依赖它的语句之间的关系。有时,简单的if语句还可以写在一行上:

if (letter == 'A') std::cout << "The first capital, alphabetically speaking.\n";

一般情况下,最好把语句(或语句块)和if条件放在不同的代码行上,这样会更清楚。

扩展这个例子,如果letter的值是'A',就改变它的值;

if(letter == 'A') {

std::cout << 'The first capital, alphabetically speaking.\n";

letter = 'a';

}

std::cout << "This statement always executes.\n";

在if条件为true时,就执行块中的所有语句。如果没有加上花括号,则只有第一个语句是if块的内容,给letter赋予'a'的语句将总是执行。注意在块中每个语句的最后都有一个分号,而在块结束的右花括号后面没有分号。在块中可以放置任意多个语句,甚至还可以嵌套块,因为letter的值是'A',所以块中的两个语句都会执行,在输出与前面相同的消息后,就把它的值改为'a'。如果条件为false,就不执行这两个语句。当然,if块后面的语句总是执行。

程序示例4.2—— 作出决策

下面试用if语句。创建一个程序,检查从键盘上输入的一个整数值:

//Program 4.2 Using an if statement

#include <iostream>

using std::cin;

using std::cout;

using std::endl;

int main() {

cout << " Enter an integer between 50 and 100: ";

int value=0;

cin>> value;

if(value<50)

cout << " The value is invalid – it is less than 50."<<endl;

if(value>100)

cout << " The value is invalid – it is greater than 100."<<endl;

cout << " You entered"<<value<<endl;

return 0;

}

输出取决于输入的值。对于值为50~100之间的数据,输出应如下所示:

Enter an integer between 50 and 100: 77

You entered 77

如果输入的值在50~100的范围之外,就给出一个消息,说明值是无效的,并显示该值。如果该值小于50,输出应如下所示:

Enter an integer between 50 and 100: 27

The value is invalid – it is less than 50.

You entered 27

如果该值大于100,输出应如下所示:

Enter an integer between 50 and 100: 270

The value is invalid – it is greater than 100.

You entered 270

例子的说明

在给出提示,读取一个值后,第一个if语句就会检查输入的值是否小于下限50:

if(value<50)

cout << " The value is invalid – it is less than 50."<<endl;

只有if条件为true时,也就是当value小于50时,才执行输出语句。下一个if语句检查上限:

if(value>100)

cout <<" The value is invalid – it is greater than 100."<<endl;

如果value大于100,就执行该输出语句。最后一个输出语句是:

cout << " You entered"<<value<<endl;

这个语句总是执行。

嵌套的if语句

在if语句中的条件为true时才执行的语句本身也可以是一个if语句,这种情况称为嵌套的if语句。只有外层if的条件为true时,才测试内层if的条件。嵌套在一个if语句中的if语句也可以包含另一个嵌套的if语句。一般情况下,可以像这样继续嵌套if语句,嵌套的次数也可以是任意多次。

程序示例4.3—— 使用嵌套的if语句

下面用一个工作示例来演示嵌套的if语句。该示例测试从键盘上输入的字符是否为字母。这个示例很好地使用了嵌套的if语句,但其中一些固有的假设最好避免,读者可以试着找出这些假设。下面是代码:

//Program 4.3 Using a nested if

#include <iostream>

using std::cin;

using std::cout;

using std::endl;

int main() {

char letter=0; // Store input in here

cout << "Enter a letter: "; // Prompt for the input

cin >> letter; // then read a character

if(letter >= 'A') { // Test for 'A' or larger

if(letter <= 'Z') { // Test for 'Z' or smaller

cout << "You entered an uppercase letter."

<< endl;

return 0;

}

}

if(letter >= 'a') //Test for 'a' or larger

if(letter <= 'z') { //Test for 'z' or smaller

cout << "You entered an lowercase letter."

<< endl;

return 0;

}

cout<<" You do not enter a letter."<<endl;

return 0;

}

本例的输出如下所示:

Enter a letter: H

You entered an uppercase letter.

例子的说明

这个程序首先是通常的注释行和支持输入输出的头文件<iostream>的#include语句,以及程序中std名称的using声明。在为char变量letter分配内存空间,并初始化为0后,函数main()提示输入一个字母。

之后的if语句检查输入的字符是否为'A'或更大:

if (letter >= 'A') { //Test for 'A' or larger

if (letter <= 'Z') { //Test for 'Z' or smaller

cout << "You entered an uppercase letter."

<< endl;

return 0;

}

}

如果letter大于等于'A',嵌套的if就检查输入的字符是否为'Z'或更小的字母。如果该字母是'Z'或更小的字母,就说明该字符是一个大写字母,于是显示一个消息,执行return语句,结束程序。因为这两个语句都放在花括号中,所以在嵌套的if条件为true时,这两个语句都会 执行。

这对嵌套的if语句建立在用编码表示字母字符的两个假设的基础上。第一个假设是字母A到Z用一组编码表示,其中'A'的编码最小,'Z'的编码最大。第二个假设是大写字母的编码是连续的,在'A'编码和'Z'编码之间不存在非字母字符。在代码中建立这样的假设并不好,因为这限制了程序的可移植性。例如,在EBCDIC编码中,字母的字符编码是不连续的。稍后介绍如何避免这种限制。

下一个if语句使用了与第一个if语句相同的机制,检查输入的字符是否为小写,然后显示一个消息并返回。

if (letter >= 'a') //Test for 'a' or larger

if (letter <= 'z') { //Test for 'z' or smaller

cout << "You entered an lowercase letter."

<< endl;

return 0;

}

但如果仔细检查,就会注意到小写字符的测试只包含一对花括号,而大写字母的测试包含两对花括号。这里花括号中的代码块属于内层的if语句。实际上,这两种方式都是对的:在C++中,if(condition){…}是一个语句,不需要放在花括号中。同样,如果觉得使用较多的花括号能使代码更清晰,就可以使用它们。最后,与大写字母测试一样,这些代码隐含了小写字母编码的假设。

只有在输入的字符不是字母时,才执行最后一个if语句块后面的输出语句,它会显示一个消息,然后执行return语句。嵌套的if语句和输出语句之间的关系更容易理解,因为每个if语句块都进行了缩进。在C++中,缩进格式通常用于提供程序逻辑的可视化线索。

如本例开头所述,该程序演示了嵌套的if语句块如何工作,但这并不是测试字符的好方法。使用标准库可以编写出独立于字符编码的程序。下面就介绍这部分内容。

不依赖编码的字符处理

标准库提供了许多函数,它们可以在程序中执行许多任务。表4-2列出了这些函数。在程序中包含<cctype>头文件,就可以访问一组非常有用的函数集,来测试字符。在测试字符时,需要给函数传送一个int类型的变量或字面量。如果传送了char类型的值,编译器会把它自动转换为int。

表4-2 测试字符的函数

函 数

所执行的动作

isupper()

测试大写字母A到Z

islower()

测试小写字母a到z

isalpha()

测试大写字母或小写字母

isdigit()

测试数字0到9

isxdigit()

测试十六进制数字0到9、a到f或A到F

isalnum()

测试字母或数字(例如字母表上的字符和数字)

isspace()

测试空白,空白可以是一个空格、换行符、回车符、换页符、水平制表符或垂直制表符

iscntrl()

测试控制符

isprint()

测试可打印的字符,即大写或小写字母、数字、标点符号或空格

isgraph()

测试图形字符,即除了空格之外的所有可打印字符

ispunct()

测试标点符号,即非字母或数字的所有可打印字符,标点符号可以是空格或下面的字符:_ { } [ ] # ( ) < > % : ; . ? * + - / ^ & | ~ ! = , \ " '

这些函数都返回一个int类型的值。如果字符的类型与要测试的类型相同,该值就为正(true),否则就为0(false)。为什么这些函数不返回bool类型的值?这看上去似乎更有意义。原因是包含这些函数的C标准库是在bool类型引入C++之前建立的。

<cctype>头文件还提供了两个函数,如表4-3所示,在大写字符和小写字符之间转换,传送给这两个函数的字符应是int类型,返回的结果为int类型:

表4-3 转换字符的函数

函 数

说 明

tolower()

如果给函数传送了一个大写字母,就返回该字母的小写形式,否则就返回未修改的传送进来的字母

toupper()

如果给函数传送了一个小写字母,就返回该字母的大写形式,否则就返回未修改的传送进来的字母

可以使用这些函数实现前面的例子,而无需字符编码的任何假设。不同环境中的不同字符编码总是由标准库函数来考虑,用户不需要考虑。因为使用标准库函数后,也不需要使用嵌套的if语句,所以代码要比前面简单得多。

注意所有这些字符测试函数,除isdigit()和isxdigit()之外,都在当前环境下测试变元。本地环境确定了本地数据是如何处理的。不同的国家使用不同的字符集表示字母,所以某个字符编码是否解释为字母取决于本地环境。货币单位和小数的显示方式也随着本地环境的不同而不同。调用在<clocale>头文件中声明的setlocale()函数可以设置本地环境。这个函数接受两个变元:第一个变元指定应用本地环境的函数的类别,第二个变元指定本地环境。用于第一个变元的值必须是在<clocale>头文件中声明的值,表4-4列出了这些值。

表4-4 受本地环境影响的类别值

说 明

LC_ALL

指定所有的类别

LC_CTYPE

指定字符处理

LC_COLLATE

指定字符串比较中的比较顺序

LC_MONETARY

指定货币信息的格式

LC_NUMERIC

指定小数点字符

LC_TIME

指定时间值的格式

setlocale()的第二个变元是一个指定本地环境的字符串。字符串"C"是默认值,对应于拉丁字母'A'到'Z'。可以用于指定其他本地环境的字符串集是由实现方式定义的,但通常包括简单明了的国家规范,如Germany。

C++头文件<locale>提供了许多扩展功能的声明,它们可以处理依赖本地环境的数据,在程序中需要支持多个本地环境时,就应使用它们。

程序示例4.4—— 使用标准库字符转换函数

在修改上一个例子,使用标准库函数时,还可以扩展程序的功能,试用转换函数:

//Program 4.4 Using standard library character testing and conversion

#include <iostream>

#include <cctype> // Character testing and conversion

using std::cin;

using std::cout;

using std::endl;

int main() {

char letter=0; // Store input in here

cout<<endl

<< "Enter a letter: "; // Prompt for the input

cin>> letter; // then read a character

cout<<endl;

if (std::isupper(letter)) { //Test for upper case letter

cout << "You entered a capital letter."

<<endl;

cout << " Converting to lowercase we get "

<<static_cast<char>( std::tolower(letter))<<endl;

return 0;

}

if (std::islower(letter)) { //Test for lower case letter

cout << "You entered a small letter."

<<endl;

cout << "Converting to uppercase we get "

<< static_cast<char>( std::toupper(letter)) <<endl;

return 0;

}

cout<<" You id not enter a letter."<<endl;

return 0;

}

该例子的输出如下所示:

Enter a letter: t

You entered a small letter.

Converting to uppercase we get T

例子的说明

if表达式已改为使用标准库函数,不再需要嵌套的if语句,因为前面要测试的两个条件现在都包含在isupper()或islower()函数中。

我们并不关心这些函数的工作原理。要使用它们,只需知道它们完成什么任务,需要给它们传送多少参数,传送什么类型的参数,以及它们返回什么类型的值。有了这些信息,就可以使用标准库函数,使代码更简单、更一般化。程序的这个版本可以处理使用任何字符编码的char类型。

注意,在输出语句中直接使用从转换函数中返回的结果,如下所示:

cout << "Converting to upper case we get "

<< static_cast<char>(std::toupper(letter)) <<endl;

由于toupper()函数返回的值是int类型,因此把它强制转换为char类型,并发送给输出流cout。如果要存储返回的字符,而不是进行显式强制转换,就可以将它存储在原来的变量letter中,如下面的语句所示:

letter =std::toupper(letter);

接着在输出语句中使用变量letter输出转换后的字符:

cout << "Converting to uppercase we get "<<letter <<endl;

如果需要使用多字节字符(其类型是wchar_t),就可以包含头文件<cwctype>。该文件包含了在<cctype>中声明的所有函数的对应多字节字符。每个测试函数名都在is的后面加上了w,所以它们的名称就变成:

iswupper() iswdigit() iswspace() iswgraph()

iswlower() iswxdigit() iswcntrl() iswpunct()

iswalpha() iswalnum() iswprint()

它们都传递多字节字符参数,并且返回一个int值,就像处理char类型的字符函数一样。同样,多字节字符转换函数也称为towupper()和towlower()。

注意:

C++中的<cctype>和<cwtype>头文件继承于C。在许多实现方式中,函数在std命名空间内部和外部都定义了,以允许旧式C程序编译和链接。此时,函数名无论是否带std限定符都能工作,但因为我们编写的是C++程序,所以应限定名称。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论