数组

1.数组的基本用法

1.1概念

数组是有序的元素序列。
将若干个类型相同的变量的集合命名,那么这个名称就是数组名。
重点是:数据类型相同并且连续的变量的集合。

1.2 定义格式

存储类型 数据类型 数组名[元素个数];
例如:(auto) int a[5];
数组名:代表数组的首地址,a是地址常量,不能为左值,不能被赋值。

数组定义方法:
(1)数组名定义规则跟变量名相同,遵循标识符命名规则。
(2)数组名后使用方括号括起来的表达式常量,表示元素的个数。
(3)常量表达式中可以包含常量和符号常量,不能包含变量。

1.3 访问元素

数组名[下标];
注意:下标从0开始
例如:
访问第一个元素: a[0];
访问第n个元素: a[n-1];

特点:
数据类型相同
在内存中连续

注意:
(1)数组的数据类型就是其元素的数据类型
(2)数组名要符合标识符命名规则
(3)在同一个函数中,数组名不要与变量名相同。
例如:int a[5];
int a;//错误
(4)数组下标从0开始,到n-1结束。

2.一维数组

一维数组、二维数组

2.1 一维数组的概念

是有一个下标的数组
格式:存储类型 数据类型 数组名[元素个数];
访问元素: 数组名[下标];
下标从0开始
数组名:数组的首地址

2.2 初始化

【1】定义时全部初始化
int a[5]={1,2,3,4,5};
printf(“%d\n”,a[0]);
printf(“%d\n”,a[1]);
printf(“%d\n”,a[2]);
printf(“%d\n”,a[3]);
printf(“%d\n”,a[4]);

【2】定义时部分初始化:
未初始化元素值为0
int a[5]={1,2};
printf(“%d\n”,a[0]);
printf(“%d\n”,a[1]);
printf(“%d\n”,a[2]);
printf(“%d\n”,a[3]);
printf(“%d\n”,a[4]);

【3】先定义,后初始化。需要单独对每个元素赋值。
int a[5];
a[0]=1;
a[1]=2;
a[2]=3;
a[3]=4;
a[4]=5;
printf(“%d\n”,a[0]);
printf(“%d\n”,a[1]);
printf(“%d\n”,a[2]);
printf(“%d\n”,a[3]);
printf(“%d\n”,a[4]);

注意定义时不能数组越界:
int a[3]={6,2,3,5,1}; //错误,数组越界

2.3 定义空数组

【1】 int a[5]={0,0,0,0,0};
【2】int a[5]={0};
【3】int a[5]={};

2.4 数组引用

(1)先定义后引用
(2)每次只能引用一个数组元素a[i], 如果想引用所有元素可以通过循环遍历数组。
(3)引用时防止数组越界
(4)打印数组元素地址用%p的格式
例如:
int a[10];
printf(“%p”,a);
printf(“%d”,a); //错误,数组名是数组的首地址。

如果想遍历数组可以通过循环:

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

练习:输入5个数组元素,然后依次打印出来。

#include<stdio.h>
int main(int argc, char const *argv[])
{
  	 int a[5]={};
	for(int i=0;i<5;i++)
   		 scanf("%d",&a[i]);
    for(int i=0;i<5;i++)
 	   printf("%d ",a[i]);
    return 0;
}

2.5 数组的大小

例如:

int a[5];//20个字节
double b[2];//16个字节
char c[32];//32字节
printf(“%d %d %d\n”, sizeof(a), sizeof(b), sizeof©);

计算方式:
(1)数组元素的个数 * 数据类型的大小
(2)sizeof(数组名)

数组元素的个数=sizeof(数组名)/sizeof(数组名[下标])
例如: printf(“%d\n”,sizeof(a)/sizeof(a[0]));

练习:计算斐波那契数列前15项并逆序输出
1 1 2 3 5 8 13 21 …

#include <stdio.h>
int main(int argc, char const *argv[])
{
    int a[15] = {1, 1};
    for (int i = 2; i < 15; i++)
    {
        a[i] = a[i - 1] + a[i - 2];
    }
    for (int j = 14; j >= 0; j--)
        printf("%d ", a[j]);
    printf("\n");
    return 0;
}

2.6 清零函数

2.6.1 bzero()函数

#include <strings.h>
void bzero(void *s, size_t n);
功能:将内存空间设置为0
参数:
s:要清空的空间的首地址
n:字节大小
返回值:无

案例:

