我家小朋友正在学C++数组,所以呢自己就边学边写点体会给他看,就以一个打印年历的实例帮他更好地理解和掌握数组。刚好在2021年元旦写完,现发出来与C初学者分享一下,有误之处敬请谅解。
声明一个数组的格式: type array[size];
#include
int main(void)
{
int a[5]={1,2,3,4,5};
char b[]="hello";
cout<
运行结果:
注1:结束符在定义中不写出来的,但也可以写成:
char b[]={"hello"}; //不省掉{}
char b[]={‘h’,’e’,’l’,’l’,’o’,’\0’};
看上图运行结果,’\0’打印出来是空的,但它不是空格‘ ’。
注2:数组的下标从0开始计!
int a[5]={1,2,3,4,5};
即: int a[5];
a[0]=1; a[1]=2; a[2]=3; a[3]=4; a[4]=5; //最后一个是a[4]
int b[6]= "hello";
即: int b[6];
a[0]=’h’; a[1]=’e’; b[2]=’l’; …; b[5]=’\0’; //最后一个是b[5]
也就是array[size]的最后一个元素是array[size-1]。
数组可以在声明时直接赋值,也可以一个一个地赋值。
如果数组的值有某种规律就可以用循环来赋值:
int a[30];
for (i=0;i<30;i++) a[i]=i+1;
//把1~30赋值给a[0]~a[29]
如下,定义一个3行5列的整型二维数组int a[3][5];
它对应的元素为:
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]
定义完数组后,一般就用二重循环来给它赋值。
#include
int main(void)
{
int a[3][5];
int i,j;
//赋值
for (i=0;i<3;i++)
for (j=0;j<5;j++){
a[i][j]=j+1+i*5;
}
//列表
for (i=0;i<3;i++)
for (j=0;j<5;j++){
cout<
运行结果如下:
下来我们定义一个6行7列的二维数组存放每个月的日期,为什么是6行,看下面系统时间的截图就知道了。
二维数组的赋值与输出:
#include
int main(void)
{
int month[6][7];
int i, j;
//赋值
for (i=0;i<6;i++)
for (j=0;j<7;j++)
month[i][j]=j+1+i*7;
//列表
for (i=0;i<6;i++)
for (j=0;j<7;j++){
cout<
运行结果如下:
每月的一号不可能都是星期一,所以我们用基姆拉尔森公式来定义一个星期函数WeekDay(),用它来计算每月第一天的星期数。
int WeekDay(int y,int m,int d)
{
if(m<3)--y,m+=12; //一、二月看作上年的13、14月
return(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7+1;
}
函数返回整数1~7,对应星期一到星期日。
#include
int WeekDay(int y,int m,int d)
{
if(m<3)--y,m+=12; return(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7+1;
}
int main(void)
{
int month[6][7];
int i, j;
int w;
w = WeekDay(2020,1,1); //计算2020年元旦的星期数。
//赋值
for (i=0;i<6;i++)
for (j=0;j<7;j++){
month[i][j]=j+1+i*7;
month[i][j]-=w-1; //赋值后减去w再加1。
// 上两行即month[i][j]=j+1+i*7-w+1;
}
//列表
for (i=0;i<6;i++)
for (j=0;j<7;j++){
cout<
运行结果如下:
正式使用时,把小于1和大于月底日期的数字不显示即可。所以,又要增加一个数组存放一年12个月的天数。
int days[12]={31,28,31,30,31,30,31,31,30,31,30,31};
另还要判断是否闰年,如闰年则置二月天数days[1]为29。
int y = 2000;
if (y%4==0&&y%100!=0||y%400==0) days[1]=29;
输出指定年份年历表的代码如下:
#include
#include //调用DOS清屏命令cls
int WeekDay(int y,int m,int d)
{
if(m<3)--y,m+=12;
return(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7+1;
}
int main(void )
{
char *s[]={"一","二","三","四","五","六","日","\n"}; //表头
int days[12]={31,28,31,30,31,30,31,31,30,31,30,31};
int i,j,k,y,w;
int month[6][7];
for(;;){
cout<<"输入年份(0退出):";
cin>>y;
system("CLS");
cout<<"你输入的年份是:"<days[k]) break;
if (month[i][j]>0) //大于0输出,反之输出3个空格
cout<
运行结果如下:
体会一下源代码中何时添加回车,何时输出空格,都用if来判断输出。
接下来就做双排的年历,这时数组需要6行14列,可以看作并排了两个7列的表格,用2个循环分别来赋值。
#include
int main(void)
{
int i,j;
int month[6][14];
for (i=0;i<6;i++)
for (j=0;j<7;j++)
month[i][j]=j+1+i*7;
for (i=0;i<6;i++)
for (j=7;j<14;j++)
month[i][j]=j-6+i*7;
for (i=0;i<6;i++)
for (j=0;j<14;j++){
cout<
把上面的置数部分的用了2个循环,可以从函数main()中拿出来另外写成一个函数initMon()用来初始化数组。此时二维数组month[][]是全局变量要放在所有函数的前面。源代码如下:
#include
int month[6][14];
void initMon(void)
{
int i,j;
for (i=0;i<6;i++)
for (j=0;j<7;j++)
month[i][j]=j+1+i*7;
for (i=0;i<6;i++)
for (j=7;j<14;j++)
month[i][j]=j-6+i*7;
} //end initMon()
int main(void)
{
int i,j;
initMon();
for (i=0;i<6;i++)
for (j=0;j<14;j++){
cout<
执行结果如下:
上图中并排两个月份的首日需要调用WeekDay()让它们分别移位,所以初始化函数initMonth()要引进2个月份参数;另外新加了一个三目运算符(true or false)?x:y,条件为真取值x反之取值y。
void initMonth(int m1, int m2)
{
int i,j,w1,w2;
w1=WeekDay(year,m1,1);
w2=WeekDay(year,m2,1);
days[1] = (year%4==0&&year%100!=0||year%400==0) ? 29:28;
for (i=0;i<6;i++)
for (j=0;j<7;j++){
month[i][j]=j+1+i*7;
month[i][j]-=w1-1;
if (month[i][j]>days[m1-1]) month[i][j]=0;
}
for (i=0;i<6;i++)
for (j=7;j<14;j++){
month[i][j]=j-6+i*7;
month[i][j]-=w2-1;
if (month[i][j]>days[m2-1]) month[i][j]=0;
}
}
初始化月份数组后,用多重循环控制行列来输出各个月份,输出时把小于1的数字都用空格替换。月份有两种排列,横排或竖排。特别要注意的是把握好循环变量与各行各列的月份数、日期数之间的函数关系。完成源代码如下:
#include
#include
#include //调用system()函数
using namespace std;
int year;
int month[6][14];
int days[12]={31,28,31,30,31,30,31,31,30,31,30,31};
int WeekDay(int y, int m, int d)
{
if(m<3)--y,m+=12; //1、2月看作上年的13、14月
return(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7+1;
//基姆拉尔森公式,返回1~7对应星期一~星期日
}
void initMonth(int m1, int m2)
{
int i,j,w1,w2;
w1=WeekDay(year,m1,1);
w2=WeekDay(year,m2,1);
days[1]=(year%4==0&&year%100!=0||year%400==0)?29:28;
for (i=0;i<6;i++)
for (j=0;j<7;j++){
month[i][j]=j+1+i*7;
month[i][j]-=w1-1;
if (month[i][j]>days[m1-1]) month[i][j]=0;
}
for (i=0;i<6;i++)
for (j=7;j<14;j++){
month[i][j]=j-6+i*7;
month[i][j]-=w2-1;
if (month[i][j]>days[m2-1]) month[i][j]=0;
}
//大于月底日期的数字都置为0;
//每月第一天之前的都设成小于或等于0
}
void Row0Col(void)
{
system("cls");
cout<<"你输入的年份是:"<>year;
if (year<1900){
system("cls");
cout<<"重新输入年份(年份数>=1900,0则退出):";
}
if (year==0) return 0;
} while(year<1900);
Row0Col();
do{
cin>>r;
if(r!=1||r!=2) Row0Col();
if(r==1||r==2) cout<0)
cout<0)
cout<
运行结果如下:
代码稍作修改,即可得到每一行排列3个月的输出。月份数组变更为6行21列,initMonth()同时初始化三个月份,同时调整一下循环变量与月份数组下标的关系。完整代码如下:
#include
#include
#include //调用system()函数
using namespace std;
int year;
int month[6][21];
int days[12]={31,28,31,30,31,30,31,31,30,31,30,31};
int WeekDay(int y, int m, int d)
{
if(m<3)--y,m+=12; //1、2月看作上年的13、14月
return(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7+1;
//基姆拉尔森公式,返回1~7对应星期一~星期日
}
void initMonth(int m1, int m2, int m3)
{
int i,j,w1,w2,w3;
w1=WeekDay(year,m1,1);
w2=WeekDay(year,m2,1);
w3=WeekDay(year,m3,1);
days[1]=(year%4==0&&year%100!=0||year%400==0)?29:28;
for (i=0;i<6;i++)
for (j=0;j<7;j++){
month[i][j]=j+1+i*7;
month[i][j]-=w1-1;
if (month[i][j]>days[m1-1]) month[i][j]=0;
}
for (i=0;i<6;i++)
for (j=7;j<14;j++){
month[i][j]=j-6+i*7;
month[i][j]-=w2-1;
if (month[i][j]>days[m2-1]) month[i][j]=0;
}
for (i=0;i<6;i++)
for (j=14;j<21;j++){
month[i][j]=j-13+i*7;
month[i][j]-=w3-1;
if (month[i][j]>days[m3-1]) month[i][j]=0;
}
}
void Row0Col(void)
{
system("cls");
cout<<"你输入的年份是:"<>year;
if (year<1900){
system("cls");
cout<<"重新输入年份(年份数>=1900,0则退出):";
}
if (year==0) return 0;
} while(year<1900);
Row0Col();
do{
cin>>r;
if(r!=1||r!=2) Row0Col();
if(r==1||r==2) cout<0)
cout<0)
cout<
运行结果如下:
int month[6][7][12];
可以把它看作12个二维数组month[6][7]联立在一起,想像成一个12页的PPT文档,每页上都有一个6行7列的表格。
最后,我们来用三维数组来输出年历,先用一个三重循环来初始化全年的日期,然后按照排版的需求来输出这个三维数组。
先看一下未屏蔽掉数组中非正整数的代码:
#include
#include
using namespace std;
int month[6][7][12];
int days[12]={31,28,31,30,31,30,31,31,30,31,30,31};
int WeekDay(int y, int m, int d)
{
if(m<3)--y,m+=12; //1、2月看作上年的13、14月
return(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7+1;
//基姆拉尔森公式,返回1~7对应星期一~星期日
}
void initMonth(int year)
{
int i,j,m,w;
const char *s[]={"一","二","三","四","五","六","日","\n"};
days[1]=(year%4==0&&year%100!=0||year%400==0)?29:28;
for (m=0;m<12;m++){
w=WeekDay(year,m+1,1);
for (i=0;i<6;i++){
for (j=0;j<7;j++){
month[i][j][m]=j+1+i*7;
month[i][j][m]-=w-1;
if (month[i][j][m]>days[m]) month[i][j][m]=0;
}
}
}
}
int main(void)
{
int i,j,m;
initMonth(2021);
cout<<2021<<"年:"<
运行结果如下:
用了三维数组后一年12个月的日期初始化一次完成,再用再几个循环控制输出即可。3列横排的代码如下:
#include
#include
using namespace std;
#include //调用system()函数
int month[6][7][12];
int days[12]={31,28,31,30,31,30,31,31,30,31,30,31};
int WeekDay(int y, int m, int d)
{
if(m<3)--y,m+=12; //1、2月看作上年的13、14月
return(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7+1;
//基姆拉尔森公式,返回1~7对应星期一~星期日
}
void initMonth(int year)
{
int i,j,m,w;
days[1]=(year%4==0&&year%100!=0||year%400==0)?29:28;
for (m=0;m<12;m++){
w=WeekDay(year,m+1,1);
for (i=0;i<6;i++){
for (j=0;j<7;j++){
month[i][j][m]=j+1+i*7;
month[i][j][m]-=w-1;
if (month[i][j][m]>days[m]) month[i][j][m]=0;
}
}
}
}
int main(void)
{
int i,j,k,w,m,year;
const char *s[]={"一","二","三","四","五","六","日"};
for(;;){
cout<<"输入年份(0退出):";
do {
cin>>year;
if (year<1900){
system("cls");
cout<<"重新输入年份(年份数>=1900,0则退出):";
}
if (year==0) return 0;
} while(year<1900);
system("cls");
cout<<"你输入的年份是:"<9) cout<<"\b";
//修正2位数月份的宽度,"\b"为退格键BackSpace
}
cout<0) //非正数用空格替代
cout<
运行结果如下:
也可以将上述代码稍作修改,改为用竖排的格式输出年历,自己动手试试吧。(全文完)