360 likes | 557 Views
第 9 章 数组. 第 1 部分: 一维数组的定义 一维数组在内存中的存放 一维数组元素的引用 一维数组的应用. 第 2 部分 二维数组的定义 二维数组的数组名 二维数组表达式 二维数组的应用. 3.100 个数排序? a1,a2,a3,….a100. 讨论:如何用简单的方法表示变量集合 : a1,a2,a3,….a100 ,不能用省略号! 引入一维数组概念 。. 问题导入. 排序问题. 1. 两个数排序? a ,b. if ( a < b ) { t = a; a = b; b = t; }. if ( a < b )
E N D
第9章 数组 • 第1部分: • 一维数组的定义 • 一维数组在内存中的存放 • 一维数组元素的引用 • 一维数组的应用 • 第2部分 • 二维数组的定义 • 二维数组的数组名 • 二维数组表达式 • 二维数组的应用
3.100个数排序?a1,a2,a3,….a100 讨论:如何用简单的方法表示变量集合: a1,a2,a3,….a100,不能用省略号! 引入一维数组概念。 问题导入 排序问题 1.两个数排序?a ,b if ( a < b ) { t = a; a = b; b = t; } if ( a < b ) { t = a; a = b; b = t; } if ( a < c ) { t = a; a = c; c = t; } if ( b < c ) { t = b; b = c; c = t; } 2.三个数排序?a, b, c
数组: 有序数据的表示 数组基本概念: 1.数组: 一组具有相同数据的有序集合。 2.数组元素: 构成数组的成员称为数组单元,即数组元素 3.数组维数 数组下标的个数
§9.1.1 一维数组的定义 1、定义一维数组 类型说明 数组名[exp], 数组名[exp],…其中:exp为常量表达式 例如:int a[100]; 包含变量: a[0],a[1],a[2],….a[99] char c[8]; float x[20]; y[4*M+1];(M是符号常量) float s1[75]; • 注意: • int a[10];不能表示为: int a(10); • 数组名定名规则和简单变量名相同;数组名后是用方括弧括起来的常量表达式,决定了数组元素个数; • 3 数组元素的下标从0开始,最大下标值为数组元素个数减1;
下标可以是 • 整型常量或 • 整型表达式, 9.2.2、一维数组元素的引用 • 数组必须先定义,后引用,C规定只能引用数组 • 元素,不能一次引用整个数组 • 数组元素的表示形式为: 数组名[下标] 例: int a[8]; //先声明 a[0] = a[5] + a[7] - a[3*2]; //后引用
9.1.3、一维数组的初始化 1. 在定义数组时对数组元素赋初值 例如: int a[5] = {1, 2, 3, 4, 5}; char c[5]={‘@’,’\n’,’a’,’b’,’\0’}; 2.可以只给部分元素赋初值 例如: int b[5] = {1, 2, 3}; 3.在对全部数组元素赋初值时,可省略数组长度 例如: int c[ ] = {1, 2, 3, 4, 5}; 4.静态数组元素具有自动初始值0 例如: static int d[5];
例9.1定义30个元素的整型数组,顺序存放1,3,5…奇数,先顺序输出,再逆序输出.例9.1定义30个元素的整型数组,顺序存放1,3,5…奇数,先顺序输出,再逆序输出. #include <stdio.h> #define M 30 main ( ) { int s[M],i,k=1; for ( i = 0; i <M; i++ ) {s[i]=k; k+=2;} for ( i = 9; i<M; i++ ) { printf ("%4d", s[i]); if((i+1)%10==0)printf(“\n”); } }
a=&x; a++; P109:数组名相当于地址常量,不可重新赋值! 首地址 数组名+整数 9.2 一维数组和指针 例: float a[10],*p,x; a表示数组的首地址:&a[0] a[0]表示第一个元素 p=&a[0]; p=a; for(k=0;k<10;k++) p=a+k; for(p=a,k=0;k<10;k++){scanf(“%d”,p);p++;} for(p=a,k=0;k<10;k++) scanf(“%d”,p++); for(p=a;p-a<10;p++) scanf(“%d”,p);
9.2 首地址的引用, 指针引用一维数组 2) 数组名表示首地址, a (即a+0)等价于&a[0] 类似: a+1: &a[1] a+i : &a[i] for(k=0;k<10;k++) printf(“%4d”,*(a+k)); 等价于: for(k=0;k<10;k++) printf(“%4d”,a[k]); 3) float a[10],*p,k; p=a; for(k=0;k<10;k++)printf(“%4d”,*(p+k));
for(p=a,k=0;k<10;k++) printf(“%4d”,*p);p++); for(p=a,k=0;k<10;k++) printf(“%4d”,*p++); for(p=a,p-a<10;p++) printf(“%4d”,*p); 4) 用带下标的指针变量引用一维数组 例: int *p, s[10], i; p=s; 等价的表达式: (1)s[i] (2)*(s+i) (3) *(p+i) (4) p[i] 非法: s++; s=p; p=&s s不可变,p可变!
§9-3 函数与一维数组及元素的引用 1.数组元素作实参 2.数组名作实参 例9-2 编程,通过一个函数为主函数输入若干大于或等于0的整数,用负数作结束标志;调用另外一个函数输出数组中数据. #include <stdio.h> #define M 100 int arrin(int *); void arrout(int *,int); main ( ) { int s[M],k; k=arrin(s); arrout(s,k); } void arrout(int *a,int n) { int i; for(i=0;i<n;i++) printf(((i+1)%5==0)?”%4d”:”%4d”,*(a+i)); printf(“\n”); } int arrin(int *a) { int i,x; i=0; scanf(“%d”,&x); while(x>=0) { *(a+i)=x; i++; scanf(“%d”,&x); } return i; }
void setstar(char *,int); void arrout(char *a,int n); 例9-3 编写函数,把具有10个元素的char类型数组元素中的除前4个外的其他元素变成*. #include <stdio.h> #define M 10 #define B 4 main( ) { char c[M]={‘A’,’B’,’C’,’D’,’E’,’F’,’G’,’H’,’I’,’J’; setstar(&c[4],M-B); arrout(c,M); } void arrout(char *a,int n) { int i; for(i=0;i<n;i++) printf(“%c”,a[i]); printf(“\n”); } void setstar(char *a,int n) { int i; for(i=0;i<n;i++) *(a+i)=‘*’; }
9.4 一维数组的应用举例 p115 例9-4 编写函数,定义15个元素的数组,完成以下功能: 1)调用C库函数的随机函数给所有元素赋以0~49的随机数 2)输出数组元素值 3)按顺序对每隔3个数求一个和数,传回主函数 4)最后输出所有求出的和值 main( ) { int x[SIZE],w[SIZE/N]={0}; getrand(x,SIZE); printf(“Output %d random numbers:\n”,SIZE); priarr(x,SIZE); getave(x,w,SIZE); priarr(w,SIZE/N); } #include <stdio.h> #include “stdlib.h” #define SIZE 15 #define N 3 void getrand(int *,int); void getave(int *,int *,int); void priarr(int *,int);
void getrand(int *a,int n) { int i; for(i=0;i<n;i++) a[i]=rand()%50; } void getave(int *a,int *b,int n) { int i,j,sum; for(sum=0,i=0,j=0;i<=n;i++) {sum+=a[i]; if(i+1)%3==0) {b[j]=sum; sum=0; j++; } } } void priarr(int *a,int n) { int i; for(i=0;i<n;i++) {printf(“%5d”,a[i]); if((i+1)%5==0)printf(“\n”); }printf(“\n”); }
例 9.5 将数组中的数重新按颠倒的顺序存放 void priout(int s[ ],int n) { int i; for(i=0;i<n;i++) printf("%4d",s[i]); printf("\n"); } void invert(int *a,int n) { int i,j,t; i=0; j=n-1; while(i<j) { t=a[i]; a[i]=a[j]; a[j]=t; i++; j--; } } #include <stdio.h> #include "stdlib.h" #define NUM 8 void invert(int *,int); void priout(int *,int); main( ) { int a[NUM]={10,20,30, 40,50,60,70,80}; printf("Output primary data:"); priout(a,NUM); invert(a,NUM); printf("Output inverse data:"); priout(a,NUM); }
e9.6 已知整型数组中的值在0~9的范围,统计每个整数的个数 void outdata(int *c) { int i; for(i=0;i<N;i++) printf("%d:%4d",i,c[i]); } main( ) { int a[M],c[N]; getdata(a); stat(a,c); printf("Output the result:\n"); outdata(c); } #include <stdio.h> #include "stdlib.h" #define M 50 #define N 10 void getdata(int *s) { int i; for(i=0;i<M;i++) s[i]=rand()%10; } void stat(int *a,int *c) { int i; for(i=0;i<N;i++) c[i]=0; for(i=0;i<M;i++) c[a[i]]++; }
例 9.7 在元素不同的数组a中查找x值相同元素的位置。若找到输出该值和位置;没找到输出相应信息。 #include <stdio.h> #define M 30 int arrin(int *a) { int i, n; do{ printf("输入元素数n<%d:",NUM); scanf(%d”,&n); }while((n<1)||n>NUM)); printf(“输入%d个元素”); for(i=0;i<M;i++) scanf(“%d”,a+i); return n; } main() { int a[NUM],x,n,p; n=arrin(a); printf(“输入要查找的元素x=”); scanf(%d”,&x); p=search(a,x,n); if(p!=-1) printf(“%d的序号%d”,x,p); else printf(“%d没找到”,x); }
例 9.7 search()函数 int search(int *a,int x,int n) {int i=0,p; a[n]=x; while(x!=a[i])i++; if(i==n)p=-1; else p=i; return p; } 例 9.8 p119 自学
9-9 用选择法或冒泡法对 6 个数排序(由小到大) 冒泡法的思路是:将相邻两个数比较,将小的调到前头 ㈠ ㈡ ㈢ ㈣ ㈤ 结果 序列 4 8 5 9 8 5 4 2 0 9 8 9 9 8 5 4 2 0 5 8 8 5 4 2 0 9 4 2 0 5 8 9 2 0 4 5 8 9 2 0 2 4 5 8 9 0 2 4 5 8 9 2 9 8 5 4 5 9 4 8 4 9 2 8 2 9 0 8 0 9 共循环多少次? 每次循环进行了多少次比较?什么时候结束? 如果序列为5、8、9、4、2、0,先排在最后的还是 9 吗? 如果要求先将最大的数排在最前面,该如何操作?
输入n个数给a[1]到a[n] for j=1 to n-1 for i=1 to n-j a[i]>a[i+1] 真 假 a[i] a[i+1] 输出 a[1]到a[n]
#include <stdio.h> #define N 6 void main ( ) { int a[7]; int i , j, t ; printf ("input %d numbers:\n", N); for ( i = 1; i <N; i++) scanf ("%d", &a[i] ); for ( j = 1; j <=N-1; j++) for ( i = 1; i <= N - j; i++) if ( a[i] > a[i+1] ) { t = a[i]; a[i] = a[i+1]; a[i+1] = t; } printf ("the sorted numbers:\n"); for ( i = 1; i <= N; i++) printf ("%d ", a[i] ); printf ("\n"); } 注:数组a的第一个元素a[0]没有被使用,请修改程序以便节省内存空间
#include <stdio.h> #define N 6 void main ( ) { int a[N+1]; int i , j, t ; printf ("input %d numbers:\n", N); for ( i = 1; i <= N; i++) scanf ("%d", &a[i] ); for ( j = 1; j < N; j++) for ( i = j + 1; i <= N ; i++) if ( a[j] < a[i] ) { t = a[j]; a[j] = a[i]; a[i] = t; } printf ("the sorted numbers:\n"); for ( i = 1; i <= N; i++) printf ("%d ", a[i] ); printf ("\n"); }
§9-5 二维数组 1、定义二维数组 类型名 数组名[exp1][exp2] 其中,exp1为行数,exp2为列数 如: int a[3][4], b[4][M]; 注:不能写成int a[3, 4], b[4, M]; 或 int a (3, 4), b(4, M);
二维数组的存储 可把二维数组看作是一种特殊的一维数组:它的元素又是一个一维数组 例如,可把 a[3][4] 看作是一个一维数组,有3个组元素:a[0]、a[1]、a[2],每个组元素中又包含 4 个元素的一维数组。见下图: a[0][0] a[0][1] a[0][2] a[0][3] a[0] a[1] a[2] [4] [4] [4] a[1][0] a[1][1] a[1][2] a[1][3] a a[2][0] a[2][1] a[2][2] a[2][3] 二维数组中元素排列的顺序是按行存放 试写出b[2][3]中元素?
9.5.2、二维数组的引用 二维数组的元素的表示为:数组名[下标][下标] 如: a[2][3] a[2-1][2*2-1] b[1][2] = a[2][3] / 2 下标可以是整型表达式 注意:1.数组定义和数组元素引用的区别 例如 int a[3][4]; 第一个元素是a[0][0],最后一个元素是 2.下标的最大取值 a[2][3]
9.5.3、二维数组的初始化 1 2 3 4 5 6 1 2 0 4 0 0 0 0 9 0 6 0 结果为:x[0][0]=0,x[0][1]=0,x[0][2]=9 x[1][0]=0, x[1][1]=6, x[1][2]=0 4)省略第一维长度; 例: int e[][3] = {1, 2, 3, 4, 5, 6}; 注意:不能省略第二维的长度。为什么? 2行3列 1)按行存放 例:int a[2][3] = {{1, 2, 3}, {4, 5, 6}}; 2)按存放顺序 例:int b[2][3] = {1, 2, 3, 4, 5, 6}; 3) 只给部分元素赋初值 例: int c[2][3] = {{1, 2}, {4}}; int x[2][3] = {{0, 0, 9}, {0, 6}};
例9-10从键盘给2×3二维数组输入数据: 1,2,3, 9.5.5 二维数组定义和引用举例 10,20,30 #include <stdio.h> main() {int a[2][3],i,j; printf("Enter data by line:\n"); for ( i=0;i<2; i++) for (j=0;j<3;j++) scanf("%d",&a[i][j]); printf("output data by line:\n"); for(i=0;i<2;i++) {for(j=0;j<3;j++) {printf("%4d",a[i][j]);} printf("\n"); } }
int *p, a[3][4]; • a[0],a[1],a[2]一维数组名,行指针,是常量a[0]+ +× • 基类型: p与a[i] 同, p与a 是不同的 • p+1,相当于a[i]+1移动1个元素 • a+1,相当于移动一行 • 二维数组元素的地址 • 1)&a[i][j] • 2) a[i]+j • 3)*(a+i)+j • 4)&a[0][0]+4*i+j • 5)a[0]+4*i+j 9.6 二维数组和指针 二维数组元素的引用 1) a[i][j] 2)*(a[i]+j) 3)*(*(a+i)+j) 4)(*(a+i))[j] 5)*(&a[0][0]+4*i+j)
#define M 3 #define N 4 main() {double s[M][N],*ps[M]; f(s); } (1) f(double *a[M]) (2) f(double *a[]) (3) f(double **a) #define M 3 #define N 4 main() {double s[M][N]; f(s); } (1) f(double (*a)[N]) (2) f(double a[][]) (3) f(double a[][]) 9.7 二维数组名和指针数组作实参
/*例9-13 输出二维数组中每行的最小值 及其行、列号*/ #include <stdio.h> main ( ) {int a[5][5]={{22,11,32,42,53}, {51,41,31,21,11}, {44,54,24,34,74}, {93,59,17,64,74}, {96,45,39,65,58}}; int i,j,col; for(i=0;i<5; i++) { col=0; for ( j = 0; j < 5; j++) {if (a[i][j] <a[i][col]) col=j;} printf("row:%d,min:%d,col:%d\n",i+1,a[i][col],col+1); } getch(); }
/*例9-13b 有一个3行4列矩阵,求出其中最大值 及所在的行号和列号*/ #include <stdio.h> main ( ) { int i,j,row=0,colum=0,max; 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); }
多维数组,参考二维数组 • int a[2][3][4]; • a为整型三维数组,元素个数为2×3×4=24 • 内存中的排列顺序为: • a[0][0][0] a[0][0][1] a[0][0][2] a[0][0][3] • a[0][1][0] a[0][1][1] a[0][1][2] a[0][1][3] • a[0][2][0] a[0][2][1] a[0][2][2] a[0][2][3] • a[1][0][0] a[1][0][1] a[1][0][2] a[1][0][3] • a[1][1][0] a[1][1][1] a[1][1][2] a[1][1][3] • a[1][2][0] a[1][2][1] a[1][2][2] a[1][2][3] • 最右边的下标变化最快 初始化方法: 1、按存储顺序:int a[2][2][2] = {1, 2, 3, 4, 5}; 2、按下标顺序: int a[2][2][2] = {{{1, 2}, {3, 4}},{{5,0},{0,0}}};
补充例2:任输入一行字符,统计其中有多少个单词(以空格分隔)。补充例2:任输入一行字符,统计其中有多少个单词(以空格分隔)。 算法: ① 输入字符串; ② 找第一个非空字符; ③ 计数; ④ 跳过本单词,即寻找空格或‘\0’; ⑤ 未结束则转②; ⑥ 否则打印个数。 输入: ---We-are----students.
/* 输入一行字,统计其中有多少个单词,单词间是空格分开*/ 书例P139 算法1: 1.空格决定单词数目,空格不 是单词word=0 2.如果字符为非空格,前面 是空格,则一个单词出现 word=1,num++ 3. 如果word=1,c!=‘ ‘,说明还是 刚才单词的字符,num不累加 #include <stdio.h>void main ( ) { char c; int i = 0 ,num = 0 ,word=0; char str[81]; gets ( str ); for(i=0;(c=str[i])!='\0';i++) if ( c == ' ') word=0; else if(word==0) { word=1; num++; } printf ("共 %d 个单词\n", num); }
0 1 2 3 4 5 6 7 8 W e a r e /* 算法2:输入一行字,统计其中有多少个单词,单词间是空格分开*/ #include <stdio.h> void main ( ) { char c; int i = 0 , num = 0; char str[100]; gets ( str ); do { while ( ( c = str[i] ) == ' ') i++; if ( c != '\0' ) { num++; i++;} while ( ( c = str[i] ) != ' ' && c != '\0') i++; } while ( c != '\0' ); printf ("共 %d 个单词\n", num); } 输入: ---We-are----students.--回车 -表示 空格
补充:找出1000以内的完数 例如:6=1+2+3 if(m==0) { printf(“%d is a wanshu\n”,j); for(i=0;i<n-1;i++) printf(“%d,”,a[i]); printf(“%d\n”,a[n-1]); } } getch(); } #include<stdio.h> main( ) { int a[100]; int i,j,n,m; for(j=2;j<1000;j++) { n=0; m=j; for(i=1;i<j;i++) { if((j%i)==0) { m=m-i; a[n]=i; n++; } } }