一、一维数组
1、常量数组
- 数组(Array)所包含的每一个数据叫做数组元(Element),所包含的数据的个数称为数组长度(Length),数组中的每个元素(a[0] a[1] a[2] a[3])都有一个序号,这个序号从0开始,称为下标。
- 数组是一个整体,它的内存是连续的;也就是说,数组元素之间是相互挨着的,彼此之间没有一点点缝隙
需要注意的是:
- 数组中每个元素的数据类型必须相同,对于int a[4];,每个元素都必须为 int。
- 数组长度 length 最好是整数或者常量表达式。
- 访问数组元素时(运用的时候),下标的取值范围为
0 ≤ index < length
,过大或过小都会越界,导致数组溢出。 - 可以只给部分元素赋值。当{ }中值的个数少于元素个数时,只给前面部分元素赋值
- 当赋值的元素少于数组总体元素的时候,剩余的元素自动初始化为 0:
2、字符数组
用来存放字符的数组称为字符数组。字符数组只有在定义时才能将整个字符串一次性地赋值给它,一旦定义完了,就只能一个字符一个字符地赋值了。
注意:
- 用双引号(" “)引起来的是字符串,如"hello” “A”
- 用单引号(’ ')引起来的就是单个字符, 如: ‘A’ ‘0’
- 字符串与字符的关系。 “hello” == ‘h’ ‘e’ ‘l’ ‘l’ ‘o’ ‘\0’ ,字符串默认结尾都有’\0’
(1)字符串结束标志
- 在C语言中,
字符串总是以'\0'作为结尾,所以'\0'也被称为字符串结束标志
,或者字符串结束符。'\0’是 ASCII 码表中的第 0 个字符,英文称为 NUL,中文称为“空字符”。该字符既不能显示,也没有控制功能,输出该字符不会有任何效果,它在C语言中唯一的作用就是作为字符串结束标志。 - 当用字符数组存储字符串时,要特别注意’\0’,要为’\0’留个位置;这意味着,字符数组的长度至少要比字符串的长度大 1。
(2)字符串长度
- 在C语言中,我们使用string.h头文件中的 strlen() 函数来求字符串的长度。
- puts():输出字符串并自动换行,该函数只能输出字符串。
- gets():直接输入字符串,并且只能输入字符串。认为空格也是字符串的一部分,只有遇到回车键时才认为字符串输入结束。
- scanf():通过格式控制符%s输入字符串。除了字符串,scanf() 还能输入其他类型的数据。遇到空格就认为当前字符串结束了。
(3)数组越界
- LC语言数组是静态的,不能自动扩容,当下标小于零或大于等于数组长度时,就发生了越界(Out Of Bounds),访问到数组以外的内存。如果下标小于零,就会发生下限越界(Off Normal Lower);如果下标大于等于数组长度,就会发生上限越界(Off Normal Upper)
- 当赋予数组的元素个数超过数组长度时,就会发生溢出(Overflow)
为了防止数组越界操作:
1)整型或者浮点型数组(short int long float double):定义时是元素个数与值个数是可以相等的。
2)字符串存储,数组的空间必须大于等于字符串长度+1(‘\0’)的长度。
二、二维数组
在C语言中,二维数组是按行排列的。也就是先存放 a[0] 行,再存放 a[1] 行;
1、二维数组的初始化
二维数组的初始化可以按行分段赋值,也可按行连续赋值
int a[2][3] ={{1,2,3},{4,5,6}}; //规范赋值方法
int a[2][3] ={1,2,3, 4,5,6}; //可以不用大括号
int a[2][3] = {{1},{2}} //a[0][0] == 1 a[1][0] == 2
int a[2][3] = {{0,1},{3}} //a[0][0] == 0
int a[][3] ={1,2,3, 4,5,6}; //定义正确的 小数组三个元素为一组
2、字符串的二维数组初始化
char a[2][5] ={{"abcd"}, {"cde"}}; //合理 小数组长度为5,也就最多只能存储5字节
char a[2][5] ={"abc", "cde"}; //合理 小数组长度为5,也就最多只能存储5字节
char a[2][5] ={"abc"}; //合理
三、数组与指针的关系
1、一维数组与指针的关系
数组元素地址表示:&a[0], &a[1], &a[2], &a[3], &a[4], &a[5],但在实际开发当中,一般不这样表示数组元素地址,一般用数组名来表示各个元素的地址。ch:数组首元素的地址
ch与&ch区别
ch:数组首元素的地址
&ch:整一块数组的首地址
ch == &ch
(ch+1) != &ch+1
ch+1 :下一个元素地址
&ch+1:下一块数组地址
总结:
- 在实际开发过程中,数组名可以直接代替指针的方式,通过数组名操作数组,一维数组名就是一级指针。
- 数组名+n,实际的地址值为:数组名(数组名就是一个地址)+n*sizeof(指向数据指针类型)
- 数组名+1与&数组名+1是不同的结果。
- 在数组中可以有指针运算,如ch+2, ch-5;如果数组名做为参数传递给函数,在函数内可通过指针++,或者指针-- 移动,可以指向不同的元素
- 两个指针相减(数组中,指针相减才有意义),结果为两个指针之间的元素个数
2、二维数组与指针的关系
char ch[3][5] = {"test","hi","good"};
ch :大数组首地址
&ch :整块数组的首地址
ch+i:存储的某块大数组地址
*(ch+i):取某块大数组基地址
(*(ch+i)+j):某块大数组小数组元素的地址
*((*(ch+i)+j)):某块大数组小数组中的元素的值
四、函数
1、main函数讲解
int main(int argc, char *argv[])
gcc main.c -o main
int argc:记录终端传入的参数个数(字符串),以空格区分个数,如./main test abc, 参数为3
char *argv[]:指针数组(存放指针的数组),存放终端字符的地址。如存放./main test abc的地址
gcc:编译工具,main.c:源文件,-o:指针生成可执行文件 ,main:可执行文件
2、递归函数
一个函数在它的函数体内调用它自身称为递归调用,这种函数称为递归函数。每调用一次就进入新的一层,当最内层的函数执行完毕后,再一层一层地由里到外退出。
递归的条件:
- 存在限制条件,当符合这个条件时递归便不再继续。
- 每次递归调用之后越来越接近这个限制条件。