Tera Termのマクロの話

わけあって、Excelスプレッドシートに設定を書き込み、VBAからTera Termマクロを呼び出してDBの内容をcsvに出力させ、さらにWinSCPを呼び出してローカルに持ってきて、さらにExcelに読み込む、ということをやってました。

で、基本的な動きをttlファイルに書いて、引数として渡す、ということをやるんですが、ここに問題が。

(1)ttpmacro.exeは9個までしか引数を取れない(ちなみに第1引数はttlファイルのパス)

今回はいっぺんに大量のSQL文を実行したいので、引数を1個ずつ渡してparamcntで個数を調べて…ということはできない。

ので、適当な文字でつなげてstrsplitで1個ずつに分けるのはどうか、というと、

(2)strsplitは9個までしか割れない

というわけで、「strsplitで最初のSQL文を取り出し、文字数を数えて頭からその文字数+区切り文字を取り除く」を残らなくなるまで繰り返す、という方法に。

しかしここでぶち当たったのが次の問題。

(3)引数の文字数の上限

実際にたくさんつながったSQL文を食わせてみると、途中までしか認識されない。サクラエディタで文字数を数えてみると512文字っぽい。

ということで、「500文字を超えそうなら次の引数に回す」ということで必要なレベルではうまくいくようになりました。ちゃんちゃん。

でも512文字が上限ってどこにも書いてないし、実はコマンドラインの制限でOS依存だったり…大丈夫かなあ。

Javaの多次元配列がめんどくさい話

※結論だけ知りたい人はサンプルコードを見てください

 

その日、私はAtCoderで、

D: 画像処理高橋君 - AtCoder Beginner Contest 039 | AtCoder

を解いていました。

 

解法は Editorial にある通りなのでそちらを参照していただくとして、これを自力で思いついた私は意気揚々と実装に入ったわけです。

まず入力から配列を生成し、コピーし、白い部分を広げて、黒い部分を広げて、元の配列と一致していればセーフ。

(「白い部分を広げる」「黒い部分を広げる」はほぼ同じ操作なので、1つのメソッドで書けますね。)

 

…サンプルが通りません。というわけで生成された配列を出力してみると、コピーの時点でおかしいことが発覚。

 

cloneを使って配列を複製しようとしていたのですが、cloneの定義はこんな感じ。

Object (Java Platform SE 8)

「絶対的な要件ではありません」ばっかりなのが腑に落ちないのですが、とりあえず配列に対して適用すると、新しい配列オブジェクトを作り、中身が全部=で代入されると思えば間違いではないようです。

で、今回使っていたのはboolean型の2次元配列。プリミティブ型だから深く考えなくても大丈夫、と思っていたのですが、深く考えなくてもJavaの多次元配列は配列の配列なわけで、つまり配列としてa[0]==b[0]が成立してしまうということになります。こういうのを「シャローコピー」とかいうらしいですね。

仕方がないので二重ループでせこせこコピー。

 

…やっぱりダメです。出力してみると、比較するべきものは正しくできています。ということは比較がダメ。配列のequalsは==と同じようです。どないやねん、ということでちょっとググり、Arrays.equalsで比較。でもダメ。仕方がないので二重ループでせこせこ比較。

 

…していたのですが、今調べたらArrays.deepEqualsというメソッドがあるじゃないですかー。やだー。でもどうせならdeepCloneも作ってほしかったなー、なんて。

 

サンプルコードと実行結果を以下にまとめておきます。

コード

import java.util.Arrays;

public class TestClass {

public static void main(String args) {
// 二次元配列
int
a ={{0,0},{0,0}};
int
b =a.clone();

System.out.println(Arrays.deepToString(a));
System.out.println(Arrays.deepToString(b));

//シャローコピーなのを確認
System.out.println(a[0]==b[0]);

//aだけ変更(のつもり)
a[0][0]=1;

//bも変わってる
System.out.println(Arrays.deepToString(a));
System.out.println(Arrays.deepToString(b));

int
[] c={{1,0},{0,0}};

//これはダメ
System.out.println(a.equals(c));
//これもダメ
System.out.println(Arrays.equals(a, c));
//これはOK
System.out.println(Arrays.equals(a[0],c[0]));
//これもOK
System.out.println(Arrays.deepEquals(a, c));

}

}

実行結果

[[0, 0], [0, 0]]
[[0, 0], [0, 0]]
true
[[1, 0], [0, 0]]
[[1, 0], [0, 0]]
false
false
true
true