C语言基础 -- 数组

数组

  1. 数组的定义

    • 数组是一组数据的集合,用于将一种类型的数据存储到一段连续的空间中,可在一定程度上面加快搜索速度。(这个是数组很重要的特性,注意和链表的区别)

    • 组成数组的元素是若干个独立的变量,这些变量的类型必须相同

    • 按照数组元素的类型的不同又可以分为:数值数组、字符数组、指针数组、结构体数组等。

    • 数组属于构造类型,因为其是以后基本数据类型组成的,像结构体也是的。

      <存储类型> <数据类型> <数组名> [<常量表达式>]

    • 数组的类型实际上说的是数组元素的类型,其所有的元素的数据类型是相同的。

    • 数组名不能与其他变量同名。

    • 数组结构与存储大小

      数组的存储空间在内存中是连续的,会根据数组元素的个数,来分配数组的大小

      数组的大小 = 数组元素的大小 * 数组元素的个数

      数组名用于记录数组首元素的地址,可以通过数组名来获取数组首元素的地址

  2. 一维数组

    一维数组的定义

    数据类型 数组名[常量表达式]

    • []: 运算优先级是最高的,而且具有右结合性。

    • 数组的存储空间在物理上是连续的,所以访问数组的元素可以通过首元素的地址就加偏移量来访问。

      数组元素的地址 = 数组首元素的地址 + 下标 * 数组元素的大小

    • 若数组定义时指定n个元素,则数组下标的范围是0~n-1;

    • 注意:千万不能出现数组越界访问的问题,数组越界访问相当于内存访问越界,后果不可预知。如:定义 int a[n] = {0};却去访问a[n],就发生了数组访问越界,因为访问了超出数组范围的未知内存

    一维数组初始化

    1. 局部数组未初始化

      对于普通局部数组(相当于局部变量),若定义时未初始化,则数组中未初始化元素的值是不确定的。

    2. static修饰的局部数组未初始化

      static数组若定义时未初始化,则数组中的元素值默认为0。(即相当于数组所有元素都以静态存储的方式进行存储)。

    3. 全局数组未初始化

      数组中的元素也会默认为0。

    4. 一维数组全部初始化

      注意在对数组进行初始化使只能放在一行,即初始化只能发生在数组定义的时候。

      如:int a[10] = {0,1,2,3,4,5,6,7,8,9,};

      这样写就是错的:
      int a[10]; a[10] = {0,1,2....};

      后面一句相当于是对数组调用,显然是错误的。即,数组若要初始化则只能发生在定义数组的时候。

    数组初始化的赋值方式只能用于数组的定义,定义之后再赋值只能一个一个进行的赋值。

    1. 部分初始化

      当{}中元素的个数小于赋值的个数时,则前面的元素被初始化,后面的元素自动为0。

    int a[10] = {1,2,3};
    //则该数组中,a[0]为1、a[1]为2、a[2]为3,其余的元素的值都为0
    
    //利用该性质,我们可以将数组清0,如:`a[10]={0}`
    
  3. 数组全部初始化

    若对数组中元素全部赋值则可以省略下标。

    int a[] = {1,2,3,4,5};
    //则我们定义了一个有五个元素的素组元素,且每个元素已经进行了初始化
    //此时编译器会自动识别我们的数组的元素个数
    
    
  4. 数组全部初始化为0

    a[10] ={0}

    当然了将数组初始化为0,还可以采用以下几种方法:

    1. 使用循环;

    2. 使用库函数memset:
      memset(数组名,初始化的值,素组大小);
      example:memset(a,0,n);

    3. 使用库函数bzero,将数组清零,头文件strings.h

      bzero(数组名,数组大小);
      bzero(a,sizeof(a)/sizeof(a[0]);

      数组元素的个数的计算方法:
      数组元素个数 = sizeof(数组名) /sizeof(数据类型)

  5. 多维数组

    • 定义形式:

      <存储类型> <数据类型> <数组名> <常量表达式> <常量表达式2>...<常量表达式n>

      多维数组只是增加了下标,其特性与一维数组基本相同。

二维数组

  1. 二维数组初始化

    1. 降维给二维数组初始化,即按行初始化,每一组的初始值都用"{}"括起来。

      如:a[2][3] = {{1,2,3},{4,5,6}};

    2. 按照线性存储给二维数组初始化

      a[2][3] = {1,2,3,4,5,6};
      即将二维数组中元素全部初始化。

    3. 可以省略左边下标的方式,初始化二维数组
      如:a[][3] = {1,2,3,4,5,6}
      编译器能够识别这是一个两行三列的数组。
      注意:第二维的长度不能省略,即可以省略行标识,但是不能省略列标识

  2. 二维数组的内存分配

    • 二维数组给我们平面的形式(行,列)但是实际上,二维数组也是在内存中也是连续的。即二维数组采用了和一维数组类似的存储方式。
    • 扩展:二维数组以一维数组为元素,这样我们能更加深刻的理解二维数组的形式。

字符数组

  • 字符数组的定义

    有一定顺序关系的若干个字符变量的集合,就是字符数数组。可以是多维的也可以是一维的。

  • 字符数组初始化

  1. 和普通数组相同,逐个进行初始化

    如:char a[5] = {'','','','',''}
    char b[][4] = {{'a','b','b','\0'},{'q','w','e','\0'}}

  2. 使用字符串常量进行初始化

    `char a[6] ="hello";`
    

    字符串以’\0’结尾,内存访问不能越界。利用字符串初始化字符数组的时候会默认加上’\0’。

  3. 字符串

    • 在C语言中没有专门的字符串变量,通常用一个字符数组来存放一个字符串。
    • 存放一个字符串时,编译器会自动加上’\0’作为结束标志。
    • 当用scanf函数输入字符串时,用空格作为字符串的结束符。(即当我们从终端上面进行字符串的输入时,当遇到空格时输入会终止,scanf函数会读取空格前的字符串)。

    常见的字符串处理函数:

    1. 字符串拷贝函数

      char *strcpy(char *dest,const char *src)

    2. 字符串连接函数

      char* strcat(char* dest,const char* src)

      将字符串src连接到字符串dest的后面。

    3. 字符串比较函数

      int strcmp(const char* s1,const char* s2)

      • 字符串相等,返回值为0
      • 字符串1>字符串2,返回值>0
      • 字符串1<字符串2,返回值<0
    4. 求字符串长度

      size_t strlen(const char* s)

      返回字符串的长度,不包括’\0’(注意:利用strlen函数来计算字符串的长度时,其所计算的长度是不包含’\0’的),举个例子
      在这里插入图片描述
      可以看到,该字符串实际上是占据了6字节的内存的,但是我们用strlen函数来计算的话,结果却是5。因为它只计算了字符串的实际长度,即不含’\0’。

    5. 字符串分界函数

      char* strtok(char* s,const char* delim)

      • 功能:将字符串分解成一个个片断
      • 参数:s为要分解的字符串,delim为分隔符字符串
      • 返回值:分解出的字符串的地址
    6. 注意点

      1. 当程序中,需要用户输入一个字符串时,我们也可以使用字符串输入函数gets,该函数没有输入长度限制,若我们利用该函数进行字符串的输入时,一定要注意字符数组的长度,避免发生发生内存越界。
      2. 好啦,数组相关的知识就介绍到这里了,后面会写文章分析一下数组与指针结合起来使用的技巧,这也是C语言的难点之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值