4、数组

1、数组的定义

  数组就是具有一定顺序关系的若干变量的集合。其中的每个变量,都被称为数组的元素。其中的每个交量。从定义中,我们可以看出几个关键点,首先,组成数组的元素是若干个独立的变量。其次,这些变量的数据类型必须相同。最后,变量之间有一定的顺序关系。

  数组属于构造类型。一个数组可以分解为多个数组元素。这些数组元素可以是基本数据类型或是构造类型。因此按数组元素的类型不同,数组可分为数值数组、字符数组、指针数组、结构体数组等。

2、一维数组

  2.1、一维数组的定义

  定义:只一个下标的数组。

格式:<存储类型>  <元素数据类型>  <数组名>  <[元素个数]>

  一维数组定义的三种方式:

数据类型 数组名[数组长度];
数据类型 数组名[数组长度]={值1,值2.....};
数据类型 数组名[]={值1,值2.....};

  数组名在程序中使用时表示的是数组中第一个元素的地址,也代表整个数组在内存中的首地址,他是一个地址常量。

  存储类型指的是auto、register、static、extern。若省路相当于auto。

  数据类型可以是任一种基本数据类型或构造数据类型。

  数组名是用户定义的数组标识符。

  方括号中的常量表达式表示数据元素的个数,也称为数组的长度。

  对于数组的定义,这里有几点是需要特别注意的。

  (1)、数组的类型实际上是指数组元素的取值类型。对于同一个数组,其所有元素的数据类型都是相同的。

  (2)、数组名应当符合标识符的命名规定,即由字母、数字和下划线组成, 但不能以数字开头。

  (3)、数组名不能与其他变量名相同。

  (4)、方括号中常量表达式表示数组元素的个数,如a[5]表示数组a有5个元素,他需要在数组定义时就确定下来,不能随着程序的运行动态更改。他的下标从0开始计数,因此5个元素分别为a[0]、a[1]、a[2]、a[3]、a[4]。

  (5)、不能再方括号中用变量来表示数组的元素个数,但是可以是符号常数或常量表达式,如a[3+2]、b[5+9]。

  (6)、允许在同一个类型说明中说明多个数组和多个变量。

  2.2、一维数组的引用

        通过下标就可以很方便地访问数组中的元素,但是,一定要注意下标从 0开始,范围为0到n-1,其中,n为元素个数。假如,引用数组元素时,下标越界了,结果将是不可预料的。ANSIC没有对使用越界下标的行为做出定义。因此,一个越界下标有可能导致以下几种结果:

  (1)、若越界访问的内存空间是空闲的,程序可能不受影响,仍能正确运行。

  (2)、若越界访问的空间已经被占用,且写了很重要的数据。在这种情况下,若程序执行了非法写操作则程序可能会异常终止或崩溃。

  (3)、若越界访问的空间是空闲的,程序只是进行了读操作,则程序能继续运行,但无法得出正确的结果

  (4)、其他情况。

  我们可以看到,数组的越界操作,相当于内存访问越界,这种错误所造成的结果是无法估计的,因此,在引用数组元素时,一定要仔细地处理下标,以防止出现数组越界问题。

  2.3、一维数组的初始化

  数组的初始化有7种情况:

  (1)、局部数组不初始化

    对于普通局部数组,若定义时没有初始化,则数组中元素的值是不确定的。

  (2)、static数组不初始化

    对于static修饰的数组,若定义时没有初始化,则数组中元素的值默认为0。

  (3)、全局数组不初始化

    对于全局数组,若定义时没有初始化,则数组中元素的值默认为0。

  (4)、部分初始化

    在定义时,只对部分元素初始化,后面的会自动赋值为0。

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

  (5)、全部初始化1

    在定义时,对数组中的元素进行全部初始化。

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

  (6)、全部初始化2

    在定义是,省略元素的个数,对数组中的元素进行全部初始化。

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

  (7)、全部初始化为0

    在定义时,可以一次性把数组中的元素全部初始化为0。

    如:int a[10]={0};   //他表示将数组中的所有元素都初始化为0了。

    注意:数组中的元素只能单个赋值,不能整体赋值。比如,int a[9]={3};只为第一个元素赋了值。

  2.4、一维数组的内存分配

  数组为一个整体,数组中的元素在内存中占用一片连续的存储空间,并且根据单个元素所占存储空间来进行内存分配。

  一维数组的数组名代表的是数组第一个元素的地址,也代表着整个数组的起始地址,它是一个地址常量,不可以赋值。

  sizeof(数组名):他表示整个数组占用的总空间。

  sizeof(数组名)/sizeof(元素数据类型):它表示数组中元素的个数。

   一维数组的数组名代表的是数组第一个元素的地址,“数组名+1”表示的是下一个元素的地址; “&+数组名”表示的整个数组的地址,“&+数组名[n]”表示第n个元素的地址。

 

 

