目录

  • 1 第一章 C语言简介
    • 1.1 C语言前世今生
    • 1.2 主流开发环境介绍
    • 1.3 第一个小程序解析
    • 1.4 常见编译错误
    • 1.5 章节知识点小结
  • 2 算法基础
    • 2.1 算法-程序的灵魂
    • 2.2 算法的描述-流程图
  • 3 数据类型与运算符
    • 3.1 数据描述
    • 3.2 运算符和表达式1
    • 3.3 运算符和表达式2
    • 3.4 章节知识点小结
  • 4 顺序结构程序设计
    • 4.1 输入和输出
    • 4.2 顺序结构程序设计
    • 4.3 章节知识点小结
  • 5 选择结构程序设计
    • 5.1 关系运算符和关系表达式
    • 5.2 逻辑运算符和逻辑表达式
    • 5.3 if语句
    • 5.4 条件运算符
    • 5.5 switch语句
    • 5.6 章节知识点小结
  • 6 循环结构程序设计
    • 6.1 while循环结构
    • 6.2 do_while循环结构
    • 6.3 for循环结构
    • 6.4 循环的嵌套
    • 6.5 break语句和continue语句
    • 6.6 章节知识点小结
  • 7 数组
    • 7.1 一维数组
    • 7.2 二维数组
    • 7.3 字符数组
    • 7.4 章节知识点小结
  • 8 函数
    • 8.1 子程序设计
    • 8.2 函数定义
    • 8.3 函数的调用
    • 8.4 局部变量和全局变量
    • 8.5 参数传递
    • 8.6 函数递归调用
    • 8.7 章节知识点小结
  • 9 指针
    • 9.1 指针的基本概念
    • 9.2 指针变量的定义及引用
    • 9.3 通过指针引用数组元素
    • 9.4 指向多维数组的指针和指针变量
    • 9.5 用指向数组的指针作函数参数
    • 9.6 指针与字符串
    • 9.7 函数指针和指针函数
    • 9.8 章节知识点小结
  • 10 用户自己建立数据类型
    • 10.1 定义和使用结构体变量
    • 10.2 使用结构体数组
    • 10.3 结构体指针
    • 10.4 章节知识点小结
  • 11 编译预处理
    • 11.1 宏定义预处理
    • 11.2 文件包含预处理
    • 11.3 条件编译预处理
    • 11.4 章节知识点小结
  • 12 文件
    • 12.1 文件的基本知识
    • 12.2 文件的基本操作
    • 12.3 章节知识点小结
二维数组


1二维数组的定义

定义形式:类型说明符  数组名[常量表达式1][常量表达式2] ;

类型说明符:数组的类型;

数组名:遵循标志符的命名规则;

其中常量表达式1表示行数,常量表达式2 表示列数。

例如: float  a[3][4];       

表示: a为3行4列的二维实型数组,共包含12个数组元素。

a[0][0] , a[0][1], a[0][2] , a[0][3]    第一行的4个元素

a[1][0] , a[1][1], a[1][2] , a[1][3]    

a[2][0] , a[2][1] , a[2][2] , a[2][3]   

注意:

1)两个下标要分别用中括号括起来。不能写成float  a[3,4];

2)常量表达式只能是常量,不能是变量。int  b[m][n]; 


2、数组元素的引用

引用二维数组元素的形式为:数组名[下标][下标]  

下标可以是整型常量或整型表达式。

在使用数组元素时,下标应在定义的范围内。

常出现的错误如下:

int a[3[4];      

a[3][4]=3; 




3、二维数组的初始化

可在定义数组的同时对二维数组元素进行初始化,形式:

数据类型 数组名 [常量1][常量2]={初始化数据};

也可以给全部数组元素赋初值,或给部分元素赋初值。

如果是给全部数组元素赋初值,两种形式:

1)分行赋初值。如:

inta[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};

2)不分行,也就是将所有数据放在一个大括号内。如:

inta[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};  

注意:对全部元素赋初值时,第一维的长度可以不指定,但第二维的长度不能省。

也可对部分元素赋初值:

inta[3][4]={ {1},{5},{9} };  

对每一行第一列的元素赋初值,其他元素为0;

 

4、数组元素在内存中的存放

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

定义a为3行3列的整型数组,共包含9个数组元素,每个数组元素占4个字节,给a数组共分配36个字节,在内存中按行存放,首先存放第一行的3个数组元素的值,然后存放第二行的3个数组元素的值……。


5、二维数组的应用

1)输出各数组元素

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

