Visual C++实用教程
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.4 基本语句

C++融入了C语言的面向过程的结构化程序设计模式,因而它也可实现结构化程序设计中所需要的三种基本结构:顺序结构、选择结构和循环结构。

1.4.1 顺序语句和块

语句是描述程序操作的基本单位,是C++源程序的重要组成部分,每条语句均以分号(“;”)来结束,分号前面可以有0个或多个空格。 这里先讨论说明语句、表达式语句和块语句,它们是构成按书写顺序依次执行的顺序结构的主要语句。

1.说明语句

在C++中,把完成对数据结构的定义和描述、对变量或标识符常量的属性说明(如初值、类型等)称为说明语句声明语句。说明语句的目的是用来在程序中引入一个新的标识符(变量名、函数名、数组名、类名、对象名、引用名及类型名等),本身一般不执行操作。

2.表达式语句

表达式语句是C++程序中最简单也是最常用的语句。任何一个表达式加上分号就是一个表达式语句,例如:

x + y;
nNum = 5;

这里的“x+y;”是一个由算术运算符“+”构成的表达式语句,其作用是完成“x+y”的操作,但由于不保留计算结果,所以无实际意义。“nNum=5;”是一个由赋值运算符“=”构成的表达式语句,简称为赋值语句,其作用是改变nNum变量的值。

在书写格式上,可以将几个简单的表达式语句同时写在一行上,但此时的语句之间必须插入一些空格以提高程序的可读性。例如:

a=1;   b=2;   c=a+b;

此时3个赋值语句写在一行,各条语句之间需要增加空格。

如果表达式是一个空表达式,那么构成的语句称为空语句,也就是说,仅有分号也能构成一个语句,这个语句就是空语句。空语句不执行任何动作,根据语法的需要而设置。

3.块语句

块语句,简称为块(block),是由一对花括号“{ }”括起来的语句,又称为复合语句。例如:

{                                       // 块开始
    int  i=2,j=3,k=4;
    cout<<i<<j<<k<<endl;                // 输出结果是2、3和4
}                                       // 块结束

则是由两条语句构成的块语句。其中,左花括号“{”表示块的开始,右花括号“}”表示块的结束,它们是成对出现的。要注意,块中的语句书写时一定要缩进。

事实上,任何合法的语句都可以出现在块中,包括空语句。需要说明的是:

(1)从整体上看,块语句等效于一条语句。反过来说,若需要将两条或两条以上的语句作为一个整体单条语句时,则必须将它们用花括号括起来。

(2)块中的语句可以是0个、1个或多个。与空语句相类似,一个不含任何语句的块,即仅由一对花括号构成的块,称为空块,它也是仅为语法的需要而设置的,并不执行任何动作。

1.4.2 选择结构语句

选择结构是对给定条件进行判断,根据判断的结果(真或假)来决定执行两个分支或多个分支程序段中的一个分支。在C++中,用于构成选择结构的分支语句有if语句和switch语句,它们又称条件语句

1.条件语句

条件语句if具有下列一般形式:

if  (<表达式e>)<语句s1>
[ else <语句s2> ]

这里的if和else是C++的关键字。注意,if后的一对圆括号不能省略。当表达式e为true或不为0时,将执行语句s1。当表达式e为false或0时,语句s2被执行。其中,else可以省略,即变成这样的简单的if语句:

if  (<表达式e>)<语句s>

这样,只有当表达式e为true或不为0时,语句s才被执行。

【例Ex_Compare】 输入两个整数,比较两者的大小

#include <iostream.h>
int  main()
{
    int nNum1, nNum2;
    cout<< "Please input two integer numbers: ";
    cin>>nNum1>>nNum2;
    if (nNum1!=nNum2)
        if (nNum1>nNum2)
            cout<<nNum1<< " > "<<nNum2<<endl;
        else
            cout<<nNum1<< " < "<<nNum2<<endl;
    else
        cout<<nNum1<< " = "<<nNum2<<endl;
    return 0;
}

程序运行结果如下:

Please input two integer numbers: 10 123↵

10 < 123

需要注意的是:

(1)条件语句中的表达式一般为逻辑表达式或关系表达式,如程序中的nNum1> nNum2。当然,表达式的类型也可以是任意的数值类型(包括整型、实型、字符型等)。例如:

if  (3)   cout<<"This is a number 3";

