[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ề

💻Nhận dạy online 1 kèm 1 Automation Test từ cơ bản tới nâng cao (From Zero to Hero) 😁😁😁
Lộ trình gồm 3 phần:
1) Kỹ thuật lập trình và tư duy lập trình cơ bản
2) Nhập môn kiểm thử (Manual Test)
3) Kiểm thử tự động (Automation Test) + Chuẩn bị cho phỏng vấn
* Lộ trình chi tiết: Xem tại đây

🎓Đối tượng người học:
- Những bạn bị mất gốc căn bản môn lập trình.
- Những bạn muốn theo con đường kiểm thử (testing), đặc biệt là kiểm thử tự động (Automation Test).

🦘Người giảng dạy:
- Mình sẽ là người trực tiếp hướng dẫn.
- Nếu là các vấn đề ngoài chuyên môn hoặc sở trường, mình sẽ nhờ các anh chị em khác cũng làm trong ngành.

🤓Giới thiệu:
- Mình đã có hơn 10 năm kinh nghiệm làm IT ở cả trong và ngoài nước. Trong đó 3 năm đầu là làm lập trình viên Java, sau đó bén duyên với mảng Automation Test và theo nghề tới tận bây giờ. Mình được đào tạo chính quy về IT từ một trường Đại học danh tiếng ở TP.HCM (hệ kỹ sư 4 năm rưỡi), có chứng chỉ ISTQB, có thể giao tiếp tốt bằng tiếng Anh và có kinh nghiệm làm việc thực tế ở cả 2 mảng Outsource và Product. Title chính thức của mình là QA Automation Engineer, tuy nhiên, mình vẫn làm những dự án cá nhân chuyên về lập trình ứng dụng như Học Tiếng Anh StreamlineSách Nhạc. Mình là người có thái độ làm việc chuyên nghiệp, chăm chỉ và luôn nhiệt tình trong công việc.

💵Chi phí và hình thức thanh toán:
- Các bạn vui lòng liên hệ qua email songtoigianvn@gmail.com (email, chat, hoặc call) để book nội dung và khung giờ học (từ 8h tối trở đi).
- Mức phí: 150.000đ/buổi, mỗi buổi 60 phút.
- Lộ trình From Zero to Hero: 4.350.000đ (29 buổi).
- Bạn có thể học riêng và đóng tiền theo từng phần nếu muốn.
- Có thể học trước 1-2 buổi trước khi quyết định đi full lộ trình hoặc từng phần.
- Thanh toán qua Momo, chuyển khoản v.v...
BÌNH LUẬN
© Copyright by CUỘC SỐNG TỐI GIẢN
Loading...