C++でcsvファイルを読み込む(読み込み編)
前回ファイルパスを取得出来たので今回はそのファイルパスの場所にあるcsvファイルを読み込むやり方を書いていこうと思います。
読み込む処理の流れは
1.ファイルを開く
2.開いたファイルの内容を1行毎に取得する。
3.取得した内容を,(カンマ)毎に区切って文字列の配列に代入する
という感じです。
コードを書いていきます。
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
using namespace std
void GetCsvData(filesystem::path CsvPath)
{
ifstream CsvFile(CsvPath);//読み込むcsvファイル
string GetLineData;//取得したデータ
//EOFに達するまで1行毎に読み込みむ処理
while(getline(CsvFile,GetLineData))
{
istringstream GetData(GetLineData);//取得したデータをsstreamへ代入
vector<string> Data;//カンマ毎に区切った配列
string s0;//カンマ毎に区切った文字列を一時的に保持する変数
//カンマ毎に区切って配列に代入
while(getline(GetData,s0,','));
{
Data.push_back(s0)//カンマ毎に区切って配列に追加
}
//ここから取得した値に対する処理を記述
}
}
こんな感じです。
流れとしてはifstreamでファイルを開いてgetlineで1行ずつ取得、
取得した文字列をカンマ毎に区切ってそれぞれを配列にしたstringで受けるという感じです。
なお、実際にATSプラグイン等で使用する場合はファイルを開けなかった場合や開いたファイルが空だったりした場合にvectorが空のまま(初期状態)となってしまうため、
そのまま参照すると例外が発生してしまいます。
対策として配列の最初または最後に何かしらの値を入れる処理を足しておくとよいでしょう。
また、取得した値は文字列なので数字の型に変換する場合stoi(),stod()などが使用出来ますがこれらの関数は取得した値が数字以外の場合は例外が発生します。
これらの処理を行う場合はtry-catchをうまく使って例外を回避するように処理を組む必要があります。
C++でcsvファイルを読み込む(ファイルパス取得編)
今回はcsvファイルの読み込み処理について書いてみようと思います。
csvファイルを読み込む際の処理の流れとしては
1.読み込む対象のファイルパスを取得
2.ファイルを読み込む
3.読み込んだ内容を配列に落とし込む
というようになります。まずはファイルのパスを取得する所からです。
今回はdllファイルと同じ階層にあるcsvというフォルダ内のsample.csvを開くと仮定してコードを書いていきます。
#include<windows.h>
#include<filesystem>
#include<stdlib.h>
using namespace std
//ファイルパス取得
void GetCsvFilePath(HINSTANCE hModule)
{
TCHAR dllpath[_MAX_PATH];//dllファイルのパス
//dllファイルのパスを取得
GetModuleFileName(
hModule,//インスタンスハンドル(dllMain内で取得可)
dllpath,//dllファイルのパスを格納する
sizeof(dllpath)
);
//csvファイルのパスを設定
filesystem::path csvpath(dllpath);
csvpath.remove_filename();
csvpath.append(csv);
csvpath.append(sample.csv);
}
自分はこんな感じで書いています。
GetModuleFileNameで取得したパスからファイル名を消して目当てのパスに変更します。
filesystemはC++の言語標準をC++17以降にしていないと対応していないので注意です。
csvに限らずファイルパスの取得はいろいろな場面で使えると思うので覚えておいて損はないと思います。
ファイルを読み込んで配列に落としこむやり方はまた今度書きます。
VisualStudioでATSプラグインを作るときに真っ先にやること
bveでATSプラグインを作成するに当たって
プロジェクトを作るところからやる場合に最初にやっておくといいことを書いていこうと思います。
・モジュール定義ファイルの作成と参照の設定
これはやっておかないとせっかく定義した関数が実行されません。
まず最初にやっておきましょう。defファイル自体の説明については割愛します。
設定方法はメニューバーのプロジェクト>XX(プロジェクト名)のプロパティ からプロパティページを開き 構成プロパティ>リンカー>入力>モジュール定義ファイル より設定します。
構成毎に設定する必要があるため参考画像では設定する構成が"debug"となっていますが
"全ての構成"にしておくとまとめて設定出来るので便利です。
・dllexportの設定
atsplugin.hを使用してATSプラグインを作成する際はATS_EXPORTSというプリプロセッサを定義しておかないとビルドが通らないので設定します。
設定方法はメニューバーのプロジェクト>XX(プロジェクト名)のプロパティ から
プロパティページを開き
構成プロパティ>C/C++>プリプロセッサ>プリプロセッサの定義 より設定します。
これも構成毎に設定する必要があるため設定する構成を"全ての構成"にしておくとまとめて設定出来るので便利です。
・デバッガーの設定
これを設定しておくとbveを実行しながらどの変数がどういう経緯で値が変化してくのかというのをコード1行毎に追いながら確認していくことが出来ます。
何も知らなかった頃は確認用のコードを追記してpanelに反映させたりして確認してました
設定方法はメニューバーのプロジェクト>XX(プロジェクト名)のプロパティ からプロパティページを開き 構成プロパティ>デバッグ>コマンド にbve5のexeのパスを指定します。
デバッグ中はこんな感じで変数や関数の呼び出し履歴が見られるのでプラグインの動きを確認することが出来ます。
デバッグを行うには(正確にはデバッグ中にブレークポイントに引っかけるには)pdbファイルを生成する必要があります。
デフォルトでは自動で生成されるので問題ないですが、構成がReleaseの場合でも生成されるようになっておりpdbが生成される場合生成した場所のフルパスがdllに埋め込まれます。
公開するファイルをビルドする際は生成しないように設定を変えておきましょう。
設定方法はメニューバーのプロジェクト>XX(プロジェクト名)のプロパティ からプロパティページを開き 構成プロパティ>リンカー>デバッグ>デバッグ情報の生成 を"いいえ"設定します。
とりあえずこれくらい設定しておけば下準備完了です。
ガンガン作っていきましょう。
気動車の性能計算(機関編)
bveで使えるかどうかはアレですが今回は気動車の性能計算(主に力行)について書いてみようと思います。
電車の場合は主にモーター電圧と電流なんかで決まるわけですが気動車の場合は
エンジンの回転数と変速段の場合はコンバーターの特性で変わってきます。
一般的な気動車の速度に対する加速力は適当に書くと下の図のようになります
一般的な電車とは割と違います(そもそもグラフ自体も適当ですが)。
今回はそのエンジンの加速性能計算をやってみようと思います。
今回はキハ40原型車(DMF15HSA )の曲線を元に解説してみます。
性能曲線はこちら
なんかグラフが2段階あるのはなぜ?と思われた方もいると思いますがこれはキハ40系列のエンジンには自動進角回路というものがありまして一定以上の回転数になると自動的に燃料を噴射する量を増加して燃焼不良を防止する機構が組み込まれているからです。
トルクの曲線が5Nしかないじゃないか!と思う方もいると思います。
出力[PS]は回転数×トルク÷定数で求めることができるので各ノッチのトルクは出力曲線の割合通りに按分してやれば出すことができます
今回はここからどうやってbveで使える力に換算していくかの計算を行います。
このグラフから導かれる値はトルク[kg・m]なのでこれをbveの引張力曲線に使える値[N]に換算します。変速段の場合はトルクがさらに増幅されて車輪に伝達されていくわけですがその部分の計算は複雑な話になってくるのでまた次の機会のお話しします。直結段はそのままエンジンの出力が車輪に伝わるのでここで求めた値を使用できます。
あるときのエンジンのトルクをT[kg・m]とするとエンジンから動輪までに変速機の減速比がGr1で減速比Gr2の減速機を介した車輪径R[m]の動輪周での引張力[N]は
T×Gr1×Gr2÷R×9.80665で表すことができます。
DW10の減速比は1なので
Gr1=1
キハ40に架装させているGB122減速機の減速比は2.995なので
Gr2=2.995
車輪径は摩耗度合いによりますがここでは820mmとします。
このことからある回転数のトルクTにおける動輪周引張力F[N]は
F=T×38.32...で求めることができます。
また、速度V[km/h]で走行中の直結段使用時の機関回転数[RPM]は
V÷60÷(車輪径×π)×Gr2×Gr1×1000で表せるのでこれで速度に対応したトルクが求められます。
あとはそこからそれに応じた引張力も求めることができるのでそれにより直結段の速度に応じた加速力を求めることができます。
直結段に関してはこの計算できっと多分加速力が出せます
間違ってたら教えてください。
時間ができたら変速段の説明をしたいです(願望)。