Hàm thời gian trong C/C++

Mọi người cho em hỏi, trong C/C++ có hàm đếm thời gian không ạ, em đang làm game đua xe cùi bắp :3, giờ em muốn ví dụ như cứ mỗi 10s là xuất hiện thêm 1 vật cản thì phải dùng hàm nào và dùng như thế nào ạ. em cảm ơn

Bạn dùng chrono nhé:
http://en.cppreference.com/w/cpp/chrono/steady_clock

4 Likes

e đọc mà k hiểu ạ, a có thể giải thích cho em 1 xíu được không?

đơn giản là bạn tạo một hàm update (làm game thì chắc chắn có hàm này rồi @@)
sau đó dùng thư viện này, tại link dưới đây:
http://en.cppreference.com/w/cpp/chrono/steady_clock/now

Nếu bạn đúng thật đang code game thì không thể không hiểu được

1 Like

Em mới năm nhất thôi a. Đang mày mò làm cái đua xe trên console à.

thư viện <chrono> cung cấp 3 kiểu dữ liệu về thời gian là kiểu đồng hồ (clock) để đo thời gian, kiểu time_point để xác định 1 thời điểm trong thời gian, và kiểu duration để xác định 1 khoảng/quãng thời gian.

  • đồng hồ trong <chrono> gồm có 2 loại: std::chrono::system_clockstd::chrono::steady_clock. system_clock là kiểu đồng có thể quay ngược được (điều chỉnh được), còn steady_clock chỉ có thể tăng dần, ko quay ngược lại được. Ngoài ra còn có kiểu high_resolution_clock là tên khác của 1 trong 2 loại trên, loại nào có độ chính xác cao hơn thì nó chọn, nên nó có thể là loại đồng hồ tua ngược được, ko thích hợp để đo thời gian. Để đo thời gian nên xài steady_clock.
  • 2 loại đồng hồ cho 2 loại thời điểm khác nhau: time_point<system_clock>time_point<steady_clock>. Thời điểm là 1 điểm trong thời gian, giống như 1 điểm trong không gian vậy. Ở đây sở dĩ phân thành nhiều loại vì thời điểm của đồng hồ kiểu này đo ko thể convert sang thời điểm đồng hồ kiểu khác đo được, hay nói cách khác kiểu của thời điểm có phụ thuộc vào kiểu đồng hồ đo thời điểm.
  • khoảng/quãng thời gian duration là khoảng cách giữa 2 thời điểm. Giá trị của quãng thời gian có thể là kiểu số nguyên hoặc số thực. Ngoài ra quãng thời gian có thể có nhiều đơn vị khác nhau, như giây, mili giây, micro giây, nano giây, phút, giờ, ngày, v.v… Như vậy kiểu của quãng thời gian phụ thuộc vào kiểu của giá trị, và kiểu của đơn vị. Kiểu giá trị co thể là số nguyên 32-bit hoặc 64-bit, hoặc số thực float/double. Kiểu đơn vị thì <chrono> xác định nó là kiểu std::ratio - tỉ lệ so với đơn vị giây: kiểu đơn vị giây có tỉ lệ 1:1, kiểu mili giây có tỉ lệ 1:1000, kiểu phút có tỉ lệ 60:1, v.v… Để tránh ghi dài dòng duration<ValueType, std::ratio<Num,Den>> thì <chrono> có định nghĩa sẵn std::chrono::seconds, std::chrono::milliseconds, std::chrono::minutes, v.v… Tất cả đều có kiểu giá trị là số nguyên. Ngoài ra người ta còn tạo thêm mấy cái chrono_literals cho dễ ghi quãng thời gian trong code: 1s, 100ms, v.v…

tới đây thì bạn có thể nhảy vô thực hành đo thời gian được rồi:

#include <iostream>
#include <chrono>
using namespace std::chrono;
using namespace std::literals::chrono_literals;

int main()
{
    // lấy thời điểm bắt đầu
    auto start = steady_clock::now();
    // lấy thời điểm kết thúc
    auto end = steady_clock::now();
    // lấy quãng thời gian end - start, tự động ép kiểu nó về kiểu giá trị số thực double,
    //kiểu đơn vị mili giây (std::milli hoặc std::ratio<1, 1000>)
    duration<double, std::milli> elapsed1 = end - start;
    std::cout << "elapsed1 = " << elapsed1.count() << "ms\n";
    // lấy quãng thời gian end - start, ép kiểu nó về kiểu giá trị số nguyên 32-bit,
    //kiểu đơn vị 10^-8 giây (std::ratio<1, 100000000>)
    //phải xài duration_cast vì end-start có thể mang đơn vị là nano giây,
    //cast về đơn vị 10^-8 giây có thể bị mất vì nano giây, phải ép kiểu tường minh:
    auto elapsed2 = duration_cast<duration<int, std::ratio<1, 100000000>>>(end - start);
    std::cout << "elapsed2 = " << elapsed2.count() << " x 10^-8 seconds\n";
    
    // so sánh dễ dàng
    auto oneThousandNanosec = 1000ns;
    std::cout << "elapsed2 " << (elapsed2 < oneThousandNanosec ? "<" : ">=")
              << " " << oneThousandNanosec.count() << "ns\n";
    std::cout << oneThousandNanosec.count() << "ns "
              << (oneThousandNanosec < elapsed1 ? "<" : ">=") << " elapsed1\n";
    std::cout << oneThousandNanosec.count() << "ns "
              << (oneThousandNanosec == 1us ? "==" : "!=") << " 1us\n";
    
    // cộng trừ ngon lành, nếu kiểu giá trị là số thực
    duration<double> sec;
    for (int i = 0; i < 123; ++i)
        sec += elapsed1;
    for (int i = 0; i < 123; ++i)
        sec -= elapsed2;
    std::cout << sec.count() << "s\n";
    
    // còn kiểu giá trị số nguyên thì vẫn phải ép kiểu tường minh duration_cast
    //khi thực hiện phép toán với quãng thời gian có kiểu giá trị số thực
    nanoseconds ns;
    for (int i = 0; i < 123; ++i)
        ns += duration_cast<nanoseconds>(elapsed1);
    for (int i = 0; i < 123; ++i)
        ns -= elapsed2;
    std::cout << ns.count() << "ns\n";
}

edit: thêm cái video nguồn: https://www.youtube.com/watch?v=P32hvk8b13M

thư viện người ta thiết kế có tầm lắm, nhưng người mới nhìn vô thường khó hiểu @_@ Thư viện thời gian hiện đại của bất kì ngôn ngữ nào cũng có 3 khái niệm này (có thể có thêm time zone nữa), nắm nó được thì qua mấy ngôn ngữ khác xài dễ lắm. Có ông C ổng gộp 2 kiểu thời điểm và quãng thời gian làm 1, rồi ko có kiểu đồng hồ nữa, coi như 3 kiểu còn 1 kiểu, đơn giản thì đơn giản nhưng ko phát triển thêm được @_@

5 Likes

rất chi tiết ạ
em cảm ơn nhiều ạ.

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?