1.4.1 表达式语句、空语句和复合语句 - PowerPoint PPT Presentation

1 4 1
Download
1 / 73

  • 94 Views
  • Uploaded on
  • Presentation posted in: General

1.4.1 表达式语句、空语句和复合语句. [ 例 Ex_Block] 块语句的变量使用范围。 #include<iostream.h> void main() { int i = 5, j = 6; cout<<i<<j<<endl;// 输出的结果是 5 和 6 { int i = 2, j = 3, k = 4; cout<<i<<j<<k<<endl;// 输出结果是 2 、 3 和 4 }

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.

Download Presentation

1.4.1 表达式语句、空语句和复合语句

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


1 4 1

1.4.1 表达式语句、空语句和复合语句

[例Ex_Block] 块语句的变量使用范围。

#include<iostream.h>

void main()

{

int i = 5, j = 6;

cout<<i<<j<<endl;// 输出的结果是5和6

{

int i = 2, j = 3, k = 4;

cout<<i<<j<<k<<endl;// 输出结果是2、3和4

}

cout<<i<<j<<endl;// 输出的结果仍然是5和6,但不能使用k,如cout<<k;

将发生错误。

}


1 4 2

1.4.2 选择结构语句

1. 条件语句

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

if (<表达式>) <语句1>

[else <语句2>]

其中if、else是C++的关键字。

if后的一对圆括号不能省。

当“表达式”为“真”(true)或不为0时,将执行语句1。

当“表达式”为“假”(false或0)时,语句2被执行。

其中,else可省略,即变成这样的简单的if语句:

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

当“表达式”为“真”(true)或不为0时,语句被执行。


1 4 21

1.4.2 选择结构语句

[例Ex_Compare] 输入两个整数,比较两者的大小

#include <iostream.h>

void 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;

}

运行情况如下:


1 4 22

1.4.2 选择结构语句

需要注意的是:

  • 条件语句中的表达式一般为逻辑表达式或关系表达式,

    当然,表达式的类型也可以是任意的数值类型(包括整型、实

    型、字符型等)。

    (2)适当添加花括号(“{ }”)来增加程序的可读性。例如:上例

    中的条件语句还可写成下列形式,其结果是一样的。

    if (nNum1!=nNum2) {

    if (nNum1>nNum2)

    cout<<nNum1<<" > "<<nNum2<<endl;

    else

    cout<<nNum1<<"< "<<nNum2<<endl;

    } else

    cout<<nNum1<<" = "<<nNum2<<endl;


1 4 23

1.4.2 选择结构语句

(3) 如果在if、esle后有多条语句(复合语句)时,则必须用花

括号将这些语句括起来,否则只有后面的第一条语句有效。

例如:

if (nNum1>nNum2)

cout<<nNum1<<" > "<<nNum2;// 此句才是if后面的有效语句

cout<<endl;// 此句无论if表达式是否为真都会执行

(4) 条件语句中的语句1和语句2也可是if条件语句,这就形成了if语句的嵌套。

(5) else总是和其前面最近的if配套的,


1 4 24

1.4.2 选择结构语句

2.开关语句

当程序有多个条件判断时,若使用if语句则可能使嵌套太

多,降低了程序的可读性。开关语句switch能很好地解决这

种问题,它具有下列形式:

switch ( <表达式> )

{

case <常量表达式1>:[语句1]

case <常量表达式2 >:[语句2]

...

case <常量表达式n> :[语句n]

[default :[语句n+1]]

}


1 4 25

1.4.2 选择结构语句

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

#include <iostream.h>

void 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;

}

}


1 4 26

1.4.2 选择结构语句

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

运行时,当用户输入A,则输出:

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

输入d时,结果是不是预期的结果?

原因在哪?

此时输入大写的C会是什么结果?


1 4 3

1.4.3 循环结构语句

1. while循环语句

while循环语句可实现“当型”循环,它具有下列形式:

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

while是关键字,

<语句>是此循环的循环体,它可以是一条语句,也可以是多

条语句,当为多条语句时,必须用花括号(“{}”)括起来,如果不

加花括号,则while的范围只到while后面第一条语句。

“当型”循环即当表达式的值为真则执行循环体;值为假,终

止循环。因此此类循环可能一次都不执行。


1 4 31

1.4.3 循环结构语句

[例Ex_SumWhile] 求整数1到50的和

#include <iostream.h>

void main()

{

intnNum = 1, nTotal = 0;

while (nNum<=50)

{

nTotal += nNum;

nNum++;

}

cout<<"The sum, from 1 to 50, is: "<<nTotal<<"\n";

}

运行结果为:

需要注意的是,每个循环体都应该有使循环趋于结束的语句,

否则循环永不终止。


1 4 32

1.4.3 循环结构语句

2.do...while循环语句

