a[10]: | a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] | a[8] | a[9] |
---|---|---|---|---|---|---|---|---|---|---|
9 | 1 | 3 | 5 | 7 | 9 | 2 | 4 | 6 | 8 |
可以把数组看作是一行连续的多个存储单元。
用更正式的说法是,数组是同类型数据元素的有序序列。
通常我们是这样定义的:
数组中元素的类型 数组变量名[元素数量]
例如:
int x[10];
char z[10];
float y[10];
解释: int x[10]; 代表生成了10个格子,每个格子中只能装int型数据(否则将会发生自动类型转换)
注意:元素数量必须是一个正整数且在C99标准以前,元素数量必须是个确定的数(这里的“确定的数”之后会做更详细的解释)。
我们可以通过多种途径对一维数组进行访问:
scanf("%d", &x[0]); //读入一个数,并存放到x[0]中
printf("%d", x[1]); //输出x[1]的值
x[2] = 2; //将x[2]赋值为2
a = x[3]; //把x[3]的值赋给变量a
注意!!!下标不能越界!(下标指的是上式子中x[2]的2)
C语言中,数组下标范围是0到n-1,而不是1到n。而C语言不要求检查下标的范围。因此,当下标超出范围时,程序可能会执行不可预知的行为。
从键盘中输入10个int型数据,分行输出这些值,并输出它们的平均值
#include
int a[10];
double sum = 0.0;
int i;
int main()
{
for (i=0;i<10;i++)
{ scanf("%d", &a[i]);
sum += a[i];
}
for (i=0;i<10;i++)
{
printf("%d\n", a[i]);
}
printf("%d", sum);
}
可以看到,如果要获取数组的所有位置进行输入或输出,就必须要通过循环来“遍历”数组,即一个一个位置访问.
大家一定要注意这里for的开始和终止条件!到底循环了几次?每次i的值是多少?
显然,在这道题目中,for是从0开始循环,到9结束,一共循环了10次。
同样,这道题不使用数组也可以完成,具体的写法在直播中有提到,大家可以通过观看录播进行学习。
从键盘中读入n(0 (这道题在直播中也详细的讲述过,我们也不再赘述) 回顾一下,如何理解下面这句话: 注意:元素数量必须是一个正整数且在C99标准以前,元素数量必须是个确定的数。 现在我们想先输入一个n,再根据n的值创建具有n个位置的数组a[n],就有: 那么,这里 int a[n]; 中的n就并不是一个确定的数。所以,这一段代码在C99标准以前就不可以运行。大家可以在自己的编译器上运行,看看自己的编译器支不支持该操作。 如果不行的话,我们可以通过申请很大空间的数据来防止此问题,例如 int a[n]; 只要能保证n小于50,则该数组就可以实现我们的目的 一维数组的初始化也有很多种方式,常用的有以下几种: 已知数组a被下述语句初始化: 编程输出数组a的所有元素,你有什么发现? 输出应该是这样的: 有的时候我们需要存储更多的信息,比如一个班级学生的语数外三门的分数,这个时候就需要用到二维数组(矩阵)。 二维数组有着一维数组类似的定义模式: 二维数组的内部大概是这样的: 注意横纵坐标的开始都是0!(这一点跟一维数组一样) 下标不能越界! 二维数组本质上是数组的数组,即以数组作为数组元素的数组。 在内存中,二维数组和一维数组一样是以线性方式存储的。如图: 同样的,二维数组也有很多种初始化的方法: 我们从键盘输入依次甲乙丙丁四人的语文、数学、英语成绩,最后如果一个人的数学成绩大于80,则输出他的三门课程的平均分(输入时按照下面表格的形式一行一行输入) 一个char类型变量在内存中仅占1个字节,即sizeof(char)的值为1,通常我们会将最高位定为0,所以此时一共会有128个字符,包括96个可打印字符和32个控制字符。字符是以ASCII码的形式储存在内存中的 (控制字符的ASCII码为0~31)。 但实际128个字符可能并不够用,所以不固定最高位的话会扩充到256个,但扩充的部分并不适用于所有的系统。 由一对单引号括起来的单个字符,如 ‘a’, ’ ', ‘\n’, ‘\0’, ‘\141’,其类型为 int 例: 输出 例: 输出: 一般来说,若两种类型的字节数不同,则会先将字节数低的数据类型转换成字节数高的类型再运算。 若字节数相同,但一种为有符号,一种无符号 (比如int与unsigned int),则会都转换成无符号再运算,因为这样可以最好地保存下来数据的精度 例: char 或 short 型和 int 型参与运算,则会将 char 或 short 转换成 int 所有的浮点型都会先转换成 double 运算,即使是含 float 的表达式 int 或 float 型和 double 型参与运算,则会先将 int 或 float 转换成 double 可以用一元运算符 sizeof 在一定程度上验证这一点 输出 当你定义一个变量的同时,操作系统就会自动为变量分配一个储存它的位置。这个"位置"就是它的地址 (地址其实就是一个数值)。例如,定义变量 例: 分配给数组储存空间通常是连续的。所以,如果我们能提供第一个元素的地址,那么我们就能够找到后续的元素。 数组有一个特殊的性质:在表达式中,以及将数组作为函数参数进行传递时,数组会隐式转换成一个指针常量,其值为数组的首地址,且和数组第一个元素的地址相等。关于指针类型的相关知识,我们将在第三次软件培训给大家详细讲解。 C语言是没有字符串类型的,那要怎么存储字符串呢?我们知道,数组所占内存空间是连续的,那就很容易想到用字符数组存储字符串。 字符串字面量:用双引号括起来的若干个字符,其类型为字符数组,不可以被修改,类似于整型字面量 1,2,3,所有字符串字面量结尾自带 前后相接的若干个字符串字面量,就等价于只保留第一个和最后一个双引号。例如 字符数组也可以像其他类型的数组一样,使用大括号初始化 除此之外,字符数组还可以用字符串字面量进行初始化。 例: 输出: 例: 输入: 输出: 例: 输入: 输出: 若要使用C语言标准库中的字符串处理函数,需要 例: 输出: 注意:为了避免溢出,必须确保用于存放的数组长度足以容纳待拷贝的字符串 (长度需要包含结束符 ‘\0’)。 例: 输出: 例: 输出: 从第一个字符开始,依次比较每个字符的 ASCII 码大小,直到发现两个字符不相等或结束时( 例: 输出:数组元素数量
#include
一维数组的初始化
int a[3] = {0};//将所有元素初始化为0
int a[3] = {1, 2, 3};//对每个元素分别赋值
int a[] = {1, 2, 3};//偷懒的写法,让编译器自己计算数组的大小
int a[6] = {1, 2, 3};
1 2 3 0 0 0
二维数组
姓名
语文
数学
英语
X
90
99
92
Y
59
59
59
定义格式
类型 数组变量名[维数1][维数2]
举个例子:
int x[5][9];
二维数组的访问
0
1
2
3
4
5
6
7
8
0
1
2
3
4
x[i-1][j-1] 表示二维数组的第i行第j列的元素。
以int x[5][9]为例:
该数组最后一个元素应该是x[4][8]
二维数组的存储结构
二维数组的初始化
对每个元素进行赋值:
int x[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int x[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
对部分元素进行赋值:
int x[3][4]={{1,2},{5,6},{9,10}};
int x[3][4]={1,2,3};
简略形式:
int x[][4]={1,2,3,4};
等价于
int x[1][4]={1,2,3,4};
例题
甲
乙
丙
丁
语文
数学
英语
代码实现
#include
字符型 char
字符在内存中的存储
单字节字符字面量
#include
4
ASCII 码表 (0~127)
#include
a
补充:不同种数据参与算术运算时的规律
#include
4
4
数据的地址
int a
,可以通过取地址符来获得它的地址,就像这样:&a
。#include
数组的地址
字符串
字符串字面量
'\0'
,例如 "esta"
,其类型为 char [5]
。"HHUC""ESTA""1234"
就等价于 "HHUCESTA1234"
。字符数组
char s0[5] = {'s', 'h', 'a', 'r', 'e'}; // 注意不要越界
char s1[] = {'e', 'f', 'f', 'o', 'r', 't'}; // 编译时自动计算长度,这里 s1 的长度为 6
char s2[10] = {'p', 'a', 'r', 't'}; // 同其他类型数组一样,若初始化不完全后面默认置0
char s0[] = "CHINA"; // 自带 '\0',故 s0 的长度为 6
char s1[20] = "CHINA"; // 初始化不完全,后面默认置 0
char s2[] = {'C', 'H', 'I', 'N', 'A'}; // s2 的长度为 5
'\0’的意义
\0
的 ASCII 码为 0,C语言标准库中的所有字符串处理函数,都是通过 '\0'
来得知字符串的结束位置。字符串的输出
char a[5] = {'a', 'b'};
// 给哪个地址就从哪里开始输出,直到'\0'时候结束输出 (不输出'\0')
printf("%s", a); // 或者 &a[0]
char b[5] = {'a', 'b'};
puts(b); // 基本同 printf,但会额外输出换行
abab
字符串的输入
char s[20]; // 数组长度为20,最多只能从键盘上输入19个字符,因为要给最后的'\0'留一个位置
scanf("%s", s); // 会自动加上'\0',注意输入空格会停止读取
printf("%s", s);
Hello World
Hello
char s[20];
gets(s); // gets可以读入空格
printf("%s", s);
My name is ZhangSan
My name is ZhangSan
常用的字符串处理函数
#include
strlen
:用于计算指定字符串的长度。char str[] = "esta";
printf("strlen(str):%d\n", strlen(str));
4
strcpy
:将一个字符串从一个字符数组拷贝到另一个字符数组里,包含最后的结束符 ‘\0’。char s0[100] = "";
char s1[100] = "How are you?";
strcpy(s0, s1); // 将 s1 中的内容拷贝至 s0
printf("%s", s0);
How are you?
strcat
:将一个字符连接到目标字符串后边,在此过程将覆盖第一个参数的结束符 '\0'
,被覆盖的这个 \0
决定了要从目标字符串开始追加内容的位置。char s0[100] = "How old";
char s1[100] = " are you?";
strcat(s0, s1);
puts(s0);
How old are you?
strcmp
:根据ASCII码比较两个字符串的大小。'\0'
)为止。char s1[100] = "abcdefg";
char s2[100] = "abcdefgh";
char s3[100] = "this is a string"; // i 的 ASCII 码为 105
char s4[100] = "this Is a string"; // I 的 ASCII 码为 73
int result = strcmp(s1, s2);
if (result < 0)
puts("s1 小于 s2");
else if (result == 0)
puts("s1 等于 s2");
else
puts("s1 大于 s2");
result = strcmp(s3, s4);
if (result < 0)
puts("s3 小于 s4");
else if (result == 0)
puts("s3 等于 s4");
else
puts("s3 大于 s4");
s1 小于 s2
s3 大于 s4