C语言程序设计基础


Loops (More examples)

计算机学院    杨已彪

yangyibiao@nju.edu.cn

Overview

Loops (More Examples)


Multidimensional Arrays (多维数组)

一维数组

数组是包含多个数据值的数据结构, 每个数据值具有相同类型.

数据值称为元素, 可以根据它们在数组中的位置选择出来.

最简单的数组是一维数组, 一维数组中的元素一个接一个地排列在单独一行中:


数组下标

要访问数组元素, 可在数组名后加上一个方括号括起来的整数值.

这被称为对数组取下标或进行索引.

长度为n的数组元素的索引从00n1n – 1.

若数组a长度为10, 元素依次可标记为a[0],a[1],...,a[9]a[0], a[1], ..., a[9]:

a[0] a[1]a[1] a[2]a[2] a[3]a[3] a[4]a[4] a[5]a[5] a[6]a[6] a[7]a[7] a[8]a[8] a[9]a[9]

多维数组

数组可以有任意维数

下面的声明创建了一个二维数组(数学术语称为矩阵):

int m[5][9];

数组m有5行9列, 行和列下标都从0开始索引:

0 1 2 3 4 5 6 7 8
0
1
2
3
4
多维数组

为了访问i行j列的元素, 需要写成m[i][j]的形式.

表达式m[i]指定数组m第i行, 而m[i][j]选择该行中第j个元素.

不要把m[i][j]写成m[i,j]

这里, C将逗号视为 逗号运算符, 因此m[i,j]等同于m[j]

多维数组

虽然我们以表格形式显示二维数组, 但这并不是它们在计算机内存中实际存储的方式.
行主序存储数组, 从第 0 行开始, 接着第 1 行, 依此类推.
数组m的存储方式:

注意:此处图片中m[0,0]仅因为展示方便,实际应为m[0][0]


多维数组

  • 使用嵌套for循环处理多维数组.

示例:单位矩阵的数组的初始化: 嵌套的for循环

#include <stdio.h>

#define N 10

double ident[N][N]; // 存放在堆中

int main() {
  for (int row = 0; row < N; row++) {
    for (int col = 0; col < N; col++) {
      if (row == col)
        ident[row][col] = 1.0;
      else
        ident[row][col] = 0.0;
    }
  }
}


多维数组初始化

通过嵌套一维初始化式的方法可以产生二维数组的初始化式:

int m[5][9] = { {1, 1, 1, 1, 1, 0, 1, 1, 1},
                {0, 1, 0, 1, 0, 1, 0, 1, 0},
                {0, 1, 0, 1, 1, 0, 0, 1, 0},
                {1, 1, 0, 1, 0, 0, 0, 1, 0},
                {1, 1, 0, 1, 0, 0, 1, 1, 1} };

高维数组的初始化式以类似的方式构造.

C 提供了多种方法来缩写多维数组的初始化式


多维数组初始化

如果初始值化式不足以填充整个多维数组, 则剩余元素赋值为0.

下面初始化式只填充了数组m的前三行; 后两行将赋值为0:

int m[5][9] = { {1, 1, 1, 1, 1, 0, 1, 1, 1},
                {0, 1, 0, 1, 0, 1, 0, 1, 0},
                {0, 1, 0, 1, 1, 0, 0, 1, 0} };

多维数组初始化

如果内层列表的长度不足以填满数组的一行, 则该行中的剩余元素将初始化为0:

int m[5][9] = { {1, 1, 1, 1, 1, 0, 1, 1, 1},
                {0, 1, 0, 1, 0, 1, 0, 1},
                {0, 1, 0, 1, 1, 0, 0, 1},
                {1, 1, 0, 1, 0, 0, 0, 1},
                {1, 1, 0, 1, 0, 0, 1, 1, 1} };

多维数组初始化

内层的花括号可以 省略:

int m[5][9] = {1, 1, 1, 1, 1, 0, 1, 1, 1,
               0, 1, 0, 1, 0, 1, 0, 1, 0,
               0, 1, 0, 1, 1, 0, 0, 1, 0,
               1, 1, 0, 1, 0, 0, 0, 1, 0,
               1, 1, 0, 1, 0, 0, 1, 1, 1};

一旦编译器发现数值足以填满一行, 它就会开始填充下一行.

多维数组中省略内层大括号有风险, 额外的元素或缺失的元素会影响剩下的初始化式, 省略的花括号会引起编译警告


多维数组初始化

C99 的指定初始化式也适用于多维数组.

创建2×2单位矩阵:

double ident[2][2] = {[0][0] = 1.0, [1][1] = 1.0};

像通常一样, 所有未指定值的元素都默认为0.

常量数组

在声明数组的最开始处加上 const 可以使数组成为 常量:

const char hex_chars[] =
  {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
   'A', 'B', 'C', 'D', 'E', 'F'};

程序不应修改声明为const的数组.


常量数组

将数组声明为const的优点:

  • 表明程序不会更改数组.

  • 帮助编译器捕获错误.

  • const不仅限于数组, 也可用于任何别的变量.

  • const常用于数组的声明, 以保护在程序执行过程中不变的信息.


Coding

game-of-life.c   merge.c   insertion-sort.c   bubble-sort.c


Conway’s Game of Life

Conway’s Game of Life @ wiki

John Horton Conway (193720201937 \sim 2020)


Conway’s Game of Life

playgameoflife.com (Cellular Automata; 元胞自动机)

  • Any live cell with two or three live neighbours survives.

  • Any dead cell with three live neighbours becomes a live cell.

  • All other live cells die in the next generation.

  • All other dead cells stay dead.

游戏规则

  • 任何活细胞周围有2-3个活细胞则存活
  • 任何死细胞周围有3个活细胞则复活
  • 其他情况下细胞死亡

Conway’s Game of Life




Merge (merge.c)


Merge (merge.c)


Merge (merge.c)


Insertion Sort


Insertion Sort


Bubble Sort


Bubble Sort