1. 使用数组的好处

要计算某班的平均分数,假设该班只有10个学生。利用前面所学知识,可以有如下两种方法:

方法一:利用一个变量存储分数

#include <stdio.h>

int main(void)
{
    int score = 0;  //存储分数的变量
    int count = 10; //学生人数
    long sum = 0L;  //总分数
    float average = 0.0f; //平均分

for(int i=0; i<count; i++)
    {
        printf("Enter score: ");
        scanf("%d", &score); //从键盘读入一个分数
        sum += score; //将读入的分数加到总分数里面
    }

average = (float)sum/count; //计算平均分

printf("\nLast score is: %d", score);
    printf("\nAverage of the 10 scores entered is: %f\n", average); //输出平均分

return 0;
}

点评:该方法只保留了最后一个学生的分数,其他学生的分数全部丢失了。因此,如果我们想在此程序的基础上继续求最高分和最低分是行不通的。

下面采用第二种方法。声明10个变量来保存10个学生的分数。

方法二:利用多个变量存储分数

#include <stdio.h>

int main(void)
{
    //定义10个变量分别存储10个学生的分数
    int score0 = 0, score1 = 0, score2 = 0, score3 = 0, score4 = 0;
    int score5 = 0, score6 = 0, score7 = 0, score8 = 0, score9 = 0;

long sum = 0L;        //总分数
    float average = 0.0f; //平均分

printf("Enter the 10 scores:");

scanf("%d%d%d%d%d%d%d%d%d%d", 
        &score0, &score1, &score2, &score3, &score4,
        &score5, &score6, &score7, &score8, &score9); //输入各个学生的分数

sum = score0 + score1 + score2 + score3 + score4 + 
          score5 + score6 + score7 + score8 + score9; //计算总分

average = (float)sum/10.0f; //计算平均分

printf("\nAverage of the 10 scores entered is: %f\n", average); //输出平均分

return 0;
}

点评:该方法克服了方法1中的缺点。但如果班里有50、100或1000个学生,该方法就不切实际了,而应该使用数组。

2. 什么是数组

方法2中,声明了10个不同的变量来存放10个分数。共同点是它们都为整型变量。为了解决方法2存在这样的话,我们可以用数组对这10个变量进行统一声明:

int score[10];

以上语句声明了一个数组,数组的名称为score,它包含10个元素,每个元素的类型为整型。

数组是一组数目固定类型相同的元素组成的集合。其中,数目固定指的是元素的个数在程序运行的时候不能更改,类型相同指所有的元素具有相同的数据类型。如:全部为int, long, float, char或其它类型。

怎样访问数组里面的元素呢?我们采用数组名和元素在这个数组中的位置来访问。需要注意的是位置总是从0开始,也称为下标或索引。因此数组中的10个元素分别为:

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

其中,score[0]为数组的第一个元素,score[9]为数组的第十个元素,也即最后一个元素。如果i=2, 那么score[i]与score[2]等价,表示数组的第三个元素。

利用数组计算平均分的程序为:

方法三:利用数组存储分数

#include <stdio.h>

int main(void)
{
    int score[10];  //存储10个整型值的数组
    int count = 10; //学生人数
    long sum = 0L;  //总分数
    float average = 0.0f; //平均分

printf("Enter the 10 scores: \n");

for(int i=0; i<count; i++)
    {
        scanf("%d", &score[i]); //从键盘读入一个分数
          sum += score[i]; //将读入的分数加到总分数里面
    }

average = (float)sum/count; //计算平均分
    
    printf("The 10 scores are: ");

for(i=0; i<count; i++)
        printf("%d ", score[i]); //输出各个分数

printf("\nAverage of the 10 scores entered is: %f\n", average); //输出平均分

return 0;
}

当编译器对以上代码进行编译时,假设计算机指定数组score中的元素从地址为1000的地方开始存放。那么,存放一个元素,计算机需要给该数组多少空间呢?

由于每个元素的数据类型为int,而一般来说,int占用4个字节,所以计算机需要为每一个元素分配4个字节的存储空间。如下图所示:元素score[0]占用了编号为1000, 1001, 1002, 1003共4个字节的内存空间。score[1]占用1004 - 1007号内存空间。其余元素依此类推。

当声明数组 int score[10]; 时,计算机就为数组预留10×4=40字节的存储空间,正式的说法是分配40字节的存储空间,此时空间里面没有存放东西。对于数组中的各元素,它们的存储空间是连续的,没有间断。因此,如果知道了某个元素的存放地址,就能准确获取其它元素的存放地址。

下图是对数组声明的一些解说:

获取元素的地址类似于普通变量,它们的对比如下:

#include <stdio.h>

