数组知识总结

一、一维数组

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

 通过对这个函数练习,我认为在一些进行账户输入信息比对,这个函数起到至关重要的帮助,能够判断你输入的账户和密码是否一致。

以上就是我对数组的总结,如果大家阅读发现错误或者有异议可以评论留言,我看到一定及时回复大家,最后感谢大家阅读我的文章。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值