본문 바로가기

Computer Programming/Cpp, Python

C 언어: Time Function

C 언어 연습 문제를 풀다, 시간을 측정하는 연습문제가 나와 풀어보다 글로 적어두면 좋을 것 같아 C 언어에서 알아두면 유용할, 시간 관련 함수들에 대해서 적어보려 한다.

이번 글에서 다룰 시간 관련 문제는 다음과 같다.

Write a C program taking an integer n as command line parameter and sleeping for n seconds. 
The execution time of the sleep function is measured and displayed. 

Examples output:
./time 3
sleep duration: 3.000082 seconds

./time 5
sleep duration: 5.000108 seconds​

문제는 다음과 같다. 실행시킬 때 command line에 양의 정수 n을 입력했을 때, n 초 이후에 "sleep duration: n seconds"라고 출력을 해야 한다.

먼저 시간을 측정할 수 있는 라이브러리를 불러와야 하는데, 윈도우(1)와 리눅스(2) 두 가지로 나뉜다.

1. 윈도우 (Windows)

#include <time.h>      // used for clock () function
#include <Windows.h>   // used for sleep ()

2. 리눅스 (Linux)

#include <sys/time.h>  // needed for gettimeofday
#include <unistd.h>    // needed for sleep

1. 윈도우 (Windows) - time.h & Windows.h

먼저 윈도우는 리눅스에서 쓰는 라이브러리를 지원하지 않기 때문에, 'time.h'와 'Windows.h'를 사용해야 했다. 먼저 'time.h' 라이브러리에 대해서 알아보자. 'time.h'는 아래와 같은 함수들을 제공한다.
(참고로 'time.h'는 리눅스에서도 사용 가능하다)

    time()
    //: This function returns the current calendar time as a time_t object. 
    // If the function fails, it returns -1. 
    // The time_t is a type suitable for storing a calendar time 
    // and date in seconds since the Unix Epoch (00:00:00 UTC, January 1, 1970).

    clock()
    //: This function returns the processor time consumed by the program, 
    // which is the CPU time. The return value is of type clock_t.

    ctime()
    //: This function takes a time_t object and converts it to a string representation.

    gmtime()
    //: This function converts a time_t object into a broken-down time, 
    // expressed as Coordinated Universal Time (UTC).

    localtime()
    //: This function converts a time_t object into a broken-down time, expressed as local time.

    mktime()
    //: This function converts a broken-down time (expressed as local time) 
    // into a time_t object.

    difftime()
    //: This function computes the difference in seconds 
    // between two calendar times (time_t objects).

    asctime()
    //: This function converts a broken-down time into a string representation.

    strftime()
    //: This function formats the broken-down time 
    // according to the format specification provided.

이 함수들 중에서 사용해야 할 함수는 시간을 측정해야 하기 때문에 'clock( )'을 사용해야 한다.

command line에서 정수를 받아야 하기 때문에 main 함수에서 'argc'와 'argv'를 사용해야 한다. 그렇다면 '코드명'과 정수를 입력하기 때문에 'argc'는 2가 되어야 하고, 'argv'의 array에서 'array [1]'에 시간의 정보가 저장되어 있을 것이다.

command line에서 입력하는 정보는 'char' Data Type이므로, 정수로 변환해주어야 한다. 아래에서 확인해 보자.

'argc'와 'argv'에 대해 모른다면 아래의 링크에서 확인할 수 있다.

 

C 언어: argc, argv [ ], void qsort ( )

C 언어를 하다 보면, 가끔 C 언어를 하다 보면 아래와 같이 main 함수에서 parameter를 사용해야 할 때가 있다. int main (int argc, char argv[]) ... 이번 글에서는 'argc'와 'argv [ ]'에 대해 소개하고 어떻게 쓰

damiansdiary.tistory.com

