C++プログラミング・データ構造の実装

C++プログラミングの基礎・データ構造の実装をご紹介します。
ここで紹介するサンプルコードを使用することで、多次元の配列データを1次元の配列データとして扱うことができます。


多次元データと1次元データ

多次元データを1次元データへ変換する方法を説明します。

多次元データとは多次元の配列で定義されたデータのことです。例えばchar num[2][3];のように2次元配列で定義されます。1次元データとは1次元の配列で定義されたデータのことです。例えばchar num[2];のように1次元の配列で定義されます。

多次元配列を1次元配列で表現することは可能であり、またその逆も可能です(私が経験した現場ではこれらの変換処理をシリアライズと呼んでいました)。

用途・どんな時に使えるの?

主に以下の処理を行う際に使用します。

  • プロセス間通信で共有メモリを用いたデータの送受信

他のプロセスのメモリマップが自プロセスと異なるため、共有メモリを使用する際は多次元データを使うことができません。そのため共有メモリを使用する際に多次元データを1次元データへ変換する必要があります。

データ構造

例えば以下のような世界陸上のデータ構造があります。これは多次元配列で定義することができます。

「世界陸上」に対して「種目」は複数の関係であり、「種目」は「種目名」と「参加者」をもっています。「種目」に対して「参加者」は0かそれ以上の関係であり、「参加者」は「名前」と「参加記録」をもっています。
データ構造

この多次元データを1次元データにで表すと以下のようになります。
1次元データ

分かりやすくするため「型」「バイト」「データ」の順に示しています。

データのはじめに「種目」の数を示すデータを割り当てます。このデータのサイズはintなので4です。次に「種目名」のデータを割り当てます。「種目名」はstringであるためサイズを可変とします。

「参加者」は複数存在することになるため、「参加者」の数を示すデータを割り当てます。サイズはintなので4です。「参加者」が持つ「名前」「参加記録」のデータを割り当てます。両者ともにstringなのでサイズは可変です。その後は同じように「種目」の数と「参加者」の数だけ割り当てていきます。

「データサイズ + データ」という構成で一次元配列へ割り当てていきます。なお可変長のstringについてはサイズ指定しておりません。
これはNULL終端を保証することで、NULL終端までをstringのデータであることを示すことができるためです。

このような構成でデータを割り当てることで多次元データを1次元データで表現することができます。

実装の解説

C++で実装したサンプルコードを解説します。
このサンプルコードは世界陸上へ参加する100m選手とマラソン選手のデータを多次元配列へ格納し、多次元配列を1次元配列へ変換した後に多次元配列と1次元配列の中身を表示します。

多次元配列は構造体で定義されている「種目」をlistで定義します。また「種目」で定義している「参加者」もlistで定義しています。

display_multidimensionall_array関数で種目毎に格納した参加選手のデータをイテレータを使って表示します。

convert_multi_to_one_dim関数で多次元配列から1次元配列へ変換します。
変換する前にget_max_data_size関数で多次元配列のデータサイズを計算します。可変長のstringがあるためNULL終端を考慮して+1のサイズで計算します。計算した最大サイズ分の1次元配列のデータを確保します。

convert_multi_to_one_dim関数では「種目の個数」「種目名」「参加者の個数」「名前」「参加記録」を1次元配列へ格納します。データを格納する毎に、格納したデータのサイズをoffsetへ加算し、次のデータの格納先を指定します。

display_one_dimensional_array関数で1次元配列の中身を表示します。
1次元配列の先頭の4バイトは「種目の個数」なので、取り出した「種目の個数」だけfor文を使って残りのデータを取り出します。次のデータは「種目名」のため athletes_type_name = &binary_data[offset]; でstringのデータを取り出します。

なおNULL終端を保証しているため、サイズ指定をしなくてもデータがNULLまでコピーしてくれます。注意としてoffsetにサイズを加算する際は、NULL終端分を足して加算します(+1)。

あとは同じように「参加者の個数」を取り出し、for文で「名前」「参加記録」を取り出すだけです。

■ ExDataStructure.cpp

■ define_common.h

サンプルコード

Visual C++ 2017で作成したサンプルコードをGitHubで公開しています。
GitHub – ExDataStructure

実行結果は以下の通りです。
多次元配列の中身と1次元配列の中身が同じであるため、正しく変換できていることが確認できます。

[170] Start.
[178] +------Multidimensional array-----+
[160]  [100m]
[162]  + name:       Usain Bolt, record:     9.58
[162]  + name:    Justin Gatlin, record:     9.74
[162]  + name:       Sani Brown, record:    10.05
[160]  [42.195km]
[162]  + name:          Kipruto, record:  2:02:57
[162]  + name:         Kawauchi, record:  2:08:14
[162]  + name:          Takaoka, record:  2:06:16
[180] +---------------------------------+
[191] +------One-dimensional array------+
[133]  [100m]
[149]  + name:       Usain Bolt, record:     9.58
[149]  + name:    Justin Gatlin, record:     9.74
[149]  + name:       Sani Brown, record:    10.05
[133]  [42.195km]
[149]  + name:          Kipruto, record:  2:02:57
[149]  + name:         Kawauchi, record:  2:08:14
[149]  + name:          Takaoka, record:  2:06:16
[193] +---------------------------------+
[198] Terminate.

参考

多次元配列 – 柳川研究室

Cの絵本 第2版 C言語が好きになる新しい9つの扉

新品価格
¥1,490から
(2017/7/29 21:38時点)

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

SNSでもご購読できます。

コメントを残す

*

Translate »