do...while循环语句可实现“直到型”循环,它具有下列形式:

do <语句>

while (<表达式>)

其中do和while都是C++关键字,

<语句>是此循环的循环体,它可以是一条语句,也可以是复

合语句。

“直到型”循环即执行循环体直到表达式为假,因此循环至少

执行一次


1 4 1

例如Ex_SumWhile用do...while循环语句可改写成:

[例Ex_SumDoWhile] 求整数1到50的和

#include <iostream.h>

void main()

{

intnNum = 1, nTotal = 0;

do

{

nTotal += nNum;

nNum++;

} while (nNum<=50);

cout<< "The sum, from 1 to 50, is: "<<nTotal<< "\n";

}


1 4 33

1.4.3 循环结构语句

3. for循环语句

for循环语句既可实现“当型”循环,又可实现“直到型”循环,

它具有下列形式:

for ([表达式1];[表达式2];[表达式3]) <语句>

其中for是关键字,

<语句>是此循环的循环体。

其循环流程图如图1.3


1 4 1

表达式1

false

表达式2

true

循环体

表达式3

for循环流程图

图1.3 for循环流程图


1 4 34

1.4.3 循环结构语句

例如,Ex_SumWhile用for循环语句可改写成:

[例Ex_SumFor]求整数1到50的和

#include <iostream.h>

void main()

{

intnTotal=0;

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

nTotal += nNum;

cout<<"The sum, from 1 to 50, is: "<<nTotal<<endl;

}


1 4 4 break continue

1.4.4 break和continue语句

在C++程序中,若需要跳出循环结构或提前结束本次循环,

就需要使用break和continue语句,其格式如下:

break;

continue;

break语句用于强制结束switch结构(如例Ex_Switch)或从一

个循环体跳出,即提前终止循环。

continue是用于那些依靠条件判断而进行循环的循环语句。


1 4 1

[例Ex_Continue] 把1~100之间的不能被7整除的数输出

#include <iostream.h>

void main()

{

for (int nNum=1; nNum<=100; nNum++)

{

if (nNum%7 == 0) continue;

cout<<nNum<<" ";

}

cout<<"\n";

}


1 5 1

1.5.1 函数的定义和调用

  • 函数的定义

    在C++程序中,定义一个函数的格式如下:

    <函数类型> <函数名>( <形式参数表> )

    {

    <若干语句> 函数体

    }

    可以看出,一个函数的定义是由函数名、函数类型、形式参

    数表和函数体四个部分组成的。

    函数类型决定了函数所需要的返回值类型等。如果不需要函

    数有返回值,只要定义函数的类型为void即可。


1 5 11

1.5.1 函数的定义和调用

2. 函数的声明 :

消除函数定义位置对程序编译产生的影响。

声明一个函数可按下列格式进行:

<函数类型> <函数名>( <形式参数表> );

其中,形参的变量名可以省略。但要注意,函数声明的内容应和函数的

定义应相同。例如对于sum()函数的声明如下:

int sum(int x, int y);

int sum(int , int);

是等价的。但末尾的分号“;”不要忘记。

函数的声明又可称为对函数的原型进行说明。


1 5 12

1.5.1 函数的定义和调用

3. 函数的调用

函数调用的一般形式为:

<函数名>( <实际参数表> );

所谓“实际参数”(简称“实参”),它与“形参”相对应,是实际调

用函数时所给定的常量、变量或表达式,且必须有确定的值。

例如:

int a[5] = {7, 9, 6, 3, 4};

sum(a[0], 6);

sum(a[0]*a[1], a[2]+a[3]);

等都是合法的调用。

需要注意的是:实参与形参的个数应相等,类型应一致,且按

顺序对应,一一传递数据。


1 4 1

C++中,调用一个函数的方式可以有很多,

例如:

sum(3, 4);//函数作为语句

int c = 2 * sum(4,5);//函数作为表达式一部分

c = sum(c, sum(c,4));//函数作为实参


1 5 2

1.5.2 函数的参数传递

[例Ex_SwapValue] 交换函数两个参数的值。

#include <iostream.h>

void swap(float x, float y)

{

float temp;

temp = x; x = y; y = temp;

cout<<"x = "<<x<<", y = "<<y<<"\n";

}

void main()

{

float a = 20, b = 40;

cout<<"a = "<<a<<", b = "<<b<<"\n";

swap(a, b);

cout<<"a = "<<a<<", b = "<<b<<"\n";

}

运行结果为:


1 5 3

1.5.3 作用域和存储类型

1. 作用域

在一个程序文件中,C++语言的作用域共有5种:块作用域、函数原型作

