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

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

指定した文字列以降を出力するrubyプログラム

指定した文字列以降を出力するrubyプログラムを作成した。

a,b,c,d,
-----------------------------
A,B,C,D,

このようなファイルがあったとして、
”-----------------------------”を含めてそれ以降を出力する。
読み込む対象のファイル名は引数で与える。

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

vectorで指定した値を持つインデックスを複数返す

vec1の要素のうち、targetで指定した値を持つインデックスを複数返す関数を作成した。

vector<int> detectIndex(vector<double> vec1, double target) {
	vector<int> result;
	for (auto itr = vec1.begin(); itr != vec1.end(); ++itr) {
		if (*itr == target) 
			result.push_back(std::distance(vec1.begin(), itr));
	}
	return result;
}

バッチファイルでフォルダを作成してから計算実行

このようにフォルダ分けをして計算結果を書き出す場合を考える。

call test.exe >case1/condition1/output.txt
call test.exe >case1/condition2/output.txt
call test.exe >case1/condition3/output.txt

この場合、case1/condition1等のフォルダが存在しないと実行時にエラーとなる。
これを防ぐため、バッチファイル内で自動でフォルダを作成するように
以下の文をバッチファイルの冒頭に記述した。

mkdir case1
cd case1
mkdir condition1 condition2 condition3
cd ../

フォルダ数が少なければこの方法で対処することができる。

特定の数値が出現するまでRでデータを読み込む

タブ区切りのデータについて。
データが何行あるかわからない場合を考える。

*----------------------*
1	10	100
2	20	200
5	50	500
10	100	1000
*----------------------*

このようなtxtファイルがあるとする。
read.table()で読み込むと

*----------------------*

の部分が悪さをしてエラーが出るため、以下の関数を作成して読み込んだ。

get_i <- function(filename, target){
	f<-file(filename,"r")
	num<-0
	for(i in 1:10000){
		a<-readLines(con=f,1)
		if(i>1){
			v<-as.vector(as.numeric(strsplit(a,"\t")[[1]]))
			if(v[1]==target){
				return(i)
			}
		}
	}
	return()
}

1行ごとに読み込み、targetとした目的の数値が出たところで読み込みを終了し、
目的の数値が何行目にあるかを返してくる。
今回はskip=1であるから、関数を以下のように使用する。

i<-1
filename<-paste("output",i,".txt",sep="")
n<-get_i(filename, 10)
data<-read.table(filename,skip=1,nrows=n-1,sep="\t")

C++で複数行のデータを読み込んでひとつのベクトルに格納する

改行を含むコンマ区切りのデータを一つのvectorに格納する場合。
fileの内容は以下の通りでintが6つである。

1,10,100,
2,20,200,
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
class InputManager {
private:
	
public:
	void Get_TxtData(string filename) {
		ifstream ifs(filename);
		if (ifs.fail())
			cout << "ifs is failed." << endl;		
		string str;
		vector<int> container;
		while (getline(ifs, str, ',')){
			if (str[0] == '\n')
				str.erase(str.begin(), str.begin() + 1);
			container.push_back(stoi(str));
		}
		return;
	}
};


コンマで区切られた各数字がcontainerに数値として格納される。

オブジェクトポインタを使用してクラスを切り替える

OperationManagerを基本クラスとし、それに追加機能をつけるクラスAdditionalManagerを考える。
存在するクラスは以下の2つ。
・OperationManager
・AdditionalManager(これはOperationManagerを継承している)

この時両クラスには同名の関数virtual void func()があるとする。
どちらのクラスのfunc()を呼び出すかをシンプルに切り替える記述は以下の通り。

	bool Additional = true;
	OperationManager *op;
	if (Additional)
		op = new AdditionalManager();
	else op = new OperationManager();
	op->func();

これにより
Additonal=trueの時 AdditionalManagerのfunc()
Additonal=falseの時 OperationManagerのfunc()
が呼び出される

なお、virtual をつけないと基本クラス(今回だとOperationManager)しか呼び出されないことに注意。

コマンドライン引数をまとめて処理する関数の作成

コマンドライン引数をまとめてベクトルに入れておけば、メイン関数をすっきりと書くことができる。
main関数では以下の処理を行う。

vector<string> input;
for (int i = 1; i < argc; i++)
	input.push_back(argv[i]);

この読み込んだinputを別のクラス内でstoiやstodをすればよい。例は以下の通り。

void SetInput(vector<string>& _input) {
	vector<string> ParaInput;
	ParaInput = _input;
	convert_type(ParaInput);
}
void convert_type(vector<string> ParaInput) {
	hoge1 = stoi(ParaInput[0]);
}