8.1.1
数组
int munber=[100]
scanf("%d",&number[i]);
定义数组
<类型>变量名称[元素数量];
int grades[100];
double weight[20];
元素数量必须是整数
c99之前:元素数量必须是编译时刻确定的字面量
8.1.2
数组
是一种容器(放东西的东西),特点是:
其中所有的元素具有相同的数据类型
一旦创立,不能改变大小
数组中的元素在内存中是紧密连续依次排列的
数组 int a[10]
一个int的数组
10个单元:a[0],a[1]....a[9]
a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] | a[8] | a[9] |
每个单元都是一个int类型的变量
可以出现在赋值号的左边和右边;
a[2]=a[1]+6
在赋值号左边的叫做左值
数组的单元
数组的每一个单元就是数组类型的一个变量
使用数组时放在[]中的数字叫做下标或索引,下标从0开始计数:grades[0]......
有效的下标范围
编译器和运行环境都不会检查下标是否越界,无论是对数组单元做读还是写
一旦程序运行,越界的数组访问可能造成问题,导致程序崩溃
segmentation fault可能是数组越界了
但可能运气好,没造成严重的后果
正确下标范围:[0,数组的大小-1]
int a[0];可以存在,但无用。
8.1.3
数组的例子
写一个程序,输入数量不确定的[0,9]范围内的整数,统计每一个数字出现的次数,输入-1表示结果
#include<stdio.h>
int main(void)
{
const int number=10; //数组大小c99
int x;
int count[number]; //定义数组
int i;
for(i=0;i< number;i++){
count[i]=0; //初始化数组(循环给每一个数组赋值)
}
scanf("%d",&X);
while(x!=-1){
if(x>=0 && x<=9){
count[x]++; //数组参与运算:求平均数时我们要把数纪录下来
} 记数时用读到的数做下标,让某一个计数器加一
scanf("%d",&x);
}
for(i=0;i<number;i++){
printf("%d:%d\n,i,count[i]);
} //遍历数组做输出
return 0;
}
8.2.1数组运算
在一组给定的数据中,如何找出某个数据是否存在?
数组的集成初始化
int a[ ]={2,4,6,1,3,5,9,11,13,23,14,32,};
inta[10]={[0]=2,[2]=3,6,};
·用[n]在初始化数据中定位
·没有定位的数据接在前面的位置后面
·其他位置的值补零
·也可以不给出数据大小,让编译器算
·特别合适初始数据稀疏的数组
数组大小
sizeof给出整个数组所占据的内容大小,单位是字节
sizeof(a)/sizeof(a[0])
sizeof(a[0])给出数组中单个元素的大小,于是相除就得到了数组的单元个数
这样的代码,一旦修改数组中初始的数据,不需要修改历的代码
数组的赋值
数组不可以直接赋值
数组本身不可以赋值
要把一个数组的所有元素交给另一个数组,必须采用遍历 for(i=0;i<length;i++){b[i]=a[i];}
遍历数组
遍历数组做赋值
for(i=0;i<length;i++){
b[i]=a[i];
}
遍历数组做初始化
for(i=0;i<number;i++){
count[i]=0;
}
遍历数组判断找的东西是否存在
for(i=0;i<length;i++){
if(a[i]==key){ //拿出数组单元判断和key是否相等
ret=i;
break;
}
}
遍历数组看结果要不要输出
for(i=0;i<cnt;i++){
if(number[i]>average){
printf("%d",number[i]);
}
}
遍历数组看每个计数值的大小
for(i=0,i<number;i++){
printf("%d:%d\n",i,count[i]);
}
通常都是用for循环,让循环变量i从0到<数组的长度,这样循环体内最大的i正好是数组最大的有效下标
常见错误:
1.循环条件是<=数组长度,或者是;
2.离开循环后,继续使用i的值来做数组元素的下标!
3.数组作为函数参数时,往往必需在用另一个参数来传入数组的大小
8.2.2数组的例子
素数
#include <stdio.h>
int isPrime(int x);
int main(viod)
{
int x;
scanf("%d',&x);
if (isPrime(x)){
printf("%d是素数\n",x);
}else{
printf("%d不是素数\n",x);
}
return 0;
}
构造素数表
欲构造n以内的素数表
1.令x为2
2.将2x,3x,4x,直至ax<n的数标记为非素数
3.令x为下一个没有被标记为非素数的数,重合2;直到所有的数都意境尝试完毕
4.令x++,如果x<n,重复3,否则结束
算法不一定和人的思考方式相同
8.2.3二维数组
二维数组
int a[3][5];
通常理解为a是一个3行5列的矩阵
a[0][0] | a[0][1] | a[0][2] | a[0][3] | a[0][4] |
a[1][0] | a[1][1] | a[1][2] | a[1][3] | a[1][4] |
a[2][0] | a[2][1] | a[2][2] | a[2][3] | a[2][4] |
二维数组的遍历
for(i=0;i<3;i++){
for(j=0;j<5;j++){
a[i][j]=i*j;
}
}
a[i][j]是一个int
表示第i行j列上的单元
a[i,j]是什么?
二维数组的初始化
int a[][5]={
{0,1,2,3,4},
{2,3,4,5,6},
};
列数是必须给出的,行数可以由编译器来数
每行一个{},逗号分隔
最后的逗号可以存在,有古老的传统
如果省略,表示补零
也可以用定位(*C99 ONLY)
tic-tac-toe游戏
读入一个3*3的矩阵,矩阵中的数字为1表示该位置上有一个X,为0表示为O
程序判断这个矩阵中是否有获胜的一方,输出表示获胜一方的字符X或O,或输出无人获胜
#include<stdio.h>
int main()
{
const int size=3;
int board [size][size];
int i,j;
int num0fX;
int num0fO;
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++){
num0fO=num0fX=0;
for(j=0;j<size;j++){
if(board[i][j]==1)
num0fX ++;
}else{
num0fO ++;
}
}
if(num0fO==size){
result=0;
}else if(num0fX==size){
result=1;
}
}
//检查列
if(result==-1)
for(j=0;j<size && result==-1;j++){
num0fO=num0fX=0;
for(i=0;i<size;i++){
if(board[i][j]==1)
num0fX ++;
}else{
num0fO ++;
}
}
if(num0fO==size){
result=0;
}else if(num0fX==size){
result=1;
}
}
还得检查对角线