int  i,j;                            用i控制行数,j控制列数

for(i=0;i<3;i++)      

  { for(j=0;j<3;j++)

       printf(“%4d”,a[i][j]);     引用数组元素,每输出4个数换行

   printf(“\n”);}                

分析程序段结果:

for(i=0;i<3;i++)

for(j=0;j<3;j++)  

          printf("%4d",a[j][i]);    引用数组元素,j控制行号,i控制列号   

思考: 如何输出上三角矩阵?

 

2)已知4个学生3门课的成绩,求:每个学生的平均分?每门课程的平均分?

    首先定义数组:

{ float a[4][3]={{80,75,68},{78,90,83},{55,64,68},{60,72,76}};

  int i,j;            用i控制学生人数,j控制课程数

i=0,表示第一个学生,i从0-3变化

j=0,表示第一门课程,j从0-2变化

先求每个学生的平均分。要求每个学生的平均分,首先要求出每个学生的总分再除3;总分用sum来存放,定义sum:

float sum=0;

 for(i=0;i<4;i++)            i控制学生人数,共4个学生

{ sum=0;                     不给出该语句,结果出错

  for(j=0;j<3;j++)           每个学生有3门成绩

         sum=sum+a[i][j];  

printf("%.1f\n",sum/3);}  计算第二个学生的总分时,把第一个学生的总分也加入

 

求每门课程的平均分:

有3门课程,每门课程有4个成绩,先从第一门课程开始,将4个成绩相加后,除以4就得到该课程的平均分,然后再求第二门课程……,一共3列,所以外层循环控制列号

 for(j=0;j<3;j++)         j控制课程数,3门课程

 { sum=0;

  for(i=0;i<4;i++)        i控制学生人数,共4个学生

         sum=sum+a[i][j];

  printf("%d :%.1f\n",j+1,sum/4);

 }

总结:对于有行有列的数据,如表格、矩阵是用二维数组来存放。对某个学生的某个成绩,用a[i][j]的形式,可以很直观地就知道代表的是第i+1个学生的j+1门课程的成绩。

 

思考题:输出杨辉三角的前6行数据。

 

1

1   1

1   2   1

1   3   3   1

1   4   6   4   1

1   5   10  10  5  1


  

规律:

(1)各行第一个数都是1;

(2)各行最后一个数都是1;

(3)其余各数是上一行同列和前一列两个数之和。


*EASY图形编程.二维数组的应用

程序要求:屏幕上有 16x8 的方格,按随机顺序在将 1128 的数字写到每个格子上。
考虑:我们需要记录这些格子,哪些写过数字,哪些没写数字。
我们用一个二维数组来记录:
bool cell[16][8];

写过数字后,我们将相应数组的值设置为 true,看程序:

#include <graphics.h>
#include <stdlib.h>
#include <conio.h>
#include <stdio.h>
#include <time.h>

void main()
{
    int x, y;
    char num[4];

   srand( (unsigned)time(NULL) );

   initgraph(640, 480);

    // 画格子
    for (x=0; x<=480; x+=30)
        for (y=0; y<=240; y+=30)
        {
            line(x, 0,x, 240);
            line(0, y,480, y);
        }

getch();

    // 定义二维数组
    bool cell[16][8];
    //
初始化二维数组
    for (x=0; x<16; x++)
        for (y=0; y<8; y++)
            cell[x][y] =false;

    // 在每个格子上写数字
    for (int i=1; i<=128; i++)
    {
        //
找到一个没有写数字的随机格子
        do
        {
            x = rand() %16;
            y = rand() %8;
        }while(cell[x][y] == true);

       // 标记该格子已用
        cell[x][y] = true;

       // 在格子上写数字
        sprintf(num, "%d", i);
        outtextxy(x * 30+5, y * 30+10, num);
    }

   getch();
    closegraph();
}

以上几个范例,无论从实用上还是美观上都很差,我只是希望大家能举一反三,写出更多漂亮的程序。 

[作业]
1.
回顾一下上一节课的作业,绘制一个任意反弹的球。这次,将程序修改成屏幕上有 10 个任意反弹的球。
2.
如果反弹的不是球,而是点呢?再将某些点之间用线连起来,就可以做一个屏保变幻线的程序了。试试做一个。
3.
涂格子(也叫点灯)的游戏。详细规则可以试玩网上的各种版本。

以下作业,有时间就写。因为讲完这 12 节课,可以写出很多游戏了,所以可能会感觉作业一下子多了许多。
4.
写个俄罗斯方块。