int main(void)
{
    int x, y, z;
    int score[3];

scanf("%d %d %d", &x, &y, &z); //输入三个值分别存入变量x, y和z中
    scanf("%d %d %d", &score[0], &score[1], &score[2]); //输入三个值分别存入数组的第1,2,3个元素中

printf("%d %d %d \n", x, y, z); //输出变量的值
    printf("%p %p %p \n", &x, &y, &z); //输出变量的地址
    printf("%d %d %d \n", score[0], score[1], score[2]); //输出数组中元素的值
    printf("%p %p %p \n", &score[0], &score[1], &score[2]); //输出数组中各元素的地址

return 0;
}

3. 二维、三维数组以及数组元素在内存中的存储方式

以下是一些一维数组的声明:

int        score[10];
char      letter[26];
float      percentage[20];
double   diameter[15];

二维数组和三维数组的声明方式如下:

/* 二维数组的声明 */
int         position[10][10];
int         wheretog[10][10];
float      coordina[52][15];
double   floor_go[60][20];

/* 三维数组的声明 */
int        position[10][20][30];
char     position[10][20][30];
double   situaion[10][20][30];

我们已经知道一维数组元素在内存中的存放方式,二维,三维在内存中是如何存放的呢?

假设声明如下的二维数组和三维数组:

int     coo[2][3];
char   pos[2][3][4];

分析:

当声明二维数组coo时,计算机分配了2×3=6个int大小的内存空间,当声明三维数组pos时,计算机分配了2×3×4=24个char大小的内存空间。以下为数组的内存分配示意图:

4. 一维、二维、三维数组的初始化

4.1 已知数组维数的初始化

(1)元素个数与初始值个数恰好相等的情况

例1:

