页数:50页文件大小:1.46 MB来源: C语言程序设计ppt课件
本课件讲解C语言的数组,先说明为何需要数组以及一维数组的定义、引用与初始化,接着通过线性查找、二分查找、冒泡排序与选择排序等实例巩固一维数组的应用,再介绍二维数组的定义、初始化与求最大值,最后展开字符数组与字符串处理函数,并说明字符串结束标志与常用库函数的实现。
第五章数组章节封面,标示本章主线:概述、一维数组、多维数组与字符数组。
例:给出10个儿童的体重,求平均体重并打印低于平均体重的数值
用10个独立变量 w1~w10 需要写10次 scanf 和10次判断,代码冗长;改用数组后可用循环统一处理。
#include <stdio.h> #define SIZE 10 main() { int w[SIZE]; int t = 0, i; for (i = 0; i < SIZE; i++) scanf("%d", &w[i]); for (i = 0; i < SIZE; i++) t += w[i]; t = t / 10; for (i = 0; i < SIZE; i++) if (w[i] < t) printf("%d\n", w[i]); }数组:构造数据类型之一,是一组有序的、类型相同的数据的集合,用数组名标识;元素属同一数据类型,用数组名和下标确定。
一维数组定义:数据类型 数组名[常量表达式];
int a[6]; 编译时分配连续内存,内存字节数 = 数组维数 * sizeof(元素类型)int i=15; int data[i]; 为非法一维数组引用:
int a[10]; printf("%d", a); 是错误的,应改为循环逐个输出 a[i]数组元素在功能上等价于一个一般的变量, toddlers 可以参与各类运算。
一维数组初始化:在定义数组时为数组元素赋初值。
int a[]={1,2,3,4,5,6}; 由编译系统据初值个数确定维数int a[5]={6,2,3}; 得 6,2,3,0,0int a[3]={6,2,3,5,1};数组定义中的常见错误:
int a[5]; a = {2, 4, 6, 8, 10}; char name[0]; float weight[10.3]; int array[-100]; 合法示例:#define N 6 后 int a[N], b['B'-60], c[]={1,2,3,4,5,6};
例:找10个整数的最大值和最小值
步骤:1、输入;2、处理:初值 max=min=x[0],循环比较,若 max<x[i] 则 max=x[i],若 min>x[i] 则 min=x[i];3、输出 max 与 min。
#include <stdio.h> #define SIZE 10 main() { int x[SIZE], i, max, min; printf("Enter 10 integers:\n"); for (i = 0; i < SIZE; i++) { printf("%d:", i + 1); scanf("%d", &x[i]); } max = min = x[0]; for (i = 1; i < SIZE; i++) { if (max < x[i]) max = x[i]; if (min > x[i]) min = x[i]; } printf("Maximum value is %d\n", max); printf("Minimum value is %d\n", min); }例:求 Fibonacci 数列前20个数
数列:1,1,2,3,5,8,… 递推式 f[i]=f[i-2]+f[i-1]。
#include <stdio.h> main() { int i; 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("%6d", f[i]); } }顺序查找 Linear search:数组 a 的元素为 3, 12, -5, 6, 142, 21, -17, 45,从下标0开始逐个与待查值比较。
查找 21:从 a[0] 起依次比较,遇到 a[5]=21 时匹配成功,输出 Found it。
顺序查找(查找失败):查找 20 时,从 a[0] 一直比较到 a[N-1],都不相等,指针越出数组末尾,输出 Not found。
顺序查找的平均比较次数为 (N+1)/2,时间复杂度 O(n)。
顺序查找程序
#include <stdio.h> #define N 8 main() { int a[N] = {3, 12, -5, 6, 142, 21, -17, 45}; int i = 0, x = 21; while (a[i] != x && i < N) i++; if (i < N) printf("Found it!"); else printf("Not found!"); }循环条件中 i<N 防止数组越界。思考:能否做得更好?——有序表可用折半查找。
折半查找 Binary search
折半查找:找 37
下标: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 元素: 5 13 19 21 37 56 64 75 80 88 92 100 111 120 125 low high mid初始 low=0,high=14,mid=7(元素75);37<75 故 high=mid-1;再取 mid=3(元素21),37>21 故 low=mid+1;再取 mid=5(元素56),继续缩小区间后命中 37,输出 Found it。
折半查找:找 90
下标: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 元素: 5 13 19 21 37 56 64 75 80 88 92 100 111 120 125 low high mid反复折半后区间缩小到 low>high,仍未出现 90,输出 Not found!。折半查找时间复杂度为 O(log₂n)。
折半查找程序
#include <stdio.h> #define N 10 int r[N], low, high, mid, k; printf("Input 10 sorted numbers:\n"); for (k = 0; k < N; k++) scanf("%d", &r[k]); printf("Input number k:\n"); scanf("%d", &k); low = 0; high = N - 1; while (low <= high) { mid = (low + high) / 2; if (k > r[mid]) low = mid + 1; else if (k < r[mid]) high = mid - 1; else { printf("%d\n", mid); break; } } if (low > high) printf("Search Failure.\n");冒泡排序 Bubble Sort
排序过程:
冒泡排序过程演示:7个元素经过第一趟、第二趟……第六趟起泡排序,每趟结束后当前未排定部分的最大元素沉到本趟末尾,小的元素象气泡一样上浮,最多 N-1 趟。
冒泡排序程序(输入N个整数存于 a[0]~a[N-1],排序后输出)
#include <stdio.h> #define N 7 main() { int a[N], i, k, t; printf("Input %d numbers:\n", N); for (i = 0; i < N; i++) scanf("%d", &a[i]); for (k = 1; k <= N - 1; k++) for (i = 0; i <= N - k - 1; i++) if (a[i] > a[i+1]) { t = a[i]; a[i] = a[i+1]; a[i+1] = t; } for (i = 0; i < N; i++) printf("%d ", a[i]); }冒泡排序的结束条件改进:若在某一趟排序过程中没有进行「交换记录」操作,则整个排序结束。
流程图中在每趟开始前把标志置为「无交换」,一旦发生交换则修改标志,趟循环条件变为「k<=N-1 且 发生过交换」。
#include <stdio.h> #define N 7 main() { int a[N], i, k, t; int flag = 1; printf("Input %d numbers:\n", N); for (i = 0; i < N; i++) scanf("%d", &a[i]); for (k = 1; k <= N - 1 && flag == 1; k++) { flag = 0; for (i = 0; i <= N - k - 1; i++) if (a[i] > a[i+1]) { t = a[i]; a[i] = a[i+1]; a[i+1] = t; flag = 1; } } for (i = 0; i < N; i++) printf("%d ", a[i]); }选择排序 Selection Sort
排序过程:
简单选择排序过程示例:初始关键字序列 34 49 28 31 52 51 12,每趟在未排序部分用 k 记录最小元素下标,趟末与 i 位置交换。
初始: 34 49 28 31 52 51 12 第一趟: 12 49 28 31 52 51 34 第二趟: 12 28 49 31 52 51 34 第三趟: 12 28 31 49 52 51 34 第四趟: 12 28 31 34 52 51 49 第五趟: 12 28 31 34 49 51 52 第六趟: 12 28 31 34 49 51 52共 n-1 趟完成排序。
选择排序程序
#include <stdio.h> #define N 7 main() { int a[N], i, j, k, t; printf("Input numbers:\n"); for (i = 0; i < N; i++) scanf("%d", &a[i]); for (i = 0; i < N - 1; i++) { k = i; for (j = i + 1; j < N; j++) if (a[j] < a[k]) k = j; if (i != k) { t = a[i]; a[i] = a[k]; a[k] = t; } } printf("The sorted numbers:\n"); for (i = 0; i < N; i++) printf("%d ", a[i]); }二维数组定义:数据类型 数组名[常量表达式][常量表达式];
int a[3][4]; float b[2][5]; int c[2][3][4];int a[3,4];例:int a[3][2] 的存储顺序为 a[0][0]、a[0][1]、a[1][0]、a[1][1]、a[2][0]、a[2][1]。
二维数组理解:int a[3][4]; 中 a[0]、a[1]、a[2] 分别是3个长度为4的一维数组;int c[2][3][4] 由 2×3 个长度为4的一维数组组成。
a 是由3个一维数组组成的数组,下标从0起,引用形式为 数组名[行下标][列下标]。
二维数组元素的初始化
int a[2][3]={{1,2,3},{4,5,6}}; 可部分初始化 int a[2][3]={{1,2},{4}}; 得 1 2 0 / 4 0 0int a[2][3]={1,2,3,4,5,6};;部分初始化 int a[2][3]={1,2,4}; 得 1 2 4 / 0 0 0int a[][3]={1,2,3,4,5}、int a[][3]={{1},{4,5}}int c[2][3][4]={{{1,2,3,4},{2,3,4,5},{3,4,5,6}},{{4,5,6,7},{5,6,7,8},{6,7,8,9}}};易错对比:
int a[2][3]={{5,6},{7,8}}; int a[2][3]={5,6,7,8}; 非法写法:int a[][10]; 未初始化且缺省第一维;double f[2][]={1.2,2.2}; 第二维不可缺省。数组初始化时只有第一维长度可缺省。
例:求二维数组中最大元素值及其行列号
#include <stdio.h> main() { int a[3][4]={{1,2,3,4},{9,8,7,6},{-10,10,-5,2}}; int i, j, row=0, colum=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; colum = j; } printf("max=%d,row=%d,colum=%d\n", max, row, colum); }输出:max=10,row=2,colum=1
例:统计三个学生四门课程的总分和平均分
| 姓名 | 英语 | 高数 | 物理 | 体育 | 总分 | 平均分 |
|---|---|---|---|---|---|---|
| 学生1 | 80 | 75 | 92 | 65 | 312 | 78 |
| 学生2 | 78 | 82 | 59 | 93 | 312 | 78 |
| 学生3 | 84 | 67 | 89 | 79 | 319 | 79 |
| 单科总成绩 | 242 | 224 | 240 | 237 | — | — |
| 单科总平均分 | 80 | 74 | 80 | 79 | — | — |
定义 #define S 3、#define C 4,用 int a[S+2][C+2] 存放个人总分、单科总分与平均分。
字符数组:定义 char c[10], ch[3][4];;初始化可分逐个字符赋值与用字符串常量两种方式。
char ch[6]={"Hello"}; 等价 char ch[6]="Hello"; 等价 char ch[]="Hello";(自动加 '\0')char ch[5]={'B','o','y'}; 得 B o y \0 \0char ch[5]={'H','e','l','l','o'}; 存满5个字符,没有 '\0' 结束符,作为字符串使用会有问题char str[]="Hello"; 与 char str[]={'H','e','l','l','o'}; 占用字节数不同,前者6字节二维字符数组初始化
char color[][5]={{'R','e','d'},{'B','l','u','e'}, {'G','r','e','e','n'},{'C','y','a','n'}, {'B','l','a','c','k'}};用字符串常量更简洁:
char fruit[][7]={"Apple","Orange","Grape","Pear","Peach"};每行按下标 fruit[0]~fruit[4] 存放,不足部分补 '\0'。
字符串:
例:字符串 "hello" 在内存中为 h e l l o \0,对应 ASCII 码 104 101 108 108 111 0,共占6字节。
字符串输入输出
%c,用循环逐个 scanf 与 printf%s,scanf("%s", str); 要求用字符数组名作地址,不加 &;输入串长度必须小于数组维数;遇空格或回车结束,自动加 '\0'&str[0] 与 str 等价char str[15]; scanf("%s", str); printf("%s", str);用 "%s" 输出时,遇 '\0' 结束
char a[5]={'H','e','l','l','o'}; printf("%s\n", a); char a[]="Hello"; printf("%s\n", a); #include <stdio.h> main() { char a[]={'h','e','l','\0','l','o','\0'}; printf("%s\n", a); }输出:hel。数组中有多个 '\0' 时,遇第一个 '\0' 即结束,后面的 l o 不再输出。
#include <stdio.h> main() { char c, a[8]; scanf("%s", a); c = 'X'; printf("%s\n%c\n", a, c); }输入 "hello" 时结果正常;输入 "helloboy" 时串长超过8,'\0' 写越界覆盖了变量 c,输出出错。故输入字符串长度必须小于字符数组维数。
#include <stdio.h> main() { char a[15], b[5], c[5]; scanf("%s", a); printf("a=%s\n", a); scanf("%s%s%s", a, b, c); printf("a=%s\nb=%s\nc=%s\n", a, b, c); }输入 How are you? 时,scanf 的 %s 遇空格结束,三次读取分别得到 How、are、you?。为避免上一次输入在缓冲区留下的垃圾字符,可在下次读入前调用 fflush(stdin); 清空缓冲区。
例:要输入字符串 "This is a string.",哪个不能实现?
scanf("%17s", s); — 不能:%s 遇空格即结束,只能得到 Thisfor(k=0;k<17;k++) s[k]=getchar(); s[k]='\0'; — 可以:逐字符读入含空格的17个字符while((c=getchar())!=' ') s[k++]=c; — 可以:读到换行前的所有字符,含空格字符数组的特殊性
int a[]={1,2,3,4,5}; 与 char str[]="Hello"; 都可在定义时整体赋初值%d 处理;字符数组既可逐个 %c,也可用 %s 整体输入输出字符串输入输出函数(头文件 string.h)
puts(字符数组名) 或 puts(字符串常量);向显示器输出字符串,输出完自动换行;字符数组必须以 '\0' 结束gets(字符数组名);从键盘输入以回车结束的字符串放入数组,并自动加 '\0';输入串长度应小于数组维数char string[80]; printf("Input a string:"); gets(string); puts(string);字符串连接函数 strcat
strcat(字符数组1, 字符数组2)字符串拷贝函数 strcpy
strcpy(字符数组1, 字符串2)char str1[20], str2[20]; str1 = {"Hello!"}; str2 = str1; 字符串比较函数 strcmp
strcmp(字符串1, 字符串2)例:strcmp("hellogirls", "helloboys") 比较到 'g' 与 'b' 处,返回 'g'-'b' 即正5。
字符串长度函数 strlen:格式 strlen(字符数组),计算字符串实际长度,不包括 '\0' 在内。
| 序号 | 字符串定义 | strlen 值 |
|---|---|---|
| 1 | char s[10]={'A','\0','B','C','\0','D'} | 1 |
| 2 | char s[]=" \v\\0will " | 3 |
| 3 | char s[]="\x69\082 " | 1 |
| 4 | char s[]="ab \012/\\"" | 10 |
说明:第2、3例中的 \0 与 \0 后紧跟数字构成的转义序列在 '\0' 处即结束串,故长度分别为3与1。
例:字符串反向——在字符串中将首尾字符进行对调
#include <stdio.h> #include <string.h> main() { char str[80], c; int i, k; gets(str); i = strlen(str); i--; for (k = 0; k < i; k++, i--) { c = str[i]; str[i] = str[k]; str[k] = c; } puts(str); }例:将两个字符串连接后输出长度
#include <stdio.h> #include <string.h> main() { char str1[10], str2[10], str[20]; int len; gets(str1); gets(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); } len = strlen(str); puts(str); printf("Len=%d\n", len); }连接结果示意:str1 为 "hellogirl",str2 为 "helloboys",经 strcpy(str, str1); strcat(str, str2); 后 str 中存放 "hellogirlhelloboys",末尾补一个 '\0',中间原 str1 的结束标志被取消。
例:查找 N 个字符串中最大的一个
#include <stdio.h> #include <string.h> #define N 3 main() { char maxstr[20], str[N][20]; int i; for (i = 0; i < N; i++) gets(str[i]); strcpy(maxstr, str[0]); for (i = 1; i < N; i++) if (strcmp(maxstr, str[i]) < 0) strcpy(maxstr, str[i]); printf("The largest string is: %s\n", maxstr); }本章小结
下载地址:{{downurl}}
{{{a}}}
{{#b}}{{{b}}}
{{/b}} {{/title}} {{#nolog}}登陆注册
{{/nolog}} {{#djsx}}点我刷新
{{/djsx}} {{#gocz}} {{/gocz}} {{#ffqr}} {{/ffqr}}