ハムスターに飼われる院生のブログ

自分用メモが中心のブログです。

既存クラスを呼び出すか継承クラスを呼び出すかif関数で選択し、仮想関数を実行

既存クラスOperationManagerを継承したクラスMethod_Aがあるとする。
既存クラスを呼び出すか、継承したクラスを呼び出すか、メイン関数からifで選択するようにした時のコードは以下の通り。

int main() {
	bool keisyou= true;
	OperationManager *operation;
	if (keisyou)
		operation= new Method_A();
	else operation= new OperationManager ();	
	operation->function();

	return 0;
}

呼び出すクラスを指定したのち、仮想関数function()を実行している。

OperationManager.h ↓

class OperationManager
{
	virtual void function() {
		//何らかの処理
	}
}

Method_A.h ↓

class Method_A:public OperationManager
{
	virtual void function() {
		//何らかの処理(既存クラスのfunction()とは中身が異なってもよい)
		}
	}
};

RでX軸をデータ名にしつつ、誤差バーをプロットする方法

平均値をプロットし、標準偏差を誤差バーにする場合を考える。
例として以下のデータでプロットする。

means<-c(-0.9946,-0.9821,-0.9733,-0.9558)
sds<-c(0.0080,0.0072,0.0143,0.0225)

それぞれのデータ名をA,B,C,Dとしてx軸に名前を表示するため、以下のようにスクリプトを作成した。

x<-c(1:4)#データ数に応じて変更
par(family="Arial")
label<-c("A","B","C","D")
plot(x,means,ylim=c(-1.05,-0.9),xaxt="n",xlab="x label [-]",ylab="y label [-]")
axis(side=1, at=x, labels=label)
arrows(x,means,x,means-sds,angle=90,length=0.1)
arrows(x,means,x,means+sds,angle=90,length=0.1)

作成できるグラフは以下の通り
f:id:chicagopile1-75:20210714100144j:plain

LNK2038の対処

Visual Studio 2017 でDebugビルドはできるがReleaseビルドができず
LNK2038 '_ITERATOR_DEBUG_LEVEL'の不一致が検出されました。値'2'が0の値'(ファイル名).obj'と一致しません。
とエラーが出た。

これを解消した時の手順をメモしておく。

プロジェクトのプロパティ(構成はRelease)→C/C++→コード生成→ランタイムライブラリ
にて
マルチスレッド(/MT)に設定してあったところをマルチスレッドデバッグ(/MTd)
に変更することで解消した。

このとき、Debugは元々マルチスレッドデバッグ(/MTd)に設定していた。

cpuの空きを確認してから処理を行うbatファイル

test.exe がコマンドライン引数 1 2 3 4 5 を取るとする。
この実行ファイルを最大で100回繰り返したいときに、
cpuの空きを確認して空きがあれば実行、空きがなければ600秒待機するバッチファイルを作成した。
今回はcpuが小数点切り捨て70%以下の使用率で実行とした。
cpuの使用率を確認する部分は64bit用のものなので

typeperf -sc 1  -si 1 "\processor(_Total)\%% Processor Time" | find ":" >cpu.csv

だが、32bitの場合は

typeperf -sc 1  -si 1 "\processor(_Total)\% Processor Time" | find ":" >cpu.csv

と変更する必要がある。

なお、test.exeのコマンドライン引数は文字列として扱っているため、
実際は小数を入れることも可能。
このように実行する。

testbat.bat test.exe 100 1 2 3 4 5

呼び出し先のtestbat.batは以下の通り。

@echo off
@setlocal enabledelayedexpansion

set exefile=%1
set /a loop_max=%2
set arg1=%3
set arg2=%4
set arg3=%5
set arg4=%6
set arg5=%7
set /a counter=1
for /l %%i in (0,1,1000000) do (
	call :Check_Termination
	typeperf -sc 1  -si 1 "\processor(_Total)\%% Processor Time" | find ":" >cpu.csv
	powershell sleep 1
	call :Check_CPU
	call :RunCalc
)
pause
exit /b


:Check_Termination
	if %counter% gtr %loop_max% (
		exit
	) else (
	)
	exit /b

:Check_CPU
	for /f "tokens=1-5 delims=," %%a in (cpu.csv) do (
		set v=%%~b
	)
	call :GetINT
	call :CheckVacancy
	exit /b
	
:RunCalc
	rem echo vacancy=%vacancy%
	if %vacancy%==1 (
			set /a counter=counter+1
			rem echo %counter%
			echo 計算%counter%を実行中
			start	%exefile%	%counter%	%arg1%	%arg2%	%arg3%	%arg4%	%arg5%	>	output%counter%.txt
		) else (
			echo cpuの空きに余裕がないので計算実行を待機しています
			powershell sleep 600
		)
	exit /b

:GetINT
	for /f "tokens=1* delims=." %%a in ("!v!") do (
		set /a cpu=%%~a
	)
	exit /b

:CheckVacancy
	echo cpu=%cpu% %%の使用率
 	if %cpu% lss 70 (
 		set /a vacancy=1
 	) else (
 		set /a vacancy=0
 	)
	exit /b

:fin
exit /b

cpuの使用率を一度cpu.csvに書き出している。

バッチファイルのみを他のフォルダに移動させる

任意のバッチファイルを実行後に、
バッチファイルを作業用のディレクトリに置きっぱなしにしておくと
意図せずクリックして作業時間をロスすることがあった。
これを防ぐため、実行するバッチファイルの末尾に以下の文を加えた。

mkdir batfiles
move *.bat .\batfiles

batfilesというフォルダを作成し、作業場所のbatファイル全てを移動させることができる。

一行ずつ読み込んだ内容を数値に変換する

長さの違うデータが複数列記述されているファイルをRで処理する。
今回は例として3行読み込む。

filename<-"text.txt"
f<-file(filename,"r")
for(i in 1:3){
   a<-readLines(con=f,1)  #一行ずつ読み込み
   a<-strsplit(a , ",")     #カンマ区切り
   a<-unlist(a)                        #リスト形式を解除
   a<-as.numeric(a)               #numericに変換
   print(a)#各行に行う処理(今回は画面出力)
}

特定の箇所のみ出力するrubyプログラム

一つのファイルに複数の情報を書き込んでいる際に、以下のように取り出したい内容が区切られているとする。

<HOGE>
取り出したい内容
</endHOGE>

この取り出したい内容を拾い出すプログラムを作成した。
ファイル名は入力で与えている。

file=open(ARGV[0])
lines=file.read().split("\n")
export=false
lines.each do |line|
	if line =~/<HOGE>/
		export=true
	end
	if line =~/<endHOGE>/
		export=false
	end
	if export then
		puts(line)
	end
end
file.close