int axis[2] = { 1, 2 };
int plane[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
int cubic[2][3][4] = { 
    {
        { 1,  2,  3,  4 },
        { 5,  6,  7,  8 },
        { 9, 10, 11, 12 } 
    },

{
        { 13, 14, 15, 16 },
        { 17, 18, 19, 20 },
        { 21, 22, 23, 24 }
    }
};

例2:

int axis[2] = { 1, 2 };
int plane[2][3] = { 1, 2, 3, 4, 5, 6 };
int cubic[2][3][4] = { 1,  2,  3,  4,  5,  6,  7,  8,  
                       9, 10, 11, 12, 13, 14, 15, 16, 
                      17, 18, 19, 20, 21, 22, 23, 24 };

(2)元素个数与初始值个数不相等的情况

例1:

/* 数组的其余位置自动设为零 */
bool axis[4] = { true, false, 1 };
char plane[2][3] = { '0', '1', '2',  3,  4 };
int  cubic[2][3][4] = { 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13 };

调试查看数组在内存中的内容如下(红色的代表数组获得的指定初值,紫色的为系统自动赋的初值):

Name        Value

+ &axis     0x0012ff4c   ""
+ &plane   0x0012ff44   "012"
+ &cubic   0x0012fee4   ""

0012FEDA  CC CC CC CC CC CC CC CC CC CC 01  烫烫烫烫烫.
0012FEE5  00 00 00 02 00 00 00 03 00 00 00  ...........
0012FEF0  04 00 00 00 05 00 00 00 06 00 00  ...........
0012FEFB  00 07 00 00 00 08 00 00 00 09 00  ......... .
0012FF06  00 00 0A 00 00 00 0B 00 00 00 0C  ...........
0012FF11  00 00 00 0D 00 00 00 00 00 00 00  ...........
0012FF1C  00 00 00 00 00 00 00 00 00 00 00  ...........
0012FF27  00 00 00 00 00 00 00 00 00 00 00  ...........
0012FF32  00 00 00 00 00 00 00 00 00 00 00  ...........
0012FF3D  00 00 00 00 00 00 00 30 31 32 03  .......012.
0012FF48  04 00 CC CC 01 00 01 00 00 00 00  ..烫.......

4.2 未知数组维数的初始化

根据数组元素在内存中的分配规则可知,数组的某个维的大小可以省略,且这个维只能是数组最左边的一个维,数组在声明的同时还必须初始化。见下例:

//正确的维大小缺省
bool condition[ ] = { true, false, 1 }; //相当于condition[3]
char plane_a[ ][3] = { '0', '1' }; //相当于plane_a[1][3],数组第一个元素为字符'0',其它为0
char plane_b[ ][3] = { '0', '1', '2', '3' }; //相当于plane_b[2][3]
int   cubic_a[ ][3][4] = { 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12 }; //相当于cubic_a[1][3][4]
int   cubic_b[ ][3][4] = { 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13 }; //相当于cubic_b[2][3][4]

//错误的维大小缺省
//char plane_a[ ][ ] = { 1, 2, 3 };
//char plane_a[1][ ] = { 1, 2, 3 };
//int  cubic_a[ ][ ][ ] = { 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12 };
//int  cubic_a[ ][ ][4] = { 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12 };
//int  cubic_a[ ][3][ ] = { 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12 };
//int  cubic_a[2][3][ ] = { 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12 };
//int  cubic_a[2][ ][ ] = { 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12 };
//int  cubic_a[2][ ][4] = { 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12 };

C语言详解 - 数组相关推荐

  1. 克鲁斯卡尔算法c语言,Kruskal算法(一)之 C语言详解

    最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树. 例如,对于如上图G4所示的连通网可以有多棵权值总和 ...

  2. c++指针详解_c语言详解sizeof

    一.sizeof的概念 sizeof是C语言的一种单目操作符,如C语言的其他操作符++.--等. 它并不是函数. sizeof操作符以字节形式给出了其操作数的存储大小. 操作数可以是一个表达式或括在括 ...

  3. 有向图邻接矩阵c语言编程,邻接矩阵有向图(一)之 C语言详解

    本章介绍邻接矩阵有向图.在"图的理论基础"中已经对图进行了理论介绍,这里就不再对图的概念进行重复说明了.和以往一样,本文会先给出C语言的实现:后续再分别给出C++和Java版本的实 ...

  4. 邻接矩阵用c语言,邻接矩阵无向图(一)之 C语言详解

    本章介绍邻接矩阵无向图.在"图的理论基础"中已经对图进行了理论介绍,这里就不再对图的概念进行重复说明了.和以往一样,本文会先给出C语言的实现:后续再分别给出C++和Java版本的实 ...

  5. c语言霍夫曼函数,使用C语言详解霍夫曼树数据结构

    1.基本概念 a.路径和路径长度 若在一棵树中存在着一个结点序列 k1,k2,--,kj, 使得 ki是ki+1 的双亲(1<=i 从 k1 到 kj 所经过的分支数称为这两点之间的路径长度,它 ...

  6. smali语言详解之一般/构造方法(函数)的声明与返回值关键字

    smali语言详解之一般/构造方法(函数)的声明与返回值关键字 一. smali语言的方法声明格式 .method与.end method成对出现,类似于java中的花括号 1.1.非静态的一般方法 ...

  7. smali语言详解之字段的声明(变量、常量)

    smali语言详解之字段的声明(变量.常量) 一.smali语言的字段声明格式 1.1.非静态变量 .field 权限修饰关键字 变量名:变量类型的全包名路径或与java对应的数据类型关键字 1.2. ...

  8. watch深度监听数组_vue watch普通监听和深度监听实例详解(数组和对象)

    vue watch普通监听和深度监听实例详解(数组和对象) 下面通过一段代码给大家介绍vue watch的普通监听和深度监听,具体代码如下所示: var vm=new Vue({ data:{ num ...

  9. Drools 规则语言详解(上)

    http://www.blogjava.net/guangnian0412/archive/2006/06/09/51574.html http://www.blogjava.net/guangnia ...

最新文章

  1. 谷粒商城学习笔记——第一期:项目简介
  2. 算法小记 · 字符串翻转
  3. 在Windows下安装chromedriver
  4. Windbg/KD驱动调试点滴–将平时调试的一些小方法共享给大家 --------- 转
  5. DIY—USB学习板设计以及驱动开发
  6. 《Web Hacking 101》中的链接整理
  7. Java编程时如何节省内存,效率高
  8. 【Windows 8 Store App】学习二:ResourceLoader
  9. scala map方法源码
  10. UnicodeMath编码教程
  11. 一些CFD名词缩写的含义(持续更新中)
  12. ffplay的音视频同步分析
  13. php 关于token、签名、加密的一点理解
  14. Spring Cloud:服务消费(Ribbon)【Dalston版】
  15. 我是如何创建学校免费上网账号上网的
  16. Python札记6_字典1
  17. java.lang.StringIndexOutOfBoundsException
  18. Pytorch介绍以及基本使用
  19. Recovering Functional Mechanical Assemblies from Raw Scans
  20. 兼职程序员可以从什么平台接私活?

热门文章

  1. Xmind笔记之HTML5+CSS
  2. MSTAR GAMMA
  3. .net core 使用 codegenerator 创建默认CRUD代码
  4. Fennec Alpha 1 for Windows Mobile available
  5. linux暂停线程和恢复,是否有可能在Linux [暂停]中检测到线程已进行上下文切换?...
  6. linux 打开文件表 文件描述符,文件描述符-mjsc1023-ChinaUnix博客
  7. FPGA自定义UART传输(包含:matlab数据拆分)
  8. android中关于手机屏幕的相关操作(获取屏幕的宽高等操作)
  9. 对家庭网络设备行业的理解
  10. 转发一个深度、实用的技术帖——实现ADM3251E与3.3V系统的RS-232接口隔离