อธิบายโค้ดโปรแกรม Todo List ภาษา C แบบเข้าใจง่าย
โค้ดนี้เป็นโปรแกรมจัดการรายการสิ่งที่ต้องทำ (Todo List) แบบ Command Line Interface ภาษา C ที่ช่วยให้ผู้ใช้สามารถจัดการงานต่างๆ ได้ เช่น เพิ่มงาน, แสดงงาน, ทำเครื่องหมายว่าเสร็จสิ้น, ลบงาน, แก้ไขงาน, และบันทึกงานลงไฟล์ ฯลฯ โปรแกรมนี้ใช้ Windows API สำหรับแสดงข้อความสีต่างๆ ในคอนโซล
โปรแกรมใช้โครงสร้างข้อมูล (struct) ชื่อ task
สำหรับเก็บข้อมูลของแต่ละงาน และใช้อาร์เรย์ list[]
ในการเก็บรายการงานทั้งหมด
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 น่าใช้งานมากขึ้น
มีฟีเจอร์การแสดงกราฟความคืบหน้า และการจัดเรียงงานตามความสำคัญ
ฟังก์ชันสำหรับเพิ่มงานใหม่เข้าไปในรายการ
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);
}
}
ฟังก์ชันสำหรับแสดงรายการงานทั้งหมด
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");
}
}
}
ฟังก์ชันสำหรับทำเครื่องหมายว่างานเสร็จสิ้นแล้ว
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);
}
}
ฟังก์ชันสำหรับลบงานออกจากรายการ
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);
}
}
ฟังก์ชันสำหรับบันทึกรายการงานลงในไฟล์ในโฟลเดอร์ที่กำหนด
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);
}
}
ฟังก์ชันสำหรับโหลดรายการงานจากไฟล์ในโฟลเดอร์ที่กำหนด
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);
}
}
ฟังก์ชันสำหรับจัดเรียงงานตามความสำคัญ (จากมากไปน้อย)
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");
}
ฟังก์ชันสำหรับแสดงกราฟความคืบหน้าของงานด้วยสัญลักษณ์
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");
}
}
ฟังก์ชันสำหรับแสดงข้อความด้วยสีรุ้ง
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() เป็นฟังก์ชันหลักของโปรแกรม แสดงเมนูให้ผู้ใช้เลือกฟังก์ชันการทำงานต่างๆ และทำงานตามที่ผู้ใช้เลือก
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;
}