#include <stdio.h>
#include <strings.h>
int main(int argc, char const *argv[])
{
    int a[10] = {1, 2, 3};
    for (int i = 0; i < 10; i++)
        printf("%d ", a[i]);
    printf("\n");
    bzero(a, sizeof(a));
    for (int i = 0; i < 10; i++)
        printf("%d ", a[i]);
    printf("\n");
    return 0;
}

打印结果:
1 2 3 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0

2.6.2 memset()函数

#include <string.h>
void *memset(void *s, int c, size_t n);

功能:将指定内存空间设为0
参数:
s:指定空间的首地址
c:要设置的数,一般为0
n:要设置的内存大小
返回值:无

练习:

#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
    int a[10] = {1, 2, 3};
    for (int i = 0; i < 10; i++)
        printf("%d ", a[i]);
    printf("\n");
    memset(a,0,sizeof(a));
    for (int i = 0; i < 10; i++)
        printf("%d ", a[i]);
    printf("\n");
    return 0;
}

3.字符数组

因为语言中没有字符串类型,所以可以用字符数组的形式去表示字符串。
概念:类型为字符的数组,也就是说数组中每个元素是字符类型。可以组成字符串。

3.1 表示形式

(1)单个字符表示:
char s[]={‘h’,’e’,’l’,’l’,’o’}; //sizeof(s)=5
char s1[5]={‘h’,’e’,’l’,’l’,’o’}; //sizeof(s1)=5

(2)用字符串表示,结尾会自动加上‘\0‘
char s2[]=”hello”; //sizeof(s2)=6
char s3[]={“hello”}; //sizeof(s3)=6
char s4[6]={“hello“} //sizeof(s4)=6
char s5[]={};//0错误

/验证字符数组大小/
printf(“%d %d\n”,sizeof(s),sizeof(s1));
printf(“%d %d %d\n”,sizeof(s2),sizeof(s3),sizeof(s4));

初始化和数组规则相同

3.2 输入和输出

3.2.1 输入

(1)用scanf:

char s[32]={};
scanf(“%s”,s);

不能输入空格,如果输入空格,空格后面内容不会存入数组。例如输入hello word, 只能存入hello。
如需要保存带空格的字符串如下:

char s[32]={};
scanf(“%[^\n]”,s); //可以输入除了\n以外的字符,遇到\n结束。
printf(“%s\n”,s);

注意:输入字符串会在结尾自动加“\0”。
(2)用循环遍历输入
例如:

char s[6]={};
for(int i=0;i<6;i++)
scanf(“%c”,&s[i]);
printf(“%s”,s);

(3)gets()

#include <stdio.h>
char *gets(char *s);

功能:从终端获取字符串输入
参数:s:目标字符串的首地址
返回值:目标字符串的首地址
没有数组越界检查,使用时会报警告。

char s[32]={};
gets(s);
printf(“%s\n”,s);

练习:输入一个字符串,计算其空格个数。
方法1:

#include <stdio.h>
int main(int argc, char const *argv[])
{
    char s[32] = {};
    int sum = 0;
    gets(s);
    for (int i = 0; i < 32; i++)
    {
        if (s[i] == ' ')
            sum++;
    }
    printf("%d\n", sum);
    return 0;
}

方法2:

#include <stdio.h>
int main(int argc, char const *argv[])
{
    char s[32] = {};
    int sum = 0;
    gets(s);
    int i=0;
    while (s[i]!='\0')
    {
        if(s[i] == ' ')
            sum++;
        i++;
    }    
    printf("%d\n", sum);
    return 0;
}

3.2.2 输出

(1)用printf():

char s[32]=“hello”;
printf(“%s”,s);

(2)for循环

for(int i=0;i<32;i++)
printf(“%c”,s[i]);

(3)puts

#include <stdio.h>
int puts(const char *s);

功能:向终端输出字符串
参数:要输出字符串的首地址
返回值:字符串长度

例子:
char s[32]=“hello”;
puts(s);

3.3 计算字符串长度

3.3.1 用循环统计

#include <stdio.h>
int main(int argc, char const *argv[])
{
    char string[15]="hello world";
    int i=0;
    while(string[i]!='\0')
        i++;
    printf("%d\n",i);
    return 0;
}

3.3.2 用strlen()

#include <string.h>
size_t strlen(const char *s);

功能:计算字符串长度
参数:字符串的首地址
返回值:返回字符串实际长度,不包括’\0’在内。
例如:

char string[]=“hello world”;
char string2[15]=“hello world”;
int l=strlen(string);
printf(“%d\n”,l); //11
printf(“%d\n”,sizeof(string)/sizeof(char));//12
printf(“%d\n”,sizeof(string2)/sizeof(char));//15