用域、函数作用域、类作用域和文件作用域。

  • 块作用域。

    例如:

    void fun(void)// 在形参表中指定void,表示没有形参,void可不要

    {

    int a;// a的作用域起始处

    cin>>a;

    if (a<0)

    {

    a = -a;

    int b;// b的作用域起始处

    } // b的作用域终止处

    } // a的作用域终止处

    注意:同域不可同名,不同域时可同名;for语句中声明的标识符,对整个包含

    for语句块的内层块起作用。


1 5 31

1.5.3 作用域和存储类型

(2) 函数原型作用域。例如:

double max(double x, double y);

double max(double, double);

是等价的。

(3) 函数作用域。具有此类作用域的标识符仅声明它的函数内可见

(4) 文件作用域。全局标识符的作用域,从声明到文件结束均可见

(函数外定义的标识符或使用extern说明的标识符是全局标识符。)

不同域时可同名,那这个时候怎么区分和调用同名变量呢?

请看书上P36【例Ex_process】


1 5 32

1.5.3 作用域和存储类型

2. 变量的存储类型

自动类型

静态类型

寄存器类型

外部类型

这些存储类型的声明是按下列格式进行的:

<存储类型> <数据类型> <变量名表>;

  • 自动类型(auto)。一般说来,用自动存储类型声明的变量都是限制在某个程序范围内使用的,即为局部变量。

    在C++语言中,声明一个自动存储类型的变量是在变量类型前面加上关键字auto,例如:

    autoint i;

    若自动存储类型的变量是在函数内或语句块中声明的,则可省略关键字auto,例如:

    int i;


1 4 1

(2) 静态类型(static)。

它和自动存储类型的变量的最大不同之处在于:

静态类型变量在内存中是以固定地址存放的,它采用静态分

配方式来分配内存空间的。在这种方式下,只要程序还在继

续执行,静态类型变量的值就一直有效,不会随它所在的函

数或语句块的结束而消失。


1 5 33

1.5.3 作用域和存储类型

在C++语言中,声明一个静态类型的变量是在变量类型前面加上关键字static。例如:

[例Ex_Static] 使用静态类型的局部变量

#include <iostream.h>

void count()

{

int i = 0;

static int j = 0; // 静态类型

cout<<”i =”<<i<<”, j = ”<<j<<”\n”;

i++;j++;

}

void main()

{

count();

count();

}

运行结果为:


1 5 4

1.5.4 带默认形参值的函数

在C++中,允许在函数的声明或定义时给一个或多个参数指定默认值。

这样在调用时,可以不给出参数,而按指定的默认值进行工作。例如:

void delay(int loops=1000);// 函数声明

void delay(int loops)// 函数定义

{

if (loops==0)

return;

for (int i=0; i<loops; i++);// 空循环,起延时作用

}

这样,当调用

delay();// 和delay(1000)等效

时,程序都会自动将loops当作成1000的值来进行处理。当然,也可重新

指定相应的参数值,

例如:

delay(2000);


1 5 41

1.5.4 带默认形参值的函数

在设置函数的默认参数值时要注意:

(1) 当函数既有声明又有定义时,不能在函数定义中指定默认参数。

(2) 当一个函数中有多个默认参数时,则形参分布中,默认参数应从右到

左逐次定义。在函数调用时,系统按从左到右的顺序将实参与形参结

合,当实参的数目不足时,系统将按同样的顺序用声明或定义中的默认

值来补齐所缺少的参数。


1 4 1

例如:[例Ex_Default] 一个设置多个默认参数的函数示例

#include <iostream.h>

void display(int a, int b=2, int c=3) // 在函数的定义中设置默认参数

{

cout<<"a = "<<a<<", b = "<<b<<", c = "<<c<<"\n";

}

void main()

{

display(1);

display(1, 5);

display(1, 7, 9);

}

结果如下:


1 5 42

1.5.4 带默认形参值的函数

在设置函数的默认参数值时要注意:

(3) 默认参数值可以是全局变量、全局常量,甚至是一个函数。但不可以

是局部\变量,因为默认参数的函数调用是在编译时确定的,而局部变量

的值在编译时无法确定。例如:

int a = 1;

int f1(int);

int g1(int x = f1(a));// 正确,允许默认参数值为函数值

void f2()

{

int i;

void g2(int x = i);// 错误,处理g2函数时,i不可见

}


1 5 5

1 当n=0时

f(n) =

n*f(n-1) 当n>0时

1.5.5 函数的递归调用

如果在调用一个函数的过程中出现直接地或

间接地调用函数本身,这种情况称为函数的

“递归”调用,相应的函数称为“递归函数”。例如:

[例Ex_Factorial] 编程n的阶乘n!


1 5 51

1.5.5 函数的递归调用

#include <iostream.h>

long factorial(int n);

void main()

{

cout<<factorial(4)<<endl;// 结果为24

}

long factorial(int n)

{

long result = 0;

if (n == 0)

result = 1;

else

result = n*factorial(n-1);

return result;

}


1 5 52

