slide1 n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
第七章 数组 PowerPoint Presentation
Download Presentation
第七章 数组

Loading in 2 Seconds...

play fullscreen
1 / 56

第七章 数组 - PowerPoint PPT Presentation


  • 140 Views
  • Uploaded on

第七章 数组. 前面所用到的数据均为基本类型 ( 整、实、字符 ) ,为了丰富数据类型 ,须提供强有力的数据表达方式。 C 语言提供了一种构造类型数据 ––– 由基本类型按某一规则组合在一起。. 其中数组:同一种 ( 基本 ) 类型按一定顺序组合在一起的数据类型。. §7.1 一维数组. 7.1.1 一维数组的定义. 形式 : 类型说明符 数组名 [ 常量表达式 ];. 例 : int a [20]; float x [100];. 1. 数组名的确定方法同变量名。. 2. C 语言用方括号 [ ] 表示数组元素个数。.

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

PowerPoint Slideshow about '第七章 数组' - linnea


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
slide1

第七章 数组

前面所用到的数据均为基本类型(整、实、字符),为了丰富数据类型 ,须提供强有力的数据表达方式。C语言提供了一种构造类型数据–––由基本类型按某一规则组合在一起。

其中数组:同一种(基本)类型按一定顺序组合在一起的数据类型。

slide2

§7.1一维数组

7.1.1 一维数组的定义

形式: 类型说明符 数组名[常量表达式];

例: int a [20];

float x [100];

1. 数组名的确定方法同变量名。

2. C语言用方括号[ ]表示数组元素个数。

slide3

3. 常量表达式为常量和符号常量。不允许有变量,其表达式的值代表了元素的个数。

例: int a[20];

表示有20个元素

且元素从0开始编排:a[0],a[1],…,a [19]

slide4

4. 可在定义时对静态数组和外部存储(全局)数组赋初值, 方法如下:

对全部元素赋初值

static int a[10]={10, 11, 12, 13, 14, 15, 16, 17, 18, 19,}

静态

对部分元素赋初值

static int a[10]={0,1,2,3,4};

如此,只有前5个元素初值确定,后5个元素由系统设置。

slide5

 如对数组元素赋同一初值,必须一一写出:

static int a[10]={0,0,0,0,0,0,0,0,0,0};

不可写成: static int a[{10*0}];

×

 若赋全部元素的初值,可省略常量表达式

…a [ ]={0,1,2,3};

表示a[4],即只有4个元素。

slide6

7.1.2 一维数组的引用

1. 须象使用变量那样,先定义,后使用

2. 引用方式: 数组名[下标]

其中的下标为整型表达式,但不得越界。

数组引用代表了一个元素,等价一个同类型的变量。

例: a [0]5+a[1]  6 为正确的算术表达式

3. 一般地,一维数组各元素分配在连续的内存单元之中。

slide7

例7.1:给 a[0] ~ a[9] 赋值 0 ~9,然后按逆序输出。

main( )

{

int i,a[10];

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

a[i]=i;

for (i=9;i>=0;i--)

printf(“%4d”,a[i]);

printf(“\n”);

}

slide8

7.1.3 一维数组的应用

例7.2:求Fibonacci 数列。

 定义数组,并赋初值

static int f [20]={1,1};

用循环for实现:

for (i=2; i<20; i++)

f [i]=f [i –2]+f [i –1];

注意:下标界限问题:i =2且i<20

slide9

1

8

89

987

1

13

144

1597

2

21

133

1584

3

34

377

4181

5

55

610

6765

程序如下:

main()

{ int i;

static int f [20]={1, 1};

for (i=2; i<20; i++)

f [i]=f [i–2]+f [i–1];

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

{ if (i%5 = =0) printf("\n");

printf("%12d",f [i] )

}

}

运行结果如下:

slide10

 打印: 每5个数换一行。

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

{ if (i%5= =0) printf(" \n ");

printf (" %12d ", f [i]);

}

slide11

例2:排序问题–––计算机处理数据的一个重要问题例2:排序问题–––计算机处理数据的一个重要问题

排序算法较多,一种最简单的算法–––选择排序法用得较多。基本思路: 设有n个数,需将它们从小到大顺序排列。则:

1. 从n个元素中,通过比较,找出最小元素,放在第一个位置上。

2. 在剩下的n –1个元素中,找出第二小的元素并把它放在第二个位置上。

3. 对上述过程重复,直至剩下一个元素。

slide12

例如: 8, 4, 20, 100, 28, 1,

第1次: 4, 8, 20, 100, 28, 1

