ในบทนี้ นักเรียนจะได้เรียนรู้เกี่ยวกับเวลาในภาษา C เราจะพูดถึงการอ่านค่าเวลาจากระบบ การวัดความแตกต่างของเวลา และการทำงานอื่นๆ เกี่ยวกับเวลา ในภาษา C มีฟังก์ชันจากไลบรารี่มาตรฐาน time.h
สำหรับการทำงานกับเวลา นี่เป็นเนื้อหาในบทนี้
- ระบบเวลาในคอมพิวเตอร์ Unix time
- การแสดงวันที่และเวลาปัจจุบัน
- โครงสร้างข้อมูลของเวลา struct tm
- การแสดงเวลาใน Time zone อื่นๆ
- การหาผลต่างของเวลา
- การวัดประสิทธิภาพของโปรแกรม
เวลา (Time) คือการดำเนินไปอย่างต่อเนื่องของการดำรงอยู่และเหตุการณ์ต่างๆ ที่เกิดขึ้นอย่างไม่สามารถย้อนกลับได้ เวลาเดินทางจากอดีตถึงปัจจุบัน และไปยังอนาคต และในคอมพิวเตอร์ เวลาจะเริ่มนับจาก Unix epoch
Unix time #
สิ่งแรกที่นักเรียนควรรู้จักเกี่ยวกับเวลาในการเขียนโปรแกรมคอมพิวเตอร์ก็ Unix timestamp; Unix time เป็นระบบสำหรับอธิบายจุดของเวลาในคอมพิวเตอร์ มันคือจำนวนของวินาทีที่ผ่านไปโดยนับตั้งแต่ Unix epoch ซึ่งจุดนี้ของเวลานั้นเท่ากับวันที่ 1 มกราคม 1970 เวลา 00:00:00 UTC และ Unix time เริ่มต้นนับจากที่นี่
time
#include <stdio.h>
#include <time.h>
int main()
{
time_t now;
time(&now);
printf("%ld seconds ", now);
printf("since January 1, 1970 00:00:00 UTC");
return 0;
}
1595266585 seconds since January 1, 1970 00:00:00 UTC
ในตัวอย่าง เป็นการใช้งานฟังก์ชัน time
เพื่อรับเอาเวลาปัจจุบันจากระบบและแสดงผลเวลาออกทางหน้าจอในรูปแบบของ Timestamp หรือ Unix time โดยค่าที่ส่งกลับมาจากฟังก์ชัน time นั้นมีประเภทข้อมูลเป็น time_t
ซึ่งเป็นจำนวนของวินาทีที่ผ่านไปตั้งแต่ Unix epoch
time_t now;
ในคำสั่งแรก เราได้ประกาศตัวแปร now
สำหรับเก็บค่าเวลาปัจจุบันก่อน โดยตัวแปรนี้มีประเภทข้อมูลเป็น time_t
มันเป็นประเภทข้อมูลที่ถูกกำหนดขึ้นในไลบรารี่ time.h
มันสามารถใช้สำหรับเก็บเวลาในจุดใดๆ
time(&now);
หลังจากนั้นเราเรียกใช้ฟังก์ชัน time
โดยการส่งค่าที่อยู่ (&now
) หรือพอบยน์เตอร์ของตัวแปร now
เป็นพารามิเตอร์ของฟังก์ชัน และในตอนนี้ค่าของเวลาปัจจุบันจะถูกเก็บในตัวแปร now
printf("%d seconds ", now);
จากนั้นเราแสดงผลค่าของเวลาปัจจุบันออกทางหน้าจอ เราสามารถแปลงค่าของ time_t
ไปเป็นตัวเลขได้โดยตรง โดยการใช้ Specifier การแสดงผลแบบตัวเลข %d
อีกรูปแบบหนึ่งสำหรับการรับเอาเวลาปัจจุบันด้วยฟังก์ชัน time
นักเรียนสามารถส่งค่าพารามิเตอร์เป็น NULL
เข้าไปยังฟังก์ชันได้ และค่าที่ส่งกลับมาจะเป็น time_t
นี่เป็นตัวอย่าง
time_t now = time(NULL);
NULL
เข้าไปยังฟังก์ชัน
การแสดงวันที่และเวลาปัจจุบัน #
Timestamp หรือ Unix time เป็นรูปแบบของเวลาที่ใช้สำหรับคอมพิวเตอร์ และเพื่อให้มนุษย์สามารถเข้าใจเวลาดังกลาวได้ง่ายขึ้น เราสามารถแปลงมันไปยังรูปแบบเวลาของปฏิทินเหมือนที่เราคุ้นเคยในชีวิตประจำวันได้ โดยการใช้ฟังก์ชัน ctime
นี่เป็นตัวอย่าง
#include <stdio.h>
#include <time.h>
int main()
{
time_t now;
time(&now);
printf("The current local time is: %s", ctime(&now));
printf("The current timestamp is: %ld", now);
return 0;
}
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
The current local time is: Tue Jul 21 01:19:45 2020
The current timestamp is: 1595269185
ในตัวอย่าง เราได้แปลงเวลาจาก Unix time เป็นรูปแบบเวลาของปฏิทินโดยการใช้ฟังก์ชัน ctime
ฟังก์ชันนี้ส่งค่ากลับเป็น String ของเวลาปัจจุบันในรูปแบบที่เราสามารถอ่านเข้าใจได้ง่าย มันรับพารามิเตอร์เป็นที่อยู่ของตัวแปร now
เพื่อทำงาน สังเกตเครื่องหมาย &
หน้าตัวแปรในตอนเรียกฟังก์ชัน
โครงสร้างข้อมูลของเวลาหรือ struct tm นั้นเป็นประเภทข้อมูลที่ถูกกำหนดไว้ในไลบรารี่ time.h
มันเป็นโครงสร้างข้อมูลที่เก็บองประกอบต่างๆ ของเวลาแยกออกจากกัน นี่จะทำให้เราสามารถเข้าถึงบางส่วนของเวลาได้ เช่น วันของสัปดาห์ เป็นต้น
เนื่องจากเวลาแบบ time_t
นั้นเก็บค่าเป็น Timestamp จะเป็นยังไงถ้าเราต้องการข้อมูลเพิ่มเติมเกี่ยวกับเวลา เช่น เราต้องการทราบว่าวันในสัปดาห์คือวันอะไร เพื่อเข้าถึงข้อมูลดังกล่าว เราสามารถแปลง time_t
เป็นโครงสร้างข้อมูลของเวลาหรือ struct tm
ได้ นี่เป็นตัวอย่าง
#include <stdio.h>
#include <time.h>
int main()
{
time_t rawtime;
struct tm * local;
// Get current time
time(&rawtime);
// Convert to time structure
local = localtime(&rawtime);
printf("The current local time is: %s", ctime(&rawtime));
printf("The current timestamp is: %ld\n", rawtime);
// Accessing time components
printf("Week day: %d\n", local->tm_wday);
printf("Year: %d\n", local->tm_year);
printf("Month: %d\n", local->tm_mon);
printf("Day: %d\n", local->tm_mday);
printf("Hour: %d\n", local->tm_hour);
printf("Minute: %d\n", local->tm_min);
printf("Second: %d\n", local->tm_sec);
return 0;
}
The current local time is: Tue Jul 21 01:56:15 2020
The current timestamp is: 1595271375
Week day: 2
Year: 120
Month: 6
Day: 21
Hour: 1
Minute: 56
Second: 15
ในตัวอย่าง เราได้แสดงเวลาปัจจุบันและค่า Timestamp ออกมาทางหน้าจอเหมือนกับในตัวอย่างก่อนหน้า แต่สิ่งที่เพิ่มเข้ามาในตัวอย่างนี้ เราสามารถเข้าถึงส่วนประกอบต่างๆ ของเวลาที่ต้องการได้จากโครงสร้างของเวลา struct tm
ในตัวแปร local
struct tm * local;
ในคำสั่งนี้เป็นการประกาศตัวแปรพอยน์เตอร์สำหรับ struct tm
ที่ชื่อว่า local
สำหรับเก็บส่วนประกอบของเวลา
// Get current time
time(&rawtime);
// Convert to time structure
local = localtime(&rawtime);
เรารับค่าเวลาปัจจุบันมาเก็บไว้ในตัวแปร rawtime
และจากนั้นแปลงเวลาปัจจุบันเป็นโครงสร้างข้อมูลของเวลาด้วยฟังก์ชัน localtime
และเก็บค่าไว้ในตัวแปรพอยน์เตอร์ local
ที่เราได้ประกาศไปก่อนหน้า
printf("Week day: %d\n", local->tm_wday);
printf("Year: %d\n", local->tm_year);
printf("Month: %d\n", local->tm_mon);
printf("Day: %d\n", local->tm_mday);
printf("Hour: %d\n", local->tm_hour);
printf("Minute: %d\n", local->tm_min);
printf("Second: %d\n", local->tm_sec);
ตอนนี้เราสามารถเข้าถึงส่วนประกอบต่างๆ ของเวลาผ่านทางตัวแปร local
ได้ ยกตัวอย่างเช่น tm_wday
นั้นเป็นวันของสัปดาห์ที่มีค่าตั้งแต่ 0 - 6
ซึ่งหมายถึงวันอาทิตย์ถึงวันเสาร์ ส่วน tm_year
tm_mon
และ tm_mday
เป็นค่าของปี เดือน และวันของเดือน ตามลำดับ และที่เหลือเป็นการเข้าถึงส่วนประกอบของเวลา ชั่วโมง นาที และวินาที
จะเห็นว่าค่าของปีนั้นแสดงเป็น 120
นั่นเป็นเพราะว่าปีในภาษา C นั้นจะเริ่มนับจากปี 70 ซึ่งหมายถึงปี 1970 ดังนั้น 120 จึงหมายถึงปี 2020 (1900 + 120) นั่นเอง ดังนั้นในการแปลงไปเป็นปีจริงๆ ในปฏิทิน เราต้องบวก 1900 เข้าไปด้วยเสมอ เหมือนกับในตัวอย่างข้างล่างนี้
printf("Year: %d\n", 1900 + local->tm_year);
และในตอนนี้เราจะได้รับค่าปีที่เหมือนกับในปฏิทินแล้ว
ฟังก์ชัน localtime
จะแปลงเวลาเป็นโครงสร้างข้อมูลของเวลาในเขตของเวลาท้องถิ่นที่นักเรียนอยู่ (อ้างอิงจากคอมพิวเตอร์ของนักเรียน) ซึ่งในประเทศไทยนั้นมีเขตเวลาเป็น +07:00
การแสดงเวลาใน Time zone อื่นๆ #
อีกหนึ่งฟังก์ชันสำหรับแปลงเวลาเป็น struct tm
คือฟังก์ชัน gmtime
มันใช้สำหรับแปลงเวลาไปยังโครงสร้างข้อมูลของเวลาในเขตเวลา GTM หรือ UTC time ซึ่งเป็นเขตเวลามาตรฐานกรีนิช ซึ่งเรามักจะใช้ฟังก์ชันนี้เมื่อเราต้องการเวลาในเขตต่างๆ ของโลก โดยใช้เขตเวลา GTM เป็นเขตเวลาอ้างอิงหลัก
ในตัวอย่างต่อมา เราจะเขียนโปรแกรมสำหรับแสดงเวลาตามสถานที่ต่างๆ ของโลก จากเขตเวลาที่สถานที่เหล่านั่นอยู่โดยการใช้งานฟังก์ชัน gmtime
นี่เป็นตัวอย่าง
#include <stdio.h>
#include <time.h>
#define PST (-7)
#define UTC (0)
#define THA (+7)
int main()
{
time_t rawtime;
struct tm * gmt;
time (&rawtime);
gmt = gmtime(&rawtime);
puts("Current time around the World:");
printf("Sacramento, CA (U.S.) : %2d:%02d\n", (gmt->tm_hour + PST) % 24, gmt->tm_min);
printf("London (England) : %2d:%02d\n", (gmt->tm_hour + UTC) % 24, gmt->tm_min);
printf("Bangkok (Thailand) : %2d:%02d\n", (gmt->tm_hour + THA) % 24, gmt->tm_min);
return 0;
}
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
Current time around the World:
Sacramento, CA (U.S.) : 12:37
London (England) : 19:37
Bangkok (Thailand) : 2:37
ในตัวอย่าง เราได้สร้างโปรแกรมนาฬิกาเพื่อแสดงเวลาที่ตำแหน่งต่างๆ ในโลกได้แก่ เมืองซาคราเมนโตที่สหรัฐอเมริกา เมืองลอนดอนที่ประเทศอังกฤษ และกรุงเทพที่ประเทศไทย
#define PST (-7)
#define UTC (0)
#define THA (+7)
ในตอนแรก เราได้ประกาศค่าคงที่เพื่อเก็บเขตเวลาของสถานที่ต่างๆ โดยอ้างอิงจากเขตเวลา GMT ซึ่ง +7
ในตัวแปร THA
หมายความว่าเวลาในประเทศไทยนั้นเร็วกว่าเวลาที่เขตเวลามาตรฐานกรีนิช (GMT) เป็นเวลา 7 ชั่วโมง ส่วนในตัวแปร PST
ที่มีค่าเป็นลบหมายความว่าเวลาช้ากว่าเขตเวลามาตรฐานกรีนิช 7 ชั่วโมง
gmt = gmtime(&rawtime);
จากนั้นเราแปลงเวลาปัจจุบันเป็นเวลาในเวลามาตรฐานกรีนิช และเก็บไว้ในตัวแปร gmt
printf("Sacramento, CA (U.S.) : %2d:%02d\n", (gmt->tm_hour + PST) % 24, gmt->tm_min);
printf("London (England) : %2d:%02d\n", (gmt->tm_hour + UTC) % 24, gmt->tm_min);
printf("Bangkok (Thailand) : %2d:%02d\n", (gmt->tm_hour + THA) % 24, gmt->tm_min);
ในการที่จะแปลงเวลาในเขตเวลามาตรฐานกรีนิช ไปยังเขตเวลาอื่นๆ เราได้ทำการบวกจำนวนชั่วโมงจากค่าเขตของเวลาของสถานที่เหล่านี้เข้าไปยัง tm_hour
เพื่อรับเอาชั่วโมงในเขตเวลานั้นๆ ออกมา
ในตัวอย่างก่อนหน้า เราได้สร้างโครงสร้างของเวลาจากฟังก์ชัน localtime
และ gmtime
อย่างไรก็ตาม เราสามารถสร้างโครงสร้างเวลาและกำหนดส่วนประกอบต่างๆ ด้วยตัวเองได้ ยกตัวอย่างเช่น เราต้องการสร้างโครงสร้างของเวลา และตัวแปรเวลาสำหรับวันเกิดของเรา เพื่อทำมาใช้งานในการเขียนโปรแกรม
#include <stdio.h>
#include <time.h>
int main()
{
time_t birthdate;
struct tm bd;
// Set time components to zero
bd.tm_hour = 0;
bd.tm_min = 0;
bd.tm_sec = 0;
// Set date of birth
bd.tm_year = 88; // 1988
bd.tm_mon = 2; // March
bd.tm_mday = 12; // 12
// Convert struct tm to time_t
birthdate = mktime(&bd);
printf("My birthday is %s", asctime(&bd));
printf("It's %d seconds since I was born\n", birthdate);
return 0;
}
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
My birthday is Sat Mar 12 00:00:00 1988
It's 574102800 seconds since I was born
ในตัวอย่าง เราสร้างโครงสร้างข้อมูลของเวลาด้วยตัวเอง หลังจากนั้นแปลงโครงสร้างข้อมูลดังกล่าวเป็น Timestamp และแสดงผลออกทางหน้าจอ
time_t birthdate;
struct tm bd;
ในตอนแรก เราประกาศสองตัวแปรที่ว่างเปล่าสำหรับเก็บค่าของเวลาและโครงสร้างของเวลา
bd.tm_hour = 0;
bd.tm_min = 0;
bd.tm_sec = 0;
เนื่องจากเราสนใจแค่วันเกิด ดังนั้นเรากำหนดส่วนประกอบของเวลาทั้งหมดเป็นศูนย์
bd.tm_year = 88; // 1988
bd.tm_mon = 2; // March
bd.tm_mday = 12; // 12
เรากำหนดวัน เดือน ปีเกิดให้กับโครงสร้างของเวลา bd
อย่างที่เราบอกไปแล้วก่อนหน้าว่า ในภาษา C ค่าของปีในโครงสร้างข้อมูลจะเริ่มต้นจาก 70 ซึ่งหมายถึงปี 1970 ดังนั้นถ้าหากเราต้องการกำหนดปีเป็น 1988 เราต้องกำหนดค่าให้กับ bd.tm_year
เป็น 88 โดยการลบปีจริงออกจาก 1900 เช่น 1988 - 1900 = 88
ซึ่งนี่เป็นสิ่งที่นักเรียนจะต้องรู้เกี่ยวกับการกำหนดปีให้กับโครงสร้างข้อมูลของเวลา
birthdate = mktime(&bd);
จากนั้นเราแปลงโครงสร้างของเวลาที่สร้างขึ้นให้เป็นเวลาในรูปแบบ time_t
ด้วยฟังก์ชัน mktime
โดยฟังก์ชันนี้รับพารามิเตอร์เป็นพอยน์เตอร์ของ bd
และส่งค่ากลับเป็นเวลาและเก็บไว้ในตัวแปร birthdate
printf("My birthday is %s", asctime(&bd));
เราสามารถแปลงโครงสร้างของเวลาเป็น String ได้ด้วยฟังก์ชัน asctime
ซึ่งฟังก์ชันนี้มีการทำงานเหมือนกับฟังก์ชัน ctime
ที่นักเรียนได้เรียนรู้ไปก่อนหน้า แต่มันรับพารามเตอร์เป็นโครงสร้างของเวลาแทน ซึ่งมีค่าเหมือนกับเราเรียกใช้คำสั่งนี้ ctime(mktime(&bd))
printf("It's %d seconds since I was born\n", birthdate);
สุดท้ายเราได้แสดงข้อความออกมาทางหน้าจอว่ามันได้ผ่านมากี่วินาทีแล้วตั้งแต่ที่เราเกิดมา นักเรียนสามารถนำตัวแปร birthdate
ไปใช้กับฟังก์ชันอืนๆ ที่สามารถใช้ร่วมกันได้ เช่น localtime
หรือ gmtime
ทีนักเรียนได้เรียนรู้ไปในตัวอย่างก่อนหน้านี้
สำหรับสมาชิกในโครงสร้างข้อมูล struct tm
ทั้งหมดสามารถดูได้ที่ http://www.cplusplus.com/reference/ctime/tm/
การหาผลต่างของเวลา #
ในการเขียนโปรแกรม เราอาจจะต้องการรู้ว่าเวลาในจุดที่หนึ่งนั้นห่างจากจุดที่สองเท่าไหร่ ยกตัวอย่าง เช่น นักเรียนอาจจะต้องการทราบว่ามัตั้แต่วันที่ December 30, 1980 จนถึงปัจจุบุบันนั้นเวลาผ่านมากี่วินาทีแล้ว ในภาษา C เราสามารถหาผลต่างระหว่างเวลาสองจุดได้โดยการใช้ฟังก์ชัน difftime
นี่เป็นตัวอย่าง
#include <stdio.h>
#include <time.h>
int main()
{
struct tm timeinfo;
timeinfo.tm_hour = 0;
timeinfo.tm_min = 0;
timeinfo.tm_sec = 0;
timeinfo.tm_year = 80; // 1980
timeinfo.tm_mon = 11; // December
timeinfo.tm_mday = 30; // 30
time_t beginning = mktime(&timeinfo);
time_t end = time(NULL);
double diff = difftime(end, beginning);
printf("BEGIN:\t\t%d\t%s", beginning, ctime(&beginning));
printf("END\t\t%d\t%s", end, ctime(&end));
printf("%.lf seconds passed since December 30, 1980", diff);
return 0;
}
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
BEGIN 346957200 Tue Dec 30 00:00:00 1980
END 1595640258 Sat Jul 25 08:24:18 2020
1248683058 seconds passed since December 30, 1980
ในตัวอย่าง เป็นโปรแกรมสำหรับหาผลต่างของเวลาระหว่างวันที่ December 30, 1980 และเวลาปัจจุบัน (ตอนที่โปรแกรมนี้ถูกรัน) โดยการใช้ฟังก์ชัน difftime
ฟังก์ชันนี้รับค่าสองพารามิเตอร์ซึ่งเป็นข้อมูลประเภท time_t
ที่ต้องการหาผลต่างของเวลา และส่งค่ากลับเป็น double ซึ่งเป็นผลลต่างของเวลาในหน่วยวินาที
time_t beginning = mktime(&timeinfo);
time_t end = time(NULL);
double diff = difftime(end, beginning);
นักเรียนสามารถสร้างเวลาที่ต้องการจากโครงสร้างของเวลาในตัวแปร timeinfo
ซึ่งเรากำหนดวันและเวลาเป็น December 30, 1980 เวลา 00:00:00 และแปลงโครงสร้างของเวลาดังกล่าวให้เป็น time_t
ก่อนที่จะนำมาหาผลต่างด้วยฟังก์ชัน difftime
ในตัวอย่างนี้ เราได้ผลต่างของเวลาเป็น 1,248,683,058 หรือประมาณ 1.2 พันล้านวินาที อย่างไรก็ตาม สำหรับมนุษย์นั้นมันอยากที่จะเข้าใจว่าเวลานั้นผ่านมานานแค่ไหนแล้ว ในตัวอย่างต่อไป เราจะสร้างฟังก์ชันมาแปลงเวลาให้แสดงเป็นข้อความของเวลาที่ผ่านไปแทน นี่จะทำให้เราสามารถเข้าใจได้ง่ายขึ้น
#include <stdio.h>
#include <time.h>
char* time_ago(long time)
{
int year = time / 31557600;
int month = (time % 31557600) / 2592000;
int day = (time % 2592000) / 86400;
int hour = (time % 86400) / 3600;
int minute = (time % 3600) / 60;
int second = time % 60;
char format[100] = "%d years %d months %d days %d hours %d mins %d seconds";
char * buffer = malloc(100);
sprintf(buffer, format, year, month, day, hour, minute, second);
return buffer;
}
int main()
{
struct tm timeinfo;
timeinfo.tm_hour = 0;
timeinfo.tm_min = 0;
timeinfo.tm_sec = 0;
timeinfo.tm_year = 80; // 1980
timeinfo.tm_mon = 11; // December
timeinfo.tm_mday = 30; // 30
time_t beginning = mktime(&timeinfo);
time_t end = time(NULL);
double diff = difftime(end, beginning);
char* passed = time_ago((long) diff);
printf("BEGIN\t%d\t%s", beginning, ctime(&beginning));
printf("END\t%d\t%s", end, ctime(&end));
printf("Time passed since December 30, 1980\n");
printf("%s ago", passed);
return 0;
}
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
BEGIN 346957200 Tue Dec 30 00:00:00 1980
END 1595641765 Sat Jul 25 08:49:25 2020
Time passed since December 30, 1980
39 years 6 months 22 days 8 hours 49 mins 25 seconds ago
ในตัวอย่างนี้ เราได้ใช้โค้ดจากในตัวอย่างก่อนหน้า แต่สิ่งที่เพิ่มเติ่มเข้ามาก็คือเราได้สร้างฟังก์ชัน time_ago
สำหรับแปลงค่าวินาทีให้เป็นข้อความบอกเวลาที่ผ่านไปจากหน่วยของเวลาที่ใหญ่ที่สุด นั่นก็คือปี เดือน วัน ชั่วโมง นาที และวินาที ตามลำดับ
int year = time / 31557600;
int month = (time % 31557600) / 2592000;
int day = (time % 2592000) / 86400;
int hour = (time % 86400) / 3600;
int minute = (time % 3600) / 60;
int second = time % 60;
ในฟังก์ชัน time_ago
เราได้แยกเอาหน่วยต่างๆ ของเวลาออกจากวินาทีทั้งหมด เพื่อแยกเอาค่าปีออกมา เราได้นำค่าวินาทีที่ผ่านไปหารด้วยจำนวนวินาทีทั้งหมดในหนึ่งปีซึ่งก็คือ 31557600
แล้วเก็บไว้ในตัวแปร year
จากนั้นเพื่อหาค่าของเดือน เอาเศษที่เหลือจากวินาทีในหนึ่งปีหารด้วยวินาทีทั้งหมดในหนึ่งเดือนซึ่งก็คือ 2592000
และเก็บในตัวแปร month
เช่นเดียวกันเพื่อหาค่าของวันในตัวแปร day
เอาเศษที่เหลือจากวินาทีในหนึ่งเดือนหารด้วยวินาทีทั้งหมดในหนึ่งวันซึ่งก็คือ 86400
และทำเช่นนี้ไปเรื่อยๆ จนถึงวินาที โดยค่าของวินาทีก็คือเศษที่เหลือของเวลาในหนึ่งนาทีหรือ 60 วินาทีนั่นเอง
char format[100] = "%d years %d months %d days %d hours %d mins %d seconds";
char * buffer = malloc(100);
sprintf(buffer, format, year, month, day, hour, minute, second);
หลังจากที่เราได้ส่วนต่างๆ ของเวลา เรานำค่าเหล่านั้นมาสร้างเป็น String ด้วยฟังก์ชัน sprintf
โดยมันจะทำการสร้าง String จากรูปแบบที่กำหนดและเขียนใส่ในตัวแปร buffer
และเราส่งค่านี้กลับไป
การจับเวลาเพื่อวัดประสิทธิภาพของโปรแกรม #
ในตัวอย่างก่อนหน้า เราได้สร้างเวลาจาก time_t
ซึ่งข้อมูลประเภทนี้เก็บเวลาได้ละเอียดสุดถึงแค่ในหน่วยวินาทีเท่านั้น จะเป็นยังไงถ้าหากเราต้องการค่าของเวลาที่ละเอียดกว่านั้น ยกตัวอย่างเช่น เราต้องการจับเวลาการทำงานของโปรแกรมที่สามารถบอกความต่างของเวลาได้ถึงระดับมิลลิวินาที เราจะมาดูว่าทำอย่างไรในภาษา C
#include <stdio.h>
#include <time.h>
int frequency_of_primes(int n)
{
int count = 0;
for (int i = 2; i <= n; i++) {
int is_prime = 1;
for (int j = 2; j <= i; j++) {
if (i % j == 0 && j != i) {
is_prime = 0; break;
}
}
if (is_prime == 1) count++;
}
return count;
}
int main()
{
clock_t start, end;
int prime_count;
start = clock();
prime_count = frequency_of_primes(100000);
end = clock();
float sec = (float)(end - start) / CLOCKS_PER_SEC;
printf("There are %d prime numbers between 1 - 100000\n", prime_count);
printf("%d clocks ticked\n", end - start);
printf("Calculation finished in %f seconds\n", sec);
return 0;
}
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
There are 9592 prime numbers between 1 - 100000
1828 clocks ticked
Calculation finished in 1.828000 seconds
ในตัวอย่าง เป็นโปรแกรมสำหรับหาว่าจำนวนเฉพาะทีี่มีค่าระหว่าง 1 – 100000 นั้นมีจำนวนกี่ตัว เนื่องจากเราต้องการทราบเวลาการคำนวณอย่างละเอียดในหน่วยมิลลิวินาที ดังนั้นเราจึงใช้ฟังก์ชัน clock
และค่าคงที่ CLOCKS_PER_SEC
แทนฟังก์ชันทั้งหมดที่เราเคยใช้ไปก่อนหน้า
int frequency_of_primes(int n)
{
...
return count;
}
เราได้สร้างฟังก์ชัน frequency_of_primes
สำหรับคำนวณและตรวจสอบว่าจำนวนเฉพาะระหว่าง 1 – n นั้นมีจำนวนเท่าไหร่ โดยในตัวอย่างของเรานั้นได้ส่งค่า n เป็น 100000 เข้ามายังฟังก์ชัน ภายในฟังก์ชันนี้ใช้อัลกรอริทึมพื้นฐานสำหรับตรวจสอบว่าตัวเลขเป็นจำนวนเฉพาะหรือไม่ และสุดท้ายเราส่งค่ากลับเป็นจำนวนของจำนวนเฉพาะทั้งหมดที่นับได้กลับไป
start = clock();
prime_count = frequency_of_primes(100000);
end = clock();
นี่เป็นโค้ดส่วนหลักที่เราต้องการเน้นในตัวอย่างนี้ เราต้องการทราบว่าการทำงานของฟังก์ชัน frequency_of_primes
นั้นใช้เวลาไปเท่าไหร่ เราได้เรียกใช้ฟังก์ชัน clock
ซึ่งส่งค่ากลับเป็นเวลาของ CPU ซึ่งมีหน่วยเป็น trick ก่อนจุดที่ต้องการวัดความแตกต่างของเวลา
float sec = (float)(end - start) / CLOCKS_PER_SEC;
หลังจากเราได้เวลาการทำงานของ CPU ก่อนและหลังแล้ว เราหาผลต่างของเวลาโดยการนำเวลาเริ่มต้นและเวลาสิ้นสุดมาลบกัน จากนั้นหารค่าที่ได้ด้วยจำนวน CLOCK ต่อวินาที (CLOCKS_PER_SEC
) ซึ่งค่านี้เป็นค่าคงที่ที่สามารถเปลี่ยนแปลงไปตามสภาพแวดล้อมการทำงานของโปรแกรม
ในตอนี้เราจะได้ค่าของเวลาที่ผ่านไปในหน่วยวินาทีซึ่งมีความละเอียดในระดับมิลิวินาทีในตัวแปร sec
และในกรณีที่เราต้องการค่าในหน่วยมิลลิวินาที คูณผลลัพธ์ที่ได้ด้วย 1000 ยกตัวอย่างเช่น
long millisec = ((float)(end - start) / CLOCKS_PER_SEC) * 1000;
ฟังก์ชัน clock ไม่ได้ส่งค่ากลับเป็นเวลาปัจจุบันของระบบ แต่มันส่งค่ากลับเป็นเวลา (CPU trick) ตั้งแต่ที่โปรแกรมเริ่มทำงาน โดยที่ในหนึ่งวินาทีนั้น CPU จะทำการ trick โดยมีค่าอยู่ที่ CLOCKS_PER_SEC
ในบทนี้ นักเรียนได้เรียนรู้เกี่ยวกับเวลาและวันที่พื้นฐานในภาษา C เราได้แนะนำให้นักเรียนรู้จักเกี่ยวกับระบบเวลาในคอมพิวเตอร์ซึ่งก็คือ Unit time การแสดงผลเวลาปัจจุบัน การใช้งานโครงสร้างของเวลา การหาผลต่างของเวลา และ การวัดประสิทธิภาพการทำงานของโปรแกรมในระดับมิลลิวินาที