■この記事の概要
この記事では、西暦と和暦を相互に変換するプログラムの例を示しています。
具体的なコードを用いて、各元号の期間を定義し、ユーザーが入力した日付に基づいて変換を行う方法を説明しています。
■西暦を干支に変換(if文もswitch文も使わない)
#include <stdio.h>
char *西暦干支変換(int 西暦){
static char *干支[] ={
[0]="申(さる)" ,
[1]="酉(とり)" ,
[2]="戌(いぬ)" ,
[3]="亥(い)" ,
[4]="子(ね)" ,
[5]="丑(うし)" ,
[6]="寅(とら)" ,
[7]="卯(う)" ,
[8]="辰(たつ)" ,
[9]="巳(み)" ,
[10]="午(うま)" ,
[11]="未(ひつじ)"
};
return 干支[西暦 % 12] ;
}
int main(void){
const int 今年=2025;
for(int 西暦 = 今年; 西暦 <= 今年+12; 西暦++){
printf("西暦%4d年の干支は%s\n",
西暦,
西暦干支変換(西暦)
);
}
}
./a.out
西暦2025年の干支は巳(み)
西暦2026年の干支は午(うま)
西暦2027年の干支は未(ひつじ)
西暦2028年の干支は申(さる)
西暦2029年の干支は酉(とり)
西暦2030年の干支は戌(いぬ)
西暦2031年の干支は亥(い)
西暦2032年の干支は子(ね)
西暦2033年の干支は丑(うし)
西暦2034年の干支は寅(とら)
西暦2035年の干支は卯(う)
西暦2036年の干支は辰(たつ)
西暦2037年の干支は巳(み)
干支の配列を子年から始めないで
西暦を十二支で割った余りが0になる
さる年から始めるのがミソです
■西暦を和暦に変換(年月日をまとめてint型にする)
#include <stdio.h>
#include <string.h>
#include <limits.h>
/*
元号期間
明治 1868-01-25 1912-07-29
大正 1912-07-30 1926-12-24
昭和 1926-12-25 1989-01-07
平成 1989-01-08 2019-04-30
令和 2019-05-01
*/
char *西暦和暦変換(int 年,int 月,int 日){
int y = 年;
int m = 月;
int d = 日;
int ymd = y*10000 + m*100 +d;
char *G;
switch(ymd){
case 18680125 ... 19120729: G="明治";y -= 1868; break;
case 19120730 ... 19261224: G="大正";y -= 1912; break;
case 19261225 ... 19890107: G="昭和";y -= 1926; break;
case 19890108 ... 20190430: G="平成";y -= 1989; break;
case 20190501 ... INT_MAX: G="令和";y -= 2019; break;
default: G="未対応"; y -= 1; break;
}
y += 1;//0年元年補正
static char 和暦[1024];
sprintf(和暦,"西暦=%d -> %s/%d年/%02d/%02d",ymd,G,y,m,d);
return strdup(和暦) ;
}
int main(void){
printf("明治以前:%s\n",
西暦和暦変換(1868,1,24));
printf("明治:%s\t%s\n",
西暦和暦変換(1868,1,25),
西暦和暦変換(1912,7,29));
printf("大正:%s\t%s\n",
西暦和暦変換(1912,7,30),
西暦和暦変換(1926,12,24));
printf("昭和:%s\t%s\n",
西暦和暦変換(1926,12,25),
西暦和暦変換(1989,1,7));
printf("平成:%s\t%s\n",
西暦和暦変換(1989,1,8),
西暦和暦変換(2019,4,30));
printf("令和:%s\t%s\n",
西暦和暦変換(2019,5,1),
西暦和暦変換(9999,12,31));
}
./a.out
明治以前:西暦=18680124 -> 未対応/1868年/01/24
明治:西暦=18680125 -> 明治/1年/01/25 西暦=19120729 -> 明治/45年/07/29
大正:西暦=19120730 -> 大正/1年/07/30 西暦=19261224 -> 大正/15年/12/24
昭和:西暦=19261225 -> 昭和/1年/12/25 西暦=19890107 -> 昭和/64年/01/07
平成:西暦=19890108 -> 平成/1年/01/08 西暦=20190430 -> 平成/31年/04/30
令和:西暦=20190501 -> 令和/1年/05/01 西暦=99991231 -> 令和/7981年/12/31
gccの拡張switch-caseを使用しているので
gccとclangではコンパイル出来ますが
Visual Studio ではコンパイルエラーになります。
■和暦を西暦に変換(sscanfで文字列解析する)
#include <stdio.h>
#include <string.h>
//例: 令和/5年/06/03->2023/06/03
char *和暦西暦変換(char *和暦){
char 元号[32];
int y,m,d ;
int ret = sscanf(和暦,"%[^/]/%d年/%d/%d",//正規表現
元号,&y,&m,&d);
if(ret != 4){
printf("ret=%d,%s:%d:%d:%d\n",ret,元号,y,m,d);
fflush(NULL);
return "未対応";
}
#define CMP(X,Y) (strcmp(X,Y)==0)
if( CMP(元号,"令和")) { y += 2019-1; }
else if(CMP(元号,"平成")) { y += 1989-1; }
else if(CMP(元号,"昭和")) { y += 1926-1; }
else if(CMP(元号,"大正")) { y += 1912-1; }
else if(CMP(元号,"明治")) { y += 1868-1; }
else { return "未対応";}
static char 西暦[255];
sprintf(西暦,"%s->%04d/%02d/%02d",和暦,y,m,d);
return 西暦 ;
}
//元号期間
//https://www.jacar.archives.go.jp/apps/help/chronological_table.html
int main(void){
printf("%s\n",和暦西暦変換("明治/01年/01/25"));
printf("%s\n",和暦西暦変換("明治/45年/07/30"));
printf("%s\n",和暦西暦変換("大正/01年/07/30"));
printf("%s\n",和暦西暦変換("大正/15年/12/25"));
printf("%s\n",和暦西暦変換("昭和/01年/12/25"));
printf("%s\n",和暦西暦変換("昭和/64年/01/07"));
printf("%s\n",和暦西暦変換("平成/01年/01/08"));
printf("%s\n",和暦西暦変換("平成/31年/04/30"));
printf("%s\n",和暦西暦変換("令和/01年/05/01"));
printf("%s\n",和暦西暦変換("令和/07年/02/17"));
printf("%s\n",和暦西暦変換("平和/99年/01"));
printf("%s\n",和暦西暦変換("平和/99年/01/01"));
}
./a.out
明治/01年/01/25->1868/01/25
明治/45年/07/30->1912/07/30
大正/01年/07/30->1912/07/30
大正/15年/12/25->1926/12/25
昭和/01年/12/25->1926/12/25
昭和/64年/01/07->1989/01/07
平成/01年/01/08->1989/01/08
平成/31年/04/30->2019/04/30
令和/01年/05/01->2019/05/01
令和/07年/02/17->2025/02/17
ret=3,平和:99:1:-2021400662
未対応
未対応
和暦の文字列から元号を切り出すために
sscanfの正規表現で”%[^/]”を使っています。
これは、”/でない物が続く物”の意味です。