c语言基础之数组


在c语言的实际应用中,我们常常需要同时对多个数据进行处理,如果没有专门批量处理数据的方法,就会给我们的程序编写造成巨大的影响。而这种批量处理数据的方法就是我们这次的主题——数组


在c语言中,数组是用来处理一系列相同类型元素的集合。所谓数组,就是用一个统一的名字代表这批数据,而用序号或下标区分各个数据。 这就是数组的定义。

一、一维数组的定义和使用

1.定义一维数组

一维数组是最简单的数组,它只有一个下标。定义一维数组的一般形式为

类型名 数组名[常量表达式];

例如

int a[10];

中“int”是数组类型,“a”为取的数组名,“10”表示数组申请了10个变量。

tps:
1.数组的命名规则与变量的命名规则是相同的。
2.用方括号括起来的常量表达式表示下标,所以以下写法也是正确的:
int a[10];
int a[2*5];
int a[n]; /*此时前面应已定义了n为常变量/
3.定义数组时,下标是从0开始的,即a[10]的第一个元素为a[0],最后一个元素为a[9]。

2.一维数组的引用和初始化

(1)一维数组的引用
定义完一个一维数组后,我们就可以引用它了,引用的一般形式为:

数组名[下标]

直接来个例题,来具体的运用下吧。

定义一个整型数组,逐步输入10个数字,并且把他们倒叙输出。

题目分析

这题并不难,主要是数组的基本运用,但是要结合我们上一章讲的循环结构,很容易就出来了。

代码实现

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int i,a[10];
    for(i=0;i<10;i++)
     scanf("%d",&a[i]);
    for(i=9;i>=0;i--)
        printf("%d ",a[i]);
    return 0;
}

输入

1 2 3 4 5 6 7 8 9 10

输出

10 9 8 7 6 5 4 3 2 1

(2)一维数组的初始化

我们在使用数组的时,有时候会涉及到数组元素关于自身的运算,这个时候我们就必须给数组赋初值了,也就是我们所说的数组的初始化。在对数组的初始化时,我们常常有三种方法对数组进行初始化赋值。
1、 把数组的全部元素赋予初值。例如:

int a[5]={1,2,3,4,5}

此时数组中的元素里,a[0]=1,a[1]=2,a[2]=3,a[3]=4,a[4]=5。
2、只给部分元素赋值。例如:

int a{5}={1,2};

此时只给了前面两个元素赋值了,后面的元素默认为0,即a[0]=1,a[1]=2,a[2]=0,a[3]=0.a[4]=0。
3、对全部元素赋值,不指定数组长度。例如:

int[]={1,2,3,4,5}

效果与(1)中相同。
介绍完这些,我们来用数组解决下有名的fibonacci数列问题吧。

如果设F(n)为该数列的第n项(n∈N*),那么fibonacci数列可以写成如下形式::F(n)=F(n-1)+F(n-2),其中,第一个数和第二个数分别为1,2。打印输出前20个fibonacci数。

题目分析

这题还是和上一题差不多,同样需要数组配合循环结构实现,但是这题要注意的是,fibonacci数列涉及到了它自身的运算,所以数组一定要赋初值。

代码实现

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int i;
    int f[20]={1,1};/*申请数组f中有20个元素,且赋初值,第一二个元素均为1,其余为0*/
    for(i=2;i<20;i++)
        f[i]=f[i-2]+f[i-1];/*运用循环结构执行fibonacci数列*/
    for(i=0;i<20;i++)/*此循环控制输出20个数*/
    {

        if(i%5==0)
            printf("\n");/*控制每5个元素换一次行*/
        printf("%8d",f[i]);/*每个元素输出时,宽度是8*/
    }
    printf("\n");/*最后一次换行*/
    return 0;
}

输出


       1       1       2       3       5
       8      13      21      34      55
      89     144     233     377     610
     987    1597    2584    4181    6765

tps:此时若不赋初值,系统会自动随机赋值且编译不报错!

二、多维数组的定义及使用

