一、一维数组
1、一维数组的定义
<存储类型> <数据类型> <数组名>[<常量表达式>];
存储类型可以不写,默认为auto(局部变量),还可以有register、static和extern三种存储类型。
数据类型就是基本数据类型,例如int 、char、float、double等等。需要注意的是,同一个数组,其所有元素的数据类型必须是相同的。
数组名和定义标识符一样,必须以字母或_开头,由_、字母和数字组成,且不能为关键字(上一篇文章已经讲过有哪32个关键字)。
常量表达式(例:2+1,2*4)表示数组元素个数,也称为数组长度。切忌不可定义一个变量且未给变量赋值,当作数组长度用到定义数组中去。数组的长度是一个常量,这一点就凸显出数组的缺点,定义了数组长度就无法再对长度进行更改,如果定义过长则造成内存资源的浪费,过短则会溢出。此外还需要注意的一点是,如果定义的数组长度为n,数组的下标是从0开始,因此最后一个元素的下标应该是n-1。
2、一维数组的引用
数组名[下标]
通过数组下标,我们就可以轻而易举地访问数组中的某一个元素,但是下标的注意点我们上面刚说过,假设数组长度为n,下标是从0~(n-1),一旦访问的下标超出这个范围,就会造成数组越界。下标越界会造成以下几种情况。
①若越界访问的内存空间是空闲的,程序可能不受影响,仍能正确运行。
②若越界访问的空间已经被占用,且对该空间进行更改,则程序可能会异常终止或崩溃。
③若越界访问的空间是空闲的,程序只是进行了读操作,则程序能继续运行,但无法得出正确的结果。
所以数组的越界操作,相当于内存访问越界,这种错误所造成的结果是无法估计的,因此,在引用数组元素时,一定要仔细地处理下标,以防止出现数组越界问题。
3、一维数组的初始化
一维数组总共有7种初始化。
①局部数组不初始化。若在定义局部数组时没有初始化,则数组中的元素为随机值。
②static 数组不初始化。若在定义static类型的数组时没有初始化,则数组中的元素默认为0。
③全局数组不初始化。若在定义全局数组时没有初始化,则数组中的元素默认为0。
④全部初始化。与变量在定义时初始化一样, 数组也可以在定义时进行初始化。
⑤部分初始化(常用)。数组在定义时可以对其中的部分数据进行初始化。当初始化的元素个数少于元素个数时,只给前面的部分元素赋值。
#include<stdio.h>
int main()
{
int a[5]={1,2,3};
for(int i=0;i<5;i++)
{
printf("a[%d]=%d\t",i,a[i]);
}
return 0;
}
//结果: a[0]=1 a[1]=2 a[2]=3 a[3]=0 a[4]=0
⑥数组全部赋值(常用)。若想要对数组中的元素全部赋值,则可以省略数组下标中的常量。编译器会根据初始化列表自动计算数组元素的个数。
⑦数组全部初始化为0(常用)。a[10]={0};
4、一维数组程序举例
冒泡排序是一种常见的排序方法,对n个元素的整型数组进行升序排列,具体过程如下。
①第一趟,比较第一个数和第二个数,如果a[0]>a[1],则交换;然后比较a[2]和a[3],a[3]和a[4],依此类推,直至a[n-2]和a[n-1]比较完,结束第一趟排序,此时的a[n-1]为该数组中的最大值。下一趟排序就不需要参与比较了。
②接着对n-1个数进行第二趟排序,排完序后,数组中第二大的元素被放置a[n-2]。
③重复以上操作,我们经过n-1趟排序,将整型数组按升序排列完成。
我们发现很多规律,对n个元素进行冒泡排序,总共要进行n-1趟,而每趟比较的次数=n-第几趟。
代码如下:
#include<stdio.h>
int main()
{
int a[10]={0},temp;
printf("请输入10个元素值:\n");
for(int i=0;i<10;i++)
{
scanf("%d",&a[i]);
}
for(int j=0;j<10-1;j++)//趟数
{
for(int k=0;k<10-j-1;k++)//比较次数
{
if(a[k]>a[k+1])
{
temp=a[k];
a[k]=a[k+1];
a[k+1]=temp;
}
}
}
for(int i=0;i<10;i++)
{
printf("%d\n",a[i]);
}
return 0;
}
//运行结果:请输入10个元素值:
// 10 9 8 7 6 5 4 3 2 1
// 1 2 3 4 5 6 7 8 9 10
二、多维数组
1、多维数组的定义
多维数组就是具有两个或两个以上下标的数组。其定义格式如下:
<存储类型> <数据类型> <数组名><常量表达式1><常量表达式2>. . .<常量表达式n>;
二维数组定义格式是:
<存储类型> <数据类型> <数组名>[常量表达式1] [常量表达式2];
这里的存储类型、数据类型、数组名和常量表达式我们刚刚在一维数组已经讲过了,就不再一一解释了。
2、多维数组的引用(二维数组)
<数组名>[ 常量表达式1 ] [ 常量表达式2 ]
与一维数组一样,需要注意数组越界问题,
3、多维数组的初始化(二维数组)
二维数组的初始化与一维数组基本类似,但是有一个点绝对不能遗漏,就是二维数组的第二维长度(列)绝对不能省略。主要有以下3种初始化方式。
①(常用)降维给二维数组赋初值,就是用花括号{ }赋初始值。下面我们看看如何定义和打印出来的结果。
#include<stdio.h>
int main()
{
int a[3][3]={{1,2,3}, //第一行
{4,5,6}, //第二行
{7,8,9}}; //第三行
printf("\t第1列\t第2列\t第3列\n");
for(int i=0;i<3;i++) //行
{
printf("第%d行\t",i+1);
for(int j=0;j<3;j++) //列
{
printf("%3d\t",a[i][j]);
}
printf("\n");
}
return 0;
}
运行结果:
// 第1列 第2列 第3列
//第1行 1 2 3
//第2行 4 5 6
//第3行 7 8 9
②(常用)按照线性存储的形式给二维数组赋初值
例如: a[2][5]={1,2,3,4,5,6,7,8,9,10};//将数组长度数的所有元素一次性写出来;
再例如:a[2][5]={1,2,3,4,5};//只初始化部分数组元素,其他元素默认为0;
③(常用)省略二维数组的第一维长度(行),但是不能省略第二维长度(列),刚刚定义里面讲过了。
例如: a[ ][3]={{1,2,3},{4,5,6}};//正确
再例如:a[2][ ]={{1,2,3},{4,5,6}};//错误
4、多维数组程序举例(二维数组)
一个三行四列的数组,请找出其中的最大值最小值以及它们的下标。
设计思路:选择a[0][0]为擂主赋值给临时变量max和min,遍历二维数组,当找到比擂主(max/min)还大/小时,将其赋值给max/min,并将下标赋值给临时变量row和col/row1和col1,循环结束,将临时变量max和对应的row和col以及min和其对应的row1和col1打印出来。
#include<stdio.h>
int main()
{
int a[][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};//第三种初始化方法
int row,col,temp,row1,col1;
int max=a[0][0];
int min=a[0][0];
for(int i=0;i<3;i++)//行
{
for(int j=0;j<4;j++)//列
{
if(max<=a[i][j])//寻找最大值
{
max=a[i][j];
row=i;
col=j;
}
if(min>=a[i][j])//寻找最小值
{
min=a[i][j];
row1=i;
col1=j;
}
}
}
printf("max=a[%d][%d]=%d,min=a[%d][%d]=%d\n",row,col,max,row1,col1,min);
return 0;
}
运行结果: max=a[2][3]=12,min=a[0][0]=1
三、字符数组
1、字符数组的定义
字符数组,顾名思义,就是存放字符的数组,是有一定顺序关系的字符型变量的集合,既可以是一维的,也可以是多维的。定义形式如下:
char 变量名[常量表达式];
char 变量名[常量表达式1][常量表达式2]. . .[常量表达式n];
2、字符数组初始化
常用两种方法来为字符数组初始化 。
①逐个为数组元素赋值。
例:char ch[6]={'a','b','c','d','e','g'};
当只初始化部分元素,其他元素默认为空,即不打印任何内容。
#include<stdio.h>
int main()
{
char ch1[][5]={{'0','1','2'},{'3','4','5','6'},{'7','8','9'}};
printf("\t第1列\t第2列\t第3列\t第4列\t第5列\n");
for(int i=0;i<3;i++)
{
printf("第%d行\t",i+1);
for(int j=0;j<5;j++)
{
printf("%3c\t",ch1[i][j]);
}
printf("\n");
}
return 0;
}
运行结果:
// 第1列 第2列 第3列 第4列 第5列
//第1行 0 1 2
//第2行 3 4 5 6
//第3行 7 8 9
②使用字符串常量来为数组元素赋值。
例:char ch[5]={"abcd"};//最后一个元素以'\0'结束
char ch[5]="abcd"; //花括号{}可省略
char ch[ ]="abcd"; //最后一个元素以'\0'结束,编译器会根据初始化列表自动计算数组元素的个数。
以上这三种初始化方法等同于:char ch[5]={‘a’,‘b’,‘c’,‘d’,‘\0’};
字符串举例:char fruit[ ][7]={“apple”,“banana”,“orange”,“pear”,“peach”};
注意:字符串需要以’\0‘结尾,如果用字符串常量为数组元素赋值,定义数组长度时,如果遗漏最后的’\0‘,会导致数组越界。
例如:char ch[4]={"abcd"};// 错误(越界)
#include<stdio.h>
int main()
{
char a[10]={'\0'};
printf("请输入一串字符:");
scanf("%s",a);
printf("打印输出:%s\n",a);
return 0;
}
运行结果:
//请输入一串字符:helloworld
//打印输出:helloworld
我们发现,在使用scanf并采用格式符%s,输入字符串存到数组中,只要给出数组首地址,也就是数组名a,会自动读取控制台中输入内容,不过使用scanf输入有一点弊端就是,当输入到空格/回车符/tab键,默认为结束。printf也是同样采用格式符%s,给出字符串的首地址,就能将其内容都打印出来。
四、字符串处理函数
刚刚我们学习了字符串数组,我们接下来学习几个字符处理函数,减少我们编程工作量。字符串处理函数需要添加头文件(#include<string.h>)
1、求字符串长度函数strlen
需要注意的是使用strlen函数计算长度时,不会将字符串中结束标志‘\0’算进去。
下面我们用代码来测试函数功能
#include<stdio.h>
#include<string.h>
int main()
{
char a[10]={'\0'};
printf("请输入一串字符:");
scanf("%s",a);
printf("字符串长度=%ld\n",strlen(a));
return 0;
}
运行结果:
//请输入一串字符:abcdefg
//字符串长度=7
2、字符串拷贝函数strcpy
使用该函数需要注意的是,拷贝到的目标数组一定要有足够的空间,否则就会数组越界,并且拷贝的内容会连同字符串结束标志'\0‘一同拷贝过去。
下面我们用代码来测试函数功能
#include<stdio.h>
#include<string.h>
int main()
{
char str1[10]={'\0'};
char str2[10]={'\0'};
printf("请输入字符串str1:");
scanf("%s",str1);
strcpy(str2,str1);
printf("str2:%s\n",str2);
return 0;
}
运行结果:
//请输入字符串str1:123
//str2:123
另外还有一点要说明的就是,如果拷贝的数组中有内容,拷贝过去后,原内容会全部被覆盖。
3、字符串连接函数strcat
简而言之,就是将两个字符串拼接到一起,2个字符数组变成1个,拼接到字符数组后面,会将其’\0‘删除,再将其连接。重要的事情说三遍,还是要注意目标数组长度要有足够空间,避免数组越界。
下面我们用代码测试该函数功能
#include<stdio.h>
#include<string.h>
int main()
{
char a[10]={'\0'};
printf("请输入字符串a:");
scanf("%s",a);
char b[10]={'\0'};
printf("请输入字符串b:");
scanf("%s",b);
strcat(a,b);
printf("拼接后的字符串:%s\n",a);
return 0;
}
运行结果:
//请输入字符串a:123
//请输入字符串b:456
//拼接后的字符串:123456
4、字符串比较函数strcmp
按照ASCII码顺序比较两个字符串的大小
字符串1=字符串2,返回值=0;
字符串1>字符串2,返回值>0;
字符串1<字符串2,返回值<0。
具体返回值是多少,我的理解就是,如果两个字符串长度相同,他们会依次对比,当发现两个字符ASCII码不同,就进行判断,算出差值返回,后面的字符不会再看。例如"a"和"ABCD"两个字符串,进行比较,不是谁长就谁更大,而是一一进行比较,字符'a'ASCII码97,'A'是65,所以a更大,所以前者更大,返回值也就是97-65=32。
下面我们用代码来测试该函数:
#include<stdio.h>
#include<string.h>
int main()
{
char str1[10]={'\0'};
printf("请输入str1:");
scanf("%s",str1);
char str2[10]={'\0'};
printf("请输入str2:");
scanf("%s",str2);
int i=strcmp(str1,str2);
printf("%s更长\n",i>0?"str1":"str2");
return 0;
}
运行结果:
//请输入str1:ABCDEFG
//请输入str2:a
//str2更长
//返回值=-32
通过对这个函数练习,我认为在一些进行账户输入信息比对,这个函数起到至关重要的帮助,能够判断你输入的账户和密码是否一致。
以上就是我对数组的总结,如果大家阅读发现错误或者有异议可以评论留言,我看到一定及时回复大家,最后感谢大家阅读我的文章。