#pragma warning(disable: 4996)
#include<stdio.h>
#define ROW_SIZE 6 //カレンダーの行のサイズ
#define SPRING_EQ 0
#define FALL_EQ 1
#define BIRTH_MARK 0x80// 誕生日マーク
#define TRANS_MARK 0x40// 振替祝日マーク
#define HOLI_MARK 0x20// 祝日マーク
#define MAX_HOLI_TBL 4 //祝日テーブルの最大
enum M_LIST { JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOW, DEC, N_MONTH };
enum W_LIST { SUN, MON, TUE, WED, THU, FRI, SAT, N_WEEK };
int monthdays[] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; //月の日数
char* weeks[] = { "日","月","火","水","木","金","土" };
//****************************************************
//
// 祝日のデータテーブル
//
char holidays[N_MONTH][MAX_HOLI_TBL] = {
{1,-2,0,0}, // 1月、元旦、成人の日
{11,23,0,0}, // 2月、建国記念日、令和天皇誕生日
{21,0,0,0}, // 3月、春分の日(計算で求める)
{29,0,0,0}, // 4月、昭和の日
{3,4,5,0}, // 5月、憲法記念日、みどりの日、子供の日
{ 0,0,0,0}, // 6月、なし
{-3,0,0,0}, // 7月、海の日
{11,0,0,0}, // 8月、山の日
{-3,23,0,0}, // 9月、敬老の日、秋分の日(計算で求める)
{-2,0,0,0}, // 10月、体育の日
{3,23,0,0}, // 11月、文化の日、勤労感謝の日
{ 0,0,0,0} // 12月、なし
};
//プロトタイプの宣言
int januaryoneday(int year);
int leapyear(int year);
int calendarmake(char calendar[N_MONTH][ROW_SIZE][N_WEEK], int week, int year, int birthmon, int birthday);
void calendarprint(char calendar[N_MONTH][ROW_SIZE][N_WEEK], int year, int display);
void spraut(int yy);
int main(void) {
char calendar[N_MONTH][ROW_SIZE][N_WEEK] = { 0 }; // カレンダーの多次元配列
int year; //入力された西暦
//int month; //入力された月
//int day; //入力された日
int week; // //入力された西暦の1月1日の曜日
int judgment; //入力された値がうるう年だったかどうか
int sumday; // 入力された西暦までの日数の合計
// int birthw; //入力された誕生日の曜日
int monthdaysum = 0; // 入力された誕生日の月までの合計の日数
int birthmon; //入力された誕生月
int birthday; //入力された誕生日
int display; //入力された表示方法
printf("西暦を入力してください");
scanf("%d", &year);
printf("誕生日を入力してください");
scanf("%d %d", &birthmon, &birthday);
printf("カレンダーの表示3行か4行か");
scanf("%d", &display);
week = januaryoneday(year); //入力された西暦の1月1日の曜日を取得
//printf("%s\n", weeks[week]); //入力された西暦の1月1日の曜日を表示
judgment = leapyear(year); //うるう年の判定結果を取得
monthdays[FEB] = (judgment == 0) ? 29 : 28; // うるう年であれば2月を29日に変更
sumday = ((year - 1) * 365) + ((year - 1) / 4) - ((year - 1) / 100) + ((year - 1) / 400); //入力された西暦までの日数の合計
/*for (int i = JAN; i < month - 1; i++) { //入力された誕生日の月までの合計の日数
monthdaysum += monthdays[i];
}
birthw = (sumday + monthdaysum + day) % 7; // 入力された誕生日までの合計の日数 の曜日を取得
printf("%s", weeks[birthw]); //入力された誕生日の曜日を表示
*/
week = calendarmake(calendar, week, year, birthmon, birthday);
//printf("%s\n", weeks[week]);
spraut(year); //春分の日と秋分の日を設定
calendarprint(calendar, year, display); //カレンダーの表示
}
//入力された西暦の1月1日の曜日を返す
int januaryoneday(int year) {
int sumday; // 入力された西暦までの累計日数
int dayw; // 曜日計算
sumday = ((year - 1) * 365) + ((year - 1) / 4) - ((year - 1) / 100) + ((year - 1) / 400); //入力された1月1日までの日数
dayw = (sumday + 1) % 7;
return dayw;
}
//入力された西暦がうるう年かの判定
int leapyear(int year) {
int leap;
leap = (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) ? 0 : -1; //うるう年なら0を 違うなら-1 を
return leap;
}
//カレンダーを作る
int calendarmake(char calendar[N_MONTH][ROW_SIZE][N_WEEK], int week, int year, int birthmon, int birthday) {
int month; // 1月から12月
int row; //カレンダーの行
int day;//月の日にち
int monday_cnt;
int holiday_cnt;
for (month = JAN; month <= DEC; month++) {
row = 0; //月ごとに初期化
day = 1; //月ごとに初期化
monday_cnt = 0;// 月曜日カウント
holiday_cnt = 0; // 祝日カウント
while (day <= monthdays[month])
{
calendar[month][row][week] |= day; //現在の日付のビットを立てる
if (week == MON) {
monday_cnt++; //月曜日なら1増やす
}
if (holidays[month][holiday_cnt] == day) { //固定祝日だったら
calendar[month][row][week] |= HOLI_MARK; //固定祝日のビットを立てる
holiday_cnt++;
if ((week == SUN) || (calendar[month][row][week] & TRANS_MARK)) { //固定祝日が日曜日またはすでに振替休日の場合
calendar[month][row][week + 1] |= TRANS_MARK;
}
}
if ((holidays[month][holiday_cnt] < 0) && (holidays[month][holiday_cnt] * -1) == monday_cnt) {
calendar[month][row][week] |= HOLI_MARK; //固定でない祝日のビットを立てる
holiday_cnt++;
}
if (week > TUE) {
if (calendar[month][row][week] & HOLI_MARK && calendar[month][row][week - 2] & HOLI_MARK) {
calendar[month][row][week - 1] |= HOLI_MARK;
}
}
if (month == birthmon - 1 && day == birthday) { //引数で渡された誕生日だったら誕生日のマーク入れる
calendar[month][row][week] |= BIRTH_MARK;
}
week++;
day++;
if (week > SAT) {
week = SUN;
row++;
}
}
}
return week; //最後の曜日を返す
}
//カレンダーを表示する
void calendarprint(char calendar[N_MONTH][ROW_SIZE][N_WEEK], int year, int display) {
int month; //月のループ
int row; //週のループ
int col;//曜日のループ
printf("%5d年\n", year); // 入力された年を表示
for (month = JAN; month <= DEC; month++) {
printf(" %2d月\n", month + 1);
printf("\n");
for (int i = 0; i <= SAT; i++) {
printf(" %2s ", weeks[i]); //曜日の表示
}
printf("\n");
for (row = 0; row < ROW_SIZE; row++) {
for (col = 0; col <= SAT; col++) {
if (calendar[month][row][col] != 0) //日数が0でなければ
{
if (calendar[month][row][col] & HOLI_MARK) {
printf("*");
}
else if (calendar[month][row][col] & TRANS_MARK) {
printf("+");
}
else if (calendar[month][row][col] & BIRTH_MARK) {
printf("&");
}
else {
printf(" ");
}
printf("%2d ", calendar[month][row][col] & 0x1F);
}
else { //日数が0なら
printf(" ");
}
}
printf("\n");
}
printf("\n");
}
}
//春分と秋分の日を求める
void spraut(int year) {
int yy;
int springEQ; // 求める春分の日
int fallEQ; // 求める秋分の日
yy = year;
if (yy <= 1899) {
springEQ = (int)(19.8277 + 0.242194 * (yy - 1980) - ((yy - 1983) / 4));
fallEQ = (int)(22.2588 + 0.242194 * (yy - 1980) - ((yy - 1983) / 4));
}
else if (yy >= 1900 && yy <= 1979) {
springEQ = (int)(20.8357 + 0.242194 * (yy - 1980) - ((yy - 1983) / 4));
fallEQ = (int)(23.2588 + 0.242194 * (yy - 1980) - ((yy - 1983) / 4));
}
else if (yy >= 1980 && yy <= 2099) {
springEQ = (int)(20.8431 + 0.242194 * (yy - 1980) - ((yy - 1980) / 4));
fallEQ = (int)(23.2488 + 0.242194 * (yy - 1980) - ((yy - 1980) / 4));
}
else if (yy >= 2100) {
springEQ = (int)(21.851 + 0.242194 * (yy - 1980) - ((yy - 1980) / 4));
fallEQ = (int)(24.2488 + 0.242194 * (yy - 1980) - ((yy - 1980) / 4));
}
holidays[MAR][SPRING_EQ] = springEQ; // 春分の日を入れる
holidays[SEP][FALL_EQ] = fallEQ; // 秋分の日を入れる
}
コンソールにカレンダーを縦 一列に表示することは出来たので、横にも表示させたいと思ったのですが、どうすればいいのか思いつきませんでした。
1 2 3
4 5 6
7 8 9
10 11 12
このように表示したりしたいのですが、アドバイス頂けると幸いです。
-----追記-------
//カレンダーを表示する
void calendarprint(char calendar[N_MONTH][ROW_SIZE][N_WEEK], int year, int display) {
int month; //月のループ
int row; //週のループ
int col;//曜日のループ
printf("%5d年\n", year); // 入力された年を表示
for (month = JAN; month <= DEC; month+=display) {
for (int m = month, dis = 0; m < N_MONTH && dis < display; m++, dis++) {
printf(" %2d月 ", m + 1);
}
printf("\n\n");
for (int m = month, dis = 0; m < N_MONTH && dis < display; m++, dis++) {
for (int i = 0; i <= SAT; i++) {
printf(" %2s ", weeks[i]); //曜日の表示
if (i == SAT) {
printf(" ");
}
}
}
printf("\n");
for (row = 0; row < ROW_SIZE; row++) {
printf("\n");
for(int m = month, dis = 0; m < N_MONTH && dis < display; m++, dis++){
for (col = 0; col <= SAT; col++) {
if (calendar[month][row][col] != 0) //日数が0でなければ
{
if (calendar[month][row][col] & HOLI_MARK) {
printf("*");
}
else if (calendar[month][row][col] & TRANS_MARK) {
printf("+");
}
else if (calendar[month][row][col] & BIRTH_MARK) {
printf("&");
}
else {
printf(" ");
}
printf("%2d ", calendar[month][row][col] & 0x1F);
}
else { //日数が0なら
printf(" ");
}
if (col == SAT) {
printf(" ");
}
}
}
printf("\n");
}
printf("\n");
}
}
カレンダーを表示の部分を回答を参考に自分なりに書いてみました。
しかし、表示の仕方を
1 2 7 8
3 4 9 10
5 6 11 12
上記ののように表示をしたいのですが、なかなかうまくいきません。
追加でアドバイス頂けると幸いです。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
+1
縦に並べたカレンダーを印刷して, 縦横に並べたイメージを切り貼りで実際に作っては如何でしょう.
そして, 上から一行ずつに定規等を当てていけば, いつどの表示をすれば良いのかが見えてくると思います.
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
checkベストアンサー
0
display を、月を横にいくつ表示するかという意味に解釈しました。
最初に、12の約数だけ有効なコードを示しましたが、
5 や 7 などでもよいようにしてみました。
//カレンダーを表示する
void calendarprint(char calendar[N_MONTH][ROW_SIZE][N_WEEK],
int year, int display)
{
printf("%5d年\n", year); // 入力された年を表示
for (int month = JAN; month < N_MONTH; month += display) {
for (int m = month, k = 0; m < N_MONTH && k < display; k++, m++)
printf("%16d月 ", m + 1);
printf("\n\n");
for (int m = month, k = 0; m < N_MONTH && k < display; k++, m++) {
if (k) printf(" ");
for (int i = 0; i <= SAT; i++)
printf(" %2s ", weeks[i]); //曜日の表示
}
printf("\n");
for (int row = 0; row < ROW_SIZE; row++) {
for (int m = month, k = 0; m < N_MONTH && k < display; k++, m++) {
if (k) printf(" ");
for (int col = SUN; col <= SAT; col++) {
if (calendar[m][row][col] != 0) { // 日数が0でないなら
if (calendar[m][row][col] & HOLI_MARK)
printf("*");
else if (calendar[m][row][col] & TRANS_MARK)
printf("+");
else if (calendar[m][row][col] & BIRTH_MARK)
printf("&");
else
printf(" ");
printf("%2d ", calendar[m][row][col] & 0x1F);
}
else // 日数が0なら
printf(" ");
}
}
printf("\n");
}
printf("\n");
}
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
3ヶ月分を横に並べられるだけの1行ぶんのバッファを用意しといて、
3ヶ月のカレンダ文字列を生成、その1行づつを位置あわせのスペースを挟みながら横に3つ並べて出力する、ということですね。
位置合わせがちょっと難しいですが、まあ、がんばってください
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
if文は「if (式) 文」という構文で、式の値が 0 でなければ文を実行します。
if (k != 0) printf(" "); と同じです。
if (k > 0) printf(" "); と書いても構いません。
2番目以降の月を書くとき、左の月との間にスペースを置くということです。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.23%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる