C语言 数组

1.一维数组

1.1 数组概念

  • 数组是含有多个数据值的数据结构,并且每个数据值具有相同的数 据类型。这些数据值称为元素 (element),可以根据元素在数组中 所处的位置把它们一个个地选出来,数组元素是存储到一片连续的内存中的。
  • 最简单的数组类型就是一维数组,一维数组中的元素一个接一个地编 排在单独一行,这里可以假设 有一个名为a 的一维数组:

 

  • 为了声明数组,需要指明数组元素的类型和数量 。例如,为了声明 数组a 有10个int 类型的元素,可以写成
int a[10];
/*
此时数组 a 中有 10 个元素,每个元素都是 int 型变量,
int 型变量占 4 字节的内存空间,那么 10 个 int 型变量就占 40 字节的内存空间,
而且它们的地址是连续分配的。
*/
  1. a 是数组名,即这片连续内存的名称
  2. [10] 代表这片连续内存总共分成10个相等的格子,每个格子称为数组的元素
  3. int 代表每个元素的类型,可以是任意基本类型,也可以是组合类型,甚至可以是数组

1.2 数组初始化

  • 在定义的时候赋值,称为初始化
int a[5] = {1, 2, 3, 4, 5};
  • 通过将数组元素的初值依次放在一对大括号中,如此初始化之后,a[0]=1;a[1]=2;a[2]=3;a[3]=4;a[4]=5,即从左到右依次赋给每个元素。
  • 需要注意的是,初始化时各元素间是用逗号隔开的,不是用分号。

  • 可以只给一部分元素赋值,这叫“不完全初始化”
int a[5] = {1, 2};
  • 定义的数组 a 有 5 个元素,但大括号内只提供两个初值,这表示只给前面两个元素 a[0]、a[1] 初始化,而后面三个元素都没有被初始化。不完全初始化时,没有被初始化的元素自动为 0。

  • 需要注意的是,“不完全初始化”和“完全不初始化”不一样。如果“完全不初始化”,即只定义“int a[5];”而不初始化,那么各个元素的值就不是0了,所有元素都是垃圾值。

  • 如果定义数组时就给数组中所有元素赋初值,那么就可以不指定数组的长度,因为此时元素的个数已经确定了,系统会自动分配空间
int a[] = {1, 2, 3, 4, 5};
  • 元素下标:数组开头位置的偏移量,下标从 0 开始,即从 a[0] 开始,而不是 a[1]

 

#include <stdio.h>
int main(void)
{
    int a[5] = {1, 2, 3, 4, 5};
    int i;
    for (i = 0; i < 5; i++)
    {
        printf("%d\n", a[i]);
    }
    return 0;
}

 

1.3 数组元素引用

  • 数组必须先定义,然后使用。C 语言规定,只能逐个引用数组元素,而不能一次引用整个数组,数组下标可以是整型常量或整型表达式
a[0] = a[5] + a[7] - a[2 * 3]
  • 注意:定义数组时用到的“数组名[常量表达式]”和引用数组元素时用到的“数组名[下标]”是有区别的,定义数组时的常量表达式表示的是数组的长度,而引用数组元素时的下标表示的是元素的编号
#include <stdio.h>
int main(void)
{
    int a[5] = {1, 2, 3, 4, 5}; // 定义长度为5的数组a
    int t;
    t = a[3]; // 引用数组a中下标为3的元素a[3], 此时的3不代表数组的长度
    printf("t = %d\n", t);
    return 0;
}
// t = 4

2.二维数组

  • 若数组元素类型也是数组,则该数组称为二维数组
int a[2][3];

// a[2] 是数组的定义,表示该数组拥有两个元素
// int [3]是元素的类型,表示该数组元素是一个具有三个元素的整型数组
  • 多维数组的语法跟普通的一维数组语法完全一致

  • 初始化
int a[2][3] = {{1,2,3}, {4,5,6}}; // 数组的元素是另一个数组

int a[2][3] = {{1,2,3}, {4,5,6}, {7,8,9}}; // 错误,越界了
int a[2][3] = {{1,2,3}, {4,5,6,7}};        // 错误,越界了

int a[ ][3] = {{1,2,3}, {4,5,6}}; // OK,自动根据初始化列表分配数组元素个数
int a[2][3] = {{1,2,3}};          // OK,只初始化数组元素的一部分
  • 元素引用
int a[2][3] = {{1,2,3}, {4,5,6}}; // 数组的元素是另一个数组
// a[0] 代表第一个元素,这个元素是一个具有 3 个元素的数组:{1,2,3}
// a[1] 代表第二个元素,这个元素也是一个具有 3 个元素的数组:{4,5,6}

printf("%d", a[0][0]); // 输出第一个数组的第一个元素,即1
printf("%d", a[1][2]); // 输出第二个数组的第三个元素,即6

 

  • 任意的数组,不管有多复杂,其定义都由两部分组成。
    • 第1部分:说明元素的类型
    • 第2部分:说明数组名和元素个数

 