执行结果是输出"This is a number 3";因为3是一个不为0的数,条件总为“真”。

(2)适当添加花括号“{ }”来增加程序的可读性。例如:上面【例Ex_Compare】中的条件语句还可写成下列形式,其结果是一样的。

if (nNum1!=nNum2)
{
    if (nNum1>nNum2)
        cout<<nNum1<<" > "<<nNum2<<endl;
    else
        cout<<nNum1<<" < "<<nNum2<<endl;
} else
    cout<<nNum1<<" = "<<nNum2<<endl;

(3)如果在if和esle后有多条语句(复合语句),则必须用花括号将这些语句括起来,否则只有后面的第一条语句有效。例如:

if (nNum1>nNum2)
    cout<<nNum1<<">"<<nNum2;       // 此句是if后面的有效语句
    cout<<endl;                    // 此句无论if表达式是否为真都会执行

(4)条件语句中的语句s、语句s1和语句s2也可以是if条件语句,这就形成了if语句的嵌套。例如,程序中if (nNum1!=nNum2)后面的语句也是一个if条件语句。

(5)else不能单独使用,它总是和其前面最近的未配套的if相配套。例如,程序中的第1个else属于第2个if,而第2个else是属于第1个if的。

2.开关语句

当程序有多个判断条件时,若使用if语句则可能使嵌套太多,降低程序的可读性。开关语句switch能很好地解决这种问题,它具有下列形式:

switch  (<表达式e>)
{
    case  <常量表达式v1>   :[语句s1]
    case  <常量表达式v2>   :[语句s2]
    ...
    case  <常量表达式vn>   :[语句sn]
    [default               :语句sn+1]
}

其中switch、case、default都是关键字,当表达式e的值与case中某个常量表达式的值相等时,就执行该case中冒号“:”后面的所有语句,直至遇到break语句跳出。若case中所有常量表达式的值都不等于表达式e的值,则执行“default:”后面的语句,若default省略,则跳出switch结构。需要注意的是,switch后面的表达式e可以是整型、字符型或枚举型的表达式,而case后面的常量表达式的类型则必须与其相匹配。

例Ex_Switch】 根据成绩的等级输出相应的分数段

#include <iostream.h>
int  main()
{
    char chGrade;
    cout<<"Please input a char(A~E): ";
    cin>>chGrade;
    switch(chGrade)
    {
        case 'A':
        case'a':   cout<<"90--100"<<endl;
                break;
        case 'B':
        case'b':   cout<<"80--89"<<endl;
                break;
        case 'C':
        case'c':   cout<<"70--79"<<endl;
        case 'D':
        case'd':   cout<<"60--69"<<endl;
        case 'E':
        case'e':   cout<<"<60"<<endl;
        default:   cout<<"error!"<<endl;
    }
    return 0;
}

运行时,当用户输入A时,则运行结果如下:

Please input a char(A~E): A↵

90--100

但当用户输入d时,则运行结果如下:

Please input a char(A~E): d↵

60--69

< 60

error!

显然,这不是想要的结果,而应该只输出60--69。仔细比较这两个结果可以发现,“case 'a':”后面含有break语句,而“case 'd':”后面则没有。由于break语句能使系统跳出switch结构,因此当系统执行“case 'a':”后面的语句“cout<<"90--100"<<endl;”后,break语句使其跳出switch结构,以保证结果的正确性;若没有break语句,则后面的语句继续执行,直到遇到下一个break语句或switch结构的最后一个花括号“}”为止才跳出该结构。因此,break语句对switch结构有时是不可缺少的(后面还会专门讨论)。

另外,还需注意的是:

(1)多个case可以共有一组执行语句,如程序中的:

case 'B':
case'b':   cout<<"80--89"<<endl;
           break;

这时,当用户输入B或b时将得到相同的结果。

(2)若同一个case后面的语句是复合语句,即有两条或两条以上的语句,则这些语句可以不用花括号“{ }”括起来。

(3)由于case语句起标号作用,因此每一个case常量表达式的值必须互不相同,否则会出现编译错误。

1.4.3 循环结构语句

构成循环结构的循环语句提供了重复操作的能力,当指定的循环条件为true时,循环体中的语句就会被重复执行,并且每循环一次,就会测试一下循环条件,如果为false,则循环结束,否则继续循环。C++为循环结构提供了三种形式的循环语句:while、do…while和for语句。这些循环语句的功能是相似的,在许多情况下它们可以相互替换,唯一区别是它们控制循环的方式。