int main (int argc, char **argv) {

    if (argc > 2) return -1;

    int n = atoi (argv[1])*1000; // convert time in milliseconds into seconds for Sleep ()

우리는 하나의 양의 정수만 필요하기 때문에 'if (argc > 2) return -1;'은 두 개 이상의 숫자를 입력하게 된다면, 코드를 강제로 종료하게 한다.

한 가지 주의해야 할 점은 Window에서는 'millisecond' (1 sec/1000)를 기본 단위로 취한다. 하지만 우리는 '초 (second)'를 세기 때문에 1000을 곱해주어야 한다.

이제 얼마 동안 Delay를 주어야 할지 (n)을 알고 있으므로 'clock ( )'을 이용하여 시간을 측정해야 한다.

    // record the time before sleep
    clock_t start = clock();
    // after n seconds, the the codes carry on
    Sleep(n); // Important: Upper Case
    // record the time after sleep
    clock_t stop = clock ();

먼저, 'clock_t'는 CC++에서 사용하는 시간을 의미하는 Data Type이다. 이제 한번 코드를 살펴보자.

'clock_t start = clock( );'에서 Delay를 주기 전의 시간을 즉시 기록한다. 마찬 가지로 'clock_t stop = clock ( );'는 Delay가 끝난 후의 시간을 즉시 기록한다.

그리고 위 두 기록하는 코드 사이에 있는 'Sleep (n);'가 Delay를 담당한다. 따라서 우리는 'start'와 'stop'에 Delay 전과 후의 시간 (초)의 정보를 가지고 있는 것이다.

이제 시간 차이를 계산해야 하는데, 그저 'stop'에서 'start' 값을 뺀 다음 이를 출력하면 된다. 아래에서 코드를 확인해 보자.

    // time_after - time_before
    double elapsed = ((double)(stop-start)/1000);

    printf("Sleep duration: %.6lf seconds\n", elapsed);

그럼 전체 코드는 아래와 같다.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>      // used for clock () function
#include <Windows.h>   // used for sleep ()

int main (int argc, char **argv) {

    if (argc > 2) return -1;

    int n = atoi (argv[1])*1000; // convert into milliseconds for Sleep ()

    // record the time before sleep
    clock_t start = clock();
    // after n seconds, the the codes carry on
    Sleep(n); // Important: Upper Case
    // record the time after sleep
    clock_t stop = clock ();

    // time_after - time_before
    double elapsed = ((double)(stop-start)/1000);

    printf("Sleep duration: %.6lf seconds\n", elapsed);


    return 0;
}

 

2. 리눅스 (Linux) - sys/time.h & unistd.h

리눅스에서 사용하는 위 두 라이브러리는 조금 더 다양한 기능을 제공한다. 리눅스에서 'clock.h' 함수를 대체하는 함수를 제공하는 라이브러리는 'sys/time.h'이다. 이 라이브러리가 제공하는 함수는 아래와 같다.

    struct timeval
    // : This is a structure used to represent time. 
    // It has two fields:
        tv_sec  //: This represents the number of whole seconds.
        tv_usec //: This represents the number of microseconds (millionths of a second).

    struct timezone
    // : This is another structure which might be used to represent the timezone, 
    // but it is generally not used. Most functions fill it with zeroes or ignore it.

    gettimeofday()
    // : This function is used to get the current time, often with microsecond precision. 
    // It typically fills in a struct timeval with the number of seconds and microseconds 
    // since the Unix epoch (00:00:00 January 1, 1970, Coordinated Universal Time).

    settimeofday()
    // : This function sets the system's notion of the current time. 
    // Its use is generally restricted due to security considerations.

    timersub()
    // : This function subtracts two struct timeval values, 
    // producing a third that represents the difference between the two times.

우리는 시간을 기록해야 하기 때문에, 'struct timeval', 'gettimeofday( )' 그리고 'timersub( )'를 사용하는 게 알맞을 것이다. 그렇다면 먼저 'struct timeval'의 코드를 작성해 보겠다.

    struct timeval start, stop, elapsed;

먼저 'struct timeval'에 우리가 필요한 정보인 'start' 'stop' 그리고 'elapsed'를 선언한다. 'struct timeval'에 속한 요소들은 모두 초(second) 혹은 마이크로초 (microsecond)로 속성을 가지게 된다.

    int n = atoi(argv[1]);

다음으로 윈도우에서와 마찬가지로 command line에서 코드명 다음에 적힌 숫자를 정수로 변환한다. 다시 한번, 정수로 변환하는 이유는 command line에서 입력하는 모든 정보는 'char'형 이기 때문에, 정수로 변환해야 한다. 자세한 설명은 아래의 링크에서 확인하면 좋을 것 같다.

 

C 언어: argc, argv [ ], void qsort ( )

C 언어를 하다 보면, 가끔 C 언어를 하다 보면 아래와 같이 main 함수에서 parameter를 사용해야 할 때가 있다. int main (int argc, char argv[]) ... 이번 글에서는 'argc'와 'argv [ ]'에 대해 소개하고 어떻게 쓰

damiansdiary.tistory.com

다음으로 이제 시간을 기록해야 하는데, 리눅스에서는 'gettimeofday'라는 함수를 이용한다. 함수의 구성요소는 아래와 같다.

gettimeofday ( struct timeval *tp ,  struct timezone *tz )

'struct timeval *tp'는 '시간 정보를 저장할 곳'(1)과 '시간대'(2)를 입력해야 한다. 하지만, 'timezone'은 과거 이전 버전의 'Unix'용 구성요소였는데 이제는 더 이상 사용하지 않는다고 한다. 따라서, 여기에는 'Null'을 넣어주면 된다.
그렇다면 이 문제에 알맞게 'gettimeofday' function을 작성해 보자.

    // record time before sleeping
    gettimeofday(&start, NULL);
    // sleep for n seconds
    sleep(n); // Important: Lower Case
    // record time after sleeping
    gettimeofday(&stop, NULL);

이제 시간 차이를 계산해야 하는데 윈도우와 달리 리눅스에서는 시간 차이를 계산해 주는 'timersub ( )'라는 함수가 있다.

timersub (const char* str1, const char* str2, const char* str3);

이 함수는 세 개의 input으로 받는데, 아래의 리스트를 확인해 보자.

1. const char* str1: 끝나는 시간이 저장된 곳
2. const char* str2: 시작하는 시간이 저장된 곳
3. const char* str3: 경과 시간을 저장할 곳

그렇다면 문제에 맞게 코드를 작성하면 아래와 같다.

    // calculation
    timersub(&stop, &start, &elapsed);

그리고 'elapsed'를 출력하면 되는데, 단위를 조정해줘야 하는데, 아래에서 확인하자.

    printf("sleep duration: %lu.%06lu seconds\n", elapsed.tv_sec, elapsed.tv_usec);

위 'struct timeval'는 두 가지 시간 필드를 갖게 되는데 다음과 같다. 초 (tv_sec), 마이크로초(tv_usec).

따라서 위와 같이 'struct'에서 불러오듯 "."을 이용해 시간 단위를 바꿔주면 된다.

아래에서 전체코드를 확인해 보자.

#include <sys/time.h>  // needed for gettimeofday
#include <unistd.h> // needed for sleep
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv){
    if (argc > 2) return -1;

    struct timeval start, stop, elapsed;

    int n = atoi(argv[1]);

    // record time before sleeping
    gettimeofday(&start, NULL);
    // sleep for n seconds
    sleep(n);
    // record time after sleeping
    gettimeofday(&stop, NULL);

    // calculation
    timersub(&stop, &start, &elapsed);

    printf("sleep duration: %lu.%06lu seconds\n", elapsed.tv_sec, elapsed.tv_usec);

    return 0;
}

여기까지다. 조금 복잡하긴 한데, 개인이 사용하는 시스템에 맞게 참고하고 도움이 되었으면 한다!

 

doyun-gu - Overview

doyun-gu has 5 repositories available. Follow their code on GitHub.

github.com

 

'Computer Programming > Cpp, Python' 카테고리의 다른 글

C 언어: argc, argv [ ], void qsort ( )  (26) 2023.06.20