数组
(博主用的visual studio编译器)
首先我们要明白什么是数组?
引入一个例子:用C语言程序设计 计算一个班35名学生课程的平均成绩。
解析:1.把35个成绩相加再除以35得到平均成绩
2.用35个变量存储35个成绩,成绩相加再除以35得到平均成绩
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int i;
float s, a, c=0;
for (i = 0; i <= 35; i++)
{
scanf_s("%f", &s);
c = c + s;
}
a = c / 35.0;
printf("a=%f", a);
}
总结这样会浪费很多的存储空间。而且35个成绩最后只保留了一个,数据变化的话,就要重新做循环。这样就让程序变得很复杂繁琐。而且他们有如下特点:
35个成绩属于同一数据类型
它们之间相互关联
代表每一个学生的成绩
变量名前面一样
后面的序号不同
所以C语言给他制造了一种数据类型:数组:
可以存储同一类型的多个数据,用下标来区分每一个数据。
1.一维数组
一维数组也称为向量
先定义数组---确定数组的名称、数组的类型、数组元素的个数,编译器根据定义语句为其分配内存空间。
一维数组的定义
一维数组定义的一般形式为:
数据类型 数组名[常量表达式];
注意:
数据类型:是数组元素的数据类型。
数组名: 遵循C语言标识符规则。
常量表达式:表示数组中有多少个元素,即数组的长度。可以是整型常量、整型常量表达式或符号常量,但不允许出现变量。
这里我写一个经典数组程序:数列反向
#include<stdio.h>
int main()
{
int arr[10] = {0};
for(int i = 9;i>=0;i--)
{
scanf("%d",&arr[i]);
}
for(int i = 0;i<10;i++)
{
printf("%d ",arr[i]);
}
return 0;
}
1.1下标索引
程序:检查数中重复出现的数字
#include<stdio.h>
#include<stdbool.h>
int main()
{
bool digit_seen[10] = { false };
int digit;
long n;
printf("Enter a number:");
scanf("%d", &n);
while (n > 0)
{
digit = n % 10;
if (digit_seen[digit])
break;
digit_seen[digit] = true;
n / 10;
}
if (n > 10)
printf("Repeated digit\n");
else
printf("NO repeatted digit\n");
return 0;
}
程序采用由布尔值构成的数组跟踪数中出现的数字。名为digit_ _seen 的数组元素的下标
索引为0~9,对应于10个可能的数字。最初的时候,每个数组元素的值都为假。( digit_ seen
的初始化器为{false},这实际上只初始化了数组的第一个元素。 但是,编译器会自动把其他
元素初始化为0,而0跟false是相等的。)
当给定数n时,程序一次一个地检查n的数字,并且把每次检查的数字存储在变量digit
中,然后用这个数字作为数组digit_ seen 的下标索引。如果digit_ seen[digit]为真, 那么
表示digit至少在n中出现了两次。另- -方面,如果digit_ seen[digit]为假,那么表示aigit
之前未出现过,因此程序会把digit_ seen [digit]设置为真并且继续执行。
1.2数组初始化
像其他变量一样,数组也可以在声名时获得一个初始值,最常见的就是用一个花括号括起来的常量表达式如:
int a[10]={1,2,3,4,5,6,7,8,9,10};
但如里初始化的位数比数组短,那么剩余元素则会赋值为0:
int a[8]={1,2,3,4};
/*initial value of a is {1,2,3,4,0,0,0,0}*/
注意:1、初始化完全为空是非法的
2、初始化比数组长同样非法,但如果给定了初始化,则可以省略数组长度。如:
int a[]={1,2,3,4,5,6,7,,8,9,0};
1.3指示器
经常会有这样的情况,数组中只有相对较少元素需要进行显式的初始化,而大部份元素用默认值如:
int a[10]={1,0,0,0,4,0,0,0,78,0};
但是我想数组元素下标2为1,5为4,9为78而其它元素为0,这是一个小数组,可如果它是一个2000的数组呢?
而C99中的指示器可以用于解决这一个问题,用指示器可写为:
int a[10]={[2]=1,[5]=4,[9]=78};而且这里是不用考虑元素位置的,可以说是非常好用
1.4数组中的sizeof运算符
运算符sizeof可以确定数组的大小(字节数)。如果数组a有10个整数,那么sizeof (a)
通常为40 ( 假定每个整数占4字节)。
还可以用sizeof来计算数组元素(如a[0] )的大小。用数组的大小除以数组元素的大小
可以得到数组的长度:
sizeof(a) / sizeof(a[0])
当需要数组长度时,一些程序 员采用上述表达式。例如,数组a的清零操作可以写成如下形式:
for(i=0;i<sizeof(a)/sizeof (a[0]) ; i++)
a[i] = 0;
不过有些编译器会对其提出警告,如要避免可将ⅰ类型改为t
2.多维数组
数组可以有任意维数,例如下方一个二维数组。可以理解一数组为线二维数组为面例如数学中的矩阵
int m [10] [7]; 是一个10行7列的数组
注意:千万不要写成m[10,7]的形式,c语言会将逗号看作运算符,因此m[10,7]就等同于m[7]
就像 for 循环和一维数组紧密结合一样,嵌套的 for 循环是处理多维数组的理想选择。例如,思考用作单位矩阵的数组的初始化问题。(数学中,单位矩阵在主对角线上的值为1,而其他地方的值为 0,其中主对角线上行、列的索引值是完全相同的。) 我们需要以某种系统化的方式访问数组中的每一个元素。一对嵌套的 for 循环可以很好地完成这项工作--一个循环遍历每一行,另一个循环遍历每一列:
#include<stdio.h>
#define a 10
int main()
{
double ident[a][a];
int row, col;
for (row = 0; row < a; row++)
for (col = 0; col < a; col++)
if (row == col)
ident[row][col] = 1.0;
else
ident[row][col] = 0.0;
}
2.1常量数组
无论1维数组还是多维数组,都可以通过在声明的最开始处加上单词const而成为“常量:
const char asd[]={'0','1','3','4','5'};
程序不应该对声明为const的数组进行修改,编译器能够检测到直接修改某个元素的意图
把数组声明为const有两个主要的好处。它表明程序不会改变数组,这对以后阅读程序
人可能是有价值的信息。它还有助于编译器发现错误一const 会告诉编译器,我们不打期
改数组。
下面我们为了更了解二维数组和常量数组的使用方法而写一段发牌游戏代码。:
发牌游戏
如何编写这样一个程序看上去并不直观。
下面将其分两个问题并分别处理这两个问题。
1、如何从一副牌中随机抽取纸牌呢?
2、如何避免两次抽到同一张牌?
我们可以采用 一些C语音的库函数,time函数,返回当前的时间,用一个数表示。
sand函数初始化c语言的随机数生成器。通过把time函数的返回值传递给函数srand可以避免程序在每次运行时发同样的牌。
rend函数在每次调用时会产生一个看似随机的数。
通过采用运算符%,可以缩放rand函数的返回值,使其落在0-3 (用于表示牌的花色)的范围内,或者是落在0~12 (用于表示纸牌的点数)的范围内。
而为了避免两次都拿到同一张牌,则需要记录已经选择过的牌。为此,程序将采用一一个名为in_hand的二维数组,数组有4行(每行表示一种花色)和13列(每列表示一一个点数)。换句话说,数组中的每个元素对应着52张纸牌中的一-张。在程序开始时,所有数组元素都为假。每次随机抽取一张纸牌时 ,将检查数组in_hand中的对应元素为真还是为假。如果为真,那么就需要抽取其他纸牌;如果为假,则把true存储到与这张纸牌相对应的数组元素中,以提醒我
们这张纸牌已经抽取过了。
一旦证实纸牌是“新”的(还没有选取过).就需要把牌的点教和花色数值朝译成字符,然后显示出来,为了把纸牌的点数和花色翻译成字符型格式,(一个用于纸牌的点数,另一个用于纸牌的花色。)。但这两个字符数组在程序执行期间不会发生改变,因此也可以把它们声明为const。
#include<stdbool.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define NUM_SUITS 4
#define NUM_RANKS 13
int main()
{
bool in_hand[NUM_SUITS][NUM_RANKS] = { false };
int num_cards, rank, suit;
const char rank_code[] = { '2','3','4','5','6','7','8','9','t','j','q','k','a' };
const char suit_code[] = { 'c','d','h','s' };
srand((unsigned)time(NULL));
printf("Enter number of cards in hand:");
scanf("%d", & num_cards);
printf("Your hand:");
while (num_cards > 0)
{
suit = rand() % NUM_SUITS;
rank = rand() % NUM_RANKS;
if (!in_hand[suit][rank])
{
in_hand[suit][rank] = true;
num_cards--;
printf(" %c%c", rank_code[rank], suit_code[suit]);
}
printf("\n");
}
return 0;
}