C语言实现cal命令

戏子无情 提交于 2020-01-27 22:13:37
/* Jan 26 2020 14:29 */

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

#define WEEKDAY 7

typedef struct _Date
{
    int year;  // 当前的年份
    int month; // 当前的月份
    int mday;  // 当月的经过的天数
    int wday;  // 从星期天开始经过的天数
} Date;

Date get_now_time();
int  is_leap_year(int year);
char *month_name(int n);
int  get_weekdays(Date date);
void display_date(Date date);
void set_color(int flag);
int get_month_days(int mon, int year);

/* 获取当前时间 */
Date get_now_time()
{
    time_t now;
    struct tm *tp;
    Date now_time;

    time(&now);
    tp = localtime(&now);
    now_time.year  = tp->tm_year + 1900;
    now_time.month = tp->tm_mon  + 1;
    now_time.mday  = tp->tm_mday;
    now_time.wday  = tp->tm_wday;
    return now_time;
}

/* 获取月份的名称 */
char *month_name(int n)
{
    static char *name[] = {
        "Illegal month",
        "January", "February", "March",
        "April", "May", "June",
        "July", "August", "September",
        "October", "November", "December"
    };
    return (n < 1 || n > 12) ? name[0] : name[n];
}

/* 获取每一年的一号的星期数 */
int get_weekdays(Date date)
{
    return (date.year-1+(date.year-1)/4-(date.year-1)/100+(date.year-1)/400+365) % 7;
}

/* 判断是否为闰年 */
int is_leap_year(int year)
{
    return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
}

/* 获取月份的天数 */
int get_month_days(int mon, int year)
{
    int leap;
    static char month_days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    leap = is_leap_year(year);
    if (leap)
        month_days[1] = 29;

    return (mon < 1 || mon > 12) ? month_days[0] : month_days[mon-1];
}

/* 打印日历表格 */
void display_date(Date date)
{
    int i, j;
    Date cal;
    int n = 0;
    int weekday, days = 0;

    cal = get_now_time();
    if (cal.month == date.month)
        n = 1;
    // 获取星期数
    weekday = get_weekdays(date);

    // 获取总天数
    for (i = 1; i <= date.month - 1; i++) {
        days += get_month_days(i, date.year);
    }

    // 获取n月1号的星期数
    weekday += days % WEEKDAY;
    if (weekday > WEEKDAY)
        weekday %= WEEKDAY;

    // 打印表格
    printf("    %s %d\n", month_name(date.month), date.year);
    printf("Su Mo Tu We Th Fr Sa\n");
    for (i = 1; i <= weekday; i++)
        printf("   ");
    for (j = 1; j <= get_month_days(date.month, date.year); i++, j++) {
        if ((i-1) % WEEKDAY == 0)
            printf("\n");
        if (j == date.mday && n == 1) {
            set_color(112);
            printf("%2d", j);
            set_color(7);
            printf(" ");
        }
        else
            printf("%2d ", j);
    }
    printf("\n");
}

/* 设置控制台颜色 */
void set_color(int flag)
{
    HANDLE out;
    // 获取句柄
    out = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(out, flag);
}

int main(int argc, char *argv[])
{
    Date date;
    int found = 0;
    int mon = 0;
    /* cal 或者 cal -m 月份 */
    while (--argc > 0 && (*++argv)[0] == '-')
        // 获取参数
        if (*++argv[0] == 'm') {
            mon = atoi(*++argv);
            if (mon < 1 || mon > 12)
                break;
            found = 1;
            break;
        }
    if (argc == 0) {
        date = get_now_time();
        display_date(date);
    }
    else {
        if (found == 1) {
            date = get_now_time();
            date.month = mon;
            display_date(date);
        }
    }
    return 0;
}

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!