3.3.3 sizeof和strlen的区别

1.sizeof是关键字,strlen是函数。
2.sizeof是计算数据所占空间大小,strlen是计算字符串的实际长度的。
3.sizeof计算时包含‘\0’, strlen计算时不包含‘\0’。
注意:sizeof如果在数组定义时指定了,数组所占空间远远大于所存储的字符串的长度时,sizeof计算的是这个数组的长度。

练习:输入一个字符串,实现字符串大小写的转换。

#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
    char s[32]={};
    int len=0;
    scanf("%[^\n]",s);
    len=strlen(s);
    for(int i=0;i<len;i++)
    {
        if(s[i]>='a' && s[i]<='z')
            s[i]-=32;
        else if(s[i]>='A' && s[i]<='Z')
            s[i]+=32;
    }
    printf("%s\n",s);
    return 0;
}

4二维数组

下标为两个的数组就是二维数组,下标分别是行下标和列下标。

4.1定义格式

存储类型 数据类型 数组名[行数][列数];
例如:int a[3][4];

4.2 访问元素

数组名[行下标][列下标]; (下标都是从0开始的)
int a[2][3];
a[0][0]:第一行第一列的元素
a[1][2]:最后一行最后一列的元素。
设n行m列:a[n-1][m-1]就是最后一行最后一列的元素。

注意:
(1)行下标和列下标都不能越界。
(2)行数可以省略,列数不能省略。
(3)数组名代表的是第一行的首地址

例如:一维数组和二维数组对比
一维数组:
在这里插入图片描述

二维数组:
在这里插入图片描述

4.3 二维数组元素的个数和二维数组的大小

元素个数:行数列数
二维数组大小:
(1)数据类型大小
行数*列数
(2)sizeof(数组名)

4.4 二维数组数组名

二维数组数组名代表第一行首地址
例如:int a[2][3]={1,2,3,4,5,6};
a: 第一行的首地址
a+1:第二行的首地址
设n行,最后一行首地址是:a+n-1

4.5 初始化

【1】全部初始化
int a[2][3]={1,2,3,4,5,6}; //顺序赋值
int b[2][3]={{1,2,3},{4,5,6}}//按行赋值
【2】部分初始化
未初始化的元素值为0
int a[2][3]={1,2,3,4,}; //顺序赋值 1 2 3 4 0 0
int b[2][3]={{1,2},{4,5}//按行赋值 1 2 0 4 5 0
【3】未初始化
随机值,需要单独赋值。

4.6 遍历二维数组

for循环嵌套,外层行数,内层列数。

int a[n][m]={};
for(int i=0;i<n;i++)//行下标
{
for(int j=0;j<m;j++)
{
//scanf()/printf()
}
}

练习:设一个二维数组,每个数等于行和列数的乘积。

#include <stdio.h>
int a[3][3]={0};
int main(int argc, char const *argv[])
{
    for(int i=0;i<3;i++)
	{
		for(int j=0;j<3;j++)
		{
			a[i][j]=i*j;
			printf("%d ",a[i][j]);
		}
		printf("\n");
	}
	return 0;
}

输出结果:

a[0][0]=0; a[0][1]=0;a[0][2]=0
a[1][0]=0; a[1][1]=1;a[1][2]=2
a[2][0]=0; a[2][1]=2;a[]2[2]=4

4.7 内存分配

int a[2][3];

(1)行地址
1.在二维数组中,数组名a的值,表示的实际含义是第一行首地址。这个数值还等于整个数组的首地址,还等于第一个元素的地址(&a[0][0])。
2.a+1代表第二的首地址。这个数值还等于第二行第一个元素的地址(&a[1][0])。

(2)列地址
1.二维数组中,a[0]的值是第一行第一列的地址,也就是该数组中首个元素的地址(&a[0][0])
2.a[0]+1的值,是数组元素第一行第二列的地址(&a[0][1])

int a[2][3]={1,2,3,4,5,6};
printf(“%p %p\n”,a,a+1);
printf(“%p %p\n”,a[0],a[1]);
printf(“%p %p\n”,&a[0][0],&a[1][0]);
printf(“%p %p\n”,a[0]+1,a[1]+1);
printf(“%p %p\n”,&a[0][1],&a[1][1]);

打印结果:
0xbf858184 0xbf858190
0xbf858184 0xbf858190
0xbf858184 0xbf858190
0xbf858188 0xbf858194
0xbf858188 0xbf858194

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