目录
2.在数组定义的过程中,[]为类型说明符,而不是下标运算符。
一、定义
一维数组的定义方式为:
类型说明符 数组名[无符号整型表达式]
1.数组的类型可以是任何数据类型,但是不能为void型。
2.数组名的命名规则和标识符相同,遵循标识符命名的规则:
a.由字母、数字和下划线组成;
b.开头不能为数字;
c.字母区分大小写;
3.在定义数组是需要指明数组中元素的个数,方括号内的无符号整型表达式就是指的数组长度,当然,若方括号内为变量,则无法定义长度,代码示例如下:
结果如下:
二、特点
数组有三个特性:
1.单一性:每个元素都是同一类型;
2.有序性:前一元素的地址比后一元素小;
3.连续性:数组的每个元素地址都是连续的,未被打断。
三、引用
一维数组必须先进行定义,才能被引用。
在引用数组的过程中,C语言规定只能逐个引用数组当中的元素,不能整体引用。
原因是:
1.左右类型不匹配:
int a[10];
a = 10;
可以看到,在进行赋值操作时,左操作数为整型数组变量,而右操作数整型常量,所以无法进行赋值(去掉变量名,剩下类型名:上述代码去掉a 则为int [10],这里的含义是10个整型变量的一维数组);
2.数组a相当于一个集合,所以系统无法知晓值赋给哪一个;
3.数组的数组名为数组首元素的地址,代码示例如下:
int a[] = {1,2,3,4,5};
printf("%p\n",&a[0]);
printf("%p\n",a);
所得结果:
四、注意事项
1.数组的越界访问
根据数组的三大特性,数组中每个元素的地址都是连续的,所以我们可以知道,在数组这一连续的地址的首尾端外的空间为其他地址空间,如果我们进行越界访问,就可能会篡改其他地址空间内的值,会造成重大的程序错误,代码示例如下:
int a[5];
a[5] = 5;
printf("%d ", a[5]);
所得结果:
2.在数组定义的过程中,[]为类型说明符,而不是下标运算符。
五、应用举例
数组作为C语言中很重要的一个学习部分,其应用也是很广,例如排序,查找等等功能都可以依靠数组实现,实例如下:
1.计算数组长度
代码示例如下:
int a[5];
int len = sizeof(a) / sizeof(a[0]);
printf("%d\n", len);
所得结果如下:
2.计算最大值
代码示例如下
int a[] = {1,2,3,4,5}; //系统会根据数组元素的个数赋予数组的长度
int max = a[0] ;
int len = sizeof(a) / sizeof(a[0]);
int i ;
for(i = 0; i < len ; ++i)
{
if(a[i] > max)
{
max = a[i];
}
}
printf("%d ",max);
return 0 ;
}
所得结果如下:
3.斐波那契数列
代码示例如下:
int a[10] = {1,1};//系统会在其他已经开辟未被初始化的地址空间内填入0值
int len = sizeof(a) / sizeof(a[0]);
int i ;
for(i = 2 ;i < len ; ++i)
{
a[i] = a[i-1] + a[i-2];
}
for(i = 0 ;i < len; ++i)
{
printf("%d ", a[i]);
}
所得结果如下:
满足斐波那契数列后一值等于前两值之和。
4.逆序
代码示例下:
int a[5] = {1,2,3,4,5};
int len = sizeof(a) / sizeof(a[0]);
int i ;
for(i = 0 ; i < len / 2;++i)
{
int t = a[i];
a[i] = a[len - i - 1];
a[len - i - 1] = t;
}
for(i = 0 ;i < len ; ++i)
{
printf("%d ",a[i]);
}
return 0;
所得结果:
在进行逆序排序的时候应注意其运行的流程,首尾两个元素进行调换,调换完成之后,应注意是数组下标进行递增,那么递增的界限如何定义呢,可以对其调换的过程分析,当数组的下标递增到数组的中间时停止递增,所以在代码中对循环定义的界限为数组长度的一半。
5.选择排序
选择排序的原理是:遍历数组,在每一次遍历数组的同时,将本次所遍历的元素与后面未遍历的元素相比较,将小的值与大的值进行交换。(为非相邻元素比较)
代码示例如下:
int a[5] = {5,1,3,4,2};
int len = sizeof(a) / sizeof(a[0]);
int i;
int j;
for(i = 1 ; i < len - 1; ++i) //界限是len - 1 是因为交换到倒数第二个值,
{
for(j = i + 1; j < len ; ++j)
{
if(a[i] > a[j])
{
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}
}
for(i = 0 ; i < len; ++i)
{
printf("%d ", a[i]);
}
代码结果如下:
6.冒泡排序
冒泡排序原理:数组中相邻元素两两比较,小的值放前面,大的值放后面
代码示例如下:
int a[5] = {5,4,3,2,1};
int len = sizeof(a) / sizeof(a[0]);
int i ;
for(i = len - 1; i > 0 ; --i) // 此行代码为比较的轮数 因为有五个元素,两两比较需要比较四次
{
int j;
for(j = 0 ; j < i;++j)
{
if(a[j] > a[j + 1])
{
int t = a[j];
a[j] = a[j + 1];
a[j + 1] = t;
}
}
}
for(i = 0; i < len ;++i)
{
printf("%d ",a[i]);
}
return 0;
所得结果如下:
7.插入排序
插入排序的原理:开辟一个新的数组b[],其大小、类型与要排序的数组a相同,将数组a中的第一个元素取出放在b数组中,再将a数组的第二个值与b数组的第一个值进行比较,若比b的第一个值大,就将较大值放后面,较小值在前面(此操作在b数组中进行),之后a的第三个值取出,与b中所保存的两个值相互比较,较大值放后面,较小值放前面,对以上操作循环直至结束,最后将b数组中的值一一对应重新赋给a数组。
代码示例如下:
int a[5] = {5,1,3,2,4};
int b[5];
b[0] = a[0];
int len = sizeof(a) / sizeof(a[0]);
int i;
for(i = 1; i < len;++i)
{
int t = a[i];
int j;
while(j > 0 && a[j - 1 ] > t)
{
a[j] = a[j - 1];
--j;
}
}
for(i = 0; i < len ; ++i)
{
a[i] = b[i];
}
for(i = 0; i < len ; ++i)
{
printf("%d",a[i]);
}
return 0;
结果如下:
8.二分查找法
所谓二分查找法,是将所要查找的值与排在数组中间值进行比较,当然这种比较方式是要在一个顺序数组中进行的,判断所要查找值与中间值的大小,若比中间值大则在右边,则对数组进行截断,取中间值以右的数组,对上述流程进行循环,若数组最后首与尾的下标的差值等于零,则证明找到,跳出循环,若没有找到继续循环(在此过程中会出现一种情况,程序循环玩依旧会跳出,无法判断是否找到了所要查找值,需要在循环外进行判定)。
int a[10] = {0,1,2,3,4,5,6,7,8,9};
int len = sizeof(a) / sizeof(a[0]);
int num ;
scanf("%d", &num);
int begin = 0;
int end = len - 1 ;
int mid;
while(begin <= end)
{
mid = (begin + end) / 2;
if(a[mid] > num)
{
end = mid - 1 ;
}
else if(a[mid] < num)
{
begin = mid + 1 ;
}
else
{
break;
}
}
if(begin <= end)
{
printf("found!");
}
else
{
printf("not found!");
}
return 0;
代码结果如下: