Todo List - Console Application

อธิบายโค้ดโปรแกรม Todo List ภาษา C แบบเข้าใจง่าย

ภาพรวมของโปรแกรม

โค้ดนี้เป็นโปรแกรมจัดการรายการสิ่งที่ต้องทำ (Todo List) แบบ Command Line Interface ภาษา C ที่ช่วยให้ผู้ใช้สามารถจัดการงานต่างๆ ได้ เช่น เพิ่มงาน, แสดงงาน, ทำเครื่องหมายว่าเสร็จสิ้น, ลบงาน, แก้ไขงาน, และบันทึกงานลงไฟล์ ฯลฯ โปรแกรมนี้ใช้ Windows API สำหรับแสดงข้อความสีต่างๆ ในคอนโซล

โครงสร้างข้อมูลที่สำคัญ

โปรแกรมใช้โครงสร้างข้อมูล (struct) ชื่อ task สำหรับเก็บข้อมูลของแต่ละงาน และใช้อาร์เรย์ list[] ในการเก็บรายการงานทั้งหมด

โครงสร้าง task
typedef struct {
    char des[LG];  // คำอธิบายงาน (description)
    int prio;      // ความสำคัญของงาน (priority) 1-10
    int day;       // วันที่กำหนดส่ง
    int month;     // เดือนที่กำหนดส่ง
    int year;      // ปีที่กำหนดส่ง
    int comp;      // สถานะว่าเสร็จสิ้นหรือไม่ (0=ยังไม่เสร็จ, 1=เสร็จแล้ว)
} task;
ตัวแปรสำคัญ
task list[TK];  // อาร์เรย์เก็บงานสูงสุด TK รายการ (ค่า TK = 100)
int numt = 0;   // จำนวนงานที่มีในปัจจุบัน
จัดการงานได้หลากหลาย

สามารถเพิ่ม, แสดง, ทำเครื่องหมายว่าเสร็จสิ้น, ลบ, และแก้ไขงานได้

ระบบไฟล์สำหรับบันทึกและโหลดข้อมูล

บันทึกและโหลดข้อมูลงานจากไฟล์ได้ รวมถึงมีระบบสำรองข้อมูล (Backup)

การแสดงผลสีสัน

ใช้ Windows API เพื่อแสดงผลสีต่างๆ ในคอนโซล ทำให้ UI น่าใช้งานมากขึ้น

เครื่องมือจัดการและแสดงความคืบหน้า

มีฟีเจอร์การแสดงกราฟความคืบหน้า และการจัดเรียงงานตามความสำคัญ

ฟังก์ชันหลักของโปรแกรม

addtask()

ฟังก์ชันสำหรับเพิ่มงานใหม่เข้าไปในรายการ

void addtask(char des[], int prio, int day, int month, int year) {
    if (numt < TK) {
        strcpy(list[numt].des, des);  // คัดลอกคำอธิบายงาน
        list[numt].prio = prio;       // กำหนดความสำคัญ
        list[numt].day = day;         // กำหนดวัน
        list[numt].month = month;     // กำหนดเดือน
        list[numt].year = year;       // กำหนดปี
        list[numt].comp = 0;          // เริ่มต้นด้วยสถานะยังไม่เสร็จ
        numt++;                       // เพิ่มจำนวนงาน
        
        // แสดงข้อความว่าเพิ่มงานสำเร็จด้วยสีเขียว
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
        printf("Task added successfully!\n");
        // รีเซ็ตสีกลับเป็นสีเริ่มต้น
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
    } else {
        // แสดงข้อความว่ารายการเต็มด้วยสีแดง
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY);
        printf("Sorry list is full.\n");
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
    }
}
output()

ฟังก์ชันสำหรับแสดงรายการงานทั้งหมด

void output() {
    if (numt == 0) {
        // แสดงข้อความว่าไม่มีงานด้วยสีแดง
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY);
        printf("No tasks found.\n");
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
    } else {
        printf("To-Do List:\n");
        for (int i = 0; i < numt; i++) {
            // แสดงรายละเอียดของแต่ละงาน
            printf("%d. %s - Priority: %d - Date: %02d/%02d/%d - %s\n", 
                i + 1, list[i].des, list[i].prio, list[i].day, list[i].month, 
                list[i].year, list[i].comp ? "Complete" : "Incomplete");
        }
    }
}
mark()

ฟังก์ชันสำหรับทำเครื่องหมายว่างานเสร็จสิ้นแล้ว

void mark(int index) {
    if (index >= 0 && index < numt) {
        list[index].comp = 1;  // เปลี่ยนสถานะเป็นเสร็จสิ้น
        // แสดงข้อความยืนยันด้วยสีเขียว
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
        printf("Task marked as complete.\n");
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
    } else {
        // แสดงข้อความว่าดัชนีไม่ถูกต้องด้วยสีแดง
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY);
        printf("Invalid task index.\n");
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
    }
}
Delete()