1, 8, 20, 100, 28, 4

两次交换

第2次: 1, 4, 20, 100, 28, 8 –––一次交换

第3次: 1, 4, 8, 100, 28, 20 –––一次交换

第4次: 1, 4, 8, 28, 100, 20,

1, 4, 8, 20, 100, 28

两次交换

第5次: 1, 4, 8, 20, 28, 100 –––一次交换

slide13

初始化

输入n个元素a数组

i1

B

ji+1

A

No

a[i]>a[j]

Yes

交换a[i]

a[j]

从以上例子可以看到: 用到两种循环,第一种循环––找第i小的元素,第二种循––对其后的元素的一一比较。

流程图:

slide14

jj+1

内循环

No

A

j>n

Yes

ii+1

外循环

No

B

i> n–1

Yes

打印结果

结束

slide15

程序:

main()

{ int a [11];

int i, j, t;

printf (" please input 10 numbers:\n ");

for (i=1; i<=10; i++) scanf("%d", &a[i]);

printf(" \n ");

for (i=1; i<=9; i++)

for (j=i+1; j<=10; j++)

if (a[i]>a[j]) { t=a[i]; a[i]=a[j]; a[j]=t;}

printf (" the sorted numbers: \n ");

for (i=1; i<=10; i++) printf(" %d ", a[i]);

printf(" \n " );

}

思考:此算法还可改进!

slide16

程序:

main()

{ int a [11];

int i, j, t,minj;

printf (" please input 10 numbers:\n ");

for (i=1; i<=10; i++) scanf("%d", &a[i]);

printf(" \n ");

for(i=1;i<=9;i++) {minj=i; for(j=i+1;j<=10;j++) if(a[j]<a[minj]) minj=j;if(minj!=i) {t=a[i];a[i]=a[minj];a[minj]=t;}

}printf (" the sorted numbers: \n ");

for (i=1; i<=10; i++) printf(" %d ", a[i]);

printf(" \n " );

}

slide17

(1)若a0>a1,则a0、a1交换;(使a1为a0,a1的大者)(2)若a1>a2,则a1、a2交换;(使a2为a1,a2的大者)…(i) 若ai-1>ai,则ai-1、ai交换;(使ai为ai-1,ai的大者)按照这种方法运算下去,数组中的最大元一定可以移动到最后一个下标位置!

另一种排序法:冒泡排序法(教材例7.3)

相邻元素比较大小,发生交换,使最大值(最小值)“浮出”到数组尽头:

slide18

冒泡排序举例:

初始序列为49,38,65,97,76,13,27,49’由小到大排序

第1趟冒泡:38 49 65 76 13 27 49’ [97]

第2趟冒泡:38 49 65 13 27 49’ [76 97]

第3趟冒泡:38 49 13 27 49’ [65 76 97]

第4趟冒泡:38 13 27 49 [49’ 65 76 97]

第5趟冒泡:13 27 38 [49 49’ 65 76 97]

第6趟冒泡:13 27 [38 49 49’ 65 76 97]

排序结果为:13 27 38 49 49’ 65 76 97

slide19

冒泡排序算法:

N元数组a[0]~a[N-1]由小到大排序:第1步:找到a[0]~a[N-1]中的最大元浮动到a[N-1];第2步:找到a[0]~a[N-2]中的最大元浮动到a[N-2];第3步:找到a[0]~a[N-3]中的最大元浮动到a[N-3];…第i步:找到a[0]~a[N-i]中的最大元浮动到a[N-i];…第N-1步:找到a[0]~a[1]中的最大元浮动到a[1]。算法停止.

slide20

#include “stdio.h”#define N 10 void main(){int a[N],i,j,t;printf(“Input %d int numbers:\n”,N); for(i=0;i<N;i++) scanf(“%d”,a+i);for(i=1;i<N;i++) for(j=0;j<N-i;j++) if(a[j]>a[j+1]) { t=a[j];a[j]=a[j+1];a[j+1]=t; }printf(“Reslut:”);for(i=0;i<N;i++) printf(“%6d”,a[i]);printf(“\n”);}

此处, a+i等价于&a[i]

slide21

顺序查找(一种查找方法)

main()

{int i, a[10],x;

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

scanf(“%d”,&a[i]);

scanf(“%d”,&x);

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

if (a[i]==x) break;

if (i<=9) printf (“%d is a [%d] ”,x,i);

else printf (“not find %d” ,x);

}

例:键盘输入10个数存于数组a[10]中,再输入一数x,查找x在a[10]中的位置。

