コード:
/******************************************************************************/
/* カレンダー出力プログラム */
/******************************************************************************/
/* <使い方>
* cal [-h | -?] [-n] [-s] [year [month]] <Enter>
*
* year :年(1851~2150)
* month:月(1~12)
*
* 年・月の両方を省略すると、現在の月のカレンダーを出力
* 年だけを指定して月を省略すると、その年のカレンダーを出力
* 年・月の両方を指定すると、その年・月のカレンダーを出力
* '-n'を指定すると、日曜・祝日のマークを付けない(デフォルト)
* '-s'を指定すると、現行の祝日法に従った日曜・祝日のマークを付ける
* '-h'または'-?'を指定すると、使い方を出力
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
/* ---- 記号定数 ---- */
#define MONTHS_PER_YEAR (12) /* 1年の月数 */
#define WEEKS_PER_MONTH (6) /* 1ヶ月の最大週数 */
#define DAYS_PER_WEEK (7) /* 1週間の日数 */
#define YEAR_LOWER_LIMIT (1851) /* 年の下限 */
#define YEAR_UPPER_LIMIT (2150) /* 年の上限 */
#define MONTH_LOWER_LIMIT (1) /* 月の下限 */
#define MONTH_UPPER_LIMIT (MONTHS_PER_YEAR) /* 月の上限 */
#define LENGTH (40) /* 年・月や週の文字列長 */
/* ---- 構造体定義 ---- */
/* 国民の祝日・国民の休日の定義用 */
typedef struct {
int month; /* 月 */
int day_or_week; /* 日または週 */
int week; /* 曜日(0:日曜~6:土曜) */
/* 日にちが決まっている祝日の場合は負の数 */
} HOLIDAYS;
/* 出力形式の定義用 */
typedef struct {
char *week; /* 曜日の名前 */
char *date; /* 日にち */
int space; /* 無効な日にち用の空白数 */
int horizontal_months; /* 横方向に出力する月数 */
int horizontal_space; /* 月どうしの横方向の間隔 */
int vertical_space; /* 月どうしの行間 */
} FORMAT;
/* ---- 外部変数など ---- */
HOLIDAYS national_holidays[] = { /* 国民の祝日 */
{ 1, 1, -1}, /* 1月1日:元日 */
{ 1, 2, 1}, /* 1月第2月曜日:成人の日 */
{ 2, 11, -1}, /* 2月11日:建国記念の日 */
{ 3, 0, -1}, /* 春分の日 */
{ 4, 29, -1}, /* 4月29日:昭和の日 */
{ 5, 3, -1}, /* 5月3日:憲法記念日 */
{ 5, 4, -1}, /* 5月4日:みどりの日 */
{ 5, 5, -1}, /* 5月5日:こどもの日 */
{ 7, 3, 1}, /* 7月第3月曜日:海の日 */
{ 9, 3, 1}, /* 9月第3月曜日:敬老の日 */
{ 9, 0, -1}, /* 秋分の日 */
{10, 2, 1}, /* 10月第2月曜日:体育の日 */
{11, 3, -1}, /* 11月3日:文化の日 */
{11, 23, -1}, /* 11月23日:勤労感謝の日 */
{12, 23, -1}, /* 12月23日:天皇誕生日 */
{99, 0, -1}, /* 番兵 */
};
FORMAT format[] = { /* 出力形式 */
{"%2s " , "%2d " , 3, 3, 6, 2}, /* ノーマル */
{" %2s ", "<%2d>", 4, 2, 8, 2}, /* スペシャル1 */
{" %2s ", " %2d ", 4, 2, 8, 2}, /* スペシャル2 */
};
int first_sunday[MONTHS_PER_YEAR+1]; /* 毎月第1日曜日の日にち */
int year_is_set; /* 年のセット方法 */
int month_is_set; /* 月のセット方法 */
enum { /* 出力パターンと対応 */
NORMAL, /* 日曜・祝日のマークなし */
SPECIAL, /* 日曜・祝日のマークあり */
};
enum { /* 年・月のセット方法 */
BY_AUTOMATIC, /* 自動 */
BY_MANUAL, /* 手動(引数で与える) */
};
enum { /* エラーメッセージと対応 */
INVALID_OPT, /* 不正なオプション */
INVALID_NUM, /* 不正な数値 */
INVALID_Y_OR_M, /* 不正な年または月 */
};
typedef enum {
FALSE, /* 偽 */
TRUE, /* 真 */
} Boolean;
/* ---- 関数プロトタイプ宣言 ---- */
void getopt(int argc, char **argv, int *pat, int *y, int *m);
char *set_week_name(int pat, char *w);
void get_vernal_and_autumnal(int y);
void get_date_of_first_sunday(int y);
void print_calendar(int pat, int y, int m, char *w);
void print_one_month(int pat, int y, int m, char *w);
void print_one_year(int pat, int y, char *w);
void print_year_and_month_name(int y, int m, int len);
void print_week_name(char *w);
void print_date(int pat, int y, int m, int d, int u);
Boolean is_holiday(int m, int d, int u);
void print_space_between_months(int pat, int m);
void print_space(int n);
void print_new_line(int n);
int day_of_week(int y, int m, int d);
int leap(int y);
void print_error_msg(int n);
void usage(char *pgm);
char *remove_path_and_extension(char *s);
/*----------------------------------------------------------------------------*/
/* メイン */
/* */
/* 引数 */
/* argc コマンド行の引数の個数 */
/* argv 引数の文字列へのポインターへのポインター */
/* 戻り値 */
/* EXIT_SUCCESS 正常終了 */
/*----------------------------------------------------------------------------*/
int main(int argc, char **argv)
{
int pattern; /* 出力パターン */
int year, month; /* 年・月 */
char week[LENGTH+1]; /* 曜日の名前 */
getopt(argc, argv, &pattern, &year, &month); /* 引数の読み込み */
set_week_name(pattern, week); /* 曜日の名前のセット */
get_vernal_and_autumnal(year); /* 春分の日・秋分の日 */
get_date_of_first_sunday(year); /* 毎月第1日曜日の日にち */
print_calendar(pattern, year, month, week); /* カレンダーの出力 */
return EXIT_SUCCESS;
}
/*----------------------------------------------------------------------------*/
/* 引数の読み込み */
/* */
/* 引数 */
/* argc コマンド行の引数の個数 */
/* argv 引数の文字列へのポインターへのポインター */
/* pat 出力パターンの値へのポインター(呼び出し元へ返却) */
/* y 年の値へのポインター(呼び出し元へ返却) */
/* m 月の値へのポインター(呼び出し元へ返却) */
/* 戻り値 */
/* なし */
/*----------------------------------------------------------------------------*/
void getopt(int argc, char **argv, int *pat, int *y, int *m)
{
char *pgm = *argv; /* 実行プログラム名 */
struct tm *tm; /* ローカル時間保存用 */
time_t t = time(NULL); /* 現在のカレンダー時間 */
int opt; /* 実行時のオプション */
int wk; /* 年・月の値の一時保管用 */
/* 出力パターン、年・月の初期設定 */
*pat = NORMAL; /* 日曜・祝日のマークなし */
tm = localtime(&t); /* 年・月は現在の値 */
*y = tm->tm_year + 1900;
*m = tm->tm_mon + 1;
year_is_set = month_is_set = BY_AUTOMATIC; /* 年・月とも自動セット */
/* 実行時引数の処理 */
while (--argc) { /* 引数の数だけループ */
opt = **(++argv); /* 引数の先頭文字 */
if (opt == '-') { /* '-'で始まっていると */
opt = *++(*argv); /* その次がオプション */
switch (opt) {
case 'n':
*pat = NORMAL; /* 日曜・祝日のマークなし */
break;
case 's':
*pat = SPECIAL; /* 日曜・祝日のマークあり */
break;
case 'h': case '?':
usage(pgm); /* 使い方を出力 */
break;
default: /* エラー */
print_error_msg(isdigit(opt) ? INVALID_NUM : INVALID_OPT);
usage(pgm);
}
}
else { /* '-'以外で始まっている */
if (!isdigit(opt)) { /* 数字でなければ */
print_error_msg(INVALID_OPT); /* 不正なオプション */
usage(pgm);
}
wk = atoi(*argv); /* 数値を一時的に保管 */
/* 年・月とみなせない範囲ならば */
if (((wk < YEAR_LOWER_LIMIT ) || (YEAR_UPPER_LIMIT < wk)) &&
((wk < MONTH_LOWER_LIMIT) || (MONTH_UPPER_LIMIT < wk))) {
print_error_msg(INVALID_Y_OR_M); /* 不正な年または月 */
usage(pgm);
}
/* 月とみなせる範囲ならば */
if ((MONTH_LOWER_LIMIT <= wk) && (wk <= MONTH_UPPER_LIMIT)) {
if (year_is_set != BY_MANUAL) { /* 年が手動セット済でない */
print_error_msg(INVALID_Y_OR_M); /* 不正な年または月 */
usage(pgm);
}
else { /* 年が手動セット済ならば */
*m = wk; /* 月とする */
month_is_set = BY_MANUAL; /* 月を手動セット済にする */
}
}
/* 年とみなせる範囲ならば */
else {
*y = wk; /* 年とする */
year_is_set = BY_MANUAL; /* 年を手動セット済にする */
}
}
}
}
/*----------------------------------------------------------------------------*/
/* 曜日の名前のセット */
/* */
/* 引数 */
/* pat 出力パターン */
/* w 出力パターンに応じた曜日の名前を表わす文字列への */
/* ポインター(呼び出し元へ返却) */
/* 戻り値 */
/* 出力パターンに応じた曜日の名前を表わす文字列へのポインター */
/* (今回、呼び出し元では戻り値を特に使ってはいない) */
/*----------------------------------------------------------------------------*/
char *set_week_name(int pat, char *w)
{
static char *wname[] = { /* 曜日の名前 */
"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"
};
int i, j;
for (i = j = 0; i < DAYS_PER_WEEK; i++, j += format[pat].space) {
sprintf(&w[j], format[pat].week, wname[i]);
}
return w;
}
/*----------------------------------------------------------------------------*/
/* 春分の日・秋分の日の計算 */
/* */
/* 引数 */
/* y 年 */
/* 戻り値 */
/* なし */
/*----------------------------------------------------------------------------*/
void get_vernal_and_autumnal(int y)
{
int vernal; /* 春分の日の日にち */
int autumnal; /* 秋分の日の日にち */
int i;
/* 以下の計算式の出典は、
* 株式会社恒星社厚生閣発行 暦計算研究会編「新こよみ便利帳」
*/
if (y >= 2100) {
vernal = 21.8510 + 0.242194 * ((double) y - 1980.0) -
(int) (((double) y - 1980.0) / 4.0);
autumnal = 24.2488 + 0.242194 * ((double) y - 1980.0) -
(int) (((double) y - 1980.0) / 4.0);
}
else if (y >= 1980) {
vernal = 20.8431 + 0.242194 * ((double) y - 1980.0) -
(int) (((double) y - 1980.0) / 4.0);
autumnal = 23.2488 + 0.242194 * ((double) y - 1980.0) -
(int) (((double) y - 1980.0) / 4.0);
}
else if (y >= 1900) {
vernal = 20.8357 + 0.242194 * ((double) y - 1980.0) -
(int) (((double) y - 1983.0) / 4.0);
autumnal = 23.2588 + 0.242194 * ((double) y - 1980.0) -
(int) (((double) y - 1983.0) / 4.0);
}
else {
vernal = 19.8277 + 0.242194 * ((double) y - 1980.0) -
(int) (((double) y - 1983.0) / 4.0);
autumnal = 22.2588 + 0.242194 * ((double) y - 1980.0) -
(int) (((double) y - 1983.0) / 4.0);
}
/* 祝日テーブルにセット */
for (i = 0; national_holidays[i].month <= MONTHS_PER_YEAR; i++) {
if (national_holidays[i].day_or_week == 0) {
if (national_holidays[i].month == 3) {
national_holidays[i].day_or_week = vernal; /* 春分の日 */
}
if (national_holidays[i].month == 9) {
national_holidays[i].day_or_week = autumnal; /* 秋分の日 */
}
}
}
}
/*----------------------------------------------------------------------------*/
/* 毎月第1日曜日の日にちを求める */
/* */
/* 引数 */
/* y 年 */
/* 戻り値 */
/* なし */
/*----------------------------------------------------------------------------*/
void get_date_of_first_sunday(int y)
{
int m; /* 月 */
/* 毎月の初日の曜日をもとに、第1日曜日が何日であるかを求める
* 0以下の値になってもかまわない(出力しないだけのこと)
*/
for (m = 1; m <= MONTHS_PER_YEAR; m++) {
first_sunday[m] = 1 - day_of_week(y, m, 1);
}
}
/*----------------------------------------------------------------------------*/
/* カレンダーの出力 */
/* */
/* 引数 */
/* pat 出力パターン */
/* y 年 */
/* m 月 */
/* w 出力パターンに応じた曜日の名前を表わす文字列への */
/* ポインター */
/* 戻り値 */
/* なし */
/*----------------------------------------------------------------------------*/
void print_calendar(int pat, int y, int m, char *w)
{
/* 年・月のセット方法が同じとき */
if (year_is_set == month_is_set) {
print_one_month(pat, y, m, w); /* 1ヶ月分を出力 */
}
/* 年・月のセット方法が異なるとき(実質的には年だけを手でセットしたとき) */
else {
print_one_year(pat, y, w); /* 1年分を出力 */
}
}
/*----------------------------------------------------------------------------*/
/* 1ヶ月分のカレンダーの出力 */
/* */
/* 引数 */
/* pat 出力パターン */
/* y 年 */
/* m 月 */
/* w 出力パターンに応じた曜日の名前を表わす文字列への */
/* ポインター */
/* 戻り値 */
/* なし */
/*----------------------------------------------------------------------------*/
void print_one_month(int pat, int y, int m, char *w)
{
int len = strlen(w); /* 曜日用文字列の長さ */
int d; /* 日にち */
int u; /* 日曜日の日にち */
int i;
print_year_and_month_name(y, m, len); /* 年・月名の出力 */
print_new_line(1);
print_week_name(w); /* 曜日名の出力 */
print_new_line(1);
/* 月によっては6週にまたがることがある */
for (i = 0; i < WEEKS_PER_MONTH; i++) {
/* 第1日曜日から見かけ上の末日まで */
u = first_sunday[m] + i * DAYS_PER_WEEK;
for (d = u; d < u + DAYS_PER_WEEK; d++) {
print_date(pat, y, m, d, u); /* 日にちの出力 */
}
print_new_line(1); /* 週ごとに改行 */
}
}
/*----------------------------------------------------------------------------*/
/* 1年分のカレンダーの出力 */
/* */
/* 引数 */
/* pat 出力パターン */
/* y 年 */
/* w 出力パターンに応じた曜日の名前を表わす文字列への */
/* ポインター */
/* 戻り値 */
/* なし */
/*----------------------------------------------------------------------------*/
void print_one_year(int pat, int y, char *w)
{
int m; /* 月 */
int d; /* 日にち */
int u; /* 日曜日の日にち */
int h = format[pat].horizontal_months; /* 横方向に出力する月数 */
int len = strlen(w); /* 曜日用文字列の長さ */
int i, j;
/* 横方向に所定の月数分出力することを繰り返す */
for (i = 1; i <= MONTHS_PER_YEAR; i += h) {
for (m = i; m < i + h; m++) {
print_year_and_month_name(y, m, len); /* 年・月名の出力 */
print_space_between_months(pat, m); /* 月どうしの間隔・改行 */
}
for (m = i; m < i + h; m++) {
print_week_name(w); /* 曜日名の出力 */
print_space_between_months(pat, m); /* 月どうしの間隔・改行 */
}
/* 月によっては6週にまたがることがある */
for (j = 0; j < WEEKS_PER_MONTH; j++) {
for (m = i; m < i + h; m++) {
/* 第1日曜日から見かけ上の末日まで */
u = first_sunday[m] + j * DAYS_PER_WEEK;
for (d = u; d < u + DAYS_PER_WEEK; d++) {
print_date(pat, y, m, d, u); /* 日にちの出力 */
}
print_space_between_months(pat, m); /* 月どうしの間隔・改行 */
}
}
print_new_line(format[pat].vertical_space); /* 月どうしの行間 */
}
}
/*----------------------------------------------------------------------------*/
/* 年・月名の出力 */
/* */
/* 引数 */
/* y 年 */
/* m 月 */
/* len 出力パターンに応じた曜日の名前を表わす文字列の長さ */
/* 戻り値 */
/* なし */
/*----------------------------------------------------------------------------*/
void print_year_and_month_name(int y, int m, int len)
{
char str[LENGTH+1]; /* 年・月を格納 */
static char *mname[MONTHS_PER_YEAR+1] = { /* 月の名前 */
"",
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December",
};
sprintf(str, "%d %s", y, mname[m]); /* 年・月名 */
printf("%s", str);
/* 横方向に複数の月を出力する場合に備えて、年・月名の後ろに空白を空ける */
print_space(len - strlen(str));
}
/*----------------------------------------------------------------------------*/
/* 曜日名の出力 */
/* */
/* 引数 */
/* w 出力パターンに応じた曜日の名前を表わす文字列への */
/* ポインター */
/* 戻り値 */
/* なし */
/*----------------------------------------------------------------------------*/
void print_week_name(char *w)
{
printf("%s", w); /* 曜日名 */
}
/*----------------------------------------------------------------------------*/
/* 日にちの出力 */
/* */
/* 引数 */
/* pat 出力パターン */
/* y 年 */
/* m 月 */
/* d 日 */
/* u y年m月d日が属する週の日曜日の日にち */
/* 戻り値 */
/* なし */
/*----------------------------------------------------------------------------*/
void print_date(int pat, int y, int m, int d, int u)
{
static int daytab[][MONTHS_PER_YEAR+1] = { /* 毎月の日数 */
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, /* 平年 */
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, /* 閏年 */
};
int i;
if ((1 <= d) && (d <= daytab[leap(y)][m])) { /* 有効な日にち */
i = ((pat == NORMAL) || is_holiday(m, d, u)) ? 0 : 1;
printf(format[pat+i].date, d); /* パターンに従う */
}
else { /* 無効な日にち */
print_space(format[pat].space); /* 空白を出力 */
}
}
/*----------------------------------------------------------------------------*/
/* 日曜・祝日かどうかのチェック */
/* */
/* 引数 */
/* m 月 */
/* d 日 */
/* u その年のm月d日が属する週の日曜日の日にち */
/* 戻り値 */
/* TRUE 日曜・祝日である */
/* FALSE 日曜・祝日ではない */
/*----------------------------------------------------------------------------*/
Boolean is_holiday(int m, int d, int u)
{
int d_w; /* 日または週 */
int w; /* 曜日(0:日曜~6:土曜) */
/* 日にちが決まっている祝日の場合は負の数 */
int i;
/* 週の初日(日曜日) */
if (d == u) {
return TRUE;
}
for (i = 0; national_holidays[i].month <= m; i++) {
/* その月に祝日があれば */
if (m == national_holidays[i].month) {
d_w = national_holidays[i].day_or_week;
w = national_holidays[i].week;
/* 日にちが決まっている祝日 */
if ((w < 0) && (d == d_w)) {
return TRUE;
}
/* 祝日が日曜日と重なる場合、翌日は振替休日 */
if ((w < 0) && (u == d_w) && (d == u + 1)) { /* +1は月曜日 */
return TRUE;
}
/* 前項に加え、その日より後で祝日でない日が振替休日となる
* 現行の祝日法では、5月6日が月曜日~水曜日の場合が相当する
*/
if ((m == 5) && (d == 6) && (3 <= u) && (u <= 5)) {
return TRUE;
}
/* 第n○曜日(成人の日など) */
if ((w >= 0) && (d == u + w) &&
((d_w - 1) * DAYS_PER_WEEK < d) && (d <= d_w * DAYS_PER_WEEK)) {
return TRUE;
}
/* 前日と翌日がともに祝日である日は休日
* 現行の祝日法では、9月第3月曜日の敬老の日が21日で、
* 秋分の日が23日である場合に限り、それらの間にはさまれた
* 22日(火)が休日となる
* (法改正に伴ってロジックを修正する可能性が生じる)
*/
if ((m == 9) && (w < 0) && (d == d_w - 1) && /* 秋分の日の前日 */
(d == u + 2) && /* +2は火曜日 */
(d - 1 == DAYS_PER_WEEK * 3)) { /* 敬老の日が21日 */
return TRUE;
}
}
}
return FALSE;
}
/*----------------------------------------------------------------------------*/
/* 月どうしの間隔・改行 */
/* */
/* 引数 */
/* pat 出力パターン */
/* m 月 */
/* 戻り値 */
/* なし */
/*----------------------------------------------------------------------------*/
void print_space_between_months(int pat, int m)
{
if (m % format[pat].horizontal_months != 0) {
print_space(format[pat].horizontal_space); /* 月どうしの間隔 */
}
else {
print_new_line(1); /* 所定の月数分出力したら改行 */
}
}
/*----------------------------------------------------------------------------*/
/* 空白の出力 */
/* */
/* 引数 */
/* n 空白の数 */
/* 戻り値 */
/* なし */
/*----------------------------------------------------------------------------*/
void print_space(int n)
{
while (n--) {
putchar(' ');
}
}
/*----------------------------------------------------------------------------*/
/* 改行 */
/* */
/* 引数 */
/* n 改行の数 */
/* 戻り値 */
/* なし */
/*----------------------------------------------------------------------------*/
void print_new_line(int n)
{
while (n--) {
putchar('\n');
}
}
/*----------------------------------------------------------------------------*/
/* 曜日の計算(原典は坂本智彦氏によるコード) */
/* */
/* 引数 */
/* y 年 */
/* m 月 */
/* d 日 */
/* 戻り値 */
/* 0 日曜日(以下、1~6が月曜日~土曜日) */
/*----------------------------------------------------------------------------*/
int day_of_week(int y, int m, int d)
{
static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
y -= m < 3; /* 1~2月は前年とみなす */
return (y + y / 4 - y / 100 + y / 400 + t[m-1] + d) % 7;
}
/*----------------------------------------------------------------------------*/
/* 閏年かどうかのチェック */
/* */
/* 引数 */
/* y 年 */
/* 戻り値 */
/* 0 平年である */
/* 1 閏年である */
/*----------------------------------------------------------------------------*/
int leap(int y)
{
/* 「4で割り切れて100で割り切れない」または「400で割り切れる」年が閏年 */
return ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0);
}
/*----------------------------------------------------------------------------*/
/* エラーメッセージの出力 */
/* */
/* 引数 */
/* n エラー番号 */
/* 戻り値 */
/* なし */
/*----------------------------------------------------------------------------*/
void print_error_msg(int n)
{
static char *error_msg[] = { /* エラーメッセージ */
"オプションの指定が正しくありません。\n\n",
"年・月に負の数は指定できません。\n\n",
"年または月の値が正しくありません。\n\n",
};
fprintf(stderr, "E%03d:%s", n, error_msg[n]);
}
/*----------------------------------------------------------------------------*/
/* プログラムの使い方の出力 */
/* */
/* 引数 */
/* pgm プログラム名のフルパスを表わす文字列へのポインター */
/* 戻り値 */
/* なし */
/*----------------------------------------------------------------------------*/
void usage(char *pgm)
{
char *s = remove_path_and_extension(pgm); /* パスと拡張子の除去 */
fprintf(stderr, "<使い方>\n");
fprintf(stderr, "%s [-h | -?] [-n] [-s] [year [month]] <Enter>\n\n", s);
fprintf(stderr, " year :年(%d~%d)\n",
YEAR_LOWER_LIMIT, YEAR_UPPER_LIMIT);
fprintf(stderr, " month:月(%d~%d)\n\n",
MONTH_LOWER_LIMIT, MONTH_UPPER_LIMIT);
fprintf(stderr, " 年・月の両方を省略すると、現在の月のカレンダーを出力\n");
fprintf(stderr, " 年だけを指定して月を省略すると、その年のカレンダーを"
"出力\n");
fprintf(stderr, " 年・月の両方を指定すると、その年・月のカレンダーを"
"出力\n");
fprintf(stderr, " '-n'を指定すると、日曜・祝日のマークを付けない"
"(デフォルト)\n");
fprintf(stderr, " '-s'を指定すると、現行の祝日法に従った日曜・祝日の"
"マークを付ける\n");
fprintf(stderr, " '-h'または'-?'を指定すると、使い方を出力\n");
exit(EXIT_FAILURE);
}
/*----------------------------------------------------------------------------*/
/* パスと拡張子の除去 */
/* */
/* 引数 */
/* s プログラム名のフルパスを表わす文字列へのポインター */
/* (フルパスを受け取り、必要に応じてディレクトリーと */
/* 拡張子の部分を取り除いた結果を呼び出し元へ返す) */
/* 戻り値 */
/* プログラム名を表わす文字列へのポインター */
/*----------------------------------------------------------------------------*/
char *remove_path_and_extension(char *s)
{
char *str; /* 最も右にある'\'以降の文字列を指す */
int i;
/* 実行プログラム名のフルパスから、ディレクトリーと拡張子の部分を取り除く
* MS-DOSの流れを受け継ぐOSを想定し、ディレクトリー区切り文字を'\'とする
*/
str = strrchr(s, '\\'); /* 最も右にある'\'以降を求める */
if (str != NULL) { /* 求まったら */
str++; /* 1文字分進める */
i = strcspn(str, "."); /* 拡張子区切り文字までの文字数 */
strncpy(s, str, i); /* その文字数分だけコピー */
s[i] = '\0'; /* 文字列の終端 */
while (i--) { /* UNIXっぽくするため */
s[i] = (char) tolower(s[i]); /* 小文字に変換 */
}
}
/* ディレクトリー区切り文字がなければ、そのまま戻る */
return s;
}