一、
数组
int number[100]; scanf("%d, &number[i]);
-
求平均数,打印出大于平均数的数
int x; double sum = 0; int cnt = 0; int number[100]; // 定义数组 scanf("%d", &x); while (x!=-1){ number[cnt] = x; // 对数组中的元素赋值 sum +=x; cnt++; scanf("%d", &x); } if (cnt >0){ int i; double average =sum/cnt; for (i=0;i<cnt;i++){ if(number[i]>average){ printf("%d", number[i]); // 使用数组中的元素 } } // 遍历数组 }
定义数组
-
<类型>变量名称[元素数量];
-
int grades[100];
-
double weight[20];
-
-
元素数量必须是整数
-
C99之前:元素数量必须是编译时刻确定的字面量
数组
-
是一种容器(放东西的东西),特点是:
-
其中所有的元素具有相同的数据类型;
-
一旦创建,不能改变大小
-
(数组中的元素在内存中是连续依次排列的)
-
int 1[10]
-
10个单元: a[0],a[1,a],...,a[9]
-
每个单元就是一个int类型的变量
-
可以出现在赋值的左边或右边:
-
a[2] = a[1] + 6;
-
-
在赋值左边的叫做左值
数组的单元
-
数组的每个单元就是数组类型的一个变量
-
使用数组时放在[]中的数字叫做下标或索引,下标从0开始计数:
-
grades[0]
-
grades[99]
-
average[5] (最大下标是数组个数减一,而不是数组的个数)
-
有效的下标范围
-
编译器和运行环境都不会检查数组的下标是否越界,无论是对数组单元做读还是写
-
一旦程序运行,越界的数组访问可能造成问题,导致程序崩溃
-
segmentation fault
-
但也可能运气好,没造成严重的后果
-
所以这是程序员的责任来保证程序只使用有效的下标值:[0,数组的大小减一]
长度微0的数组?
-
int a[0];
-
可以存在,但是无用
例子:输入数量不确定的[0,9]范围内的整数,统计每一种数字出现的次数,输入-1表示结束
const number = 10; int x; int cnt[number]; int i; for(i=0; i<number;i++){ cnt[i]=o; } scanf("%d", &x); while(x!=-1){ if(x>=0 && x<=9){ cnt[x]++; } scanf("%d", &x); } for(i=0;i<number;i++){ printf("%d:%d", i,cnt[i]); }
-
确定数组的大小
-
定义数组
-
初始化数组
-
数组参与运算
-
遍历数组输出
数组的集成初始化
int a[] = {2,3,4,5,6,7,8,9,};
-
直接用大括号给出数组的所有元素的初始值
-
不需要给出数组的大小,编译器替你数数
集成初始化时的定位
int a[10] = { [0]=2, [2]=3, 6, };
-
用[n]在初始化数据中给出定位
-
没用定位的数据接在前面位置的后面
-
其他位置的值补0
-
也可以不给数组大小,让编译器算
-
特别适合初始数据稀疏的数组 (C99 only)
数组的大小
-
sizeof给出整个数组所占据的内容的大小,单位是字节
sizeof(a)/sizeof(a[0])
-
sizeof(a[0])给出数组中单个元素的大小,于是相除就得到了数组的单元个数
-
这样的代码,一但修改数组中初始的数据,不需要修改遍历的代码
数组的赋值
int a[] = {1,2,4,7,9,453,214,123}; int b[] = a; // 错误
-
数组本身不能被赋值
-
要把一个数组的所有元素交给另一个数组,必须采用遍历
for ( i=0; i<length; i++){ b[i] = a[i]; }
遍历数组
-
通常使用for循环,让循环变量i从0到<数组的长度,这样循环体内最大的i正好是数组最大的有效下标
-
常见的错误:
-
循环结束条件是<=数组长度,或;
-
离开循环后,继续用i的值来做元素的下标!
-
-
数组作为函数参数时,往往必须再用另一个参数来传入数组的大小
-
数组作为函数参数时:
-
不能在[]中给出数组的大小
-
不能再利用sizeof;来计算数组的元素个数!
-
构造素数表
-
欲构造n以内(不含)的素数表
-
开辟prime[n],初始化其所有的元素为1,prime[x]为1表示x是素数
-
令x=2
-
如果x是素数,则对于(i=2;xi<n;n++)令prime[ix]=0
-
令x++,如果x<n,重复3,否则结束
# include <stdio.h> int main() { const int maxNumber = 25; int isPrime[maxNumber]; int i; int x; for ( i=0; i<maxNumber; i++){ isPrime[i]= 1; } for (x=2; x<maxNumber; x++){ if( isPrime[x] ){ for( i=2; i*x<maxNumber; i++){ isPrime[i*x] = 0; } } } for (x=2; x<maxNumber; x++){ if(isPrime[i]){ printf("%d/t", i); } } printf("/n"); return 0; }
二维数组
-
int a3;
-
通常理解为a是一个3行5列的矩阵
二维数组的遍历
-
读入矩阵
for ( i=0; i<3; i++){ for ( j=0; j<5; j++){ a[i][j] = i*j; } }
-
ai是一个int
-
表示第i行第j列上的一个单元
-
a[i,j]是什么? // 错误
-
二维数组的初始化
int a[][5] = { {0,1,2,3,4}, {2,3,4,5,6}, };
-
列数是必须给出的,行数可以由编译器来数
-
每一行{},逗号分隔
-
最后的逗号可以存在,有古老的传统
-
如果省略,表示补0
-
也可以永定位(*C99 ONLY)
井字棋游戏
-
读入矩阵
const int size =3; int board[size][size]; int i,j; int numOfX; int numOfO; int result = -1; // -1:没人赢;1:X赢;0:O赢 // 读入矩阵 for ( i=0; i<size; i++){ for ( j=0; j<size; j++){ scanf("%d", &board[i][j]); } }
-
检查行
// 检查行 for ( i=0; i<size && result ==-1; i++){ numOfO = numOfX =0; for ( j=0; j<size; j++){ if( board[i][j] == 1){ numOfX ++; } else { numOfO ++; } } if (numOfO == size){ result = 0; } else if ( numOfX ==size ){ result =1; } }
-
检查列
if( result == -1){ for ( j=0; j<size && result == -1; j++){ numOfO = numOfX = 0; for ( i=0; i<size; i++ ){ if(board[i][j] == 1 ){ numOfX ++; } else { numOfO ++; } } if ( numOfO == size ){ result = 0; } else if ( numOfX == size ){ result = 1; } } }
-
检查对角线
// 正对角线 numOfO = numOfX = 0; for ( i=0; i<size; i++){ if( board[i][i] == 1 ){ numOfX ++; } else { numOfO ++; } } if ( numOfO == size ){ result = 0; } else if (numOfX == size){ result = 1; }
// 反对角线 numOfO = numOfX = 0; for ( i=0; i<size; i++){ if ( board[i][size-i-1] == 1 ){ numOfX ++; } else { numOfO ++; } }