一个数组有一个下标时,我们叫它一维数组;当一个数组有两个下标时,我们叫它二维数组;当一个数组有n个下标时,我们就叫它n维数组。这些数组中的元素要依赖n个下标才能唯一地确定一个元素
最常见也最简单的多维数组就是二维数组,它必须提供俩个下标才能确定唯一的一个元素,一个二维数组“int a[m][n]”可以看成一个m乘n的行列式。下面我会拿二维数组举例子来帮助大家理解多维数组。

1.多维数组的定义

定义n维数组的一般形式为:

类型名 数组名[常量表达式1][常量表达式2].....[常量表达式n]

例如:定义二维数组a

int a[3][4];

表示定义了一个3乘4的整形数组。

tps:不要写成了int a[3,4];

2.多维数组的引用及初始化

多维数组的引用和初始化与一维数组相似.

(1)引用
引用的一般形式为:

数组名[下标1][下标2]......[下标n]

下标可以使整形表达式,如

a[2][3];

也可以写成

a[2-1][2*2-1];

(2)初始化
初始化与一维数组类似有三种方式
1、按行给数组全部元素进行赋值。例如:
给二维数组赋值

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

此时为,将第一个“{}”内的元素赋给了第一行,第二个“{}”内元素赋给了第二行,第三个“{}”内的元素赋给了第三行。
2、将所有数据写在一个大括号内,按数组顺序进行赋值。例如:
给二维数组赋值

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

效果与(1)相同,但是1中行对行,列对列,简单易懂。
3、只对部分元素赋值。例如:
对二维数组赋值

int a[2][3]={{1},{1}};

此时只对每一行第一个元素赋值为1,其余均为0。

关于数组讲了这么多,我们来一个数组的具体运用吧。
(此题来自pta)
本题要求编写程序,求一个给定的m×n矩阵各行元素之和。

输入格式:

输入第一行给出两个正整数m和n(1≤m,n≤6)。随后m行,每行给出n个整数,其间
以空格分隔。

输出格式:

每行输出对应矩阵行元素之和。

题目分析

由于此题要求输入一个m×n矩阵,所以我们可以申请二维数组对输入的矩阵进行存放,由于还要输出对应行元素之和,所以我们还需申请一个一维数组进行存储。

代码实现

#include<stdio.h>
#include<stdlib.h>
int main(){
    int i,j,a[7][7],m,n;/*申请二维数组a来存放矩阵*/
    int b[7]={0,0,0,0,0,0,0};/*申请一维数组b来储存对应行的和,由于涉及到了它自身的运算,所以赋初值*/
    scanf("%d %d",&m,&n);/*输入m,n*/
    for(i=0;i<m;i++)/*控制输入行*/
     for(j=0;j<n;j++)/*控制输入列*/
      scanf("%d",&a[i][j]);
    for(i=0;i<m;i++)
    { for(j=0;j<n;j++)
        b[i]=b[i]+a[i][j];/*进行对应行的相加,并用b数组储存*/
    }
    for(i=0;i<m;i++){
      printf("%d\n",b[i]);/*打印输出b数组*/
    }
    return 0;
}

从这题可以看出,数组与循环结构常常结合在一起使用,用法十分灵活。

tps:此题也可以先输入m,n的值再定义数组a[m][n],我们称这种数组为变长数组。C语言中,直到C99标准出现之前,声明数组时在方括号内只能使用整数常量表达式。而C99做了很大改进,允许数组的[ ]中的值是整形变量或是整形表达式。所以它只能在c99标准中使用,我这里并未使用它。

三、字符数组

数组除了可以用来存放数字还可以用来存放字符或其他数据类型的数据。用来存放字符的数组我们叫它字符数组。由于字符数组的定义方式与上面的没有太大的区别,我这里就重点讲下字符数组的赋值与引用输入输出

1.字符数组的赋值与引用

我们平时使用字符数组用赋值语句时是不能用赋值语句对整个数组赋值的。例如:

char c[5];
c={'c','h','i','n','a'};/*错误,不能对整个数组赋值*/
c[0]='c';c[1]='h',c[2]='i',c[3]='n',c[4]='a';/*分别赋值,正确*/