int   a[4];       // 第2部分:a[4]; 第1部分:int
int   b[3][4];    // 第2部分:b[3]; 第1部分:int [4]
int   c[2][3][4]; // 第2部分:c[2]; 第1部分:int [3][4]
int  *d[6];       // 第2部分:d[6]; 第1部分:int *
int (*e[7])(int, float); // 第2部分:e[7]; 第1部分:int (*)(int, float)
  • 注意:
    • 上述示例中,a[4]、b[3]、c[2]、d[6]、e[7]本质上并无区别,它们均是数组
    • 上述示例中,a[4]、b[3]、c[2]、d[6]、e[7]唯一的不同,是它们所存放的元素的不同
    • 第1部分的声明语句,如果由多个单词组成,C语言规定需要将其拆散写到第2部分的两边

3.字符数组

  • 用来存放字符的数组称为字符数组
char a[10];    // 一维字符数组
char b[5][10]; // 二维字符数组
char c[20] = {'c', '  ', 'p', 'r', 'o', 'g', 'r', 'a', 'm'}; // 给部分数组元素赋值
char d[] = {'c', ' ', 'p', 'r', 'o', 'g', 'r', 'a', 'm'};    // 对全体元素赋值时可以省去长度
  • 字符数组实际上是一系列字符的集合,也就是字符串(String)。
  • 在C语言中,没有专门的字符串变量,没有string类型,通常就用一个字符数组来存放一个字符串。
  • 字符串是一系列连续的字符的组合,要想在内存中定位一个字符串,除了要知道它的开头,还要知道它的结尾。找到字符串的开头很容易,知道它的名字(字符数组名或者字符串名)就可以;然而,如何找到字符串的结尾呢?
    • 在C语言中,字符串总是以'\0'作为结尾,所以'\0'也被称为字符串结束标志,或者字符串结束符。
      • '\0'是 ASCII 码表中的第 0 个字符,英文称为 NULL,中文称为“空字符”。该字符既不能显示,也没有控制功能,输出该字符不会有任何效果,它在C语言中唯一的作用就是作为字符串结束标志。
      • C语言在处理字符串时,会从前往后逐个扫描字符,一旦遇到'\0'就认为到达了字符串的末尾,就结束处理。'\0'至关重要,没有'\0'就意味着永远也到达不了字符串的结尾。
      • 由" "包围的字符串会自动在末尾添加'\0'。例如,"abc123"从表面看起来只包含了 6 个字符,其实不然,C语言会在最后隐式地添加一个'\0',这个过程是在后台默默地进行的,所以我们感受不到。

 

  • 当用字符数组存储字符串时,要特别注意'\0',要为'\0'留个位置;这意味着,字符数组的长度至少要比字符串的长度大1
char str[7] = "abc123";
/*
"abc123"看起来只包含了 6 个字符,我们却将 str 的长度定义为 7,就是为了能够容纳最后的'\0',
如果将 str 的长度定义为 6,它就无法容纳'\0'了。
*/
  • C语言规定,可以将字符串直接赋值给字符数组
char s1[5] = {'a', 'b', 'c', 'd', 'e'};       // s1存放的是字符序列,非字符串
char s2[6] = {'a', 'b', 'c', 'd', 'e', '\0'}; // s2存放了一个字符串

char s[6] = {"abcde"}; // 使用字符串直接初始化字符数组
char s[6] = "abcde";   // 大括号可以省略,这种形式更加简洁,实际开发中常用

s[0] = 'A'; // 索引第一个元素,赋值为 'A'

// 为了方便,你也可以不指定数组长度
char str[] = "www.baidu.com";
  • 所谓字符串长度,就是字符串包含了多少个字符(不包括最后的结束符'\0')。例如"abc"的长度是 3,而不是 4。

4.变长数组

  • 数组变量的长度必须用常量表达式进行定义。但是在 C99中,有时候也可以使用非常量表达式。
  • 定义时,使用变量作为元素个数的数组。
  • 变长数组仅仅指元素个数在定义时是变量,而绝非指数组的长度可长可短。实际上,不管是普通数组还是所谓的变长数组,数组一旦定义完毕,其长度则不可改变。
#include <stdio.h>
int main(void)
{
    int i, n;
    printf("请输入数组长度\n");
    scanf("%d", &n);

    int a[n]; // C99 only - length of array depends on n

    printf("Enter %d numbers: ", n);

    for (i = 0; i < n; i++)
        scanf("%d", &a[i]);

    printf("数组元素如下\n:");

    for (i = n - 1; i >= 0; i--)
        printf(" %d", a[i]);

    printf("\n");
    return 0;
}
  • 上面程序中的数组 a 是一个变长数组,变长数组的长度是在程序执行时计算的,而不是在程序编译 时计算的。变长数组的主要优点是程序员不必在构造数组时随便给定 一个长度,程序在执行时可以准确地计算出所需的元素个数。如果让 程序员来指定长度,数组可能过长(浪费内存)或过短(导致程序出 错)。
  • 数组 a 的长度由用户的输入确定而 不是由程序员指定一个固定的值,这是与老版本不同的地方。

注意:变长数组不可初始化,即以下代码是错误的:

int len = 5;
int a[len] = {1,2,3,4,5}; // 数组 a 不可初始化

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

cam_______

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

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

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

打赏作者

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

抵扣说明:

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

余额充值