Download presentation
Presentation is loading. Please wait.
1
主要内容: ◆ 一维数组 ◆二维数组 ◆ 字符数组
第6章 数组 主要内容: ◆ 一维数组 ◆二维数组 ◆ 字符数组
2
为什么需要数组 sum=sum+cj; —— 循环不变式 输入10个成绩(int型),求总成绩、平均成绩、最好成绩、最差成绩。
for (n=1; n<=10; n++) { scanf(“%d”, &cj); sum+=cj; if (cj>max) max=cj; else if (cj<min) min=cj; } 10个成绩分别放在a、b、c、…? 如果这样,如何利用循环进行批量处理? sum=sum+cj; —— 循环不变式 10个成绩并未保存起来,cj中只存放了最后一个输入的成绩。
3
概 述 数组是一个由若干个相同类型数据组成的有序集合。这个有序集合中的每一个数据称为数组的元素,数组元素用共同的名字(数组名)和下标唯一标识,下标用方括号[]括起来。如: a[5]、a[8]、… 每一个数组元素均可以作为一个独立变量使用。 因此,引用这些数组元素时可用“同一名字,不同下标”来 实现。如: sum+=cj[n]; 数组是由内存中连续的存储单元组成,最低地址对应于数组 的第一个元素,最高地址对应于最后一个元素。 数组可以是一维的,也可以是多维的。
4
6.1 一维数组 一维数组(变量)的定义 数组定义: 类型说明符 数组名[长度]
6.1 一维数组 一维数组(变量)的定义 数组定义: 类型说明符 数组名[长度] 例:int a[10]; // 定义数组时,长度只能是常量表达式 char ch[20]; 说明:数组所占字节大小可由下式计算: 总字节数 = sizeof(类型) * 数组长度 下图说明了数组a在内存中的存储情况,假设起始地址为1000. 数组a a[0] a[1] a[2] a[3] … a[8] a[9] 地址 1000 1002 1004 1006 1016 1018 注意:C语言中的下标是从0开始的,而不是从1开始的!
5
一维数组的引用 注意:数组下标是否超出范围由程序设计者负责! 越界使用可能会导致严重后果!!! 引用形式: 数组名[下标]
注:下标的取值范围:0 ~ 数组长度-1 【例】将数字1到19之间的奇数装入一个整型数组。 void main( ) { int x[10]; /* 定义包含1 0个整型数的数组 * / int n; for (n=0; n<10; n++) x[n]=2*n+1; } 注意:数组下标是否超出范围由程序设计者负责! 越界使用可能会导致严重后果!!!
6
选择法排序 对于N个元素构成的数据列表:a[1], a[2], … , a[N-1], a[N] 选择法排序(升序)的基本思想是: 第一遍扫视整个数据列表,从整个数据列表中选出一个最小元素,并放到数据列表的第1个位置; 第二遍扫视从第2个数开始的数据列表,从该数据列表中选出一个最小元素,并放到数据列表的第2个位置; ...... 第N-1遍扫视从第N-1个数开始的数据列表,从该数据列表中选出一个最小元素,并放到数据列表的第N-1个位置。 至此,数据列表中的最大元素已放在第N个位置,排序完成。 第i次排序:从a[i], a[i+1], … , a[N]中选择一个最小元素(如a[p], i≤p≤N),并将a[p]与a[i]对调。
7
[算法]选择排序 实现第 i 趟排序的程序如下: for (i=1; i<N; i++) { // 共N-1趟排序 }
第i次排序:从a[i], a[i+1], … , a[N]中选择一个最小元素,并将它与a[i]对调。 post=i; // 找出最小元素的下标 for (j=i+1; j<=N; j++) if (a[j]<a[post]) post=j; if (post!=i) { // 实现对调 t=a[i]; a[i]=a[post]; a[post]=t; } 实现第 i 趟排序的程序如下: for (i=1; i<N; i++) { // 共N-1趟排序 } 共有 N-1 趟排序! 即 i 的取值分别为:1、2、…、N-1
8
[算法]选择排序 #include <stdio.h> #define N 10 int main() {
int a[N+1], i, j, post, t; // a[0]不使用,N个数据在a[1], …, a[N] printf(“Please input 10 integers: ”); for (i=1; i<=N; i++) scanf(“%d”, &a[i]); for (i=1; i<N; i++) { // 共N-1趟排序 post=i; // 找出最小元素的下标 for (j=i+1; j<=N; j++) if (a[j]<a[post]) post=j; if (post!=i) { // 实现对调 t=a[i]; a[i]=a[post]; a[post]=t; } return 0;
9
【例】在电视歌手大奖赛时,有10个评委评分。从键盘输入10个评委给某歌手的评分,要求找出10个评委中哪一个给了最低分、哪一个给了最高分。去掉一个最低分并去掉一个最高分后剩下的八个评分的平均值为该歌手的最后得分,求该歌手的最后得分。 // N为符号常量10,score[1]、score[2]、…、score[N]存放成绩 float score[N+1], sum=0, aver; // score[0]不使用 int i, minno=1, maxno=1; // 最低评分、最高评分的下标设为1 for (i=1; i<=N; i++) // 输入N个评分 scanf(“%f”, &score[i]); for (i=2; i<=N; i++) { // 找出最低评分、最高评分的下标 if (score[i]<score[minno]) minno=i; if (score[i]>score[maxno]) maxno=i; } for (i=1; i<=N; i++) // 求总评分,可并入输入成绩的循环中 sum+=score[i]; sum-=score[minno]+score[maxno]; aver=sum/(N-2); // 求平均得分
10
一维数组的初始化 一般方法: 1. 赋值语句或输入函数 2. 在数组定义语句中赋值 【例】
1. 赋值语句或输入函数 2. 在数组定义语句中赋值 【例】 int a[10]={0,1,2,3,4,5,6,7,8,9}; /* 全部初始化 */ int a[10]={0,1,2,3}; /* 部分赋值 */ int a[10]={0}; /* 部分赋值 */ int a[ ]={1,2,3,4,5}; /* 可省略数组长度 */ static int a[5]={1,2,3,4,5}; /* 静态初始化 */ 区别:静态初始化是在程序的编译阶段完成,而一般初始化是在程序的运行过程中完成的!
11
实例1 杨辉三角形性质: 编程产生杨辉三角形: 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1
(1) 第 1 行(i=1)只有一个元素; (2) 第 i 行有 i 个元素; (3) 第 i (i>1) 行的最左、最右元素为 1; (4) 第 i 行的中间元素是它上一行(i-1行)对应位置元素及其左边一个元素之和。 编程产生杨辉三角形: 1 因此,如果要存放整个杨辉三角形的值,就需要二维数组; 也可以采用一维数组存放某一行杨辉三角形的值,采用迭代的方法边产生、边输出杨辉三角形的值。
12
【算法】 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 生成第1行; int yf[N+1], i, j; 输出第1行;
for (i=2; i<=N; i++) { 由第 i-1 行生成第 i 行; 输出第 i 行; } int yf[N+1], i, j; yf[1]=1; // 生成第1行 printf(“%5d\n”, yf[1]); for (i=2; i<=N; i++) { // 生成第i行,注意i=2时 yf[i]=1; for (j=i-1; j>=2; j--) yf[j]=yf[j]+yf[j-1]; // 输出第i行 for (j=1; j<=i; j++) printf(“%5d”, yf[j]); printf(“\n”); } 1
13
实例2: 对于一个自然数,如果该数的所有因子之和等于该数,则该数称为完数。找出1000以内的所有完数,并输出它的所有因子。(如:6=1+2+3,6为完数!)
for (n=1; n<=1000; n++) { } sum=0; for (i=1; i<n; i++) // 找出所有因子并求和 if (n%i==0) sum+=i; 找出 n 的所有因子,并计算因子之和sum; if (sum==n) 输出 n 的所有因子; for (i=1; i<n; i++) // 重新产生一遍因子并输出 if (n%i==0) printf(“%d, ”, i); printf(“\n”);
14
实例2: 对于一个自然数,如果该数的所有因子之和等于该数,则该数称为完数。找出1000以内的所有完数,并输出它的所有因子。(如:6=1+2+3,6为完数!)
for (n=1; n<=1000; n++) { } sum=0; for (i=1; i<n; i++) // 找出所有因子并求和 if (n%i==0) sum+=i; sum=0; gs=0; for (i=1; i<n; i++) // 找出所有因子并保存,且求和 if (n%i==0) { factor[gs++]=i; sum+=i; } 找出 n 的所有因子,并计算因子之和sum; if (sum==n) 输出 n 的所有因子; for (i=1; i<n; i++) // 重新产生一遍因子并输出 if (n%i==0) printf(“%d, ”, i); printf(“\n”); for (k=0; k<gs; k++) // 输出所有已保存因子 printf(“%d, ”, factor[k]); printf(“\n”);
15
6.2 二维数组 1. 二维数组的定义 2. 二维数组的引用 3. 二维数组的初始化
16
二维数组的定义 数组说明: 类型说明符 数组名[长度1][长度2] 占用字节数:行数×列数×类型字节数=总字节数
类型说明符 数组名[长度1][长度2] 占用字节数:行数×列数×类型字节数=总字节数 例:float a[3][4]; [例] 将整数1到12装入一个3*4的二维数组。 int main ( ) { int i, j, num[3][4]; for (i=0; i<3; ++i) for (j=0; j<4; ++j) num[i][j]=(i*4)+j+1; return 0;}
17
二维数组的定义 数组 1 2 3 4 5 6 7 8 9 10 11 12 数组说明: 类型说明符 数组名[长度1][长度2]
1 2 3 4 5 6 7 8 9 10 11 12 数组说明: 类型说明符 数组名[长度1][长度2] 占用字节数:行数×列数×类型字节数=总字节数 例:float a[3][4]; [例] 将整数1到12装入一个3*4的二维数组。 int main ( ) { int i, j, num[3][4]; for (i=0; i<3; ++i) for (j=0; j<4; ++j) num[i][j]=(i*4)+j+1; return 0;}
18
二维数组的理解 内存存储 a[0] 例 int a[3][4]; a[1] a[2] 二维数组a是由3个构造元素组成 1 4 5 2 3
1 4 5 2 3 a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] a[0][0] a[1][3] a[2][0] a[2][1] a[2][2] a[2][3] a[1][2] 6 7 10 11 8 9 a[0] a[1] a[2] 例 int a[3][4]; 2016 17 2018 19 2020 21 2022 23 2008 9 2010 11 2012 13 2014 15 2000 1 2002 3 2004 5 20006 7 a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] a[1][2] a[1][3] a[2][0] a[2][1] a[2][2] a[2][3] a[0] a[1] a[2] 行名 每个构造元素a[i]是一个 包含4个元素的一维数组
19
二维数组的引用 ★ 0 1 2 3 4 形式: 数组名[下标1][下标2] 0 □ □ □ □ ◆ 1 □ □ □ □ 2 □ □ □ □
0 □ □ □ □ 1 □ □ □ □ 2 □ □ □ □ 4 ◆ int main() { int sum, i, j, a[4][5]; for (i=0; i<3; i++) // 输入数据 for (j=0; j<4; j++) scanf("%d", &a[i][j]); for (i=0; i<3; i++) { // 控制行 sum=0; for (j=0; j<4; j++) // 控制列 sum=sum+a[i][j]; a[i][4]=sum; // 横向汇总 printf(“Sum of row %d is %d\n”, i, sum); } return 0;} 3 ▲ ▲ ▲ ▲ ★ for (j=0; j<4; j++) { // 控制列 sum=0; for (i=0; i<3; i++) // 控制行 sum=sum+a[i][j]; a[3][j]=sum; // 纵向汇总 }
20
二维数组的初始化 例 int a[2][3]={{1, 2, 3}, {4, 5, 6}}; a[0][0] a[0][1] a[0][2]
全部初始化 分行初始化 例 int a[2][3]={{1, 2},{4}}; a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2] 1 2 4 部分初始化 例 int a[][3]={{1}, {4, 5}}; a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2] 1 4 5 第一维长度 省略初始化
21
二维数组的初始化 分行初始化 按元素排列顺序初始化 例 int a[2][3]={1, 2, 3, 4, 5, 6}; a[0][0]
全部初始化 例 int a[2][3]={1, 2, 4}; a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2] 1 2 4 部分初始化 例 int a[][3]={1, 2, 3, 4, 5}; a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2] 1 2 3 4 5 第一维长度 省略初始化
22
程序举例 例:将二维数组行列元素互换,存到另一个数组中. #include <stdio.h> int main() {
int a[2][3]={{1, 2, 3}, {4, 5, 6}}; int b[3][2], i, j; printf("array a:\n"); for (i=0; i<2; i++) { for (j=0; j<3; j++) { printf("%5d", a[i][j]); b[j][i]=a[i][j]; } printf("\n"); …… a= b= 1 4 2 5 3 6
23
#include <stdio.h> Int main() { int a[3][4]={{1, 2, 3, 4},
{9, 8, 7, 6}, {-10, 10, -5, 2}}; int i, j, row=0, col=0, max; 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; col=j; } printf("max=%d\n", max); printf("row=%d, col=%d\n", row, col); return 0;} 例: 求二维数组a[M][N]中最大元素值及其行号、列号。 max=a[0][0], row=0, col=0 for i=0 to M-1 for j=0 to N-1 a[i][j]>max 真 假 max=a[i][j] row=i col=j 输出:max 和 row、col
24
#include <stdio.h> int main() { int a[3][4]={{1, 2, 3, 4},
{9, 8, 7, 6}, {-10, 10, -5, 2}}; int i, j, row=0, col=0, max; max=a[0][0]; for (i=0; i<=2; i++) for (j=0; j<=3; j++) if (a[i][j]>a[row][col]) { max=a[i][j]; row=i; col=j; } printf("max=%d\n", a[row][col]); printf("row=%d, col=%d\n", row, col); return 0; 例: 求二维数组a[M][N]中最大元素值及其行号、列号。 max=a[0][0], row=0, col=0 for i=0 to M-1 for j=0 to N-1 a[i][j]>max 真 假 max=a[i][j] row=i col=j 输出:max 和 row、col
25
6.3 字符数组 1. 定义、引用、初始化 2. 用字符数组处理字符串 3. 字符数组的输入输出 4. 字符串处理函数
26
字符数组、引用、初始化 字符数组 定义 例 char c[10], ch[3][4]; 字符数组的初始化 逐个字符赋值
例 char ch[5]={‘H’, ‘e’, ‘l’, ‘l’, ‘o’}; ch[0] H e l o 逐个字符赋值 ch[1] ch[2] ch[3] ch[4] 例 char ch[5]={‘B’, ‘o’, ‘y’}; ch[0] B o y \0 逐个字符赋值 ch[1] ch[2] ch[3] ch[4]
27
字符数组、引用、初始化 字符数组 定义 例 char c[10], ch[3][4]; 字符数组的初始化 逐个字符赋值
例 char ch[6]={“Hello”}; char ch[6]=“Hello”; char ch[]=“Hello”; 用字符串常量 ch[0] H e l o ch[1] ch[2] ch[3] ch[4] \0 ch[5] 用字符串常量 例 char ch[5]=“Boy”; ch[0] B o y \0 用字符串常量 ch[1] ch[2] ch[3] ch[4]
28
字符数组、引用、初始化 字符数组 定义 例 char c[10], ch[3][4]; 字符数组的初始化 逐个字符赋值 用字符串常量
字符数组的引用 字符数组也可以通过a[i]来引用它的第 i 个元素(字符)。 一般情况下,是将整个字符数组作为一个字符串来使用。 字符串的操作是通过一些系统函数来实现的,主要包括: char str[60]=“Jiangxi”, str1[80]=“It is ”, str2[20]=“a dog.” puts(str), gets(str), strlen(str), strcat(str1, str2), strcpy(str1, str2), strcmp(str1, str2)
29
二维字符数组的初始化 例 char diamond[][5]={{'•', '•', '*'}, {'•', '*', '•', '*'},
{'*', '•', '•', '•', '*'}, {'•', '*', '•', '*'}, {'•', '•', '*'}}; 二维字符数组初始化 • * \0 diamond[0] diamond[1] diamond[2] diamond[3] diamond[4]
30
二维字符数组的初始化 例: char fruit[][7]={ “Apple”, “Orange”,
“Grape”, “Pear”, “Peach” }; 二维字符数组初始化 fruit[0] fruit[1] fruit[2] fruit[3] fruit[4] A p l e \0 O r a n g G P c h
31
h e l l o \0 用字符数组处理字符串 字符串及其结束标志 没有字符串变量,用字符数组处理字符串 字符串结束标志:‘\0’
内存存放字符ASCII码
32
用字符数组处理字符串 char ch[10]={“JXUFE”}; char ch[10]=“JXUFE”;
33
字符数组的输入输出 例: 字符数组的输出. 1、逐个字符输入输出:%c 2、将整个字符串一次输入输出:%s I a m b o y 普通
1 2 3 4 5 6 7 8 9 普通 字符数组 I a m b o y 1 2 3 4 5 6 7 8 9 \0 10 处理字符串 的字符数组 例: 字符数组的输出. #include <stdio.h> int main() { char c[10]={'I', ' ', 'a', 'm', ' ', 'a', ' ', 'b', 'o', 'y'}; char str[]=“I am a boy”; int i; for (i=0; i<10; i++) printf(“%c”, c[i]); // 逐个字符输出 printf("\n"); printf(“%s\n”, str); // 作为字符串输出 return 0; } 用字符数组名, 遇‘\0’结束
34
字符数组的输入输出 例:字符数组的输入。 例 用%c int main() { char str[5]; int i;
1、用字符数组名, 不要加& 2、输入串长度 < 数组维数 3、遇空格或回车结束 4、自动加‘\0’ 例:字符数组的输入。 例 用%c int main() { char str[5]; int i; for (i=0; i<5; i++) scanf(“%c”, &str[i]); printf(“%c”, str[i]); printf(“\n”); return 0; } // 此时,不构成字符串 例 用%s int main() { char str[5]; scanf(“%s”, str); printf(“%s\n”, str); return 0; } // 构成字符串 // 但要求输入少于5个字符
35
字符数组的输出 int main() { char a[]={'h', 'e', 'l', '\0', 'l', 'o', '\0'};
printf("%s", a); return 0; } 输出:hel h e l \0 l o \0 数组中有多个‘\0’时, 遇第一个结束
36
字符串输入举例 int main() { int i; char a[5]; scanf("%s", a);
printf(“%s\n”, a); return 0; } 输入字符串长度 < 数组维数 hel↙ hell↙ hello↙ 输入: h e l \0 h e l l \0 h e l l o 运行情况: (1)若输入 hel , 正常 (2)若输入 hell , 正常 (3)若输入 hello , 超出了数组长度,会出现问题
37
字符串输入举例 #include <stdio.h> int main() { char a[15], b[5], c[5];
运行情况: 输入:How are you? 输出:a=How b=are c=you? 字符串输入举例 #include <stdio.h> int main() { char a[15], b[5], c[5]; scanf("%s%s%s", a, b, c); printf("a=%s\nb=%s\nc=%s\n", a, b, c); scanf("%s",a); printf("a=%s\n",a); return 0;} scanf中%s输入时,遇空格或回车结束 运行情况: 输入:How are you? H o w \0 a r e \0 y o u ? \0
38
举 例 例 输入字符串“This is a string.”。 考虑如下输入语句: (A)scanf(“%20s”, s);
举 例 例 输入字符串“This is a string.”。 考虑如下输入语句: (A)scanf(“%20s”, s); (B)for (k=0; k<17; k++) s[k]=getchar(); // 输入17个字符 (C)k=0; while ((c=getchar())!=‘\n’) s[k++]=c; // 表示回车结束输入 s[k]=‘\0’; // 增加该语句,则可构成字符串 不构成字符串 不构成字符串
39
字符串处理函数 字符串的输入输出函数: 字符串输出函数puts
功能:向显示器输出<字符串>(输出完,自动换行) 说明:字符数组必须以‘\0’结束,即必须构成字符串 字符串输入函数gets 格式:gets(<字符数组>) // 只能是变量,即字符数组名 功能:从键盘输入一字符串(以回车结束)到<字符数组>中, 并自动加‘\0’,即构成字符串 说明:输入字符串长度应小于字符数组维数
40
字符串处理函数 字符串的输入输出函数: 例 #include <stdio.h> int main( ) {
char string[80]; printf(“Input a string:”); gets(string); puts(string); return 0; } 输入: How are you? 输出: How are you ? 字符串输出函数puts 格式:puts(<字符串>) // <字符串>为字符串常量或数组名 功能:向显示器输出<字符串>(输出完,自动换行) 说明:字符数组必须以‘\0’结束,即必须构成字符串 字符串输入函数gets 格式:gets(<字符数组>) // 只能是变量,即字符数组名 功能:从键盘输入一字符串(以回车结束)到<字符数组>中, 并自动加‘\0’,即构成字符串 说明:输入字符串长度应小于字符数组维数
41
字符串处理函数 头文件: string.h 字符串连接函数strcat
功能:把<字符串2>(可以是常量或数组)连到<字符数组1>后面 返值:返回<字符数组1>的首地址 说明: <字符数组1>的长度必须足够大 连接前,两串均以‘\0’结束;连接后,新串最后加‘\0’ 字符串拷贝函数strcpy 格式:strcpy(<字符数组1>,<字符串2>) 功能:将<字符串2>拷贝到<字符数组1>中去 返值:返回<字符数组1>的首地址 说明: <字符数组1>的长度必须足够大 拷贝时‘\0’一同拷贝 不能使用赋值语句为一个字符数组赋值
42
字符串处理函数 例 char str1[20], str2[20]=“Good.”; str1=“Hello!”; (×)
头文件: string.h 字符串连接函数strcat 格式:strcat(<字符数组1>,<字符串2>) 功能:把<字符串2>(可以是常量或数组)连到<字符数组1>后面 返值:返回<字符数组1>的首地址 说明: <字符数组1>的长度必须足够大 连接前,两串均以‘\0’结束;连接后,新串最后加‘\0’ 例 char str1[20], str2[20]=“Good.”; str1=“Hello!”; (×) str1=str2; (×) strcpy(str1, str2); (√) strcpy(str1, “Hello!”) (√) 字符串拷贝函数strcpy 格式:strcpy(<字符数组1>,<字符串2>) 功能:将<字符串2>拷贝到<字符数组1>中去 返值:返回<字符数组1>的首地址 说明: <字符数组1>的长度必须足够大 拷贝时‘\0’一同拷贝 不能使用赋值语句为一个字符数组赋值
43
#include <string.h> #include <stdio.h> int main() {
例 strcpy与strcat举例 #include <string.h> #include <stdio.h> int main() { char destination[25]; char blank[]=" ", c[]="C++", turbo[]="Turbo"; strcpy(destination, turbo); strcat(destination, blank); strcat(destination, c); puts(destination); return 0; } T r b o C + 1 2 3 4 5 6 7 8 9 u \0 24 ……. T r b o 1 2 3 4 5 6 7 8 9 u \0 24 ……. T r b o \0 1 2 3 4 5 6 7 8 9 u 24 ……. …... Turbo C++
44
字符串比较函数strcmp 格式:strcmp(<字符串1>,<字符串2>) 功能:比较<字符串1>与<字符串2>是否相同(均为常量或数组) 比较规则:对两个字符串从左向右逐个字符比较(ASCII码), 直到遇到不同字符或‘\0’为止 返回值:返回int型整数, a. 若<字符串1> < <字符串2>, 返回负整数 —— 第一个不相同字符的ASCII码值之差! b. 若<字符串1> > <字符串2>, 返回正整数 c. 若<字符串1> == <字符串2>, 返回零 说明:字符串比较不能用“==”,必须用strcmp 字符串长度函数strlen 格式:strlen(<字符串>) 功能:计算<字符串>(可以是常量或数组)长度(指字符串长度) 返值:返回<字符串>实际长度,不包括‘\0’在内
45
例 对于以下字符串,strlen(s)的值为:
字符串比较函数strcmp 格式:strcmp(<字符串1>,<字符串2>) 功能:比较<字符串1>与<字符串2>是否相同(均为常量或数组) 比较规则:对两个字符串从左向右逐个字符比较(ASCII码), 直到遇到不同字符或‘\0’为止 返回值:返回int型整数, a. 若<字符串1> < <字符串2>, 返回负整数 —— 第一个不相同字符的ASCII码值之差! b. 若<字符串1> > <字符串2>, 返回正整数 c. 若<字符串1> == <字符串2>, 返回零 说明:字符串比较不能用“==”,必须用strcmp 例 对于以下字符串,strlen(s)的值为: (1)char s[10]={‘A’, ‘\0’, ‘B’, ‘C’, ‘\0’, ‘D’}; (2)char s[ ]=“\t\v\\\0will\n”; (3)char s[ ]=“\x69\082\n”; 答案: 字符串长度函数strlen 格式:strlen(<字符串>) 功能:计算<字符串>(可以是常量或数组)长度(指字符串长度) 返值:返回<字符串>实际长度,不包括‘\0’在内
46
#include <string.h> #include <stdio.h> int main() {
char str1[]="Hello!", str2[]="How are you?", str[20]; int len1, len2, len3; len1=strlen(str1); len2=strlen(str2); if (strcmp(str1, str2)>0) { strcpy(str, str1); strcat(str, str2); } else if (strcmp(str1, str2)<0) { strcpy(str, str2); strcat(str, str1); } else strcpy(str, str1); len3=strlen(str); puts(str); printf(“Len1=%d,Len2=%d,Len3=%d\n”,len1,len2,len3); return 0;} 例 strcmp与strlen举例 How are you? Hello! Len1=6, Len2=12, Len3=18
47
数组应用举例 #include <stdio.h> int main() { char string[81];
int i, word=0, flag=1; gets(string); for (i=0; string[i]!='\0'; i++) if (string[i]==' ') flag=1; else if (flag==1) { flag=0; word++; } printf("There are %d words in the line\n", word); return 0; 例1: 输入一行字符,统计其中有多少个单词。(P126) 输入一字符串给数组 string i=0 word=0 flag=1 string[i]!=‘\0’ String[i]==空格 真 假 flag=1 flag=0 word++ i=i+1 输出:word flag==1
48
例 输入:Iamaboy. 1 1 1 1 1 1 1 当前字符==空格 是 否 未出现新单词,使flag=1, word不累加
是否空格 否 1 是 是 未 1 否 1 是 2 否 未 2 是 未 1 2 否 1 是 3 是 未 1 3 否 1 是 4 否 未 4 否 未 4 否 未 4 flag原值 新单词开始否 flag新值 word值
49
#include <stdio.h> #include <string.h> int main() {
char string[20], str[3][20]; int i; for (i=0; i<3; i++) gets(str[i]); // str[i]为一维数组 if (strcmp(str[0], str[1])>0) strcpy(string, str[0]); else strcpy(string, str[1]); if (strcmp(str[2], string)>0) strcpy(string, str[2]); printf("\nThe largest string is: %s \n", string); return 0;} 例2:有三个字符串,找出其中最大者。 H o w \0 H e l l o \0 H i g h \0 str[0] str[1] str[2]
50
例4:字符串匹配。设主串数组名为S,子串数组名为T,现在要找出子串T在主串S中第一次出现的位置。(P129)
例如,假设子串和主串分别为:S="ababcabcacbab",T="abcac",则匹配过程如下: (1) 第1趟从主串的第1个字符起与子串比较,匹配过程如下: a b a b c a b c a c b a b a b c (2)第2趟从主串的第2个字符起与子串比较,匹配过程如下: a b a b c a b c a c b a b a
51
例4:字符串匹配。设主串数组名为S,子串数组名为T,现在要找出子串T在主串S中第一次出现的位置。(P129)
(3)第3趟从主串的第3个字符起与子串比较,匹配过程如下: a b a b c a b c a c b a b a b c a c 字符串匹配的基本思想是:从主串S的第一个字符起与子串T的第一个字符比较,若相等,则继续逐个比较后续字符,否则从主串的下一个字符其在重新和子串的字符比较。 依此类推,直到子串T中的每个字符依次和主串S中的一个连续的字符序列相等,则称匹配成功,否则就是匹配失败。 (4)同理,第4、5趟匹配不成功,第6趟从主串的第6个字符起与子串比较,匹配过程如下: a b a b c a b c a c b a b a b c a c 例如,假设子串和主串分别为:S="ababcabcacbab",T="abcac",则匹配过程如下: (1) 第1趟从主串的第1个字符起与子串比较,匹配过程如下: a b a b c a b c a c b a b a b c (2)第2趟从主串的第2个字符起与子串比较,匹配过程如下: a b a b c a b c a c b a b a
52
h e l l o \0 h e l l o 几种值得注意的使用情况: 例 char name[0];
float weight[10.3]; int array[-100]; 例 char str[]=“Hello”; char str[]={‘H’,‘e’,‘l’,‘l’,‘o’}; 例 int a[10]; float i=3; a[i]=10; 2 3 1 4 h e l l o h e l l o \0 5 例 int a[5]; a={2, 4, 6, 8, 10}; 例 int a[ ][10]; float f[2][]={1.2, 2.2}; 例 比较 int a[2][3]={{5, 6}, {7, 8}}; 与 int a[2][3]={5, 6, 7, 8};
53
排序与查找 一、排序 二、查找 1. 选择法排序; 2. 冒泡法排序; 3. 插入法排序。 1. 顺序查找法;
1. 选择法排序; 2. 冒泡法排序; 3. 插入法排序。 二、查找 1. 顺序查找法; 2. 二分查找法(折半查找法)。
54
冒泡排序法 第一遍冒泡排序:对数组中的n个元素,自左至右将相邻两个数进行比较(需要比较n-1次),把小的调到前头(小的往上冒,故称为“冒泡法”)。 结果:最大的数沉到第n个元素中。 第二遍冒泡排序:对数组中前n-1个元素,自左至右将相邻两个数进行比较(需要比较n-2次) ,把小的调到前头。 结果:次大的数沉到第n-1个元素中。 …… 第n-1遍冒泡排序:对数组中的前2个元素,对它们进行比较,把小的调到前头。 结果:第n-1个大的数沉到第2个元素中。 最后,第一个元素中就是n个数中最小的,排序完成。
55
第 i 次排序(i=1, 2, …, n-1): 对a[0]、a[1]、…、a[n-i]进行处理(共n-i+1个元素)。 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; } 共需要进行n-1遍排序。
56
插入排序法 问题:输入10个数,按插入排序法将它们按升序排列。
思路:先输入一个数放在数组的第一个元素,它是有序的;从第二个输入的数开始,对每个输入的数寻找在数组中的插入位置,将插入位置之后的所有元素向后移动,并在插入位置上插入该数;直到10个数输入完毕。 #define N 10 void main() { int a[N], i, j, temp; scanf(“%d”, &a[0]); for (i=1; i<N; i++) { scanf(“%d”, &temp); for (j=i; j>0; j--) // 寻找插入位置 j if (temp>=a[j-1]) break; else a[j]=a[j-1]; a[j]=temp; // 插入 }
57
顺序查找法 问题:编写一个函数,在指定的数组a[ ]中查找一个指定的数key,若找到则返回在数组中位于第几个,否则返回0。 程序:
int search(int a[ ], int n, int key) { int i=0, r=0; for (i=0; i<n; i++) if (key==a[i]) { r=i+1; break; } return r;
58
二分查找法(折半查找法) 问题:编写一个函数,在数组a[ ]中查找一个指定的元素key。 算法:
1、将数组按升序排列(或假设数组已经有序)。 2、top, bott, mid top=0; bott=n-1; mid=(top+bott)/2; 3、当top<=bott时判断: (1)若a[mid]==key,则表示找到; 若key>a[mid],则:top=mid+1; 若key<a[mid],则:bott=mid-1; (2)求中点:mid=(top+bott)/2 4、当top>bott时,表示查找目标不存在.
59
实 例 问题:求字符串中字符‘s’的个数。 int main( ) { int n=0, i=0;
实 例 问题:求字符串中字符‘s’的个数。 int main( ) { int n=0, i=0; while (str[i]!='\0') { if (str[i]=='s') n++; i++; } print(“s的个数为%d”, n); return 0;
60
实 例 问题:找出二维整数数组中的鞍点。二维数组中鞍点位置的判断条件:其值在其行上为最大,而在其列上为最小。 注意:矩阵中可能没有鞍点。
61
实 例 问题:读入字符行,统计其中英文字母出现的次数。
Similar presentations