1.while语句

语句具有下列格式:

while(<表达式e>)  <语句s>

其中,while是C++的关键字,语句s是循环体,它可以是一条语句,也可以是多条语句。当为多条语句时,一定要用花括号“{ }”括起来,使之成为块语句,如果不加花括号,则while的循环体s只是紧跟while (e)后面的第1条语句。当表达式e为true或不为0时便开始执行while循环体中的语句s,然后反复执行,每次执行都会判断表达式e是否为true或不为0,若为false或为0,则终止循环。

例Ex_SumWhile】 求整数1~50的和

#include <iostream.h>
int  main()
{
    int  nNum=1,  nTotal=0;
    while (nNum<=50)
    {
        nTotal += nNum;
        nNum++;
    }
    cout<<"The sum from 1 to 50 is: "<<nTotal<<"\n";
    return 0;
}

程序运行结果如下:

The sum from 1 to 50 is: 1275

需要说明的是,对于循环结构来说,循环体中一定要有使循环趋向结束的语句。比如上述示例中,nNum的初值为1,循环结束的条件是不满足nNum<=50,随着每次循环都改变nNum的值,使得nNum的值也越来越大,直到nNum>50为止。如果没有循环体中的“nNum++;”,则nNum的值始终不改变,循环永不终止。

2.do…while语句

语句具有下列格式:

do
    <语句s>
while (<表达式e>) ;

其中do和while都是C++关键字,语句s是循环体,它可以是一条语句,也可以是块语句。程序从do开始执行,然后执行循环体语句s,当执行到while时,将判断表达式e是否为true,若是,则继续执行循环体语句s,直到下一次表达式e等于false为止。要注意,while后面的表达式e两边的圆括号不能省略,且表达式e后面的分号不能漏掉。

例Ex_SumDoWhile】 求整数1~50的和

#include <iostream.h>
int  main()
{
    int   nNum=1,  nTotal=0;
    do
    {
        nTotal+=nNum;    nNum++;
    } while (nNum<=50);
    cout<<"The sum from 1 to 50 is: "<<nTotal<<"\n";
    return 0;
}

由于程序总是自上而下地顺序运行(除非遇到if、while等流程控制语句),因此do语句中的循环会先执行,这样sum值为1,i为2。然后判断while后面的“(i<=50)”是否为true,若是,则流程转到do循环体中,直到“(i<=50)”为false。

程序运行结果如下:

The sum from 1 to 50 is: 1275

从上述例子中可以看出:

(1)do…while循环语句至少执行一次循环体,而while循环语句可能一次都不执行。

(2)从局部来看,while和do…while循环都有“while (表达式e)”。为区别起见,对于do…while循环来说,无论循环体是单条语句还是多条语句,习惯上都要用花括号将它们括起来,并将“while (表达式e);”直接写在右花括号“}”的后面,如【例Ex_SumDoWhile】中的格式。

3.for语句

语句具有下列格式:

for ([表达式e1]; [表达式e2]; [表达式e3])
    <语句s>

其中for是C++的关键字,语句s是循环体,它可以是一条语句,也可以是块语句。一般情况下,表达式e1用做循环变量的初始化,表达式e2用做循环体的循环条件,当其为true时,开始执行循环体语句s,然后计算表达式e3,再判断表达式e2的值是否为true,若是,再执行循环体s,再计算表达式e3,如此反复,直到表达式e2为false或0为止。如图1.7所示,图中箭头表示程序运行的方向,称为流向,程序运行的次序称为流程,这样的图称为流程图。下面用for语句来改写【例Ex_SumDoWhile】中的代码。

图1.7 for语句的流程

例Ex_SumFor】 求整数1~50的和

#include <iostream.h>
int  main()
{
    int  nTotal=0;
    for (int nNum=1; nNum<=50; nNum++)
        nTotal += nNum;
    cout<<"The sum from 1 to 50 is: "<<nTotal<<"\n";
    return 0;
}

程序运行结果如下:

The sum from 1 to 50 is: 1275

需要说明的是:

(1)由于表达式e1用做循环变量的初始化,因此也可将循环变量的定义放在表达式e1中进行,如代码中for语句的“int nNum=1”。但此时nNum的作用范围仅限于for循环结构中,这是ANSI/ISO C++中的新规定。但在Visual C++ 6.0中,nNum的作用范围和在for前面定义的变量(如nTotal)的作用范围是一样的。

(2)表达式e1、表达式e2和表达式e3可以是一个简单的表达式,也可以是逗号表达式,即包含两个或两个以上的简单表达式,中间用逗号分隔。例如:

for(nNum=1,nTotal=0;nNum<=50;nNum++)   nTotal+=nNum;

(3)循环体s中的语句也可以是一条空语句,这样的循环往往用于时间延时。例如:

for(int i=0;i<10000;i++) ;        // 注意后面的分号表示一条空语句

(4)实际运用时,for循环还有许多变化的形式,这些形式都是将for后面括号中的表达式e1、表达式e2、表达式e3进行部分或全部省略,但要注意起分隔作用的分号“;”不能省略。常见的省略形式有下列几种:

① 若省略表达式e1,不影响循环体的正确执行,但循环体中所需要的一些变量及其相关的数值要在for语句之前定义。例如:

int  nNum=1;
for(;nNum<=50;nNum++)    nTotal+=nNum;

② 若省略表达式e2,则默认的表达式e2的值被认为true,循环无终止地进行下去,应在循环体中添加额外代码使之有跳出或终止循环的可能。例如:

for(int nNum=1;  ;nNum++)
{
    nTotal += nNum;
    if  (nNum>50)break;         // 当nNum>50时,执行break语句,跳出循环
}

③ 若省略表达式e3,应在设计循环结构时保证表达式e2的值有等于false的可能,以便能终止循环。例如:

for (int nNum=1; nNum<=50 ;)
{
    nTotal+=nNum;    nNum++;
}

④ 若省略表达式e1和表达式e3,则相当于while循环。例如:

⑤ 若表达式全部省略,例如:

int  nNum=1;
for ( ; ; )
{
    nTotal+=nNum;    nNum++;
    if (nNum>50) break;
}

则循环体中所需要的一些变量及其相关的数值要在for语句之前定义,如“int nNum = 1;”,且应在循环体中添加额外代码使之有跳出或终止循环的可能,如“if (nNum>50) break;”。

(5)由于循环体可由任何类型的语句组成,因此在循环体内还可以包含前面几种循环语句,这样就形成了循环的嵌套。例如:

for(…; …; …)
{
    while (…)
    {
    }
}
while (…)
{
    for(…; …; …)
    {
    }
}

以上是C++几种类型的循环语句,使用时可根据实际需要进行适当选择。但不管是怎样的循环结构,在编程时应保证循环有终止的可能。否则,循环永不结束,就像“死机”一样。

1.4.4 break和continue语句

在C++程序中,若需要跳出循环结构或提前结束本次循环,就需要使用break和continue语句,其格式如下:

break;
continue;

break语句用于强制结束switch结构(如【例Ex_Switch】)或从一个循环体跳出,即提前终止循环。要注意,break仅使流程跳出其所在的最近的那一层循环或switch结构,而不是跳出所有层的循环或switch结构。

continue适用于那些依靠条件判断而进行循环的循环语句,如for、while、do…while语句,它的目的是提前结束本次循环。对于while和do…while语句来说,continue提前结束本次循环后,流程转到while后面的表达式e。对于for语句来说,continue提前结束本次循环后,其流程转到for语句的表达式e3,然后转到表达式e2。

例Ex_Continue】 将1~100之间不能被7整除的数输出

#include <iostream.h>
int  main()
{
    for (int nNum=1; nNum<=100; nNum++)
    {
        if (nNum%7 == 0) continue;
        cout<<nNum<<"  ";
    }
    cout<<"\n";
    return 0;
}

当nNum能被7整除时,执行continue语句,流程转到for语句中的nNum++,并根据表达式nNum<=100的值来决定是否再做循环。而当nNum不能被7整除时,才执行cout<<nNum<<""语句。

程序运行结果如下:

1 2 3 4 5 6 8 9 10 11 12 13 15 16 17 18 19 20 22 23 24 25 26 27 29 30 31 32 33 34 36 37 38 39 40 41 43 44 45 46 47 48 50 51 52 53 54 55 57 58 59 60 61 62 64 65 66 67 68 69 71 72 73 74 75 76 78 79 80 81 82 83 85 86 87 88 89 90 92 93 94 95 96 97 99 100