ฟังก์ชันสำหรับลบงานออกจากรายการ

void Delete(int indexdl) {
    if (indexdl >= 0 && indexdl < numt) {
        // เลื่อนรายการทั้งหมดที่อยู่หลังรายการที่ต้องการลบขึ้นมา 1 ตำแหน่ง
        for (int i = indexdl; i < numt - 1; i++) {
            strcpy(list[i].des, list[i + 1].des);
            list[i].prio = list[i + 1].prio;
            list[i].day = list[i + 1].day;
            list[i].month = list[i + 1].month;
            list[i].year = list[i + 1].year;
            list[i].comp = list[i + 1].comp;
        }
        numt--;  // ลดจำนวนงานลง 1
        // แสดงข้อความยืนยันการลบด้วยสีเขียว
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
        printf("Task deleted successfully.\n");
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
    } else {
        // แสดงข้อความว่าดัชนีไม่ถูกต้องด้วยสีแดง
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY);
        printf("Invalid task index.\n");
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
    }
}

การจัดการไฟล์และการสำรองข้อมูล

save()

ฟังก์ชันสำหรับบันทึกรายการงานลงในไฟล์ในโฟลเดอร์ที่กำหนด

void save(const char *foldername) {
    char filename[LG];
    sprintf(filename, "%s/ku101.txt", foldername);  // สร้างพาธไฟล์

    if (_mkdir(foldername) == -1) {  // สร้างโฟลเดอร์
        // แสดงข้อความผิดพลาดถ้าสร้างโฟลเดอร์ไม่สำเร็จ
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY);
        printf("Error: Unable to create folder '%s'.\n", foldername);
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
        return;
    }

    FILE *file = fopen(filename, "w");  // เปิดไฟล์สำหรับเขียน
    if (file != NULL) {
        // เขียนข้อมูลแต่ละงานลงในไฟล์
        for (int i = 0; i < numt; i++) {
            fprintf(file, "%s|%d|%d|%d|%d|%d\n", 
                list[i].des, list[i].prio, list[i].day, 
                list[i].month, list[i].year, list[i].comp);
        }
        fclose(file);
        // แสดงข้อความยืนยันการบันทึกด้วยสีเขียว
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
        printf("Tasks saved to folder '%s' successfully.\n", foldername);
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
    } else {
        // แสดงข้อความผิดพลาดถ้าไม่สามารถบันทึกไฟล์ได้
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY);
        printf("Error: Unable to save tasks to folder '%s'.\n", foldername);
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
    }
}
load()

ฟังก์ชันสำหรับโหลดรายการงานจากไฟล์ในโฟลเดอร์ที่กำหนด

void load(const char *foldername) {
    char filename[NAME];
    sprintf(foldername, "%s/ku101.txt", foldername);  // สร้างพาธไฟล์
    FILE *file = fopen(foldername, "r");  // เปิดไฟล์สำหรับอ่าน
    if (file != NULL) {
        char temp[LG];
        int prio, day, month, year, comp;
        // อ่านข้อมูลจากไฟล์ทีละบรรทัด
        while (fgets(temp, LG, file) != NULL) {
            // แยกข้อมูลโดยใช้ | เป็นตัวคั่น
            sscanf(temp, "%[^|]|%d|%d|%d|%d|%d", 
                list[numt].des, &prio, &day, &month, &year, &comp);
            list[numt].prio = prio;
            list[numt].day = day;
            list[numt].month = month;
            list[numt].year = year;
            list[numt].comp = comp;
            numt++;  // เพิ่มจำนวนงาน
        }
        fclose(file);
        // แสดงข้อความยืนยันการโหลดด้วยสีเขียว
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
        printf("Tasks loaded from folder '%s' successfully.\n", foldername);
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
    } else {
        // แสดงข้อความผิดพลาดถ้าไม่สามารถโหลดไฟล์ได้
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY);
        printf("Error: Unable to load tasks from folder '%s'.\n", foldername);
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
    }
}

ฟีเจอร์พิเศษ

setprio()

ฟังก์ชันสำหรับจัดเรียงงานตามความสำคัญ (จากมากไปน้อย)

void setprio() {
    // จัดเรียงโดยใช้ Bubble Sort
    for (int i = 0; i < numt - 1; i++) {
        for (int j = 0; j < numt - i - 1; j++) {
            if (list[j].prio < list[j + 1].prio) {
                // สลับตำแหน่งของงาน
                task temp = list[j];
                list[j] = list[j + 1];
                list[j + 1] = temp;
            }
        }
    }
    printf("Tasks sorted by priority.\n");
}
showPG()

