0
点赞
收藏
分享

微信扫一扫

成长之路---C语言笔记(构造类型之数组)


目标既定,在学习和实践过程中无论遇到什么困难、曲折都不灰心丧气,不轻易改变自己决定的目标,而努力不懈地去学习和奋斗,如此才会有所成就,而达到自己的目的——吴玉章

C语言具有丰富的数据结构,除了基本数据类型,如整型(int)、字符型(char)、实型(float和double)外,还有各种构造类型,如数组,指针,结构体等。在前面的学习中我们已经初步的学习了一些基本数据类型的使用方法,现在让我们来了解一下各种构造类型吧:

数组

在我们学习C语言过程中常常遇到需要处理大量的相关数据的问题,如果我们为每一个数据都定义一个独立的变量用于记录,这样虽然可以解决问题,但会造成变量过多,各数据之间并无联系,没有整体概念,不变管理等问题,为了解决这些问题C语言中定义了数组的概念

数组是指一系 列具有相同类型的有序数据元素的集合,这些数据元素在内存中按颗序连续存放。数组是一一个整体,一 次性定 义一组相同类型的变量, 每个变量没有单独的名字,而是使用数组名加变量在数组中的位置来进行访问。一维数组是最简单的数组,C语言支持一维数组和多维数组。

一维数组

1.一维数组的定义:

数组定义中的类型名可以是基本数据类型或构造数据类型。数组名是用户自定义的标识符,要符合标识符的定义规范。方括号中常量表达式的值必须大于等于1.表示数组的长度,即数组中包含的元素个数。

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

例如:我们声明了一个一维数组变量 int arr[10];其中它含有10个int 类型的变量而arr第一个数据元素是从下标为0开始的即(arr[0]),第二个数据元素是arr[1],以此类推,第10个数据元素是arr[9]。

2.数组元素在内存中的存储:

按顺序连续存放


arr[0]

......

arr[9]


注:下标用于引用数据元素,与数组定义时的常量表达式含义不同,后者用于声明数组长度,数组长度i是固定的在后续操作中不允许改变。

3.一维数组的引用:

数组元素只能逐个访问,不能一次性整体引用。数组元素可以通过数组名加下标进行访问

数组名[下标];

注:下标只能为整型或整型表达式,下标值从0开始,不得超过数组长度-1,否则将造成数组溢出导致不可预测的情况发生。

4.一维数组得初始化:

在定义数组的同时我们还可以为数组元素赋予初值,初值列表用花括号“{}”括起来。

类型名 数组名[常量表达式]={值...值};
例如:int a[5]={1,2,3,4,5};

注:

1.初值列表中的值的数目不可大于数组长度,当初值列表中的元素个数小于数组长度时,只对数组前面的部分元素赋值,剩下未指定初值的数自动赋值为0。

2.只能逐个为数组元素赋初值(除0外),诺对数组的全部元素赋初值可以不指定数组长度。

int a[10]={0};
int a[]={1,2,3,4,5};//这都是可行的

3.诺数组定义在函数体外,则数组元素均初始化为0,诺数组定义在函数体内则使用这些元素必须赋予初值。

4.除初始化外,不能使用花括号列表的形式为元素赋值。

这里我引用斐波那契输出前20位数举例:

#include<stdio.h>
#define N 20
void main() {
    long int a[N];
    int i;
    a[0] = a[1] = 1;
    for (i = 2; i < N; i++) {
        a[i] = a[i - 1] + a[i - 2];
    }
    for (i = 0; i < N; i++) {
        printf("%d ", a[i]);
        if ((i + 1) % 5 == 0) printf("\n");
    }
}



成长之路---C语言笔记(构造类型之数组)_学习


二维数组

一维数组只有一个下标,可以看作一行连续的数据。C语言允许构造多维数组。多维数组元素有多个下标,以确定它在数组中的位置。多维数组其实就是数组的数组。二维数组是多维数组最简单的形式,而多维数组可由二维数组类推得到。

1.二维数组的定义:

第一维,即第一个方括号内的值通常称为行(ROW),第二维,即第二个方括号内的值通常称为列(Colomn)。

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

以二维数组int a[3][5];为例:

数组a含有3个数组元素,每个数组元素内含有5个int型元素,那么数组a整体共有15(3x5)个整型元素。这个例子可以分成两部分加以理解,首先a是一个数组,内含3个元素(图7-2中的加粗部分),即a[0]~a[2],每个元素的类型是int[5], 也就是每个元素本身都是一个含有5个int元素的数组: a[0]是一 个数组, 其第1个数据元素是a[0][0],第2个数据元素是a[0][1]。


a[0][0]

a[0][1]

a[0][2]

a[0][3]

a[0][4]

a[1][0]

a[1][1]

a[1][2]

a[1][3]

a[1][4]

a[2][0]

a[2][1]

a[2][2]

a[2][3]

a[2][4]


2.二维数组在内存中的存储:

二维数组在概念上是二维的,但在计算机内部,一维数组是按顺序连续存储的,是线性结构。C语言采用按行存储方式,即先按存放第1行元素,再接着存放第2行元素。对于一个m行n列的二维数组a[m][n],假设,的第一个 元素a[0][0]的存储位置为LOC(a[0][0]),每个数组元素占用的存储单元为t字节,那么数组元素al[i][j]的地址可以按以下公式计算:LOC(a[i][j])= LOC(a[0][0])+(i*n+j)*t

3.二维数组的引用:

对二维数组元素进行访问,必须指明行下标和列下标,行下标指出的是哪个内部数组,列下标则在内部数组中指定相应元素。下标值应为整型常量或整型表达式。

数组名 [行下标][列下标];
b[2][3]=1;//数组元素被赋值
b[2][3]=b[1][0]+b[i][j];//数组元素参与运算
printf("%d",b[2][3]);//輸出数组元素的值

与一维数组类似,要确保行下标值和列下标值不越界,二维数组也不能整体赋值,需要以次访问各元素来赋值。

4.二维数组的初始化:

(1)分行初始化

对二维数组的初始化建立在一维数组初始化的基础上,因为二维数组的每一行是一个一维数组,因此可以按行初始化,有几行就使用几个初始化列表。

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

(2)将所有初值写在一个大括号内,可以按行连续赋初值,只保留最外面的一对花括号。

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

(3)只对部分元素赋值,与一维数组的初始化类似,二维数组的初始化可以只为部分元素赋初值,剩下的元素值为0。

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

如果省略了内部的花括号,且给出的初值个数不足,那么将按顺序逐步进行初始化,剩下没有初值的元素初始化为0。

(4)省略数组行数

如果给出了全部元素的初值,那么第维的长度可以省略, 但第二滩的长度 不能省略。

int a[[4]=10, 1.2.3.4.5.6,7,8.9.10,11);

编译器会根据元素总个数和列数计算出行数。上述代码的效果与以下代码等价:

int a[3][4]=(0.1,.2.3.4,5.6,7.8,9.10, 1);

如果在省略行数的情况下只对部分元素赋初值,那么应分行赋初值,不能省略嵌套的括号.

这里我引用生成杨辉三角为例:

//此代码实现的是输出杨辉三角前10行
#include <stdio.h>
int main()
{
    int a[10][10];
    int i,j;
    for (i=0;i<10;i++)
    {
        for (j=0;j<=i;j++)
        {
            if (j==0 || i==j) a[i][j]=1;      //无规律则直接赋值
            else a[i][j] = a[i-1][j]+a[i-1][j-1];      //有规律直接找规律赋值
            printf("%d\t",a[i][j]);
        }
        printf("\n");
    }
    return 0;
}



成长之路---C语言笔记(构造类型之数组)_学习_02


今日练习

给你⼀个 m ⾏ n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素(难度 有点⼤,需要⼀定的逻辑思维能⼒,每次都需要考虑好边界条件)



成长之路---C语言笔记(构造类型之数组)_经验分享_03


输⼊:matrix = [[1,2,3],[4,5,6],[7,8,9]] 输出:[1,2,3,6,9,8,7,4,5]

答案及解题思路见下方,欢迎讨论。

最后的话 :如果大家觉得这篇文章对你们有帮助的话希望你们能够点点关注,你们的关注是我继续写下去的动力,谢谢大家。

答案与思路:

螺旋方阵的输入: 输入方阵从最外层到内层可以看做大正方形套小正方形,即我们从最外层输入,通过四个for语句调换方 向输入,当外层输入完成后,进入内层( cnt -- )后再次进行输入直到最后

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <memory.h>
int main() {
    int n, k, b;
    scanf("%d", &n);
    int i, j, c = 0, r = 0, num = 0, cnt = n / 2;
    int a[10][10];
    memset(a, 0, sizeof(a)); //初始化
    while (cnt--) { //控制循环输入次数
        for (i = r; i < n - c; i++) //→ 输入行,固定行移动列,数字依次增加,当移至第n列则进行下一步
            a[r][i] = ++num;
        r++;
        for (i = r; i < n - c; i++) //↓ 同理移动输入
            a[i][n - c - 1] = ++num;
        c++;
        for (i = c - 1; i < n - c; i++) //←
            a[n - r][n - i - 2] = ++num;
        for (i = r; i < n - r; i++) //↑
            a[n - 1 - i][c - 1] = ++num;
    }
    if (n % 2 != 0) //如果是奇数,填上正中间那个数
        a[n / 2][n / 2] = ++num;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            printf("%d ", a[i][j]);
        }
    }
    return 0;
}

举报

相关推荐

0 条评论