程序如右:

slide22

折半查找(也称为对分查找)

算法:

设a[0]~a[N-1]已升序,待查找元素为x令起点下标 h=0; 终点下标 r=N-1;中点下标 m=(h+r)/2;

@当h<=r时执行以下步骤:

若x==a[m]则表明查找成功,a[m]为所找元素;x<a[m],显然x在a[h]~a[m-1]之间,则h不变;r=m-1;m=(h+r)/2;转@ x>a[m],显然x在a[m+1]~a[r]之间,则 r不变;h=m+1;m=(h+r)/2;转@ 若h>r,则表明查找失败.

该算法仅适用于在已排序的数组中快速查找所需要的元素,具有效率高的突出优点。可以证明,当数组长度为n个元素时,该算法的平均比较次数不会超过log2n+1。

slide23

/*升序数组a[N]中查找x,找到返回有效下标0~N-1, 查找失败返回-1*/main() {int a[10]={1,2,3,4,5,6,7,8,9,10}; int x,h,r,m;scanf(“%d”,&x);h=0;r=9;m=(h+r)/2; while(h<=r&&x!=a[m]) if(x<a[m]) {r=m-1;m=(h+r)/2;} else { h=m+1;m=(h+r)/2; }if(h>r) printf (“not find %d” ,x); else printf (“%d is a [%d] ”, x,i);

}

slide24

§7.2 二维数组

7.2.1 二维数组的定义

形式 类型说明符 数组名[常量表达式] [常量表达式]

例: int a[4] [10];

float x[8] [20];

1. 不可将定义写为int a[4,10]。

slide25

2. 可将二维数组的元素看成为若干个特殊的一维数组。

如:int b[3] [4];

则: 有三个特殊的一维数组b[0],b[1], b[2],每一个又有四个元素:

b[0]: b[0][0], b[0][1], b[0][2], b[0][3],

b[1]: b[1][0], b[1][1], b[1][2], b[1][3],

b[2]: b[2][0], b[2][1], b[2][2], b[2][3],

slide26

3. 二维数组的存放方式为: 按行存放。由此可推广 至三维、n维数组的定义和存放。

即: 最右边的下标变化最快。

4. 初始化:

按行给二维数组赋初值:

static int a[3][4]={{1,2,3,4}, {5,6,7,8,},

{9,10,11,12,}};

可以去掉其中的{ }。

slide27

则相当于 1 2 0 0 3 0 0 0 8 0 0 0

 可以对部分元素赋初值,但需表达清楚。如:

static int a[3][4]={{1,2},{3},{8}}。

可通过赋初值决定数组大小。如为二维,则只可省略第一维的大小.

static int a[ ][4]={1,2,3,…,12};

slide28

7.2.2 二维数组元素的引用

形式: 数组名[下标][下标]

其中的下标为整型表达式,但不得越界。

与一维数组元素一样,二维数组元素相当于同类型的简单变量。

slide29

1 4

2 5

3 6

1 2 3

4 5 6

a=

b=

7.2.3 程序举例

例1将一个二维数组行和列元素互换,存到另一个二维数组中。例如:

程序如下:

slide30

main()

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

static int b[3] [2], i, j;

printf("array a: \n");

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

{ for (j=0; j<=2; j++)

{printf("%5d", a[i][j]); b[j][i]=a[i][j];}

printf("\n");

}

printf("array b:\n");

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

{ for (j=0; j<=1; j++) printf("%5d", b[i]j]);

printf("\n");

}

}

slide31

运行结果如下:

array a:

1 2 3

4 5 6

array b:

1 4

2 5

3 6

 数组元素数据的输入必须以循环方式进行或者定义时置初值。

slide32

max= a[0][0]

for i=0 to 2

for j=0 to 3

a[i][j]>max

max= a[i][j]

row=i

colum=j

输出:max和row,colum

 二维数组一般用二重循环

例2. 有一个3×4的矩阵,要求编程序求出其中值最大的那个元素的值,以及所在的行号和列号。

先用N-S流程图表示算法,见图7.6

slide33

据此写出以下程序:

main()

{ int i,j, row=0, colum=0, max;

static int a[3][4]={{1,2,3,4},{9,8,7,6}, {–10,10, –5, 2}};

max=a[0][0];

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

for (j=0; j<=3; j++)

if (a[i][j]>max){max=a[i][j]; row=i; colum=j;}

printf( "max=%d,row=%d, colum=%d\n ", max, row, colum);

}

输出结果为:

max=10, row=2, colum=1

