8.C语言数组
8.1.1 初识数组
-
如何写一个程序计算用户输入的数字的平均数?
- 不需要记录输入的每一个数
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> int main() { int x; double sum = 0; int cnt = 0; scanf("%d", &x); while (x != -1) { sum += x; cnt++; scanf("%d",&x); } if (cnt > 0) { printf("%f\n", sum / cnt); } return 0; }
-
如何写一个程序计算用户输入的数字的平均数,并输出所有大于平均数的数?
-
如何记录很多数?
-
int num1,num2,…循环
-
-
数组:
-
int number[100];
-
scanf(“%d”,&number[i]);
-
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> int main() { int x; double sum = 0; int cnt = 0; scanf("%d", &x); int number[100];//不同 while (x != -1) { number[cnt]=x;//不同number这个数组里面的cnt这个位置上的单元=x,随着x的不断的读入,只要x不等于-1,都会放到number这个数组中 sum += x; cnt++; scanf("%d",&x); } if (cnt > 0) { printf("%f\n", sum / cnt); int i;// for(i=0;i<cnt++;i++) { if(number[i]>sum/cnt) { printf("%d\n",number[i]) } } } return 0; }//这个程序是危险的,因为输入的数据可能超过100个 解决方法: 1.在读数过程中加上计数,加上cnt,一旦达到100,就不能读数 2.利用c99的特性:在定义时数组采用的那个大小是动态的 可以让用户先输入一个数字,改变题目:不能说输入-1表示结束,改为先让用户输入数字,这个数字用来表明下面要输入多少个数字来求平均数,得到这个cnt后 去创建number数组
-
int number[100];//
定义数组
-
number[cnt]=x;
对数组中的元素赋值
-
-
number[i]>sum/cnt
-
printf(“%d\n”,number[i]
使用数组中的元素
-
-
for(i=0;i<cnt++;i++)
{
if(number[i]>sum/cnt)
{
printf(“%d\n”,number[i])
}
if(number[i]>sum/cnt)
{
printf(“%d\n”,number[i])
}
}遍历数组
-
-
8.1.2 定义数组
<类型>变量名称[元素数量];
- int grade[100];
- double weight[20];
- 元素数量必须是整数
- C99之前:元素数量必须是编译时刻确定的字面量
- 是一种容器(放东西是东西),特点是:
- 其中所有的元素具有相同的数据类型;
- 一旦创建,不能改变大小
*
(数组中的元素在内存中是连续依次排列的)
- eg:int a[10]
- 一个int的数组
- 10个单元:a[0],a[1],…a[9]
- 每个单元就是一个int类型的变量
- 可以出现在赋值的左边或右边
- a[2]=a[1]+6;
*
在赋值左边的叫做左值
- 数组的单元:
- 数组的每个单元就是数组类型的一个变量
- 使用数组时放在[]中的数字叫做
下标或索引
,下标从0开始计数:- grade[0]
- grade[99]
- averge[5]
- ps:根据情况选择读法, 数学中叫做下标
- 最大下标的是数组的个数减1,而不是数组的个数
- 有效的下标范围
- 编译器和运行环境都不会检查数组下标是否越界,无论是对数组单元做读还是写
- 一旦程序运行,越界的数组访问可能造成问题,导致程序崩溃
- segmentation fault
- 但有可能是运气好,没造成严重的后果
- 所以这是程序员的责任来保护程序只使用有效的下标值:
[0,数组的大小-1]
- eg:
#include<stdio.h>
void f();
int main()
{
f();
return 0;
}
void f()
{
int a[10];
a[10] = 0;//范围超出
}
- 长度为0的数组?
- int a[0];
- 可以存在,但是无用
- 长度为0的数组意味它的有效的下标是不存在的,即使是0也是越界了
8.1.3 数组的例子
- 写一个程序,输入数量不确定的[0,9]范围内的整数,统计每一种数字出现的次数,输入-1表示结束
#include<stdio.h>
int main(void)
{
const int number = 10;//数组的大小
int x;
int count[10];//定义数组
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;
}
for (i = 0; i < number; i++)
{
count[i] = 0;
}//初始化数组看
可写为int count[10]={0};
- 一般来说都要有这些步骤:
- 数组的大小
- 定义数组
- 初始化数组
- 数组参与运算
- 遍历数组输出
8.2.1 数组运算
- 在一组给定的数据中,如何找出某个数据是否存在?
int search(int key, int a[], int length);
int main(void)
{
int a[] = { 2,4,6,7,1,3,5,9,11,12,23,14,32 };
/*{
int i;
for (i = 0; i < 13; i++)
{
printf("%d\t", a[i]);
}
printf("\n");
}*/
int x;
int loc;
printf("请输入一个数字:");
scanf("%d", &x);
loc = search(x, a, sizeof(a) / sizeof(a[0]));
if (loc != -1)
{
printf("%d在第%d个位置上\n", x, loc);
}
else
{
printf("%d不存在\n", x);
}
return 0;
}
int search(int key, int a[], int length)
{
int ret = -1;
int i;
for (i = 0; i < length; i++)
{
if (a[i] == key) {
ret = i;
break;
}
}return ret;
}
- 数组的集成初始化:
- int a[] = { 2,4,6,7,1,3,5,9,11,12,23,14,32 };
- 直接用大括号给出数组的所有元素的初始值
- 不需要给出数组的大小,编译器替你数数
- 集成初始化的定位:
- int a[10]={[0]=2,[2]=3,6,};
- 用[n]在初始化数据中给出定位
- 没有定位的数据接在前面的位置后面
- 其他位置的值补零
- 也可以不给出数组大小,让编译器算
- 特别适合初始数据稀疏的数组
- 只有c99使用
- 数组的大小:
-
sizeof给出整个数组所占据的内存的大小,单位是字节
-
- sizeof(a)/sizeof(a[0])
- sizeof/sizeof那个数组的第一个单元得到这个数组有多少个元素
- sizeof(a)/sizeof(a[0])
-
sizeof(a[0])给出数组中单个元素的大小,于是相除就得到了数组的单元个数
-
这样的代码,一旦修改数组中初始的数据,不需要修改遍历的代码
-
- 数组赋值:
- int a[] = { 2,4,6,7,1,3,5,9,11,12,23,14,32 };
- int b[]=a;
- 数组变量本身不能被赋值
- 要把一个数组的所有元素交给另一个数组,必须采用遍历,意味着需要写一个循环遍历那个数组,把它的每一个元素赋给另一个数组的每个元素
- for(i=0;i<length;i++)
{
b[i]=a[i];
}
- for(i=0;i<length;i++)
- 遍历数组:
- 通常使用for循环,让循环变量i从0到<数组的长度,这样循环体内最大的i正好是数组最大的有效下标
- 常见错误:
- 循环结束条件是<=数组长度
- 离开循环后,继续用i的值来做数组元素的下标
- 数组作为函数参数时:
- 往往必须再用另一个参数来传入数组的大小
- 不能在[]中给出数组的大小
- 不能再利用sizeof来计算数组的元素个数
8.2.2 数组例子:素数
- 欲构造n以内的素数表:
- 令x为2
- 将2x,3x,4* x直至ax<n的数标记为非素数
- 令x为下一个没有被标记为非素数的数,重复2;直到所有的数都已经尝试完毕
- 2.伪代码
- 开辟Prime[n],初始化其所有元素为1,Prime[x]为1表示x是素数
- 令x=2
- 如果x是素数,则对于(i=2;xi<n;i++)令Prime[ix]=0
- 令x++,如果x<n,重复3,否则结束
8.2.3 二维数组
- eg: int a[3][5];
- 理解为a是一个3行5列的矩阵
- 二维数组遍历:
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]是什么?
- i,j是一个表达式,计算结果是j,等于a[j],并不是正确的二维数组表达方式
- 二维数组初始化:
- eg: 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,或输出无人获胜