コード:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef struct Message {
int date;
char *msg;
struct Message *prev, *next;
} Message;
typedef struct {
int year, month, day;
Message root, *message[32];
} Data;
void print_help(void)
{
puts(" q : 終了 (quit)\n"
" h : ヘルプ (help)\n"
" 1901~2099 : 年の指定\n"
" m [1~12] : 月の指定とカレンダーの表示 (month)\n"
" 1~31 : 日の指定とメモの表示\n"
" w [1~31] : 日の指定とメモの書き込み (write)\n"
" d [1~31] : 日の指定とメモの削除 (delete)\n");
}
int day_of_week(int y, int m, int d)
{
y -= m < 3;
return (y + y/4 - y/100 + y/400 + ".bed=pen+mad."[m] + d) % 7;
}
#define IS_LEAP(y) ((y) % 4 == 0 && ((y) % 100 || (y) % 400 == 0))
int last_day(int y, int m)
{
return (m == 2) ? IS_LEAP(y) + 28 : (0x15aa>>m & 1) + 30;
}
void print_calendar(Data *dp)
{
int w = day_of_week(dp->year, dp->month, 1);
int z = last_day(dp->year, dp->month), d;
printf("%13d年 %d月\n" " 日 月 火 水 木 金 土\n" "%*s",
dp->year, dp->month, w * 4, "");
for (d = 1; d <= z; d++)
printf("%*c%d%c", (d<10)+1, dp->message[d]?'*':' ', d, ++w%7?' ':'\n');
puts(w % 7 ? "\n" : "");
}
void print_message(Data *dp)
{
printf("%d/%d/%d: %s", dp->year, dp->month, dp->day,
dp->message[dp->day] ? dp->message[dp->day]->msg : "\n");
}
int confirm(const char *message)
{
char buf[1024];
printf("%s (y/n): ", message);
return fgets(buf, sizeof(buf), stdin) && buf[0] == 'y';
}
Message *insert(Message *pos, int date, const char *msg)
{
Message *mp = static_cast<Message *>(malloc(sizeof *mp));
mp->date = date;
mp->msg = strdup(msg);
mp->prev = pos->prev;
mp->next = pos;
return pos->prev = pos->prev->next = mp;
}
void load_message(Data *dp)
{
char buf[1024];
int y, m, d, n;
FILE *fp = fopen("Calendar.txt", "r");
dp->root.prev = dp->root.next = &dp->root;
if (!fp) return;
while (fgets(buf, sizeof(buf), fp))
if (sscanf(buf, "%d/%d/%d %n", &y, &m, &d, &n) == 3)
insert(&dp->root, y << 9 | m << 5 | d, buf + n);
fclose(fp);
}
void save_message(Data *dp)
{
FILE *fp = fopen("Calendar.txt", "w");
if (fp) {
Message *mp = dp->root.next;
while (mp != &dp->root) {
Message *np = mp->next;
fprintf(fp, "%d/%02d/%02d %s", mp->date >> 9,
mp->date >> 5 & 0x0f, mp->date & 0x1f, mp->msg);
free(mp->msg);
free(mp);
mp = np;
}
fclose(fp);
}
}
void set_message(Data *dp)
{
int date1 = dp->year << 9 | dp->month << 5 | 1;
int date31 = dp->year << 9 | dp->month << 5 | 31;
Message *mp = dp->root.next;
int d;
for (d = 0; d < 32; d++) dp->message[d] = 0;
for (; mp != &dp->root && mp->date <= date31; mp = mp->next)
if (mp->date >= date1) dp->message[mp->date & 0x1f] = mp;
}
void delete_message(Data *dp)
{
Message *mp = dp->message[dp->day];
if (mp) {
mp->prev->next = mp->next;
mp->next->prev = mp->prev;
free(mp->msg);
free(mp);
dp->message[dp->day] = 0;
print_calendar(dp);
}
}
void write_message(Data *dp, const char *buf)
{
Message *mp = dp->message[dp->day];
if (mp) {
free(mp->msg);
mp->msg = strdup(buf);
} else {
int date = dp->year << 9 | dp->month << 5 | dp->day;
for (mp = dp->root.next; mp != &dp->root && mp->date < date; mp = mp->next) ;
dp->message[dp->day] = insert(mp, date, buf);
}
print_calendar(dp);
}
int main(void)
{
Data data;
char buf[1024];
time_t t = time(0);
struct tm *tp = localtime(&t);
data.year = tp->tm_year + 1900;
data.month = tp->tm_mon + 1;
data.day = tp->tm_mday;
load_message(&data);
set_message(&data);
print_help();
print_calendar(&data);
print_message(&data);
while (printf("> "), fgets(buf, sizeof(buf), stdin)) {
int n = atoi(buf);
if (n > 1900 && n < 2100 && n != data.year) // change year
data.year = n, print_calendar(&data);
else if (n >= 1 && n <= last_day(data.year, data.month)) // the day
data.day = n, print_message(&data);
else if (buf[0] == 'm') { // change month and print calendar
n = atoi(buf + 1);
if (n >= 1 && n <= 12 && n != data.month)
data.month = n, set_message(&data);
print_calendar(&data);
} else if (buf[0] == 'w') { // write
n = atoi(buf + 1);
if (n >= 1 && n <= last_day(data.year, data.month)) data.day = n;
printf("%d/%d/%d: ", data.year, data.month, data.day);
if (fgets(buf, sizeof(buf), stdin) && buf[0] != '\n')
if (!data.message[data.day] || confirm("上書きしますか?"))
write_message(&data, buf);
} else if (buf[0] == 'd') { // delete
n = atoi(buf + 1);
if (n >= 1 && n <= last_day(data.year, data.month)) data.day = n;
if (data.message[data.day] && confirm("削除しますか?"))
delete_message(&data);
} else if (buf[0] == 'q') { // quit
if (confirm("終了しますか?")) break;
} else if (buf[0] == 'h') print_help();
}
save_message(&data);
return 0;
}