factorial(4)

表示调用“初始化”,执行被调函数

1

表示调用“后处理”,返回主调函数

10

result = 4*factorial(3);

result=4*6=24;

2

result = 3*factorial(2);

9

result=3*2=6;

3

result = 2*factorial(1);

8

result=2*1=2;

4

result = 1*factorial(0);

7

result=1*1=1;

6

5

result = 1;

1.5.5 函数的递归调用

[例Ex_Factorial] 编程n的阶乘n!

上述过程可用图1.5来表示,从中可以看出:递归函数实际上是同名函数的多级

调用。但要注意,递归函数中必须要有结束递归过程的条件,即函数不再进行自

身调用,否则递归会无限制地进行下去。

图1.5 factorial(4)递归函数执行过程


1 5 6

1.5.6 内联函数

内联函数的定义方法是在函数定义时,在函数的类型前增加关键字inline。例如:

[例Ex_Inline] 用内联函数实现求两个实数的最大值

#include <iostream.h>

inline float fmax(float x, float y)

{return x>y?x:y;}

void main()

{

float a, b;

cout<<"请输入两个实数:";

cin>>a>>b;

cout<<"最大的数为:"<<fmax(a,b)<<"\n";

}

使用内联函数时,还需要注意的是:

(1) 内联函数也要遵循定义在前,调用在后的原则。形参与实参之间的关系与一般函数相同。

(2) 在C++中,需要定义成的内联函数不能含有循环、switch和复杂嵌套的if语句。

(3) 递归函数是不能被用来做内联函数的。

(3) 编译器是否将用户定义成的内联函数作为真正的内联函数处理,由编译器自行决定。


1 5 7

1.5.7 函数的重载

函数重载是指C++允许多个同名的函数存在,但同名的各个函数的形参必须有区别:形参

的个数不同,或者形参的个数相同,但参数类型有所不同。例如:

[例Ex_OverLoad] 编程求两个或三个操作数之和

#include <iostream.h>

int sum(int x, int y);

int sum(int x, int y, int z);

double sum(double x, double y);

double sum(double x, double y, double z);

void main()

{

cout<<sum(2, 5)<<endl;// 结果为7

cout<<sum(2, 5, 7)<<endl;// 结果为14

cout<<sum(1.2, 5.0, 7.5)<<endl;// 结果为13.7

}

int sum(int x, int y)

{return x+y;}

int sum(int x, int y, int z)

{return x+y+z;}

double sum(double x, double y)

{return x+y;}

double sum(double x, double y, double z)

{return x+y+z;}


1 5 71

1.5.7 函数的重载

从上面的例子可以看出:由于使用函数的重载,因而不仅方便函数名的

记忆,而且更主要的是完善了同一个函数的代码功能,给调用带来了许

多方便。程序中各种型式的sum函数都称为sum的“重载函数”。

需要说明的是:

(1) 重载函数必须具有不同的参数个数或不同的参数类型,若只有返回值的类型不同是不行的。

(2) 当函数的重载带有默认参数时,应该注意避免二义性。例如:

int fun(int a, int b = 0);

int fun(int a);

是错误的。因为如果有函数调用fun(2)时,编译器无法准确地确定应调用

哪个函数。


1 5 8

1.5.8 预处理

1. 不带参数的宏定义

宏定义就是用一个指定的标识符来代替一个字符串。宏定义有两种形式:不带参数

的宏定义和带参数的宏定义。宏定义是通过宏定义命令#define来实现。

在以前的程序中,曾用#define定义一个符标常量,如:

#define PI 3.141593

其中,#define是宏定义命令,PI称为宏名。

在程序编译时,编译器首先将程序中的PI用3.141593来替换,然后再进行代码编

译,故称为“编译预处理”。需要注意的是:

  • #define、PI和3.141593之间一定要有空格,且一般将宏名定义成大写,以与

    普通标识符相区别。

    (2) 宏后面的内容实际上是“字符串”,编译器本身不对其进行任何语法检查,仅仅

    是用来在程序中作与宏名的简单替换。例如,若有:

    #define PI 3.141ABC593

    它是一个合法的宏定义。


1 4 1

(3) 宏被定义后,使用下列命令后可重新定义:

#undef 宏名

(4) 一个定义过的宏名可以用来定义其它新的宏,但要注意其中的括号,例如:

#define WIDTH 80

#define LENGTH ( WIDTH + 10 )

宏LENGTH等价于:

#define LENGTH ( 80 + 10 )

但其中的括号不能省略,因为当

var = LENGTH * 20;

若宏LENGTH定义中有括号,则预处理后变成:

var = ( 80 + 10 ) * 20;

若宏LENGTH定义中没有括号,则预处理后变成:

var = 80 + 10 * 20;

显然,两者的结果是不一样的。


1 5 81

1.5.8 预处理

2. 带参数的宏定义

带参数的宏义命令的一般格式为:

#define <宏名>(参数名表) 字符串

在字符串中包括了括号内的参数,称为形参,以后在程序中这些形参将

被实参替换。例如例如:

#defineMAX(a,b) ((a)>(b)?(a):(b))

其中(a,b)是宏MAX的参数表,如果在程序出现下列语句:

x = MAX(3, 9);

则预处理后变成:

x = ((3)>(9)?(3):(9));// 结果为9

很显然,带参数的宏相当于一个函数的功能,但却比函数简捷。

需要注意的是:定义有参宏时,宏名与左圆括号之间不能留有空格。否

则,编译器将空格以后的所有字符均作为替代字符串,而将该宏视为无

参数的宏定义。


1 5 82

1.5.8 预处理

3. 文件包含命令

所谓“文件包含”是指将另一个源文件的内容合并到源程序中。C++语言提

供了#include命令用来实现文件包含的操作,它有下列两种格式:

#include <文件名>

#include “文件名”

在使用#include命令需要注意的是,一条#include命令只能包含一个文

件,若想包含多个文件须用多条文件包含命令。例如:

#include <iostream.h>

#include <math.h>

...


1 5 83

1.5.8 预处理

4. 条件编译命令

一般情况下,源程序中所有的语句都参加编译,但有时也希望根据一定的条件去

编译源文件的不同部分,这就是“条件编译”。条件编译使得同一源程序在不同的

编译条件下得到不同的目标代码。

C++提供的条件编译命令有几种常用的形式,现分别介绍如下:

第一种形式

#ifdef <标识符>

<程序段1>

[#else

<程序段2>]

#endif

其中,#ifdef、#else和#endif都是关键字,<程序段>是由若干条预处理命令或语

句组成的。这种形式的含义是:如果标识符已被#define命令定义过,则编译<程

序段1>,否则编译<程序段2>。


1 5 84

1.5.8 预处理

(2) 第二种形式

#ifndef <标识符>

<程序段1>

[#else

<程序段2>]

#endif

这与前一种形式的区别仅在于,如果标识符没有被#define命令定义过,则编译<程序段1>,否则就编译<程序段2>。


1 5 85

1.5.8 预处理

[例Ex_UseIfdef] 使用#ifdef条件编译命令

(3) 第三种形式

#if <表达式1>

<程序段1>

[#elif <表达式2>

<程序段2>

...]

[#else

<程序段n>]

#endif

其中,#if 、#elif、#else和#endif是关键字。它的含义是,如果

<表达式1>为“真”就编译<程序段1>,否则如果<表达式2>为“真”就编译

<程序段2>,...,如果各表达式都不为“真”就编译<程序段n>。


1 4 1

1.6 构造类型

1.6.1 数组

数组是相同类型的元素的有序集合,每个元素在数组中的位置可用统一

的数组名和下标来惟一确定。

1. 数组的定义

定义一个数组可按下列格式进行:

<数据类型> <数组名> [<常量表达式1>][<常量表达式2>]...

<数组名>后面的[<常量表达式1>][<常量表达式2>]...用于确定数组的维

数和大小。

一般地,表示某维大小的常量表达式中不能包含变量,但可以包括常量

和符号常量,其值必须是一个确定的整型数值,且数值大于1。例如:

inta[4 - 2][3 * 6];

const intSIZE=18;

intb[SIZE];

都是合法的数组定义。


1 6 1

1.6.1 数组

2. 数组元素的引用

数组定义后,就可以引用数组中的元素,引用时按下列格式:

<数组名> [<下标>]...

需要注意的是:

  • C++数组的下标总是从0开始的,也就是说,a[0]是数组a的第一个元素;但下标一定要小于数组定义时的大小。也就是说,长度为n的数组,其下标范围为0 ~ (n-1)。

  • 下标可以是整型常量或整型表达式,且引用的元素下标个数应与数组定义的维数一致。

  • 数组定义后,系统会根据数组的大小开辟相应的内存,并依照下标的高低依次存放数组中的各个元素。例如一维数组a[5]的存放次序是:a[0],a[1],a[2],a[3],a[4]。

  • 由于每一个数组元素都可以看成是一个与数组类型相同的变量,因此在程序中对某个或所有数组元素进行赋值或其他处理时,它的操作与变量类似。


1 6 11

1.6.1 数组

3. 一维数组的初始化和赋值

数组中的元素既可以在数组定义的同时赋初值,即初始化,也可以在定

义后赋值。例如:

int a[5] = {1, 2, 3, 4, 5};

是将整数1,2,3,4,5分别赋于数组a的各个元素,注意要将这些初值用花括

号“{ }”括起来。它与下列的赋值语句的结果是相同的:

a[0 ]= 1; a[1] = 2; a[2] = 3; a[3] = 4; a[4] = 5;