3、多维数组

  一维数组只有一个下标。具有两个或两个以上下标的数组,就称为多维数组。多维数组有多个下标,以标识它在数组中的位置。

  格式:<存储类型>  <元素数据类型>  <数组名>  <常量表达式1>  <常量表达式2>….<常量表达式n>

  3.1、二维数组的定义

    定义:具有两个下标的数组。

格式:<存储类型>  <元素数据类型>  <数组名>  <[行数]>  <[列数]>

    行数表示第一维数组中元素的个数(数组的个数),列数表示第二维数组中元素的个数(元素的个数)。

  二维数组定义的方式:

数据类型 数组名[行数][列数];
数据类型 数组名[行数][列数]={{数据1,数据2},{数据3,数据4}};
数据类型 数组名[行数][列数]={数据1,数据2,数据3,数据4};
数据类型 数组名[][列数]={数据1,数据2,数据3,数据4};

  3.2、二维数组的初始化

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

                   例:int a[2][3]={ {7,8,9}  ,  {6,5,4} };   //全部初始化

                          int a[2][3]={ {4,5}  ,  {5} };     //部分初始化,其它元素都为0

  (2)、按线性存储的形式给二维数组赋初值

                   例:int a[3][2]={4,5,6,7,8,9};       //全部初始化

                          Int a[3][2]={4,5,6};           //部分初始化,其它元素都为0

  (3)、可以省略左下标的元素个数(省略行数)为二维数组赋初值。

                   例:int a[ ][3]={ {4,8,9}  ,{5,6,3} };

                   注意:只能省略第一维的长度,不能省略第二维的长度。

  3.3、二维数组的内存分配

  二维数组在概念上是二维的,也就是说其下标在两个方向上变化,有行和列的说法。下标变量在数组中的位置也处于一个平面之中,而不是像一维数组只是一个向量。但是二维数组在内存上是按一维进行线性排序的。按行优先存储,存储了第一行,在存储第二行,依次往下类推。

 

  二维数组的数组名表示是二维数组首个元素的地址,即第一个一维数组的地址;

  “数组名[n]”表示一维数组的首个元素的地址,也表示一维数组的首地址;

  “&+数组名”表示整个二维数组的地址;

 

 

4、字符数组

  4.1、字符数组的定义

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

  格式:<存储类型>  <字符型数据类型(char)>  <数组名>  <[元素个数]>  //一维

             <存储类型>  <字符型数据类型(char)>  <数组名>  <[行数]>  <[列数]> //二维

  4.2、字符数组初始化

  (1)、和普通数组一样,逐个为元素赋值

                    例:char a[6]={‘a’ , ‘b’ , ‘c’ , ‘d’ , ‘e’ , ‘\0’};   //字符串必须以‘\0’结束

                   char a[2][3]={ { ‘a’ , ‘b’, ‘\0’} , { ‘c’ , ‘d’ ,’\0’} };

  (2)、使用字符串常量来为元素赋值

                   例:char a[8]={“abcdefg”}   //字符串中隐含了‘\0’

                            char a[8]=“abcdefg”

                            char a[]=“abcdefg” 

         注意:字符串必须以’\0’作为结束符,在赋值时不能越界。

