C数组

1 引言
● 数组是由相同数据类型的相关联的数据组成的一种数据结构
● 数组是"静态的"实体,即它所占存储空间的大小在程序运行的过程中保持不变
2 数组
● 数组是一组连续的存储单元,它们以相同的名字和相同的数据类型关联在一起
● 若要访问数组中某个特定的存储单元或数组元素,需要指定数组的名字以及该元素在数组中的位置号(即下标)
● 任何一个数组的第一个元素都是第0号元素,即位置号为0的元素。因此,数组c的第一个元素就是c[0],第二个元素就是c[1],第七个元素就是c[6]。总之数组c的第i个元素就是c[i-1]
● 像其他变量名一样,数组名只能包含字母,数字,下划线,并且不能以数字开头
● 被方括号括起来的位置号应该更规范的称为索引或下标。下标必须是一个整数或者是一个整数类型的表达式
● 用于将数组下标括起来的方括号,在C语言中也被视为一种运算符。它们与函数调用运算符具有相同的优先级
3 数组定义
● 数组是要占用存储空间的,在定义数组时,必须指定数组元素的数据类型以及数组中元素的个数,这样计算机系统才能为数组预留出相应数量的存储空间
● 一个char型数组可以用来存储一个字符串
4 数组实例
● 类型 size_t表示无符号整数类型。该类型被推荐用于定义数组长度或下标的变量。size_t由头文件<stddef.h>定义,而该头文件又常常包含在其他头文件中(例如<stdio.h>)
● 可以在定义数组的同时,对数组元素进行初始化,即在定义语句的后面加上一个等号和一对花括号,花括号内填写用逗号分隔的初始值列表。如果初始值列表中的初始值个数少于数组拥有的元素个数,则余下的数组元素将被初始化为0
● 语句“int n[10]={0};”显式的将数组的第一个元素初始化为0,由于初始值列表中提供的初始值个数少于数组拥有的元素个数,因此,余下的9个元素也会被系统初始化为0。切记:自动数组不能自动地初始化为0。之前要将第一个数组元素初始化为0,这样余下的元素才会被自动地初始化为0。这种将元素初始化为0的方法,对于静态属于是在编译时执行的,而对于自动数组是在程序运行是执行的
● 在使用初始化列表来实现元素初始化的数组定义语句中,如果没有填写数组元素的个数,则系统将初始值列表中提供的初始值的个数作为数组所拥有的元素总数
● #define 预处理命令 可以用来定义一个符号常量——一个标识符,这个标识符在源程序中被编译之前那个将被C语言预处理程序用替换文本来替换掉。在源程序被处理时,程序中出现的所有符号常量都被替换文本替换掉。采用符号常量来定义数组的大小将使程序更加易于修改
● C语言没有数组边界检查功能来防止程序访问一个不存在的数组元素。这样,一个执行中的程序就会在没有警告的情况下“跨过”数组的底线。确保对所有数组元素的访问是在数组的边界以内是程序员的责任
5 用字符数组来存储和处理字符串
● 形如hello这样的字符串在C语言中就是一个由多个单字符组成的数组
● 一个字符数组可以用一个字符串文本来初始化。在这种情况下,数组的大小是由编译器根据字符串的长度来确定的
● 每一个字符串都包含一个被称为空字符的特殊的字符串结束符。表示空字符的字符常量是 ‘\0’
● 一个用来表示字符串的字符数组必须定义的足够大,以便能够容纳字符串中的全部字符和字符串结束符
● 字符数组还可以用单个字符常量组成的初始值列表来进行初始化
● 由于一个字符串就是一个字符数组,所以可以用数组下标的方式直接访问到字符串中的单个字符
● 可以使用 scanf 函数以及转换说明符%s,从键盘上直接将一个字符串输入到字符数组中。字符数组名直接传递给 scanf 函数,而无需在它的前面加上非字符串型变量所必须加上的 &
● scanf 函数不断的从键盘上读入字符,直到遇到第一个空格字符字符为止——即它不检查数组的大小。因此,scanf函数可能将字符写到字符数组边界以外
● 可以通过printf函数以及转换说明符%s来输出代表一个字符串的字符数组。字符串中的字符将不断的被打印出来直到遇到一个代表字符串结束的空操作符时为止
6 静态局部数组和自动局部数组
● 一个静态的局部变量在程序的整个运行时间都存在,但是只能在函数体内是可见的。我们可以将存储类型说明符static应用在局部数组的定义中,这样,在函数每次被调用时该数组就不需要重新创建并初始化,而且在函数每次调用结束时,也不会被释放。这样就缩短了程序的运行时间特别是对于那些频繁地调用包含有大型数组的函数的程序
● 静态数组会在程序启动时被一次性地自动初始化。如果没有显式地初始化一个静态数组,那么它的元素值将被编译器初始化为0
7 将数组传递给函数
● 若要将一个数组作为实参传递给一个函数,那么只要指定不带方括号的数组名即可
● 与包含字符串的字符数组不同,其他类型的数组没有一个特殊的结束符。因此,调用函数时,数组的大小也必须传递给被调函数,这样,被调函数才能处理正确数目的数组元素
● C语言自动地以(模拟)按引用方式将数组传递给被调函数——即被调函数能够修改主调函数中的原数组中的元素值。数组名代表数组第一个元素的地址,所以用数组名作为函数实参就可以将数组的起始地址传给被调函数,这样被调函数就能准确的知道数组存储在哪里。因此,当被调函数在其函数体内修改数组元素时,它实际上修改的是存储在原存储单元中的数组元素
● 尽管整个数组以传地址的方式传递给被调函数。但是单个数组元素也可以传值的方式传递给被调函数,就像简单变量那样
● 这种简单的单个数据(如单个的整型,浮点型或字符型数据)称为标量
● 若要将数组元素传递给函数,只需将带下标的数组元素名当成一个实参写在调用函数的语句中即可
● 对于通过函数调用接收一个数组的函数,在定义函数的形参列表时,必须指明将要接收的是一个数组。数组的大小并不需要出现在数组名后面的方括号里。如果方括号内出现了数字,编译器只检查它是否大于0,然后将其忽略掉
● 若在表示数组的形参前面加上了类型限定符const,则相应数组的元素值将在函数体内保持不变,函数体内任何试图修改数组元素的操作都将导致一个编译时错误
8 数组排序
● 对数据进行排序(即将数据按照诸如升序或降序的顺序排列)是计算机最重要的应用之一
● 有一种排序算法被称为冒泡排序或沉降排序。因为算法中,值相对较小的数据会像水中的气泡一样逐渐上升到数组的最顶端,而较大的数据逐渐的下沉到数据的底部。这个处理过程需要在整个数组范围内反复执行多遍。每一遍执行时,相邻的两个元素都要做比较。若一对数据处于升序(或这两个值相等),我们就不去动它们。若一对数据处于降序就调换它们在数组中的位置
● 由于这样的两个元素的比较是连续进行的所以在一遍处理中一个较大的数据可能会向数组的底部移动多个位置,而一个较小的数据只可能向数据的顶部移动一个位置
● 冒泡排序最大的优点是它易于编程实现。但是冒泡排序运行速度比较慢。在对一个数组进行排序时,这一点表现得尤为明显
9 案例分析:用数组来计算平均值,中指和众数
● 平均值就是一组数据的算术平均
● 中值就是一组有序数据的 中间的值
● 众数就是一组数据中出现次数最多的那个数
10 数组查找
● 在数组中搜索一个特定元素的过程,称为查找
● 线性查找就是用查找键逐个与数组元素相比较以实现查找。由于数组元素事先并没有按照一个特定的顺序排列,所以有可能第一个元素的元素值就与查找键相等,也有可能在最后一个元素位置找到它。从平均情况来看,查找键需要与一半的数组元素进行比较
● 对于规模较小的数组或者无序排列的数组,适合采用线性查找方法。但是对于有序排列的数组就可以采用快速的折半查找方法
● 每次比较之后,折半查找将目标数组中一半的元素排除在比较范围之外。算法首先选取位于属于中间的元素,将其与查找键进行比较。若他们相等,则查找键被找到,返回数组中间元素的下标。否则将查找的范围缩小为在一半的数组元素中查找。在数组元素按升序排序的情况下,若查找键小于数组的中间元素,则在前一半数组元素中继续查找,否则在后一半数组元素中继续查找。若在该子数组中仍未查找到查找键则算法将在原数组的四分之一大小的子数组中继续查找。不断重复这样的查找过程,直到查找键等于某个子数组中间的元素的值(找到查找键)。或者子数组只包含一个不等于查找键的元素(即没有找到查找键)为止
● 使用折半查找时,最多需要的比较次数是第一个大于数组元素个数的2的幂次数
11 多下标数组
● 多下标数组主要用来表示由按行、列组织起来的信息构成的表格。为了确定表格中的第一个元素,我们必须指定两个下标:第一个下标(按惯例)确定的是元素所在的行号第二个下标(按惯例)确定的是元素所在的列号
● 需要两个下标才能确定一个元素位置的表格或数组,称为双下标数组
● 多下标数组具有多于两个的下标
● 与单下标数组类似,多下标数组可以在定义时被初始化。初始化按行用花括号括成若干组。若没有为指定的行提供足够多的初始值,则剩余的元素将被初始化为0
● 针对多下标数组的形参声明中,第一个下标值可以不填,但后继的所有下标值则必须填写。编译器将通过这些下标来确定多下标数组的元素在存储器的位置,无论有多少个下标,所有的数组元素在存储器中都是按行的顺序连续存储的。对于一个双下标数组,它的第二行在存储器中的位置总是紧跟在第一行之后的
● 编译器根据函数的形参列表中提供的下标值,来告诉函数如何在一个数组中定位一个数组元素,编译器就必须知道一行中有多少元素,这样它才能跳过适当数量的存储单元来准确地找到要访问的数组元素
12 可变长数组
● 可变长数组的数组长度是以表达是的形式表示的,而表达式的值要在运行时才能确定
● 当处理对象是一个可变长数组时,运算符sizeof是在运行时执行
● 当处理固定长度的数组时,我们反而没有出现“处理到数组边界之外”的措施
● 将可变长数组作为参数传递函数的语法规则与传递一个常规数组的语法规则相同

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枳洛淮南✘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值