ฟังก์ชันสำหรับแสดงกราฟความคืบหน้าของงานด้วยสัญลักษณ์

void showPG() {
    printf("Progress Graph:\n");
    for (int i = 0; i < numt; i++) {
        printf("%d. %s - ", i + 1, list[i].des);
        // แสดงแถบความสำคัญด้วยสัญลักษณ์ # และสีรุ้ง
        for (int j = 0; j < 10; j++) {
            if (j < list[i].prio) {
                const char *message = "#";
                rainbow(message);  // แสดงสัญลักษณ์ # ด้วยสีรุ้ง
            } else {
                printf("-");  // แสดงขีด - สำหรับส่วนที่เหลือ
            }
        }
        printf(" - %s\n", list[i].comp ? "Completed" : "Incomplete");
    }
}
rainbow()

ฟังก์ชันสำหรับแสดงข้อความด้วยสีรุ้ง

void rainbow(char *text) {
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hConsole == INVALID_HANDLE_VALUE) {
        fprintf(stderr, "Failed to get console handle\n");
        return;
    }

    // แสดงข้อความเดียวกันด้วยสีต่างๆ ตามลำดับเพื่อสร้างเอฟเฟกต์สีรุ้ง
    SetConsoleTextAttribute(hConsole, FOREGROUND_RED);
    printf("%s", text);

    SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN);
    printf("%s", text);

    SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE);
    printf("%s", text);

    SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN);
    printf("%s", text);

    SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_BLUE);
    printf("%s", text);

    SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN | FOREGROUND_BLUE);
    printf("%s", text);

    // คืนค่าสีกลับเป็นสีเริ่มต้น
    SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}

ฟังก์ชัน main() - โปรแกรมหลัก

ฟังก์ชัน main() เป็นฟังก์ชันหลักของโปรแกรม แสดงเมนูให้ผู้ใช้เลือกฟังก์ชันการทำงานต่างๆ และทำงานตามที่ผู้ใช้เลือก

int main() {
    int choice, index, prio, day, month, year;
    char des[LG], newdes[LG];
    char foldername[NAME];
    HANDLE hConsole;

    printf("Welcome to the To-Do List Program!");
    do {
        // แสดงเมนูด้วยสีม่วง-ฟ้า
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY); 
        printf("\n1. Add Task\n2. Display Tasks\n3. Mark Task as Complete\n4. Delete Task\n5. Edit Task\n");
        printf("6. Clear All Tasks\n7. Save Tasks to Folder\n8. Load Tasks from Folder\n9. Sort Tasks by Priority\n");
        printf("10. Show Progress Graph\n11. Backup Tasks\n12. Restore Tasks\n13. Quit\n");
        printf("------------------------------------------------------------------------------------------------------------------------\n");
        
        // รีเซ็ตสีกลับเป็นสีเริ่มต้น
        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); 
        printf("Enter your choice: ");
        scanf("%d", &choice);

        // ประมวลผลตามตัวเลือกที่ผู้ใช้เลือก
        switch (choice) {
            case 1:  // เพิ่มงาน
                // รับข้อมูลจากผู้ใช้และตรวจสอบความถูกต้อง
                // ...
                addtask(des, prio, day, month, year);
                break;
            case 2:  // แสดงงาน
                output();
                break;
            case 3:  // ทำเครื่องหมายว่าเสร็จสิ้น
                printf("Enter the index of the task to mark as complete: ");
                scanf("%d", &index);
                mark(index - 1);
                break;
            // ตัวเลือกอื่นๆ...
            case 13:  // ออกจากโปรแกรม
                printf("Exiting program...\n");
                break;
            default:  // ตัวเลือกไม่ถูกต้อง
                SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY);
                printf("Invalid choice. Please enter a number between 1 and 13.\n");
                SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
        }
    } while (choice != 13);  // ทำงานวนซ้ำจนกว่าผู้ใช้จะเลือกออกจากโปรแกรม

    return 0;
}

สรุปการทำงานของโปรแกรม

  1. โปรแกรมนี้เป็นแอปพลิเคชัน Todo List แบบ Command Line Interface
  2. ใช้ภาษา C และ Windows API ในการสร้างส่วนติดต่อผู้ใช้ที่มีสีสัน
  3. มีความสามารถในการจัดการงานหลายรูปแบบ เช่น เพิ่ม, แสดง, ลบ, แก้ไข
  4. สามารถบันทึกและโหลดข้อมูลจากไฟล์ได้
  5. มีฟีเจอร์พิเศษเช่น การสำรองข้อมูล, การเรียงลำดับตามความสำคัญ, และการแสดงกราฟความคืบหน้า
  6. ใช้โครงสร้างข้อมูลอาร์เรย์ของ struct เพื่อเก็บรายการงาน

ข้อจำกัดและสิ่งที่ควรปรับปรุง