数组定义的语法:
存储类型 数据类型 数组名[数组长度] ;
说明:
存储类型:auto,register,static,extern。若省略,相当于auto
数据类型:可以是任何一种基本数据类型或构造数据类型
数组名:每个数组都有一个名字,我们称之为数组名。数组名代表数组的起始地址。数组名应当符合标识符的命名规则,即以字母、数字、下划线组成,但不能以数字开头。
数组长度:所包含的数据的个数称为数组长度(Length)。数组长度一般只能是常量和常量表达式(但在C99新增了变长数组VLA)
示例:一个拥有10个元素的int型数组a
int a[10];
注意:数组必须先定义后使用
一维数组元素的引用
C语言规定数组必须逐个元素引用,不能整体引用。
数组元素由索引或下标(Index)标识,索引或下标从0开始。
数组元素的表示方法:
数组名[下标]
int a[10]
其元素是a[0]、a[1]、a[2]、a[3]、a[4]、a[5]、a[6]、a[7]、a[8]、a[9]
注意:C语言对数组不作越界检查,使用时要注意
初始化赋值的一般形式
类型 数组名[常量表达式]={值,值…};
例如:int arry[10]={0,1,2,3,4,5,6,7,8,9};
部分元素初始化
如果只给数组一部分元素赋值,则剩下的会变成0
例如:int a[10]={1,2,3}; 相当于 int a[10]={1,2,3,0,0,0,0,0,0,0};
则a[3]及以后的值都是0
如果想使一个int型数组中元素全部为0可以这样写:
int a[10]={0};
全部元素初始化
例如:int a[5]={1,2,3,4,5};<---等价--->int a[]={1,2,3,4,5};
如果采取第二种写法,系统就会根据后面花括号内的个数来分配数组长度是5。但若数组长度与提供初值个数不同,则数组长度不可省略。
示例:定义一个数组,反序输出
变长数组
C99新增了变长数组(variable-length array, VLA),允许使用变量表示数组的长度。
例如:
int lenth = 5;
int array[lenth];
注意:变长数组不能改变大小
变长数组中的”变”不是指可以修饰已创建数组的大小,一旦创建了变长数组,它的大小则保持不变。这里的”变”指的仅仅是:在创建数组时,可以使用变量指定数组的长度。
冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
*算法描述:*
① 比较相邻的元素。如果第一个比第二个大(小),就交换它们两个;
② 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大(小)的数;
③ 针对所有的元素重复以上的步骤,除了最后一个;
重复步骤1~3,直到排序完成。
eg:从键盘输入10个各不相同的整数,存储在数组中,使用冒泡排序法将数组排序并输出
选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
*算法描述:*
n个记录的直接选择排序可经过n-1趟直接选择排序得到有序结果。具体算法描述如下:
① 初始状态:无序区为R[1..n],有序区为空;
② 第i趟排序(i=1,2,3…n-1)开始时,当前有序区和无序区分别为R[1..i-1]和R(i..n)。该趟排序从当前无序区中-选出关键字最小的记录 R[k],将它与无序区的第1个记录R交换,使R[1..i]和R[i+1..n)分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区;
③ n-1趟结束,数组有序化了。
一维数组只有一个下标。具有两个或两个以上下标的数组称为多维数组(multidimensional array)。
其说明的一般形式如下:
<存储类型> <数据类型> <数组名><常量表达式1>…[<常量表达式n>] ;
例如:double b[3] [4] [5]; //定义了一个三维双精度实型数组b
二维数组的定义
二维数组的声明方式:
数据类型 数组名常量表达式;
示例:
int a[2] [3];//定义一个2*3的二维int型数组
float f[3] [4];//定义一个3*4的二维float型数组
二维数组的存储方式
二维数组常常被称为矩阵(matrix)。把矩阵想成行(row)和列(column)的排列方式,更有助于形象化地理解二维数组地逻辑结构。
深入理解多维数组
(二维数组)
在C语言中我们可以将二维数组视为一种特殊的一维数组,它的元素又是一个一维数组。例如,上图的二维数组 int a3。可以理解成由三个元素a[0],a[1],a[2]组成的数组,每个元素a[i]是包含四个元素的一维数组:
因此在C语言中的多维数组其实就是元素为数组的数组。n 维数组的元素是 n-1 维数组。例如,二维数组的每个元素都是一维数组,一维数组的元素当然就不是数组了。
示例:char screen[10] [40] [80]; // 一个三维数组
数组 screen 包含 10 个元素,从 screen[0] 到 screen[9]。每个元素又是一个二维数组,它有 40 个元素,这 40 个元素均是一维数组,然后每个一维数组内都有 80 个字符。整体来说,screen 数组有 32000(10×40×80)个 char 类型元素。
二维数组元素的引用及初始化
2.5.1二维数组元素的引用
数组名[行下标] [列下标]
例如:ary[1] [3] = 12;
2.5.2分行初始化
分行给二维数组赋值。例如:
int a[3] [4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
每行的元素使用花括号分隔开,中间用逗号分隔开,如果有未写的则默认为0。
2.5.3线性初始化
把所有的元素都写在一个花括号内,这样会按照数组在内存中的存储顺序给二维数组赋值。例如:
int a[3] [4]={1,2,3,4,5,6,7,8,9,10,11,12};
类似于一维数组,如果有未写的则默认为0。
2.5.4全部元素初始化
可以提供全部元素的初值,这样常量表达式1(即第一个下标)可以缺省不写,系统会根据输入的多少来计算行数。但常量表达式2(即第二个下标)不可缺省。例如:
int a={1,2,3,4,5,6,7,8,9,10,11,12};
则系统自动计算出这个二维数组是a[3] [4]。
注意:第一维的长度可以省略,但是第二维长度不能省,
例如:
int a[3] []={1,2,3,4,5,6,7,8,9,10,11,12};
编译程序时,会有语法错误
二维数组程序实例
示例:自定义一个3*4的矩阵,输出矩阵中值最大的元素,并输出其数组下标
练习:打印杨辉三角型前10行
杨辉三角型:杨辉三角型是形如以下矩阵的三角形:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
……
字符串
字符串常量是由一对双引号括起来的,以’\0’为结束标志的一组字符序列。例如字符串“hello”在内存中按照如下方式存储:
字符数组的定义形式如下:
char c[10], ch[3] [4];
字符数组初始化
逐个元素初始化
和普通数组相同,逐个为数组元素赋值。
示例1:char ch[6]={‘H’,’e’,’l’,’l’,’o’,’\0’};
示例2:char diamond={{'.', '.',''},{'.','','.',''},{'', '.', '.', '.' ,''},{'.','', '.',''},{'.', '.',''}};
使用字符串常量为数组元素赋值
示例1:char ch[6]={“abcde”};
示例2: char fruit={“Apple”,”Orange”, ”Grape”,”Pear”,”Peach”};
字符串的输入输出
输出字符串不必使用for()循环遍历整个数组,直接使用%s格式控制符即可。
printf("%s",c);例如:
当然,我们也可以使用%s在scanf()函数中直接输入一个字符串:
scanf("%s",c);
不过,使用%s输入整个字符串需要注意以下几点:
① 因为C语言不检查数组下标越界问题,因此如果直接键入字符串给字符数组,需要将字符数组设置的足够大,这样才不会丢失数据。
② 输入字符串给字符数组,注意scanf()的第二个参数不要带&(取地址符)。因为数组名就代表了数组的地址。
示例:
① 用scanf输入地字符串里面可能有空格、制表符等空白字符,空白字符后面地字符不能被存入到数组中。这种情况可以通过下面方式处理
字符串处理函数
字符串拷贝strcpy与strncpy
函数说明
[1] strcpy把 src 所指向的字符串复制到 dest。
[2] strncpy把 src 所指向的字符串复制到 dest, 最多复制 n 个字符。
参数:
l dest : 指向用于存储复制内容的目标字符数组。
l src : 要复制的字符串(可以是字符串常量也可以是字符数组)
l n :指定要从源中复制的字符数。
返回值
返回 指向目标字符串dest的指针
注意:目标数组dest 不够大,而源字符串的长度又太长,可能会造成缓冲溢出的情况。
字符串拼接strcat与strncat
函数说明:
[1] strcat把 src 所指向的字符串追加到 dest 所指向的字符串的结尾。
[2] strncat把 src 所指向的字符串追加到 dest 所指向的字符串的结尾,直到 n 字符长度为止。
参数
l dest :指向目标数组,该数组包含了一个 C 字符串,且足够容纳追加后的字符串。
l src :指向要追加的字符串
l n : 要追加的最大字节数
返回值:
返回 指向目标字符串dest的指针
示例
字符串比较
strcmp、strncmp、strcasecmp 、strncasecmp
函数说明:
[1] strcmp把s1 所指向的字符串和 s2 所指向的字符串进行比较。
[2] strncmp把s1 所指向的字符串和 s2 所指向的字符串进行比较,最多比较前 n 个字符
[3] strcasecmp把s1 所指向的字符串和 s2 所指向的字符串进行比较(忽略大小写)。
[4] strncasecmp把s1 所指向的字符串和 s2 所指向的字符串进行比较(忽略大小写),最多比较前 n 个字节
参数:
l s1 :要进行比较的第一个字符串。
l s2 :要进行比较的第二个字符串。
l n :要比较的最大字符数。
返回值:
如果返回值 < 0,则表示 s1 小于 s2。
如果返回值 > 0,则表示 s1 大于s2。
如果返回值 = 0,则表示 s1 等于 s2。
示例:
字符串长度strlen
*函数说明:*
计算字符串 s 的长度,直到空结束字符’\0’,但不包括空结束字符’\0’。
*参数:*
l str : 要计算长度的字符串。
*返回值:*
该函数返回字符串的长度,但不包括’\0’。
*示例:*
注意:sizeof()与strlen()的区别:
sizeof()的长度是整个字符数组的总长度,其中包括'\0';而strlen()不包括'\0'。例如:
char s1[]="Hello";
则sizeof(s1)=6,而strlen(s1)=5。