C++陣列在年曆列印中的運用
C++陣列在年曆列印中的運用
我家小朋友正在學C++陣列,所以呢自己就邊學邊寫點體會給他看,就以一個列印年曆的例項幫他更好地理解和掌握陣列。剛好在2021年元旦寫完,現發出來與C初學者分享一下,有誤之處敬請諒解。
一維陣列的定義:
宣告一個陣列的格式: type array[size];
#include <iomanip.h>
int main(void)
{
int a[5]={1,2,3,4,5};
char b[]="hello";
cout<<sizeof(int)<<endl; //變數int佔用的位元數
cout<<sizeof(a)<<endl; //陣列a[]佔用的位元數
cout<<"陣列a的元素個數:"<<sizeof(a)/sizeof(int)<<endl;
cout<<sizeof(char)<<endl; //變數int佔用的位元數
cout<<sizeof(b)<<endl; //陣列b[]佔用的位元數
cout<<"陣列b的元素個數:"<<sizeof(b)/sizeof(char)<<endl;
for (i=0;i<6;i++) cout<<b[i]<<"|"; cout<<endl;
//列印陣列b[],最後一個字元是'\0',字串結束符。
return 0;
}
執行結果:
注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 <iomanip.h>
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<<setw(5)<<a[i][j];
if (j==4) cout<<endl;
}
//setw(x)函式設定輸出的寬度,並且右對齊。
}
執行結果如下:
下來我們定義一個6行7列的二維陣列存放每個月的日期,為什麼是6行,看下面系統時間的截圖就知道了。
二維陣列的賦值與輸出:
#include <iomanip.h>
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<<setw(3)<<month[i][j];
if (j==6) cout<<endl;
}
return 0;
}
執行結果如下:
每月的一號不可能都是星期一,所以我們用基姆拉爾森公式來定義一個星期函式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 <iomanip.h>
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<<setw(3)<<month[i][j];
if (j==6) cout<<endl;
}
return 0;
}
執行結果如下:
正式使用時,把小於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 <iomanip.h>
#include <stdlib.h> //呼叫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<<"你輸入的年份是:"<<y<<endl;
if (y==0) return 0;
if (y%4==0&&y%100!=0||y%400==0) days[1]=29;
for (k=0;k<12;k++){
for (i=0;i<6;i++)
for (j=0;j<7;j++){
w = WeekDay(y,k+1,1); //注意月份是k+1
month[i][j]=j+1+i*7;
month[i][j]-=w-1; //賦值後減去w再加1。
}
cout<<k+1<<"月:"<<endl; //注意月份是k+1
for(i=0;i<8;i++) cout<<setw(3)<<s[i]; //列印星期表頭
for (i=0;i<6;i++)
for (j=0;j<7;j++){
if (month[i][j]>days[k]) break;
if (month[i][j]>0) //大於0輸出,反之輸出3個空格
cout<<setw(3)<<month[i][j];
else
cout<<" ";
if (j==6&&month[i][j]!=days[k]) cout<<endl;
//最後一列輸出回車,但月底一天剛好週日則不用回車
}
cout<<endl;
}//next k
days[1]=28; //因多次用到days[],置平月天數千萬不能省略
cout<<endl;
}
}//end main();
執行結果如下:
體會一下原始碼中何時新增回車,何時輸出空格,都用if來判斷輸出。
接下來就做雙排的年曆,這時陣列需要6行14列,可以看作並排了兩個7列的表格,用2個迴圈分別來賦值。
#include <iomanip.h>
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<<setw(3)<<month[i][j];
if (j==6) cout<<" | "; //兩個表格用|分隔
if (j==13) cout<<endl;
}
return 0;
} //end main()
把上面的置數部分的用了2個迴圈,可以從函式main()中拿出來另外寫成一個函式initMon()用來初始化陣列。此時二維陣列month[][]是全域性變數要放在所有函式的前面。原始碼如下:
#include <iomanip.h>
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<<setw(3)<<month[i][j];
if (j==6) cout<<" | ";
if (j==13) cout<<endl;
}
return 0;
} //end main()
執行結果如下:
上圖中並排兩個月份的首日需要呼叫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 <iostream>
#include <iomanip>
#include <process.h> //呼叫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<<endl<<endl;
cout<<"你要豎向排列(1)還是橫向排列(2)?(1 or 2)";
}
int main(void)
{
int i,j,k,r=0;
const char *s[]={"一","二","三","四","五","六","日","\n"};
for(;;){
cout<<"輸入年份(0退出):";
do {
cin>>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<<r;
}while(!(r==1||r==2));
if (r==1){
//豎向排列
cout<<"\n\n豎向排列:"<<endl;
for (k=0;k<6;k++){
cout<<k+1<<"月:";
for (i=0;i<6;i++) cout<<" ";
cout<<k+7<<"月:"<<endl;
for(i=0;i<7;i++) cout<<" "<<s[i];
cout<<" ";
for(i=0;i<8;i++) cout<<" "<<s[i];
initMonth(k+1,k+7);
for (i=0;i<6;i++){
for (j=0;j<14;j++){
//大於0的輸出日期,否則輸出空格
if (month[i][j]>0)
cout<<setw(3)<<month[i][j];
else
cout<<" ";
if (j==6) cout<<" | ";
if (j==13) cout<<endl;
}//next j
}//next i
}//next k
} //else if(r==2)
else{
//橫向排列
cout<<"\n\n橫向向排列:"<<endl;
for (k=0;k<6;k++){
cout<<k*2+1<<"月:";
for (i=0;i<6;i++) cout<<" ";
cout<<k*2+2<<"月:"<<endl;
for(i=0;i<7;i++) cout<<" "<<s[i];
cout<<" ";
for(i=0;i<8;i++) cout<<" "<<s[i];
initMonth(k*2+1,k*2+2);
for (i=0;i<6;i++){
for (j=0;j<14;j++){
if (i==5&&month[5][0]==0&&month[5][7]==0) break;
//遮蔽空行
if (month[i][j]>0)
cout<<setw(3)<<month[i][j];
else
cout<<" ";
//大於0的輸出日期,否則輸出空格
if (j==6) cout<<" | ";
if (j==13) cout<<endl;
}//next j
}//next i
}//next k
}//end if-else
cout<<endl;
}//end for(;;)
}//end main();
執行結果如下:
程式碼稍作修改,即可得到每一行排列3個月的輸出。月份陣列變更為6行21列,initMonth()同時初始化三個月份,同時調整一下迴圈變數與月份陣列下標的關係。完整程式碼如下:
#include <iostream>
#include <iomanip>
#include <process.h> //呼叫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<<endl<<endl;
cout<<"你要豎向排列(1)還是橫向排列(2)?(1 or 2)";
}
int main(void)
{
int i,j,k,r=0;
const char *s[]={"一","二","三","四","五","六","日","\n"};
for(;;){
cout<<"輸入年份(0退出):";
do {
cin>>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<<r;
}while(!(r==1||r==2));
if (r==1){
//豎向排列
cout<<"\n\n豎向排列:"<<endl;
for (k=0;k<4;k++){
for(j=0;j<2;j++){
cout<<k+j*4+1<<"月:";
for(i=0;i<19;i++) cout<<" ";
}
cout<<k+9<<"月:"<<endl;
for(j=0;j<2;j++){
for(i=0;i<7;i++) cout<<" "<<s[i];
cout<<" ";
}
for(i=0;i<8;i++) cout<<" "<<s[i];
initMonth(k+1,k+5,k+9);
for (i=0;i<6;i++){
for (j=0;j<21;j++){
if (i==5 && month[5][0]==0 && month[5][7]==0 && month[5][14]==0) break; //遮蔽空行
if (month[i][j]>0)
cout<<setw(3)<<month[i][j];
else
cout<<" ";
//大於0的輸出日期,否則輸出空格
if (j==6||j==13) cout<<" | ";
if (j==20) cout<<endl;
}//next j
}//next i
}//next k
} //else if(r==2)
else{
//橫向排列
cout<<"\n\n橫向排列:"<<endl;
for (k=0;k<4;k++){
for(j=0;j<2;j++){
cout<<k*3+j+1<<"月:";
for(i=0;i<19;i++) cout<<" ";
}
cout<<k*3+3<<"月:"<<endl;
for(j=0;j<2;j++){
for(i=0;i<7;i++) cout<<" "<<s[i];
cout<<" ";
}
for(i=0;i<8;i++) cout<<" "<<s[i];
initMonth(k*3+1,k*3+2,k*3+3);
for (i=0;i<6;i++){
for (j=0;j<21;j++){
if (i==5 && month[5][0]==0 && month[5][7]==0 && month[5][14]==0) break; //遮蔽空行
if (month[i][j]>0)
cout<<setw(3)<<month[i][j];
else
cout<<" ";
//大於0的輸出日期,否則輸出空格
if (j==6||j==13) cout<<" | ";
if (j==20) cout<<endl;
}//next j
}//next i
}//next k
}//end if-else
cout<<endl;
}//end for(;;)
}//end main();
執行結果如下:
三維陣列的定義:
int month[6][7][12];
可以把它看作12個二維陣列month[6][7]聯立在一起,想像成一個12頁的PPT文件,每頁上都有一個6行7列的表格。
最後,我們來用三維陣列來輸出年曆,先用一個三重迴圈來初始化全年的日期,然後按照排版的需求來輸出這個三維陣列。
先看一下未遮蔽掉陣列中非正整數的程式碼:
#include <iostream>
#include <iomanip>
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<<"年:"<<endl;
for (m=0;m<12;m++){
cout<<m+1<<"月:"<<endl;
for(i=0;i<8;i++) cout<<" "<<s[i];
for (i=0;i<6;i++){
for (j=0;j<7;j++){
cout<<setw(3)<<month[i][j][m];
if (j==6) cout<<endl;
}
}
}
}//end main();
執行結果如下:
用了三維陣列後一年12個月的日期初始化一次完成,再用再幾個迴圈控制輸出即可。3列橫排的程式碼如下:
#include <iostream>
#include <iomanip>
using namespace std;
#include <process.h> //呼叫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<<"你輸入的年份是:"<<year<<endl<<endl;
initMonth(year);
cout<<year<<"年:"<<endl;
for (m=0;m<4;m++){
for (j=0;j<3;j++){
if (j==0) cout<<endl;
cout<<m*3+j+1<<"月:";
for (i=0;i<19;i++) cout<<" ";
if (m*3+j+1>9) cout<<"\b";
//修正2位數月份的寬度,"\b"為退格鍵BackSpace
}
cout<<endl;
for (j=0;j<3;j++)
for (i=0;i<7;i++){
cout<<" "<<s[i];
if (i==6&&j!=2) cout<<" | ";
}
cout<<endl;
for (i=0;i<6;i++){
for (k=0;k<3;k++){
if (i==5 && month[5][0][m*3]==0 && month[5][0][m*3+1]==0 && month[5][0][m*3+2]==0)
break; //遮蔽空行
for (j=0;j<7;j++){
if (month[i][j][m*3+k]>0) //非正數用空格替代
cout<<setw(3)<<month[i][j][m*3+k];
//注意陣列下標[m*3+k]不用+1
else
cout<<" ";
if (j==6&&k!=2) cout<<" | ";
}//next j
}//next k
if (i!=5) cout<<endl;
if (i==5 && (month[5][0][m*3]==0 || month[5][0][m*3+1]==0 || month[5][0][m*3+2]==0))
cout<<endl; //第6行有日期則換行
}//next i
} //next m
cout<<endl;
}//next for(;;)
}//end main();
執行結果如下:
也可以將上述程式碼稍作修改,改為用豎排的格式輸出年曆,自己動手試試吧。(全文完)
相關文章
- c++中的陣列C++陣列
- Java陣列的運用Java陣列
- python中怎麼列印陣列Python陣列
- Oracle用SQL列印日曆OracleSQL
- 【陣列】1394. 找出陣列中的幸運數(簡單)陣列
- Java、C、C++中的陣列的比較JavaC++陣列
- [C++]陣列C++陣列
- C++用new建立二維陣列的方法C++陣列
- C++ 練氣期之二維陣列與矩陣運算C++陣列矩陣
- 脈動陣列在二維矩陣乘法及卷積運算中的應用陣列矩陣卷積
- 陣列的位移運算陣列
- 劍指offer——陣列中的逆序對C++(75%)陣列C++
- C++陣列 字串C++陣列字串
- C/C++ 二維陣列的理解(多維陣列)C++陣列
- iOS 陣列中那些實用的方法iOS陣列
- C++陣列的儲存|C++陣列所佔記憶體空間C++陣列記憶體
- 教你如何運用golang實現陣列分割Golang陣列
- 在C++中實現變長陣列 (轉)C++陣列
- C和C++陣列的用法C++陣列
- C++陣列的連續性C++陣列
- C++ 陣列的 auto 和 decltypeC++陣列
- C++陣列長度C++陣列
- c++陣列排序插入C++陣列排序
- ORACLE 陣列在過程中的應用Oracle陣列
- 教你如何運用golang 實現陣列的隨機排序Golang陣列隨機排序
- 劍指offer之順序列印陣列陣列
- 【面試題】從上向下列印陣列|||面試題陣列
- JS實現順時針列印陣列JS陣列
- C語言列印年曆C語言
- Ruby中的陣列陣列
- Go中的陣列Go陣列
- Java中的陣列Java陣列
- 從命令列中列印(轉)命令列
- [php]運用變數引用實現一維陣列轉多維樹狀陣列PHP變數陣列
- C++ 指標陣列與陣列指標的區別C++指標陣列
- 陣列(2)陣列運算及典例(求解素數的方法)陣列
- C++獲取陣列的長度C++陣列
- C和C++中所謂的陣列C++陣列