二维数组
对于int a[3][5] 通常理解数组a是一个三行五列的矩阵;
二维数组的遍历
for( i=0;i<3;i++){
for( j=0;j<5;j++){
a[i][j] = i*j;
}
}
a[i][j]是一个int,表示第i行第j列上的单元;
二维数组的初始化:
int a[][5] = {
{0,1,2,3,4},
{2,3,4,5,6},
};
列数是必须给出的,行数可以由编译器来数,可以省略
每行一个{},用逗号隔开
与一维数组一样,如果省略数组中的莫个数,表示补零
{0,1,2,3,4}表示有五个int的一个数组作为a1;
接下来通过学写井字格游戏的代码学习如何对一行做遍历,如何对一列做遍历,如何对矩阵的对角线做遍历。如下:
读入一个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 numOfX;
int numOfO;
int result = -1;//-1没人赢;1X赢;0O赢
//读入矩阵
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 = 0;
numOfX = 0;
for(j=0; j<size; j++)//内循环检查这一行每一列
{
if(board[i][j]==1)
{
numOfX ++;
}
else
{
numOfO ++;
}
}
if(numOfX==size)
{
result=0;
}
else if(numOfO==size)
{
result=1;
}
}
//检查列,与上一段代码只有外循环和内循环的顺序不一样
for( j=0; j<size && result==-1; j++)
{
numOfO = 0;
numOfX = 0;
for(i=0; i<size; i++)
{
if(board[i][j]==1)
{
numOfX ++;
}
else
{
numOfO ++;
}
}
if(numOfX==size)
{
result=0;
}
else if(numOfO==size)
{
result=1;
}
}
//检查对角线
numOfO = numOfX =0;
for(i=0;i<size;i++)
{
if(board[i][i]==1)//主对角线每个值是00,11,22
{
numOfX++;
}
else
{
numOfO++;
}
if(numOfX==size)
{
result=0;
}
else if(numOfO==size)
{
result=1;
}
}
numOfO = numOfX =0;
for(i=0;i<size;i++)
{
if(board[i][size-i-1] ==1)//副对角线是所有的行数-所在的行数-1,即02,11,21
{
numOfX++;
}
else
{
numOfO++;
}
if(numOfX==size)
{
result=0;
}
else if(numOfO==size)
{
result=1;
}
}
if(result==1)
{
printf("X");
}
else if(result==0)
{
printf("O");
}
else if(result==-1)
{
printf("no winner");
}
return 0;
}
数组的运算
问题引入:在一组给定的数据中,如何找出某个数据是否存在?
数组的集成初始化
即直接用大括号给出数组的所有元素的初始值,,不需要各处数组的大小,编译器替我数,如下:
int a[] = {1,2,3,4,5,6,7,8,9,10,11,12,13};
如上图,未输入的数字直接补零
上图说明,当需要用到遍历数组将每个数初始化为0的时候,可以直接int a[]=0;
集成初始化时的定位
用[n]在初始化数据中给出定位,没有定位的数据接在前面的位置后面,其他位置的值补零,也可以不给出数组大小,让编译器算。如下:
这种方法特别适合初始数据稀疏的数组。
数组的大小
sizeof给出整个数组所占据的内容的大小,单位是字节
sizeof(a)/sizeof(a[0])
sizeof(a[0])给出数组中单个元素的大小,于是相除就得到了数组的单元个数
#include<stdio.h>
int main()
{
int a[13]= {12,1,2,3,4,5,6,31,23,13,1,12,17};
{
int i;
printf("%lu\n",sizeof(a));
printf("%lu\n",sizeof(a[0]));
for(i=0;i<sizeof(a)/sizeof(a[0]);i++){
printf("%d\t",a[i]);
}
}
return 0;
}
像这样的代码,一旦修改数组中初始的数据,不需要修改遍历的代码
数组的赋值
数组变量本身不能被赋值
像这样:
int a[]={2,4};
int b[]=a; 是错误的
for(i=0;i<length;i++){
b[i]=a[i];
}
要把一个数组的所有元素交给另一个数组,必须采用遍历,如上。
遍历数组
通常都是使用for循环,让循环变量i从0到小于数组的长度,这样循环体内最大的i正好是数组最大的
以上五个遍历数组的作用分别是:
1.遍历数组做赋值 2.遍历数组做初始化 3.判断要找的东西是否存在
4.判断结果是否要输出 5.查看每个计数值的大小
遍历数组的常见错误:
循环结束条件是<=数组长度,或:
离开循环后,继续用i的值来做数组元素的下标
有了以上的基础,接下来就可以解决最开始提出的问题了(在一组给定的数据中,如何找出某个数据是否存在?)
/*search函数:
找出key在数组a中的位置
key 要寻找的数字
a 要寻找的数组
length 数组a的长度
如果找到,返回其在a中的位置,如果找不到则返回-1
*/
#include<stdio.h>
int search(int key,int a[],int length) //构造一个search函数来帮我们搜索
{
int ret = -1;
int i;
for(i=0;i<length;i++){
if(a[i] ==key){
ret = i;
break;
}
}
return ret; //返回ret的值
}
int main(void)
{
int a[]= {11,1,2,3,4,5,6,31,23,13,1,12,17};
int x;
int loc;
int search(int key,int a[],int length);
printf("请输入一个数字:");
scanf("%d",&x);
int m=sizeof(a)/sizeof(a[0]);
loc=search(x,a,m);
if( loc != -1 ){
printf("%d在第%d个位置上\n",x,loc);
}else {
printf("%d不存在\n",x);
}
return 0;
}
数组作为函数的参数时:
往往必须再用另一个参数来传入数组的大小(如上条代码中的length),而不能在[]中给出数组的大小
不能再利用sizeof来计算数组的元素个数