目录 |
一、一维数组1、数组的概念多个变量,共同使用同一变量名称,并用“下标”加以区分。 eg: int score[50]; score[1]、score[35]…… [1]称为下标; 数组的每一个元素都是同类型的变量;通常将数组中的每一个变量称为“元素”;数组元素的下标是从0开始的! 数组的每一个元素都是一个独立的变量。 |
2、数组的使用方法2.1 数组的定义数组与变量一样,都必须“先定义,方可引用”;定义数组的语句必须出现在所有有效语句之前。 数组定义的语法:type arrayName[非浮点常量(表达式)]; 数组定义语句中[]里的内容,表示数组元素个数。只能用char、short、int、long类型的常量或简单常量表达式,不能使用float、double类型,也不能使用变量或由变量组成的表达式!
定义数组的语句,与数组元素引用的语句,采用不同的语法和原则,绝对不能混用! 2.2 数组元素的引用int a[10]; // 定义了一个拥有10个int元素的数组a; 数组a中有10个元素,分别是: a[0]、a[1]、a[2]、……、a[9] 拥有n个元素的数组,其下标取值范围是:[0, n),即,下标最大取值为n-1 数组下标在引用数组元素时,可以是非常灵活的使用方法:可以是常量,也可以是变量或者由变量组成的表达式!
特别注意: 若定义: int ar[5]; 那么,在数组元素引用语句中,ar[5]只代表“下标为5的第6个元素” 数组的内存映像图:
用上述方法,可以将int ar[5];在内存中的情况表示如下:
ar中的5个元素分别如图是a[0]到a[4];在存储结构(物理)角度讲,ar[0]的前面存在着4B空间(而且有很多很多);ar[4]的后面存在着4B空间(而且有很多很多);即,ar[5],ar数组的下标为5的第6个元素,在物理角度是存在的!但是在逻辑角度是不存在的! 而且,所谓“下标越界”的“错误”,在C语言编译软件中,是无法发现的!
数组下标越界这种错误是C编译软件所无法察觉的,而它又是致命错误;这意味着“下标越界”的错误,只能由C语言程序员自己避免和发现!
若定义一个拥有5个元素的数组ar,那么,在逻辑上ar[5]是不存在的;但是,在物理(内存存储空间)上,ar[5]是存在的! 在数组元素引用过程中,ar[5]不代表ar数组(的所有元素或任意一个元素),而是表示下标为5的第六个元素,属于下标越界错误!
3、数组元素赋初值“赋初值”操作仅存在于定义语句中! (1)int a[5] = {1, 2, 3, 4, 5}; (2)int a[5] = {1, 2, 3, 4, 5, 6}; // 初值个数多于所申请的元素个数,非法! (3)int a[5] = {1, 2, 3}; <=> int a[5] = {1, 2, 3,}; 加不加逗号是一样的 不完全赋初值方案:初值个数少于数组定义时所申请的元素个数,这种情况被称为:不完全赋初值; 不完全赋初值,将对数组从下标为0的第一个元素的连续若干个元素赋初值,而未赋初值的其它元素的值,是0! (4)int a[] = {1, 2, 3, 4, 5, 6, 7,}; 上述情况是:定义数组时,不明确声明数组元素个数,但赋初值,则,数组元素个数取决于初值个数! 若定义数组时,不明确声明数组元素个数,但是又不赋初值,则,这是语法错误!
引入一个重要话题:对于数组定义的深度理解 int a[5]; 这种定义可以看做:int[5] a; 关于变量定义的基本语法是: type 变量名称; 此时type就是int[5];变量名称就是a;说明a是一个类型为int[5]的空间。 int[5]成为一种数据类型。 对比:int a[];可以看做:int[] a; 对于表示类型的int[],不能满足数据类型的两个要素!
4、使用数组处理数据的特点用数组存储数据时,应遵循如下3个基本原则: 1、从下标为0的第一个元素空间开始存放; 2、连续存放数据; 3、上述两个原则必须动态成立! 关于第三点是说:如果在处理存储于数组中的数据时,存在“增加”、“删除”数据等操作,必须在这些操作结束时,依然满足上述两个原则。 为什么? 数组元素的遍历: 将存储于数组中的数据,无缺失、无重复的访问一遍,称为“遍历”。 假设一个拥有n个元素的数组中,存放着m个数据,且m <= n的;若按照上述三原则存储这些数据,则,可以用如下方法遍历这个数组: for(i = 0; i < m; i++) …a[i]…
5、一维数组例题要求编程实现:录入学生成绩,并对成绩进行插入、删除、查找、排序、求平均分数等操作。 |
二、二维数组1、二维数组int m[3][4]; 上述语句定义了一个3行4列的二维数组。 二维数组的定义与一维数组一样,应该遵循相同的原则。 二维数组m共有12个元素,每个元素都是int类型的。 这12个元素的下标分别是: m[0][0]、m[0][1]、m[0][2]、m[0][3]、 m[1][0]、m[1][1]、m[1][2]、m[1][3]、 m[2][0]、m[2][1]、m[2][2]、m[2][3]、
2、二维数组的内存映像图二维数组在内存中是一维存放的:
C语言中,二维数组中元素排列的顺序是按行存放的,即在内存中先顺序存放第一行的元素,再存放第二行的元素。 3、二维数组赋初值与一维数组赋初值一样,二维数组赋初值只能在定义语句中进行! 二维数组赋初值与一维数组赋初值遵循相同的原则: (1)int a[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}; // 逻辑角度 (2)int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; // 物理(存储)角度 (3)int a[3][4] = {{1, 2, 3, 4, 5}, {6, 7, 8}, {9, 10, 11, 12}}; //错误 (4)int a[3][4] = {{1}, {5}, {9}}; //部分元素赋初值 int a[3][4] = {{1}, {0, 6}, {0, 0, 11}}; (5)int a[3][] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; //上述写法是错误的! int a[][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; //正确的
分析如下: int a[3][4]; => int[4] a[3]; 假设type为int[4],则,左式可以看做: type a[3]; 说明:a是一个一维数组,每一个元素的类型是type,即,int[4]类型,即,由4个int元素组成的一个一维数组! int a[][4] = {…}; => int[4] a[] = {…}; 由于int[4]明确的说明,应该将初值中的数据,每4个划为一组(一维数组);这使得C编译软件有明确的指示,可以无二义性的操作。 int a[3][] = {…}; => int[] a[3] = {…}; 由于int[]没有说明长度,即,数据类型长度不确定,不能构成正确的,有效的数据类型,因此,是语法错误!
同理: int a[3][4][5]; 正确 int a[][4][5] = {…}; 正确 int[4][5] a[] = {…} int a[3][][5] = {…}; 错误 int[][5] 长度不定! int a[3][4][] = {…}; 错误 int[4][] 长度不定! int a[3][][]… 同样是错误的 4、二维数组的输出
|
三、字符数组与字符串用来存放字符数据的数组是字符数组。字符数组中的一个元素存放一个字符。 字符串:是以0结束的字符数组。 1、字符数组的定义int a[10]; 整型数组,即,数组的每个元素类型都是int类型的。 char a[10]; 字符数组,即,数组的每个元素类型都是char类型的。 2、字符数组初始化如果在定义字符数组时不进行初始化,则数组中各元素的值是不可预测的,是垃圾数据。 方法1:逐个字符赋值给数组中各元素 (1)char c[10] = {'I', '', 'a', 'm', '', 'h', 'a', 'p', 'p', 'y'}; //数组长度为10 (2)char c[10] = {'c', '', 'p', 'r', 'o', 'g', 'r', 'a', 'm'}; 初值个数(9)小于数组长度(10),则只将这些字符赋值给数组中前面那些元素,其余的元素自动定为空字符(即'\0')。 (3)char c[10] = {'I', '', 'a', 'm', '','s', 'o', '', 'h', 'a', 'p', 'p', 'y'}; //错误的 (4)char c[ ] = {'I', '', 'a', 'm', '', 'h', 'a', 'p', 'p', 'y'}; //不指定数组长度,根据后面的元素确定数组长度 方法2:用字符串常量使字符数组初始化 (1)char c[10] = {"I am happy"}; char c[10] = "I am happy"; char c[10] = {'I', '', 'a', 'm', '', 'h', 'a', 'p', 'p', 'y', '\0'}; 上面三个式子是等价的。上面两个字符数组的数组长度为11,而不是10.因为字符串常量的最后由系统加上一个'\0'. 3、字符数组的引用通过c[i]引用字符数组中的一个元素,得到一个字符。 4、字符串和字符串结束标志'\0'代表ASCII码为0的字符,从ASCII码表中可以查到,ASCII码为0的字符不是一个可以显示的字符,而是一个“空操作符”,即它什么也不做。用它作为字符串结束标志不会产生附加的操作或增加有效字符,只起一个供辨别的标志。
对于一个字符串,在遇到字符'\0'时,表示字符串结束,由它前面的字符组成字符串。 如果前面9个字符都不是空字符,第10个字符是空字符,则此字符串的有效字符为9个;若用字符数组存储此字符串,则数组长度为10.
关于“以0结束”的问题: char s[4] = {‘A’, ‘B’, ‘C’, ‘0’}; 是字符数组,不是字符串 char s[5] = {‘A’, ‘B’, ‘C’, ‘0’, 0}; 既是字符数组,也是字符串 char s[5] = {‘A’, ‘B’, ‘C’, ‘0’}; 既是字符数组,也是字符串 char s[5] = ”ABC0”; <=> char s[5] = {‘A’, ‘B’, ‘C’, ‘0’}; <=> char s[5] = {‘A’, ‘B’, ‘C’, ‘0’, 0}; char s[] = “ABCDEFG”; printf(“%d\n”, sizeof(s)); 屏幕输出结果为8,表明s数组的元素个数确实是8个,也就表明了”ABCDEFG”的最后确实存在着一个看不见的0!
C语言对于字符串的处理遵循一个基本原则: 遇0则止! C语言的库函数、我们所编写的程序,对于字符串的处理,都需要遵循这个原则! 这个原则同时要求提供C语言库函数的、C语言编译软件的制造者们和程序员,对于字符串的处理,都需要“以0为止”!即,在构造字符串时,必须在字符串的最后,存在(写上)0结束标志。
5、字符串与字符数组的关系在C语言中没有专门的字符串变量,如果想将一个字符串存放在变量中以便保存,必须使用字符数组,即用一个字符型数组来存放一个字符串,数组中每一个元素存放一个字符。例如“char a[10]="love". 字符串常量定义:用双引号(“”)括起来的0个或者多个字符组成的序列 字符串常量存储:每个字符串尾自动加一个 ‘\0’ 作为字符串结束标志 6、字符数组的输入输出方法1:逐个字符输入输出。
方法2:将整个字符串一次输入或输出。
|
//一维数组和二维数组的例子
#include<stdio.h>
//疑问:如何把数组名称加进去???????
void showArrayValue(int *a, int count);
void showTwoDimensionArrayValue(int (*m)[4], int rowCount, int colCount);
void showMatrix(int *matrix, int rowCount, int colCount);
void showMatrix(int *matrix, int rowCount, int colCount){
int i;
int j;
for(i = 0; i < rowCount; i++){
for(j = 0; j < colCount; j++){
printf("%d ", matrix[i * colCount + j]);
}
printf("\n");
}
}
void showTwoDimensionArrayValue(int (*m)[4], int rowCount, int colCount){
int i;
int j;
printf("二维数组的值为:");
for(i = 0; i < rowCount; i++){
for(j = 0; j < colCount; j++){
printf("%2d ", m[i][j]);
}
}
printf("\n");
}
void showArrayValue(int *a, int count){
int i;
printf("数组的值为:");
for(i = 0; i < count; i++){
printf("%d ", a[i]);
}
printf("\n");
}
void main(void){
int a1[5] = {1, 2, 3, 4, 5}; //“赋初值”操作仅存在于定义语句中!
int a2[5] = {1, 2, 3,};
int a3[5] = {1, 2, 3};
//int a4[5] = {1, 2, 3, 4, 5, 6}; //错误提示:too many initializers
int m1[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
int m2[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
//int m3[3][4] = {{1, 2, 3, 4, 5}, {6, 7, 8}, {9, 10, 11, 12}}; //错误提示:too many initializers
int m4[3][4] = {{1}, {5}, {9}};
int m5[3][4] = {{1}, {0, 6}, {0, 0, 11}};
showArrayValue(a1, 5);
showArrayValue(a2, 5);
showArrayValue(a3, 5);
printf("\n");
showTwoDimensionArrayValue(m1, 3, 4);
showTwoDimensionArrayValue(m2, 3, 4);
showTwoDimensionArrayValue(m4, 3, 4);
showTwoDimensionArrayValue(m5, 3, 4);
printf("\n");
showMatrix(&m1[0][0], 3, 4); //无任何警告
//showMatrix(m1, 3, 4); //能输出,但有警告,说类型不同
printf("\n");
}