当然,也可以给其中的一部分元素赋值。例如:

intb[5] = {1, 2};

是将数组b的元素b[0],b[1]分别赋予1,2的值。需要说明的是,在对数组进

行初始化中,若没有明确列举元素值的元素,则其值均为0。

有时,在对全部数组元素赋初值时,可以不指定数组的长度;


1 6 12

1.6.1 数组

4. 二维数组的初始化和赋值

二维数组可以看成一个具有行和列的数据表,例如

intb[3][4];

它在内存空间的存放次序是:

b[0][0],b[0][1],b[0][2],b[0][3],// 第0行

b[1][0],b[1][1],b[1][2],b[1][3],// 第1行

b[2][0],b[2][1],b[2][2],b[2][3]。// 第2行

因此,在进行二维数组进行初始化时可以采用以“行”为单位来进行。

例如:

int d[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};

每对花括号里的数据个数均不能大于列数。它等价于

Int d[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; // 依次对元素进行初始化


1 6 13

1.6.1 数组

5. 排序

数组作为一种常见的数据结构,在许多方面都得到了应用。“排序”就是一个常用的

应用实例。例如:

[例Ex_ArraySort] 把5个整型数按从小到大的次序排列

#include <iostream.h>

#define N 5

void main()

{

int a[N]={20, 40, -50, 7, 13};

int min,k;

for (int i=0; i<N-1; i++)

{// 外循环

min = a[i];k = i;

for (int j=i+1; j<N; j++)

{// 内循环

if (min>a[j])

{min = a[j];k = j;}

}

a[k] = a[i];a[i] = min;

}

for (i=0; i<N; i++)

cout<<a[i]<<"\t";

cout<<endl;

}

结果如下:


1 6 14

1.6.1 数组

5. 排序

上述排序是用“选择法”进行的。所谓“选择法”,其过程是这样的:首先从

N个数中找出最小值,放在第一个元素位置上,再从剩下的N-1个数中找

出最小值,放在第二个元素位置上,这样不断重复下去,直到剩下最后

一个数。

当然,也可以用“冒泡法”(或称“起泡法”)进行排序,其过程是:首先将N

个数中相邻两个数进行比较,若当前的数比下一个数大,则相互交换,

再与下一个相邻的数逐一比较,直到最大的数“沉”到第N个位置为止,再

将剩下的N-1个数,从头开始进行相邻两个数的比较,直到最大的数“沉”

到第N-1个位置为止,这样不断重复下去,直到剩下最后一个数。

程序如下:


1 6 15

1.6.1 数组

[例Ex_ArrayBubbleSort] 用“冒泡法”把5个整型数按从小到大的次序排列

#include <iostream.h>

#define N 5

void main()

{

int a[N]={20, 40, -50, 7, 13};

for (int i=1; i<N; i++)

{

for (int j=0; j<N-i; j++)

{

if (a[j]>a[j+1])

{

int temp;

temp = a[j];a[j] = a[j+1];a[j+1] = temp;

}

}

}

for (i=0; i<N; i++)

cout<<a[i]<<"\t";

cout<<endl;

}


1 6 16

1.6.1 数组

6. 字符数组

字符数组中的字符串是以空字符“\0”作为结束符,它虽不是字符串的内容,但却

占据了一个存储空间。例如:

charch[ ] = {“Hello!”};// 第一种形式

charch[ ] = “Hello!”;// 第二种形式

char ch[ ] = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘!’, ‘\0’};// 第三种形式

都是使得ch[0]为‘H’,ch[1]为‘e’,ch[2]为‘l’,ch[3]为‘l’,ch[4]为‘o’,ch[5]为‘!’,

ch[6]为‘\0’。但第二种形式是最简捷的。

charch[ 9] =“Hello!”; //从ch[6]-ch[8]都是空字符

charch[ 6] = “Hello!”; //char ch[7]=“Hello!”正确

char str[3][ ]={“How”, “are”, “you”};

这时,数组元素str[0][0]表示一个字符,值为’H’;但str[0][ ]却表示一个字符串“How”,因为str[0][ ]

是一个一维字符数组。


1 6 2

1.6.2 传递数组参数

数组也可作为函数的形参和实参,若数组元素作为函数的实参,则其用法与变量

相同。当数组名作为函数的实参和形参时,传递的是数组的地址。例如:

[例Ex_StrChange] 改变字符串中的内容

#include <iostream.h>

#include <string.h>

void change(char ch[5]);

void main()

{

char name[5]="Ding";

cout<<name<<endl;

change(name);// 调用时,只需指定数组名

cout<<name<<endl;

}

void change(char ch[5])

{

strcpy(ch,"Zhen");

}


1 6 21

1.6.2 传递数组参数

[例Ex_StrChange] 改变字符串中的内容

代码中,strcpy是一个处理字符串的C++库函数,它是将字符串“Zhen”复

制到ch字符数组中。使用时要添加包含文件string.h。

程序运行结果为:

(1) 实参数组与形参数组类型应一致,如不一致,结果将出错。

(2) 形参数组也可以不指定大小,在定义数组时数组名后面跟一个空的方括号,为了在被调用函数中处理数组元素的需要,可以另设一个参数,传递数组元素的个数。例如:

int sum(int array[], int n);


1 6 3

1.6.3 结构体

一个结构体是由多种类型的数据(变量)组成的整体。组成结构的各个分量

称为结构体的数据成员(简称为“成员”,或称为“成员变量”)。结构体是

C++提供的构造复杂数据类型的手段之一。

1. 定义结构体

结构体定义的格式为:

struct [结构体名]

{

<成员定义1>;

<成员定义2>;

...

<成员定义n>;

} [结构变量名表];


1 6 31

1.6.3 结构体

结构体定义是以关键字struct开始的,[结构体名]应是一个有效的标识

符,若该结构体变量以后不再定义,结构体名也可不指定。结构体中的

每个成员都必须通过“成员定义”来确定成员名及其类型。例如:

struct PERSON

{

int age; // 年龄

char sex; // 性别

float weight;// 体重

char name[25];// 姓名

} family_member;


1 6 32

1.6.3 结构体

其中,PERSON是结构体名,该结构有4个成员变量。family_member是

跟随结构体一起定义的结构体变量。当然,也可以在结构体定义后再定

义结构体变量。

例如:

struct PERSON sister; // struct关键字可以省略

PERSON brother;

PERSONyou, me, he;

PERSONpersons[10];// 定义一个结构体数组

都是合法的结构体变量的定义。


1 6 33

1.6.3 结构体

需要注意:

(1) 在定义结构体时,不要忘记最后一个花括号的结尾后面的分号“;”。

(2) 结构体的成员变量类型既可以是基本数据类型,也可以是其他合法的类型。

相同类型的成员变量也可用一行语句来定义,但定义的变量之间要用逗

号隔开。

例如:

struct STUDENT

{

PERSONone;// 用已定义的结构体类型声明成员

float eng, phy, math, poli; // 英语、物理、数学和政治的成绩

};


1 6 34

1.6.3 结构体

2. 结构体变量的初始化

结构体变量的初始化的一般形式是在变量后面加上:

= {<初值列表>};

例如:

struct POINT

{

int x;

int y;

} spot = { 20, 40 }; // 依次使spot中的x为20, y为40

POINT pt2={100};// 只是使pt2中的x为100

都是合法的初始化形式。


1 6 35

1.6.3 结构体

若当结构体中的本身又是一个结构体变量时,其初始化可用“{}”来

增加其可读性。例如:

struct RECT

{

POINTptLeftTop;

int nWidth;

int nHeight;

} rc={{10,20},40,50};


1 6 36

1.6.3 结构体

3. 结构体变量的引用

  • 当一个结构体变量定义之后,就可引用这个变量。使用时,遵循下列规则:

    只能引用结构体变量中的成员变量,并使用下列格式:

    <结构体变量名>.<成员变量名>

    例如:

    cout<<spot.x<<spot.y;

    “.”是成员运算符,它的优先级很高,仅次于域运算符,因而可以把spot.x

    和spot.y作为一个整体来看待,它可以像普通变量那样进行赋值或进行其

    他各种运算。


1 6 37

1.6.3 结构体

(2) 若成员本身又是一个结构体变量,引用时需要用多个成员运算符一级一级地找到最低一级的成员。例如:

struct RECT

{

POINTptLeftTop;

POINTptRightDown;

} rc={{10,20},{40,50}};

则有:

cout<<rc.ptLeftTop.x<< rc.ptLeftTop.y;


1 6 38

1.6.3 结构体

3. 结构体变量的引用

(3) 结构类型相同的变量之间可以直接赋值,这种赋值等效于各个成员的依次赋

值。例如:

struct PERSON

{

int age;// 年龄

char name[25];// 姓名

};

PERSON one = {30, "LiMing"};

PERSON another = one;

cout<<another.name<<"\n";// 输出"LiMing"

其中,another = one等效于:

another.age = one.age;

strcpy(another.name, one.name);


1 6 4

1.6.4 传递结构体参数

[例Ex_StructValue] 将结构体的值作为参数传给函数

#include <iostream.h>

struct PERSON

{

int age; // 年龄

float weight;// 体重

char name[25];// 姓名

};

void print(PERSON one)

{

cout <<one.name<<"\t"

<<one.age<<"\t"

<<one.weight<<"\n";

}

PERSON all[4] = {{20, 60, "Zhang"},

{28, 50, "Fang "},

{33, 78, "Ding "},

{19, 65, "Chen "}};

void main()

{

for (int i=0; i<4; i++)

print(all[i]);

}

结构体也可以作为函数的

形参和实参。

当以按值传递方式时,整

个结构体都将被复制到形

参中去。

例如:


1 6 41

1.6.4 传递结构体参数

[例Ex_StructValue] 将结构体的值作为参数传给函数

运行结果为:

print函数的参数是PERSON结构变量,main函数调用了4次print函数,实参为PERSON结构数组的元素。


1 6 42

1.6.4 传递结构体参数

事实上,结构体还可以作为一个函数的返回值。例如:

[例Ex_StructReturn] 将结构体的值作为参数传给函数

#include <iostream.h>

struct PERSON

{

int age; // 年龄

float weight;// 体重

char name[25];// 姓名

};

void print(PERSON one)

{

cout<<one.name<<" "

<<one.age<<" "

<<one.weight<<"\n";

}

PERSON getperson()

{

PERSON temp;

cout<<"请输入姓名、年龄和体重:";

cin>>temp.name>>temp.age>>temp.weight;

return temp;

}

void main()

{

PERSON one = getperson();

print(one);

}


1 6 43

1.6.4 传递结构体参数

[例Ex_StructReturn] 将结构体的值作为参数传给函数

运行结果为:

由于getperson函数返回一个结构体的值,因此需要先将用户输入的数据保存到临时结构体变量temp中,然后返回temp的值。


1 6 5

1.6.5 共用体

定义一个共用体可用下列格式:

union <共用体名>

{

<成员定义1>;

<成员定义2>;

...

<成员定义n>;

} [共用体变量名表];// 注意最后的分号不要忘记。

例如:

union NumericType

{

int iValue; // 整型变量,4个字节长

long lValue; // 长整型变量,4个字节长

float fValue; // 实型,8个字节长

};

这时,系统为NumericType开辟了8个字节的内存空间,因为成员fValue是实型,

所占空间最大。


1 6 6

1.6.6 枚举类型

枚举也是一种构造类型,它是一系列的有标识名的整型常量的集合,其

主要功能是增加程序代码的可读性。它的格式如下:

enum <枚举类型名> {<枚举常量表>} [枚举变量];

// 注意最后的分号不要忘记。

enum是关键字,枚举常量表中的枚举常量名之间要用逗号分隔,例如:

enum Days { Sun , Mon, Tue, Wed, Thu, Fri, Sat } today;

其中Days是定义的一个枚举类型名,它有七个枚举常量(又称枚举值、枚

举元素)。


1 6 61

1.6.6 枚举类型

默认时,系统为每一个枚举常量都对应一个整数,并从0开始,逐个增

1,也就是说枚举常量Sun等于0,Mon等于1,Tue等于2等等。这些默认

的值也可重新指定,例如:

enum Colors { Black , Blue, Green=4, Cyan, Red=8, Yellow, White };

则各枚举常量对应的整数依次为0,1,4,5,8,9,10。

上述定义中,today是定义的枚举类型Days的变量,也可以用下列格式

来定义。例如:

enum Days today, yesterday;

Days tomorrow;// 省略enum关键字


1 6 62

1.6.6 枚举类型

枚举变量最终的值只能等于该枚举类型中的某个枚举常量,而不能用一

个整型数值直接赋值。

例如:

today = Mon;// 合法,值为1

tomorrow = today;// 合法,值为1

int i = today;// 合法,值为1

yesterday = 3;// 不合法,不能直接赋值

需要注意的是,不要在定义枚举类型的同时,再对枚举常量、枚举变量

及枚举类型名重新定义。例如下列的定义是不合法的:

inttomorrow;

int Yellow;

intSun;


1 6 7 typedef

1.6.7 用typedef定义类型

使用typedef可以将已有的数据类型名用新的类型名(别名)来代替,它具

有下列格式:

typedef <已有的数据类型名> <类型别名>;

例如:

typedef float FLOAT;

typedefchar CH10[10];

这里,FLOAT表示float类型,CH10表示具有10个元素的字符数组类

型。这样在以后的代码中,就可以使用这些类型名定义新的变量,如:

FLOATx, y;

CH10a, b;// a和b都是具有10个元素的字符数组。

它们等价于

float x,y;

char x[10],y[10];


1 6 7 typedef1

1.6.7 用typedef定义类型

typedef几乎可以对所有的数据类型进行定义,但却不能用来定义变量;

而且与struct、union、enum等相比,它不能构造出新的数据类型。下面

的一些示例可帮助理解:

typedef unsigned long ULONG;

ULONG ul; // 等价于 "unsigned long ul;"

typedef struct mystructtag

{

} MYSTRUCT;

MYSTRUCT ms; // 等价于"struct mystructtag ms;"


  • Login