2015年10月29日木曜日

Javascriptで最大公約数を求める(ユークリッドの互除法)

今回は、数学的なお話。ユークリッドの互除法をJavascriptでしてみようと思います。

まず...
ユークリッドの互除法とは?という方へ。

ユークリッドの互除法は、簡単に最大公約数を求めるための計算法です。説明より例を示した方がいいかと思いますので、例題を一つ。
(例題) 1071と1029の最大公約数を求めよ。

  • 1071 を 1029 で割った余りは 42
  • 1029 を 42 で割った余りは 21
  • 42 を 21 で割った余りは 0
  • よって、答えは 42

では、これをプログラムに書き起こしてみましょう。関数名は最大公約数の略であるG. C. D.としました。

function gcd(m, n) {
  // 剰余
  var r;

  if(m < n) {  // m >= nにする
    r = m;  //一時退避
    m = n;
    n = r;
  }

  while ((r = m % n) != 0) {
    m = n;
    n = r;
  }

  return n;
}

2015年10月28日水曜日

C#で外部スイッチとやり取りする

パソコンと(2極)スイッチで通信する方法を考えてみました。(動作未確認)
※2極スイッチとは、簡単なON/OFFだけを切り替えるスイッチのこと。

そんなとき問題になるのは、

  • パソコンとスイッチをどうやって繋ぐか
  • ソフト側でどうやってON/OFFを認識するか
です。

まず考えたのは、USBで接続する方法。USBポートでスイッチと接続できないかと。しかし、これではドライバを作らないといけないし、スイッチ側に自己紹介する機能を持たせなければやり取りは不可能です。

次に考えたのがシリアルポートを使う方法です。1ビットのシリアル接続が可能なら、ON/OFFも可能なのではないか。
結論から先に書くと、「できました」。

RS-232C規格のシリアルポートを使った具体的なしくみです。
まず、DTR線の状態をONにしておきます。スイッチはDTR-(スイッチ)-DSRの順で接続しておきます。スイッチがONになると、DTRから出力された12Vの電流がDSRに流れることになります。スイッチをOFFにしたときは-12Vが正確に入力されるわけではありませんが、電流0はFalse扱いをうけるようです。

その理論(?)をもとに、C#でコードを書いてみました。

using System;

// シリアルポートクラスがある名前空間
using System.IO.Ports;

namespace myPort
{
  public class myPort1
  {

    // シリアルポートクラスのインスタンス
    SerialPort port = new SerialPort("COM1");

    // ポートをオープンする
    port.Open();

    // DTR線を出力
    port.DtrEnable = true;

    // ONかOFFかは次の値で確認する
    port.DsrHolding;

    // 例
    private void checkSwich(){
      if(port.DsrHolding)  // ON
      {
        MessageBox.Show("スイッチはONです。");
      }
      else
      {
        MessageBox.Show("スイッチはOFFです。");
      }
    }
  }
}

これで、ON/OFFの2極スイッチとパソコンとでやり取りができるようになりました。

なお、この記事を書くにあたって、どこでも発車ベルヘルプ - スイッチのつなぎ方を参考にいたしました。
ありがとうございました。

なお、この記事で記載された内容は、管理人(chiko ryo)では動作確認を行っておりません。くれぐれも自己責任でお願いします。また、このサンプルは著作権フリーですが、これを参考にしていかなる損害が出たとしても管理人(chiko ryo)は責任を負いませんのでご容赦ください。

2015年10月27日火曜日

JavascriptでINIファイルを解読する その3

JavascriptでINIファイルを解読するシリーズの第3弾です。

前回のJavascriptでINIファイルを解読する その2でお約束していた通り、INIを読み込んで連想配列に返す関数を完成させることができました。

さっそく、ソースをはります。

function myReadInI(myFname){

    var i = 0; // プロパティiはカウンタです。
    var t = null; // コメント除去に使用します。
    var ts = 0;   // これもです。
    var sec = null; //処理中のセクションを記録
    var pal = null; //処理中のパラメータ名を記録
    var returnData = {}; //返り値
 
    // オブジェクト生成
    var objFileSys = new ActiveXObject("Scripting.FileSystemObject");
 
    var objTextStream = objFileSys.GetFile(myFname).OpenAsTextStream(1, 0);
    /*読み込みモードを使用、文字コードはUnicodeです。(Unicode文字が扱えるようにするため)*/
 
    var data = new Array(); // 空の配列
 
    // ファイルが最後まで読み込まれるまでループ  読み込み
    while (!objTextStream.AtEndOfStream) {
 
        t = objTextStream.ReadLine();
        ts = t.indexOf(";"); // コメントを探す
        if(ts == -1){ // コメントがない
            data[i] = t;
        }else{ // コメントあり
            data[i] = t.substring(0, ts);
        }

        //解読

        if(data[i] != ""){  //空行でないか?

            if(data[i].indexOf("[") == 0){  //セクション行

                sec = data[i].slice(1, -1);    //セクション名を抽出する

                returnData[sec] = {}  //さらにパラメータ名の2次元連想配列が作れるようにする

            }else{                          //パラメータ行

                if(data[i].indexOf("=") != -1){  // "="を含む行であることを確認する

                    /* パラメータ名と値を分割(pal[0]がパラメータ名、pal[1]が値) */
                    pal = data[i].split("=");

                    /* 連想配列に代入する */
                    returnData [sec] [pal[0]] = pal[1];
                }

            }

        }
        i++;
    }

    return returnData;

}