slide34

§7.3 字符数组

用来存放字符数据。字符串–––用字符数组存放。

7.3.1字符数组的定义

char c[10];

大小

数组名

类型名

1. 初始化:

 直接给出字符串中的各字符

static char a[4]={' G ', ' o ', ' o ', ' d '};

若字符多于元素个数,则语法错。

slide35

可以去掉定义时的大小设置,而通过自动赋值决定 长度(大小)可以去掉定义时的大小设置,而通过自动赋值决定 长度(大小)

static char x[ ]={' I ', ' ', ' a ', ' m ', ' ', 'a', ' ', ' s ', ' t ', ' u ', ' d ', ' e ', ' n ', ' t '};

 前面说过,字符串常量用“ ” 表示,且由‘ \0’结尾.

static char x[ ]={"I am a student. "};

则长度为15+1=16, 其中x[15]存放‘\0’,其中 { }亦可省略。

2. 字符数组的引用

每一个字符数组元素相当于一个字符变量。

slide36

7.3.2 字符数组的输入输出

格式符: %c –––逐个输入/输出字符。

%s ––– 整个串一次输入/输出。

1. 输出 (用%s)

用%s输出时,不输出‘\0’。

在printf中须直接写数组名.

static char c[ ]={"I am a student"};

printf("%s", c);

slide37

 若数组长度大于字符串长度,则遇到‘ \0’

即停止输出

static char c[10]=" china";

printf(" %s", c);

 输出时遇到第一个‘ \0’即结束。

slide38

2. 输入(用%s)

 输入字符串时,系统自动加上‘ \0’

 输入多个字符串,可用空格隔开。

Static char str1[5], str2[5], str3[5];

scanf(" %s%s%s", str1, str2,str3);

则:输入 How are you?

str1: H o w \0

str2: a r e \0

str3: y o u \0

slide39

str: H o w \0 ……

只能输入不包括空格、\t和\n的字符串

若: static char str[13];

scanf("%s", str);

输入: How are you  则只会将How输入,且存为

 scanf中须用地址量,数组名表示地址量。

slide40

视C的版本而定

7.3.3 字符串处理函数

在使用1、2字符串函数时要包含头文件“stdio.h”。

在使用3-6字符串函数时要包含头文件“string.h”。

1. puts(字符数组名) 输出一个字符串

  • 例:static char str[ ]={" China\nBeijing"};
  • puts(str);
  • 输出:China Beijing
  • 字符串中可包含转义字符
  • \0自动转换为\n
slide41

2. gets(字符数组名)

功能:输入一个字符串到字符数组

  • 例:static char c[6];
  • gets(c);
  • 输入:China↙
  • 数组c在内存中实际存放情况为:

串长=5

C

H

I

N

A

\0

c[0]

c[1]

c[2]

c[3]

c[4]

c[5]

slide42

x

y

...

z

\0

a

b

c

d

e

f

g

\0

3. strcat(字符数组名1,字符数组名2)

功能:连接两个字符数组中的字符串,串2接在串1的后面

str2

  • 例:char str1[30]=“xyxyz”;char str2[]=“abcdefg”; printf(“%s”,strcat(str1,str2));
  • 输出: xyxyzabcdefg
  • 字符数组1要足够长。
  • 根据字符串1中 \0 的位置进行字符串连接。
  • 关键:要用str2的第1个字符覆盖str1的串结束标记\0。

...

...

...

a

b

c

d

e

f

g

\0

str1

slide43

a

b

...

...

...

f

g

\0

4. strcpy(字符数组名1,字符串2)

功能:将字符串2复制到字符数组1中去

  • 例:char str1[10] ;char str2[10]=“abcdefg”;strcpy(str1,str2); printf(“%s”,str1);
  • 输出: abcdefg

没有必要复制整个数组,根据字符串中 \0 的位置,只对\0前面的字符进行复制。

字符串2可以是字符串常量

例: strcpy(str1, "China");

str1

...

...

...

str2

a

b

...

...

...

f

g

\0

slide44

5. strcmp (字符串1,字符串2)

功能:比较字符串1和字符串2

确定字符串大小的基本规则:按照串中对应位置字符的ASCII码值的大小确定大小。

例如:”abc” < ”b”因为字符 a < b

”abc” > ”abadef”因为字符 c > a

例:strcmp(str1,str2); strcmp(“China”,”Korea”); strcmp(str1,”beijing”);

slide45

结果由函数值带回:

字符串1=字符串2,函数值为0;字符串1>字符串2,函数值为正;字符串1<字符串2,函数值为负;

例:当str1=str2时,打印输出“yes”

if(str1==str2) printf(“yes”); ×

if(strcmp(str1,str2)==0) printf(“yes”); √

slide46

6. strlen(字符数组名)

功能:测试字符串长度

例:char str [10] =“China”;printf(“%d”,strlen(str));

输出结果: 5

slide47

7.3.4 字符串数组举例

例:输入一行字符,统计其中有多少个单词,单词之间用空格分隔开。

程序如下:

slide48

# include "stdio.h"

main ( )

{char string[81];

int i, num=0, word=0;

char c;

gets (string);

for (i=0; (c=string[i])!= '\0 '; i++)

if ( c= = ' ')word=0;

else if (word = =0)

{word=1; num++;}

printf("There are %d words in the line \n ", num);

}

slide49

运行情况如下:

I am a boy.

There are 4 words in the line

slide50

length=0

length=1

length=2

a

b

c

d

e

f

g

\0

串长

例:求字符串长度

  • 根据字符串中 \0 的位置来计算字符串长度。
  • 若:数组中第i 个元素为\0,则,串长=i。
  • #include <stdio.h>
    • main ( )
    • { intlength;
    • char line[100];
    • gets(line);
    • length=0;
    • while( line[length] != ’\0’)
    • length++;
    • printf (”String length=%d”, length);
    • }

length=7

slide51

例:字符串反向。

  • 在字符串中将首尾字符进行对调。

str

a

b

c

d

\0

e

f

g

h

i

j

k

\0

9

8

i=10

j=0

1

2

算法:当 j <i时,逐步交换 i 和 j 指向的字符

k

j

i

c

b

a

i=10,9,8,7,

j=0,1,2,3,

  • main ( )
    • { char str[100], c; inti,j;
    • printf (”Enter string:”); gets (str);
    • for( i=0; str[i]!=’\0’;i++ ) ;
    • i--;
    • for( j=0;j<i;i- -, j++)
    • { c=str[i]; str[i]=str[j]; str[j]=c;
    • }
    • printf(”Output string:%s\n”, str);
    • }

/* 确定\0的位置 */

/* i 指向\0之前的最后一个字符 */

/* 向中间逐步交换 i 和 j 指向的字符 */

slide52

x

y

...

z

\0

a

a

b

b

c

c

d

d

e

e

f

f

g

g

\0

\0

例:字符串连接——编写strcat(str1,str2)

  • 将串str2连接到串str1之后。
  • 根据字符串中 \0的位置进行字符串连接。
  • 关键:要用str2的第1个字符覆盖str1的串结束标记\0。

str2

  • #include <stdio.h>
  • main( )
  • { charstr1[100],str2[100];
  • int i, j;
  • printf (”Enter string 1:”);
  • gets(str1);
  • printf (”Enter string 2:”);
  • gets (str2);
  • for(i=0; str1[i]!=’\0’;i++ ); /* 确定\0位置 */
  • for (j=0; (str1[i]=str2[j]) != ’\0’;;i++,j++ );
  • printf(”Output string 1:%s\n”, str1);
  • }

...

...

...

a

b

c

d

e

f

g

\0

str1

算法:

1、查找str1的串结束标记\0

2、从str1的\0开始,将str2复制到str1。

slide53

7.10:统计字符串中每个字符出现的次数。

  • 基本思路:开一个“统计数组”记录每个字符出现的次数。
  • 关键:每个字符与数组中进行统计记数元素之间的对应关系。
  • 根据ASCII码的性质,将字符作为统计数组中元素的下标。
  • #include <stdio.h>

int count[128]; /* 统计数组,初始化时全为 0 */

    • main ( )
    • { char line[200]; int k=0;
    • printf (”\nEnter String:”);
    • gets (line);
    • while ( line[k] != ’\0’ ) /* 对字符这个进行统计 */
    • count [ line[ k++ ] ] ++; /* 将字符作为下标*/

for (k=0; k<=127; k++) /* 输出统计结果不为0的字符 */

if ( count[k]>0 ) printf (”%c=%d\t”, k,count[k]);

    • }
slide54
课外学习
  • 看书 p122——128
  • 作业题 7.1、7.5
  • 上机题 7.2、7.4
slide55
课外学习
  • 看书 p122——130
  • 作业题 7.7、7.8
  • 上机题 7.6、7.9
slide56
课外学习
  • 看书 p130——140
  • 作业题 7.11、7.14、7.15
  • 上机题 7.10、7.13