読者です 読者をやめる 読者になる 読者になる

1101

工学系大学院生の雑記。

POSIX関数でタイムスタンプ用に現在時刻の文字列データを作る

作るもの

現在時刻(日本時間)の文字列データ

使用言語

C,C++

主な材料

  • 適当な大きさのchar型配列
  • 各種POSIX関数
    • gettimeofday()関数
    • strftime()関数
    • localtime()関数
  • timeval構造体
  • tm構造体

手順

1. 現在のUNIX時間を取得する
現在時刻の文字列データを作るには、当然現在時刻を知る必要があります。
Linuxには、現在の時刻を知るためにgettimeofday()という関数が用意されています。
Man page of GETTIMEOFDAY

但し、この関数で取得できるのは現在のUNIX時間(エポック秒)です。
UNIX時間とは、西暦1970年1月1日0時0分0秒から現在までの経過時間を秒数で表したものです。

gettimeofday()関数では、第一引数にtimeval構造体を渡します。
これによりgettimeofday()関数がうまいことやってくれて、現在のエポック秒とエポックマイクロ秒がtimeval構造体に格納されます。

ちなみにtimeval構造体は以下のように定義されています。

struct timeval {
    time_t      tv_sec;     /* エポック秒 */
    suseconds_t tv_usec;    /* エポックマイクロ秒 */
};


2. UNIX時間をカレンダー時刻(日本時間)に変換する
さて、現在のUNIX時間が手に入ったわけですが、このままでは使い勝手が悪いので、私達に馴染みのあるカレンダー時間に変換する必要があります。
そのために、localtime()関数を使います。
Man page of CTIME

localtime()の他にctime()関数などもありますが、こっちは世界標準時に変換されてしまうので(日本より9時間遅い)、今回はlocaltime()を用います。

この関数では、引数にtime_t型変数のポインタをとり、その変数が指すUNIX時間をカレンダー時間に変換して、tm構造体のポインタとして返してくれます。

ここで、tm構造体は以下のように定義されています。

struct tm {
    int tm_sec;        /* 秒 (0-60) */
    int tm_min;        /* 分 (0-59) */
    int tm_hour;       /* 時間 (0-23) */
    int tm_mday;       /* 月内の日付 (1-31) */
    int tm_mon;        /* 月 (0-11) */
    int tm_year;       /* 年 - 1900 */
    int tm_wday;       /* 曜日 (0-6, 日曜 = 0) */
    int tm_yday;       /* 年内通算日 (0-365, 1 月 1 日 = 0) */
    int tm_isdst;      /* 夏時間 */
};

timeval構造体に格納されたエポック秒データtv_secはtime_t型なので、このtv_secへのポインタをlocaltime()の引数に突っ込むことで、日本時間でのカレンダー時間が手に入ります。


3. 数値を文字列に変換する
最後に、カレンダー時間を文字列データに変換します。
tm構造体に格納されたカレンダー時間のデータを任意の順序で並べた文字列データを作るために、strftime()関数という関数があります。
Man page of STRFTIME

この関数は、第4引数で指定したtm構造体の中の各データを、第3引数で指定したフォーマット指定文字列の順番に並べ替えて、第1引数に指定したchar型ポインタへ格納してくれます。
具体的には、以下のように書きます。

char str[80];
strftime(str, 80, "%Y/%m/%d %H:%M:%S", &tm);

第3指定引数に用いる主なフォーマット指定子の種類は以下の通りです。

%Y : 世紀部分を含めた ( 4 桁の) 西暦年。
%y : 西暦の下2桁 (世紀部分を含まない年) (00-99)。
%m : 月 (10 進数表記)。 (01-12)。
%d : 月内通算日 (10 進数表記) (01-31)。
%H : 24 時間表記での時 (hour)。 (00-23)。
%M : 分 (10 進数表記) (00-59)。
%S : 秒 (10 進数表記) (00-60) (時々ある閏秒に対応するため、値の範囲は 60 までとなっている)。

(Man page of STRFTIMEより一部抜粋)

完成

以上により、タイムスタンプのための現在時刻の文字列データを作成することができました。

最後に、作成したテストコードを載せます。

#include<iostream>
#include<time.h>
#include<sys/time.h>

int main(int argc, char** argv){
    //時刻の文字列データを格納するための配列を作成
    char str[80] = {};

    //UNIX時間データを格納する構造体
    timeval tv;
    
    //現在のUNIX時間を取得
    gettimeofday(&tv, NULL);

    //第4引数でlocaltime()を呼び出し,カレンダー時間に変換された
    //現在時刻データをstrftime()で文字列に変換
    strftime(str, 80, "%Y/%m/%d %H:%M:%S", localtime(&tv.tv_sec));

    std::cout << str << std::endl;

    return 0;
}

出力結果

2017/02/28 23:18:10

デタッチとは

Linuxでスレッドプログラムを作成中に知らないワードに出くわしたので覚え書き。



スレッドはデタッチという状態をもつ。

デタッチとは、アタッチの対義語で、分離する、切り離す、といった意味をもつ。

pthreadでは、スレッドをデタッチ状態にするためにpthread_detach()を使用する。

スレッドがデタッチ状態にあると、スレッドが終了したとき、直ちにこのスレッドが消費していたメモリ資源が開放される。

つまり、いちいちpthread_join()を使ってスレッドを終了してあげる必要がない。

逆に言えば、デタッチ状態のスレッドを別スレッドからpthread_join()を用いて任意のタイミングで終了させることはできないので注意が必要。


ちなみに、デタッチ状態でないスレッドは終了してもメモリを消費したままなので、外からjoinしてあげる必要がある。

スレッドプログラムってめんどくさいことが多いねー。




参考 :

Man page of PTHREAD_JOIN

Man page of PTHREAD_DETACH

progate

progateというプログラミング学習サイトを見つけた.
prog-8.com

最近よく見かけるような,WEB上で予め用意された入力画面にプログラムを打ち込んでいくスタイルのWEBサービス

言語毎にコース分けされていて,主要な言語は一通り揃ってるみたい.

各言語では更に初級,中級,上級等のレッスンに分けられてる.

こういう学習サイトの存在は知っていたけど,今まで利用したことはなかった.

物は試しにと,前から習得したかったhtmlとpythonに手をつけてみたら,これがすごくわかりやすい.

学習の流れとしては,各レッスンの初めに,ある完成されたプログラムが提示されて,
コース全体を通して,そのプログラムが開発される手順を手を動かしながら追体験していくようになってる.

レッスンはいくつかの小さなステップに分かれていて,各ステップでその言語の言語機能をひとつずつ学んでいく.

言語機能を解説するためのスライドは簡潔にまとめられていてすんなり理解できるし,
各ステップは2〜3分もあれば終わるようになっていて,サクサク進められるのもいい.

なにより,全く初めての言語にも関わらず,自分の手でひとつのプログラムを作り上げていくことができるというのがおもしろい.

おかげでなんとなく手をつけてみたpythonの初級レッスンを,気がついたら修了してしまっていた.

次のレッスンにも手を出してみたけど,途中からは有料会員限定になるらしく進めなくなった.

うーん,うまいやり方だなあ.有料会員に登録しようか迷うなあ.