5、字符串

  5.1、字符串的定义

  定义:字符串指的是以‘\0’作为结束符的一组字符,在C语言中没有专门的字符串变量,通常用一个数组来存放一个字符串。因此当把一个字符串放入数组中时,也把结束符‘\0’存入数组,并以此作为字符串是否结束的标志。字符串必须以‘\0’结束。

  格式:<存储类型>  <字符型数据类型(char)>  <数组名>  <[]> 

  例:  char a[ ]={‘a’ , ‘b’ , ‘c’ , ‘d’ , ‘e’ , ‘f’ , ‘g’ , ‘\0’};

           char b[ ]={“abcdefg”};

                char c[ ]=“abcdefg”;

  用字符串赋值比用字符逐个赋值要多占一个字节,用于存放字符串结束标志’\0’。

  ’\0’是由编译系统自动加上的。由于采用了’\0’标志,所以在用字符串赋初值时,通常省略数组的长度。

  注意:在省略数组长度时,用字符逐个赋值时必须加上‘\0’,来结束字符数组的内存占据。

  5.2、字符串的输入输出

  字符串的输入输出,最容易想到的方式是,使用循环语句逐个的输入输出每个字符。还可以用scanf函数和printf函数来进行字符串的输入输出。使用格式化符号“%s”,来表示处理的是字符串。scanf的各输入项必须以地址方式出现,如&a,&b,但由于数组名就代表了数组的首地址,所以只用写数组名就行了,不用再加取值符号。

    printf(“%s”,数组名);

    scanf(“%s”,数组名);   //scanf在遇到空格、’\t’、’\n’时会认为字符串输入结束。

  5.3、字符串处理函数

  A、 字符串拷贝函数strcpy

头文件

#include <string.h>

函数原型

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

参数

dest

目标字符串的起始地址

src

源字符串的起始地址

返回值

目标字符串的起始地址

功能

把字符串src拷贝到字符串dest中

注意

拷贝时,dest数组的空间必须足够大,拷贝时连“\0”一同拷贝

  B、 字符串连接函数strcat

头文件

#include <string.h>

函数原型

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

参数

dest

目标串的起始地址

src

源串的起始地址

返回值

目标串的起始地址

功能

把字符串src连接到字符串dest后面

注意

连接时,dest数组的空间必须足够大,两字符串均是以‘\0’结束。连接时,字符串dest和字符串src的‘\0’都取消,新串最后加‘\0’。

  C、 字符串比较函数strcmp

头文件

#include <string.h>

函数原型

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

参数

s1

字符串的起始地址

s2

字符串的起始地址

返回值

返回比较后的结果

字符串1=字符串2,返回值=0;

字符串1>字符串2,返回值>0;

字符串1<字符串2,返回值<0;

功能

按照ASCII码顺序比较字符串s1和字符串s2的大小

注意

它比较的是字符串的ASCII码值大小。

  D、 字符串长度函数strlen

头文件

#include <string.h>

函数原型

size_t  strlen(const  char *s);  //size_t表示sizeof型,即数据长度

参数

s

字符串的起始地址

返回值

字符串的长度(不包含‘\0’)

功能

求字符串的长度(不包含‘\0’)

注意

求取的字符串长度中不包含‘\0’

  E、  字符串分解函数strtok

头文件

#include <string.h>

函数原型

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

参数

s

要分解的字符串

delim

存储分割的字符串

返回值

字符串的长度(不包含‘\0’)

功能

分解出的字符串的地址

注意

将字符串分解成一个个片段

 

[行数][列数]
posted @ 2020-02-18 16:20  孤情剑客  阅读(592)  评论(0)    收藏  举报