前回からの変更点として、

  1. 引数が一つになった
  2. 戻り値が2次元連想配列になった
  3. 若干軽くなった
  4. 何度もファイルを読み込みなおす必要がなくなった
があげられます。また、空行があってもそのあとの行も読み込むようになったほか、セクションの閉じカッコ"]"の省略を禁止しました。


使い方
・引数

引数は1つ必要です。INIファイルまでのパス(絶対パス・相対パス)を文字列で渡します。
・戻り値
INIを解析した結果の2次元連想配列を返します。設定内容は(戻り値)["(セクション名)"]["(パラメータ名)"]で取得できます。

おそらくこのシリーズは今回で終わりとなります。
解説は要望があれば行います。ご希望であればコメントをお願いします。

Javascriptでテキストファイルを読み込む

近年、Javascriptがブームになりつつあります。FileAPIなどの拡張機能なども充実してきました。
そこで、IE独自のActiveXコントロールを使って色々なことをしてみましょう。

今回は(次回があるといいですね)テキストファイルの読み込みをしてみようと思います。

ファイル操作関連のことは、次のインスタンスを多くの場合使用することになります。

var hogehoge = new ActiveXObject("Scripting.FileSystemObject");

WSHの場合は、以下のようになります。

Set hogehoge = WScript.CreateObject("Scripting.FileSystemObject");

これで、ScriptingFileSystemObjectクラスのインスタンスを取得できました。ファイル操作は主にこいつを使って行います。

とりあえずファイルをテキストファイル(これ超重要)として開きます。
ファイルは開かないと何も始まりません。

テキストファイルを開くには、基本的にOpenTextFile()関数を使用します。(他にもありますが使い勝手が悪い)

var fs = new ActiveXObject("Scripting.FileSystemObject");
var file = fs.OpenTextFile("開くテキストファイルのパス");

このときOpenTextFile関数が返した値(ここではfile変数)で開いたファイルに対して様々な操作を行なえるようになります。

また、開いたファイルは用が済んだら閉じましょう。

file.Close();

/* ここからは任意 */
//解放
fs = null;
file = null;

テキストファイルを1行読み込む(1行読み込み)


1行だけ読み込むにはReadLine()関数を使用します。
/*
  あらかじめテキストファイルを開いておく
  var fs = new ActiveXObject("Scripting.FileSystemObject");
  var file = fs.OpenTextFile("開くテキストファイルのパス");
*/

/* 1行目のみ読み込む */
text[0] = file.ReadLine();

/* 2行目を読み込む */
text[1] = file.ReadLine();
ReadLine関数は、呼び出すたびに1行ずつ読み込みますので大変便利です。

テキストファイルを文字数を指定して読み込む


文字数を指定して読み込むには、Read()関数を使用します。
/*
  あらかじめテキストファイルを開いておく
  var fs = new ActiveXObject("Scripting.FileSystemObject");
  var file = fs.OpenTextFile("開くテキストファイルのパス");
*/

/* ファイルの先頭から6文字読み込む */
text = file.Read(6);

テキストファイルをすべて読み込む


テキストファイルをまとめて読み込むには、ReadAll()関数を使用します。
/*
  あらかじめテキストファイルを開いておく
  var fs = new ActiveXObject("Scripting.FileSystemObject");
  var file = fs.OpenTextFile("開くテキストファイルのパス");
*/

/* テキストファイルをすべて読み込む */
text = file.ReadAll();
ReadAll()関数は便利ですが、メモリを多く消費します。ですので極力使わず、ReadLine()関数をうまく使うようにしましょう。
var text = "";
/* ファイルが最後まで読み込まれるまでループ */
while (!file.AtEndOfStream){
  text += file.ReadLine();
}
AtEndOfStreamプロパティにはテキストファイルが終端に達しているかを示す真偽値が入っています。終端ならtrue、そうでなければfalseです。
他にも似たようなプロパティAtEndOfLineがありますが、これは空行に到達すると終端に達していないにも関わらずtrueになってしまいます。よってここでAtEndOfLineを使うと、空行混じりのファイルが読み込めなくなります。AtEndOfStreamを使うようにしましょう。

いかがだったでしょうか。意外と簡単だったと思います。Scripting.FileSystemObjectではファイルへの書き込みや追記も可能です。次回(あれば)はテキストファイルへの書き込みのお話をしたいと思います。

注意
今回使用したScripting.FileSystemObjectは、ActiveXコントロールを必要とします。ActiveXコントロールはHTAなどのセキュリティレベルの低い状態のIEまたはデジタル署名ずみのコンテンツをIEで動作させるときのみ使用できます。一般的なWebページを作成する際は、FileAPIなどを使うようにしてください。
また、私が作ったサンプルに著作権なんてあるわけがありません。ご自由に転載・引用・二次配布などしていただいて構いません。ただし、それらのサンプルでエラーが起こったり、データが消えたり、マシンが火を吹いたとしても私(chiko ryo)は一切の責任を負いませんのでご注意ください。