[Lập trình C] Xếp lịch trực nhật

Monday, May 18, 2020
Edit this post

https://pixabay.com/photos/female-diary-journal-write-865110/

Viết chương trình tạo lịch trực cho 5 bạn: A, B, C, D, E. Nhập vào năm và tháng cần xếp lịch. Sau đó in lịch trực của tháng đó. Lưu ý: 5 bạn trực lần lượt theo thứ tự trên, ngày Chủ nhật nhật không trực và bạn A sẽ trực ngày đầu tiên của năm.

Ví dụ kết quả chạy chương trình:


2006 5                                                                                                                          
    Sun    Mon    Tue    Wed    Thu    Fri    Sat                                                                               
         1 [C]  2 [D]  3 [E]  4 [A]  5 [B]  6 [C]                                                                               
  7 [ ]  8 [D]  9 [E] 10 [A] 11 [B] 12 [C] 13 [D]                                                                               
 14 [ ] 15 [E] 16 [A] 17 [B] 18 [C] 19 [D] 20 [E]                                                                               
 21 [ ] 22 [A] 23 [B] 24 [C] 25 [D] 26 [E] 27 [A]                                                                               
 28 [ ] 29 [B] 30 [C] 31 [D]                                                                                                    
                                                            

Cách tiếp cận của tôi

Tôi sẽ implement các hàm sau:

- Hàm getDow(day, month, year) tính thứ theo ngày tháng năm dựa vào công thức Zeller cho lịch Gregorian.
- Hàm isLeapYear(year) xác định một năm là năm nhuận hay không.
- Hàm getTop(month, year) trả về số ngày tối đa của một tháng trong năm.
- Hàm getPerson(month, year) trả về người trực đầu tiên của tháng bất kỳ.

Cách implement 3 hàm ở trên, các bạn có thể tham khảo ở đây. Riêng hàm getTop(month, year) thì các bạn có thể xem ở bên dưới.

Coi nhóm bạn như một mảng 5 phần tử {"A", "B", "C", "D", "E"} có index từ 0 tới 4. Tiếp theo tôi sẽ check từng tháng bắt đầu từ tháng 1 cho tới tháng kế cuối. Vì lịch của tôi là lịch bắt đầu từ Chủ Nhật nên với int dow = getDow() = {0, ..., 6} sẽ ứng với {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}. Ví dụ với ngày đầu tiên của tháng 1 năm 2006 là Thứ hai tức int dow = getDow(1, 2006). Chúng ta sẽ dùng một biến index = 0 (tương đương với bạn A). Sau đó quét qua toàn bộ ngày trong tháng. Nếu đó là ngày Chủ Nhật ( (i + dow) % 7 == 0 ) thì index không tăng, ngược lại index tăng 1 đơn vị. Nếu index = 5, tức vượt quá kích thước mảng 5 phần tử ban đầu thì reset index = 0 tức quay về lại bạn A. Sau khi thoát ra khỏi vòng lặp thì lúc này index đang ở vị trí cuối tháng, chỉ cần tăng index lên 1 thì bạn sẽ có index của người đầu tiên phải trực cho tháng kế tiếp.

Bài giải


#include <stdio.h>

int isLeapYear(int y) {
    return (!(y % 4) && y % 100) || !(y % 400);
}

int getDow(int q, int m, int y) {
    if (m == 1) { m = 13; y--; }
    if (m == 2) { m = 14; y--; }
    int k = y % 100;
    int j = y / 100;
    int h = q + (13 * (m + 1)) / 5 + k + k / 4 + j / 4 + 5 * j;
    h = h % 7;
    return h == 0 ? 6 : h - 1;
}

int getTop(int month, int year) {
    int top;
    switch(month) {
        case 4: case 6: case 9: case 11: top = 30; break;
        case 2: top = isLeapYear(year) ? 29 : 28; break;
        default: top = 31; break;
    }
    return top;
}

int getFirstPerson(int month, int year) {
    int index = -1;
    for  (int m = 1; m < month; m++) {
        int dow = getDow(1, m, year);
        int top = getTop(m, year);
        for (int i = 0; i < top; i++) {
            if ((i + dow) % 7 != 0) index++;
            if (index == 5) index = 0;
        }
    }
    index++;
    return index == 5 ? 0 : index;
}

int main() {
    char days[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
    char student[5][2] = {"A", "B", "C", "D", "E"};
    int year, month, cols = 7;
    scanf("%d%d", &year, &month);
    
    int dow = getDow(1, month, year);
    int top = getTop(month, year);
    
    for (int i = 0; i < cols; i++)
        printf("%7s", days[i]);
    printf("\n");
    for (int i = 0; i < dow; i++) printf("%7s", " ");
    int index = getFirstPerson(month, year);
    for (int i = 0; i < top; i++) {
        (i + dow) % 7 == 0 ? printf("%3d [ ]", i + 1) : printf("%3d [%s]", i + 1, student[index++]);
        if (index == 5) index = 0;
        if ((i + dow + 1) % cols == 0) printf("\n");
    }

    return 0;
}

.
Xin vui lòng chờ đợi
Dữ liệu bài viết đang được tải về

© Copyright by CUỘC SỐNG TỐI GIẢN
Loading...