但是,字符数组定义时可以直接整体赋值,如:

char str[6]={'h','e','l','l','o'};

或者

char str[6]={"hello"};

也可以省略大括号

char str[6]="hello";

细心的小伙伴就会发现,我这里str数组明明只用了“hello”五个字符,为什么要申请6个空间楞?其实当我赋值完之后,它储存的状态是这样的

h e l l o \n

系统默认“\n”是字符串结束的标志,所以当我们输入完了结束了之后,会自动加上“\n”表示结束,它会占用一个字符的空间。大家在使用的时候一定要注意啦。

2.字符数组的输入/输出

字符数组的输出方式有两种:
(1)使用%c 逐个输出,例如:

char str[6];
int i;
for(i=0;i<6;i++)
  scanf("%c",&str[i]);/*字符数组输入*/
for(i=0;i<6;i++)  
 printf("%c",str[i]);/*字符数组输出*/

(2)使用%s将字符整体输出,例如:

char str[6];
scanf("%s",str);/*字符串输入*/
printf("%s",str);/*字符串输出*/

tps:由于字符数组名表示的就是数组的地址,所以不用加“&”。这一点大家学完指针后就会明白了。

介绍完这些,是不是感觉我们有解锁了不少新技能嘞?让我们来实战一番吧。

例:

输入一个数字代表学生的个数,然后循环依次输入学生的姓名,学号,还有成绩,一个学生有三门成绩,求每个学生总成绩的平均分,然后再求出各门成绩的平均分。输出学生的姓名,学号,成绩平均分,最后输出各个学科的平均分。

题目分析

这题看上去要求的东西有点多,看一眼就感觉不想写。其实不然,只要耐心看题就会发现,这题问题很多,但求的都不难。唯一的难点在于学生姓名的输入和输出,这就要用到我们今天学到的东西了。

代码实现

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int i,n,j;
    scanf("%d",&n);/*先输入n个学生*/
    double sum[3]={0},subjects[100]={0};/*定义数组学生成绩的和,还有各个学科的和,并赋初值为0*/
    double sc[n][3];/*成绩*/
    char num[n][9];/*学号*/
    char name[n][16];/*学生姓名*/
    for(i=0;i<n;i++)/*循环输入n个学生的数据*/
    {

        scanf("%s",name[i]);/*以字符串形式输入学生姓名*/
        scanf("%s",num[i]);/*同上,输入学号*/
        for(j=0;j<3;j++)
            scanf("%lf",&sc[i][j]);/*利用循环输入三门学科的成绩*/
    }
    for(i=0;i<n;i++)
    {
        for(j=0;j<3;j++)
        {
            sum[i]+=sc[i][j];/*用i控制行,j控制列,把每一行的分数相加并用数组sum储存*/
        }
    }
     for(i=0;i<n;i++)
    {
        printf("%s ",name[i]);/*字符串形式输出名字*/
        printf("%s ",num[i]);/*同上,输出学号*/
        printf("平均成绩是%.lf\n",sum[i]/3);/*可直接在这里用总数除3,也可以在外面除,效果一样*/
    }
    for(j=0;j<3;j++)
        for(i=0;i<n;i++)
    {
        subjects[j]+=sc[i][j];/*和学生各自分数的平均数一样,不过那个是加每一行,这个加没一列,所以i j反过来*/
    }
    printf("各科平均成绩是 ");
    for(i=0;i<3;i++)
        printf("%.lf ",subjects[i]/n);/*打印输出各个科目的平均值*/
    return 0;
}

输入

3
小明 201815 40 50 60
小红 201816 50 60 70
小刚 201817 60 70 80

输出

小刚 201817 60 70 80
小明 201815 平均成绩是50
小红 201816 平均成绩是60
小刚 201817 平均成绩是70
各科平均成绩是 50 60 70

怎么样,通过这一题是不是发现了许多骚操作?赶紧再找几题去试试吧!

发布了25 篇原创文章 · 获赞 20 · 访问量 3289

猜你喜欢

转载自blog.csdn.net/qq_44886056/article/details/89602921