C语言学习——数组详解
在 C 语言中,除了整型、实型和字符型等基本数据类型之外,还可以将基本数据类型按照一定的规则组合起来构成较为复杂的数据类型,称为构造数据类型,又称导出数据类型,主要包括数组、结构体、共用体等。数组中顺序存放了一批相同数据类型的数据,这些数据不仅数据类型相同,而且在计算机内存里连续存放,地址编号最低的存储单元存放数组的起始元素,地址编号最高的存储单元存放数组的最后一个元素。通过数组名标识和序号(C 语言称为下标)可以引用这些数组元素。
数组是一组有序的数据的集合--数组中的元素类型相同,并由数组名和下标唯一地确定。
1. 数组名代表数组的起始地址,是地址常量。
2. 数组元素在内存中是连续存储的。
3. 引用数组元素:数组名[下标],下标从0开始
一、一维数组
1 一维数组的定义
语法: type ArrayName[size];
说明:
1. 定义一个含size个type类型元素的数组。 int a[10]; /*定义的整型数组a含10个元素*/
2. size必须是大于0的整型常量表达式。
3. C语言不允许对数组的大小作动态定义。
4. 编译时分配连续内存: 字节数=size* sizeof(type)
2 一维数组的初始化
语法: type ArrayName[size]={value-list};
存储形式:
1.数组如果不初始化,其元素值为随机数
2.可以只初始化部分数组元素,余者自动赋0值。
int a[5]={ 2 , 4 }等价于 int a[5]={ 2 , 4, 0, 0, 0 };
3.当全部数组元素赋初值时,可不指定数组长度
int a[]={1,2,3,4,5,6} ; //编译系统根据初值个数确定数组维数
4.全局数组或static数组元素自动初始化成0值
static int a[5];等价于static int a[5]={ 0 , 0, 0, 0, 0 };
赋初值方法:
(1)利用赋值语句初始化
char str[26],ch;
str[0]= 'A';
str[1]= 'B';
…
str[25]= 'Z';
(2)利用赋值语句初始化
char str[26],ch;
for(ch='A';ch<='Z';ch++)
str[ch-‘A’]=ch; //将26个大写字母依次存放到str[0] 、 str[1]、 ……str[25]中
(3)利用输入语句初始化
char str[26]; int i ;
for(i=0; i<26; i++) scanf("%c",&str[i]);
…...
3 一维数组的引用
- 数组必须先定义,后使用
- 只能逐个引用数组元素,不能一次引用整个数组
例 int a[10];
printf(“%d”,a); (错)
必须 for(j=0;j<10;j++)
printf(“%d\t”,a[j]); (对)
- 数组元素表示形式: 数组名[下标]
数组元素的下标:0~size-1。
4.数组名a代表的是数组a在内存中的首地址,也即数组元素a[0]的地址。
scanf(“%d”,&a[0]); 等价于 scanf(“%d”,a);
例1
#include<stdio.h>
void main(void)
{
int a[5]={1,2,3,4,5};
printf("%d, %d, %d\n",a[0],a[1],a[2]);
printf("%d, %d, %d,%d\n",a,&a[0],&a[1],&a[2]);
}
运行结果:
二、 多维数组
1 二维数组的定义
类型标识符 数组名[常量表达式SIZE 1][常量表达式 SIZE2];
例 int a[3][4];
- 若二维数组 Num共有 R行 C列;则 Num[i][j]之前有 i*C+ j
个元素。 - size必须是大于0的整型常量表达式。
例如 int a[0][3]; (错) - 不允许对数组的大小作动态定义。
int i=3 , j=4 ;
int a[i][j] ;(错)
2 二维数组的初始化
1、分行初始化:
部分初始化
第一维长度省略初始化
注意:第二维不能省略
例. 下列数组定义错误的是 D 。
A)int Score[3][3]; B)int Score[][3]={{1},{2},{3}};
C)int Score[3][3]={1}; D)int Score[3][]= {{1},{2},{3}};
3 二维数组的引用
表示形式: 数组名[行下标][列下标]
行下标、列下标可以是常量、变量、函数或表达式。如果下标带有小数,C 编译系统将自动对其取整。
例如,若有定义:float Num[3][10];则Num[2][1]、Num[i][j]、Num[j][i++]都是对数组 Num中数组元素的合法引用。
C 语言对数组元素的引用有以下几种规定:
float Num[2][4]={ 0,1,2,3,4,5,6,7 };
则可以访问的行下标为 0、1,可以访问的列下标为 0、1、2、3。不能越界引用数组元素Num[1][8]、Num[5][3],因为 C 语言从不检查数组下标是否越界,程序员要自己确认数组元素的正确引用,不能越界访问。
例如,不能用一个语句输入整个数组: scanf("%f",Num);
必须使用循环语句逐个输入数据:
for(i=0; i<2; i++)
for(j=0; j<4; j++)
scanf("%f", &Num[i][j]);
- 数组元素和普通变量一样,可以出现在任何合法的 C 语言表达式中。
例如,数组元素可以出现在函数调用:printf(“%d”, Num[i][j]);中。
程序举例:
#include<stdio.h>
void main(void)
{
int a[2][3]={{1,2,3},{4,5,6}};
printf("%d, %d\n",a[0][0],a[1][0]);
printf("%d, %d, %d, %d\n",a,a+1,&a[0][0],&a[1][0]);
}
三、字符数组
1 标题字符型数据的概念与存储
字符串常量:
2 字符数组的定义与初始化
字符数组的定义与一维数组、二维数组基本相同,类型标识符为 char。说明:
- 字符数组的每一个元素都是字符变量
- 处理n个字符,size必须≥n+1
#include "stdio.h"
void main()
{
char a[5]={65, ' ',98};
printf("%c, %d,%d, %d,",
a[0],a[1],a[2],a[3]);
}
初始化:
- 逐个数值赋给字符数组的元素
char str[10]={112,114,111,103,114,97,109,0}; - 逐个字符赋给字符数组的元素
char str[10]={‘p’,‘r’,‘o’,‘g’,‘r’,‘a’,‘m’,’\0’}; - 用字符串常量直接初始化数组
char str[10]={“program”};
char str[10]=“program”; - 字符数组定义初始化时可省略第一维长度,由系统编译时根据初值个数自动确定数组长度:
char Str[ ]=“program”; // Str数组长度自动确定为 8 - 通常一维字符数组用于存放一个字符串,二维字符数组用于存放多个字符串,而且至少要按最长的字符串长度加1设定第二维长度。二维字符数组定义初始化时同样只能省略第一维长度
char Subject[3][15]={“C programming”,“Java”,“Authorware”};
char Subject[][15] ={“C programming”,“Java”,“Authorware”};
3 字符数组的输入输出
- 逐个字符输入输出
用格式符“%c”输入或输出一个字符
#include <stdio.h>
void main(void )
{
char a[5]; int i=0;
while(i<=4)
scanf("%c",&a[i++]);
for(i=0;i<5;i++)
printf("%c", a[i]);
}
- 将整个字符串一次输入或输出。
用格式符“%s”输入输出字符串。
#include <stdio.h>
void main(void )
{
char a[5];
scanf("%s",a); //scanf中%s输入时,遇空格、TAB或回车结束
printf("%s",a);
}
- 用“%s”格式符输入字符串时,字符数组名前不要再加地址符&,因为数组名代表该数组的起始地址。
- 用“%s”格式符输入字符串时,输入的字符串应≤字符数组的长度-1。系统自动在后面加 个‘\0’结束符。
void main( void )
{
char a[]={'h','e','l','\0','l','o','\0'};
printf("%s",a);
}
输出:hel
原因:数组中有多个‘\0’时,遇第一个结束