SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Modern C++入門

コンテナに正規表現も! Modern C++に必須の基本ライブラリ

第8回 ベーシックな機能はもはや自分で書かなくていい

  • X ポスト
  • このエントリーをはてなブックマークに追加

正規表現std::regex[C++11]

 正規表現(Regular Expression)も、プログラミングの現場ではよく使われますね。正規表現など知るよしもなかったころは、文字関数や文字列関数をゴリゴリ使ってパターンマッチングを書いていたものですが……。今は、どんな言語でも正規表現が扱えるのが普通なので、C++ 11で早々に正規表現std::regexが導入されました。

 基本的な使い方を見てみましょう。

リスト:regex.cpp
#include <regex>
…略…
regex re(R"(\d+)");
cout << regex_match("1234", re) << endl;	// 実行結果:1
cout << regex_match("ABCD", re) << endl;	// 実行結果:0

 std::regexを使うには、ヘッダファイル<regex>をインクルードします。regexオブジェクトをコンストラクタ引数にパターンを指定して生成し、regex_match関数でマッチングを実行します。結果はfalse(一致なし)かtrue(一致あり)で返ります。

 このとき、コンストラクタの引数に指定されているのは、同じくC++ 11で使えるようになった生文字列リテラルです。これは第6回で紹介しましたね。バックスラッシュのエスケープが不要なので、バックスラッシュを多用する正規表現ではとても便利です。

 マッチした文字列を取得する例も示します。ここでも、regexオブジェクトを作るのは同じで、引数を3つとるregex_match関数のオーバーロードを呼び出して、パターンマッチを実行します。結果は、2番目の引数であるmatchに入ります。

リスト:regex.cpp
string zip = "225-0002";
smatch match;
regex re_zip(R"((\d+)-(\d+))");
if( regex_match(zip, match, re_zip)) {
    cout << match[0].str() << endl;	// 実行結果:225-0002
    cout << match[1].str() << endl;	// 実行結果:225
    cout << match[2].str() << endl;	// 実行結果:0002
}

 なお、正規表現には互換ライブラリSRELLというものがあって、これを使うとJavaScript(ECMAScript)互換の正規表現をregexと同様に扱えるようです。

時間と時刻std::chrono[C++20]

 時間情報を扱うのは面倒なものです。そもそも年月日、時分秒に分かれていますし、閏年もありますし、月の日数が一定でないですし、閏秒なんてものもあります。1週間前の日付を求めよ、なんて簡単そうで難しい(というか面倒)です。このような事情なので、モダンなプログラミング言語では時間情報を容易に取り扱えるライブラリを標準で備えることが多いと思います。

 我らがC++でも、C++ 11においてstd::chronoライブラリが導入されました。このchronoライブラリ、C++ 11の時点では高精度な時間計測とか短いスパンでの用途に限定されていましたが、C++ 20においてカレンダー機能が実装されて、長期の日時演算なども可能になりました。ここでは、カレンダー機能に注目してみましょう。

 まずは、定番の現在日時の取得です。

リスト:chrono.cpp
#include <chrono>
…略…
auto now_utc = chrono::system_clock::now();
cout << now_utc << endl;
// 実行結果:2024-08-12 06:23:28.538803000

 std::chronoを使うには、<chrono>ヘッダファイルをインクルードします。chrono::system_clock名前空間のnow関数を呼び出すと、デフォルトのタイムゾーンすなわちUTCにおける現在日時を取得できます。これから日本時間(JST)を取得するには、TimeZoneクラスオブジェクトをコンストラクタの引数にロケーション文字列(ここでは"Asia/Tokyo")とUTC時刻を指定して生成します。

リスト:chrono.cpp
auto now_jst = chrono::zoned_time{"Asia/Tokyo", now_utc};
cout << now_jst << endl;
// 実行結果:2024-08-12 15:23:28.538803000 JST

 年月日と時分秒から、日時情報を作成することもできます。

リスト:chrono.cpp
using namespace std::chrono_literals;
using std::chrono::August;
…略…
auto tp = chrono::sys_days{2024y/August/7d} + 16h + 27min + 38s;
cout << tp << endl;
// 実行結果:2024-08-07 16:27:38

 他言語でよく見る、フォーマット文字列や関数の引数に与える形とはずいぶん違いますね。最初のsys_daysについて、これはsys_timeのエイリアスで、ある年月日を表します(Time Pointといいます)。2024y/August/7dは日付のパターンで、2024年8月(August)7日を表します。

 ここで、yとかdとかを数値リテラルに付加していますが、これはC++ 11で使えるようになった「ユーザ定義リテラル」というもので、chrono_literals名前空間で定義されています。文字通り、年(y)、日(d)、時(h)、分(min)、秒(s)に相当します。月名(ここではAugust)は、定義済みの定数(8m)です。sys_daysは日付を表しますが、これに時分秒を加算することで、時間情報も含んだ型へと変換されます。

 Time Pointからは、年月日時分秒を個別に取り出すこともできます。

リスト:chrono.cpp
auto dp = floor<chrono::days>(tp);
auto ymd = chrono::year_month_day{dp};
cout << ymd.month() << " " << ymd.day() << " " << ymd.year() << endl;
// 実行結果:Aug 07 2024
auto hms = chrono::hh_mm_ss{tp - dp};
cout << hms.hours() << hms.minutes() << hms.seconds() << endl;
// 実行結果:16h27min38s

 chronoのCalendar機能はたくさんあるので、よくある処理に絞って紹介しました。

次のページ
ファイルシステムstd::filesystem[C++17]

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Modern C++入門連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 山内 直(WINGSプロジェクト ヤマウチ ナオ)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook <個人紹介> WINGSプロジェクト所属のテクニカルライター。出版社を経てフリーランスとして独立。ライター、エディター、デベロッパー、講師業に従事。屋号は「たまデジ。」。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/20220 2024/09/26 12:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング