2014年2月10日月曜日

Delphiでのrecordの便利な使い方 Part2

こんばんは
大阪本社 Mです。

前回に続きDelphiでのrecordの便利な使用方法を紹介
ジェネリクスのTListとrecordの組み合わせです。

早速いきましょう。

■サンプルコード■
-----------------------------------------------
type
   // record型定義
   TSyainRec = record
      社員番号: integer;
      氏名: string;
   end;

   ・
   ・
   ・
   ・

var
   // ジェネリクスのリスト
   SyainList:TList<TSyainRec>;

   SyainRec: TSyainRec;
   i: integer;
begin
   // ジェネリクスのリストを生成
   SyainList := TList<TSyainRec>.create;

   // 社員番号と社員名をリストに格納
   SyainRec.社員番号 := 1;
   SyainRec.氏名 := 'シンプル 太郎';
   SyainList.Add(SyainRec);

   SyainRec.社員番号 := 2;
   SyainRec.氏名 := 'シンプル 次郎';
   SyainList.Add(SyainRec);

   SyainRec.社員番号 := 3;
   SyainRec.氏名 := 'シンプル 三郎';
   SyainList.Add(SyainRec);

   // リストに追加したrecordのメンバー名でアクセス
   for i := 0 to (SyainList.Count -1) do
   begin
      Writeln('社員番号:' ,SyainList[i].社員番号);
      Writeln('氏名:' , SyainList[i].氏名);
   end;

   //リストを開放するだけでOK
   SyainList.free;
end;
-----------------------------------------------

■実行結果■
-----------------------------------------------
社員番号:1
氏名:シンプル 太郎
社員番号:2
氏名:シンプル 次郎
社員番号:3
氏名:シンプル 三郎
-----------------------------------------------



こういう使い方をするとなんだか実行結果が
-----------------------------------------------
社員番号:3
氏名:シンプル 三郎
社員番号:3
氏名:シンプル 三郎
社員番号:3
氏名:シンプル 三郎
-----------------------------------------------
となりそうですが、そんなことはありません。
recordは参照型ではなく値型だからです。

一番のミソは
ジェネリクスのTListに追加したrecordはひとつひとつ開放する必要がないということ。
動的配列を使っているから、コンパイラが勝手に開放してくれます。
Delphiに動的配列があってよかった。

ジェネリクスのTListとrecordは相性良しですね。



では。

2013年12月17日火曜日

Delphiでのrecordの便利な使い方

こんばんは
大阪本社 Mです。

今日はDelphiでのrecordの便利な使用方法を紹介します。

record型変数をTListに格納しメンバー名でアクセスする方法です。
これだけだと何のこっちゃという感じなのでサンプルコードを見てください。

■サンプルコード■
-----------------------------------------------
type
   // record型定義
   TSyainRec = record
      社員番号: integer;
      氏名: string;
   end;

   //TSyainRecのポインタ型
   PSyainRec = ^TSyainRec;

   ・
   ・
   ・
   ・

var
   SyainList:TList;
   SyainRec: PSyainRec;
   i: integer;
begin
   // リストを生成
   SyainList := TList.create;

   // 社員番号と社員名をリストに格納
   new(SyainRec);
   SyainRec^.社員番号 := 1;
   SyainRec^.氏名 := 'シンプル 太郎';
   SyainList.Add(SyainRec);

   new(SyainRec);
   SyainRec^.社員番号 := 2;
   SyainRec^.氏名 := 'シンプル 次郎';
   SyainList.Add(SyainRec);

   new(SyainRec);
   SyainRec^.社員番号 := 3;
   SyainRec^.氏名 := 'シンプル 三郎';
   SyainList.Add(SyainRec);

   // リストに追加したrecord型変数のメンバー名でアクセス
   for i := 0 to (SyainList.Count -1) do
   begin
      Writeln('社員番号:' ,PSyainRec(SyainList[i]).社員番号);
      Writeln('氏名:' ,PSyainRec(SyainList[i]).氏名);
   end;

   // 不要になったらrecord型変数を解放する必要がある。
   for i:= 0 to (SyainList.Count -1) do dispose(PSyainRec(SyainList[i]));

   //リストも開放
   SyainList.free;
end;
-----------------------------------------------

■実行結果■
-----------------------------------------------
社員番号:1
氏名:シンプル 太郎
社員番号:2
氏名:シンプル 次郎
社員番号:3
氏名:シンプル 三郎
-----------------------------------------------

ポイントはPSyainRec(SyainList[i]).社員番号のようにすることで
リストに格納したrecord型変数のメンバー名でアクセスできるところです。

データベースから取得したデータを変数に入れて扱うときなどに
record型変数のメンバー名をデータベースの列名と同じにしておけば、
非常にわかりやすくなるのではないでしょうか。

ただしこの方法の場合、不要になったrecord型変数はいちいち
開放してやる必要がある、というのが欠点でしょうか。

いちいち開放するのはめんどくさいし忘れそう、と思うのは
私だけではないと思います。

同じようなことをするのにジェネリックのTListを利用することで
record型変数を開放する必要が無くなるようなので、
次回はその方法を調べて投稿したいと思います。

2013年12月16日月曜日

2つの単語によるgrep検索

大阪のUです。

某エディタでgrep検索しようとしたとき、
1つの単語であれば問題ないですが、2つの単語で検索しようと思うと、
間に半角空白を入れてもできません。

grepした結果に再検索すれば済む話ともいえますが、
なんとか1回で出来ないか、と考えたとき、
正規表現で簡単に出来ることに気づきました。

【正規表現】
文字列1.*文字列2

. ・・・・ 任意の1文字
* ・・・・ 直前の1文字の0回以上の繰り返し

今まで全然考えてませんでしたが、こんな簡単な記述で出来るとは。

これだけでも十分に有用ですが、
せっかくなのでもう一段階進めて考えました。

2行にまたがる2つの単語をgrep検索は出来ないのか?

プログラムやSQLを複数行にまたがって
書くことは多いからできれば検索がかなり捗る。


・・・できました。

【正規表現】
文字列1.*\n{0,1}.*文字列2

\n ・・・・ 改行
{0,1} ・・・・ 直前の1文字の0~1回の繰り返し


軽く調べてあっさり実現。
これはかなり便利なのでは。。

対象のエディタが複数行に対応してなければ
ダメかもしれませんが、使えるなら検索がかなり楽になりそうです。

2013年9月27日金曜日

Windows7向けIE11プレビュー版

が出たみたいですね。

なんというか、ブラウザの新しくなったり
種類が多い事はユーザー側にはいいことですが、
テストする開発側にとってはあまり嬉しい事じゃないです。

ちょうど先日ウェブページを作ってて
javascriptで以下のように書いたらIE8とFirefoxで
動きませんでした。

document.all.item("xxx").src = "aaa"

当初はこいつが犯人とは分からなかったんで、
しばらく悩みましたが、判れば早い。

以下のように書き換えてクリア。

document.getElementById("xxx").src = "aaa"

社内向けのシステムであれば、
ブラウザをある程度固定する事も可能ですが、
公開されていればそうも行かず。

というかIEでもバージョンがひとつ違えばもはや別物。
これでIE11でまた動かないとなったら・・・。

2013年9月19日木曜日

Delphi XE5

発売されちゃってますね、XE5。

2ヶ月ほど前にまさか年内にXE5か!?って
書きましたけど、年内どころか9月。

XE4から半年も経ってない。

製品サイクル早すぎですよ・・・

でもまぁ噂通りandroidに対応したみたいだし、
出来るだけ早くandroid対応版を出したかったって事なんですかね。

2013年8月27日火曜日

FTPのファイルロック

こんにちは。
大阪勤務のⅠです。

IISのFTPを使用したシステムでの出来事です。


●システム概要

・DBサーバ上で常時起動する。
・テキストファイルをデータベースへ展開する。

<動作>

①別PCからDBサーバ上の所定のフォルダへ、
 不定期に下記ファイルがFTP伝送される。

 (1)データファイル(固定長のテキストデータ)
 (2)伝送制御ファイル(データファイルの伝送完了を知らせる)

②アプリケーションは、DBサーバ上の所定のフォルダをタイマーで監視し、
 伝送制御ファイルが存在すれば、値を読み込む。

③伝送制御ファイルの値が「0」の場合、
 データファイルの伝送が完了していると判断し、
 データファイルの値を読み込みデータベースへ展開する。

④データ展開後は、データファイル、伝送制御ファイルともに削除する。


上記内容のアプリケーションで、下記のエラーが発生していました。

<エラー内容>

System.IO.IOException:別のプロセスで使用されているため、
プロセスはファイル'<伝送制御ファイル名>' にアクセスできません。


ちなみにエラー時は1秒後にリトライを行う仕組みになっていて、
その際には問題なく処理されていました。

はじめはウイルス対策ソフト、もしくは、レプリケーションソフトが
伝送ファイルをロックしているのかと思いましたが、
それらが原因ではないようでした。

調べてみると、どうやらIISのFTPは、
ファイル伝送開始から終了までの間ずっと、
そのファイルを読み書き禁止でロックしているようです。

つまり、データファイルの伝送完了を知らせる伝送制御ファイルが伝送中のため、
FTPのプロセスによってロックされているわけで、
ある意味どうしようもないエラーということでしょうか。

リトライ機能があるため、伝送完了後は問題なく処理されるようですが、
何か回避策を考える必要があるな…感じる出来事でした。

それでは。



2013年8月22日木曜日

正規表現でパスワード入力チェック

大阪のUです。
正規表現ってみんなどれぐらい使ってるんでしょう?

自分は正直あまり使ってません。。

使えば便利なのは判ってますが、
考えるのが面倒臭かったりするので、
プログラムで逃げたりして、なかなか使わない。。

たまに使う機会があっても、普段使ってないので、
すぐ忘れてしまう始末。

というわけで、プログラムで逃げてばっかりもアレなので
今回はちょっとパスワードの入力チェックを
正規表現でやる方法を考えてみました。

【条件】
・6文字以上であること。
・使用できる文字は半角数字、半角英小文字、半角英大文字、ハイフンのみであること。
・数字、英小文字、英大文字の混在であること。

【正規表現】
^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z\-]{6,}$


いきなり答えを書いてますが、
自分はこれの元になった正規表現を見つけたとき、
何が書いてあるか判りませんでした。

[a-z]とかは普通によく使う表現ですが、
(?=.*[a-z])となると意味不明です。


というわけで順番に調べました。

^ ・・・・・・文字列の先頭
$ ・・・・・・文字列の末尾(改行文字除く)
. ・・・・・・改行文字(\n)以外の任意の一文字(カギ括弧内除く)
* ・・・・・・直前の文字を0回以上繰り返し。({0,}と同じ)

{n} ・・・・・直前の文字をn回繰り返し
{n,}・・・・・直前の文字をn回以上繰返し

[0-9] ・・・・0~9のいずれか1文字が含まれてること。
[a-z] ・・・・a~zのいずれか1文字が含まれてること。
[A-Z] ・・・・A~Zのいずれか1文字が含まれてること。
[\-] ・・・・ハイフンが含まれてること。(※\マークは任意だがあった方が判りやすい)

ここまでは基本中の基本って感じでしょうか。
で、上記を組み合わせて↓みたいにして使うと。

[0-9a-zA-Z\-] ・・・・・0~9、a~z、A~Z、ハイフンのいずれか1文字が含まれてること。
^[0-9a-zA-Z\-]$ ・・・・0~9、a~z、A~Z、ハイフンのいずれか1文字。
^[0-9a-zA-Z\-]{3}$・・・0~9、a~z、A~Z、ハイフンのいずれかで構成された3文字。

で、問題はこいつ。

(?= )

「ゼロ幅の肯定的先読みアサーション」というらしいですが
言葉だけだと意味不明です。

色々用例を調べた感じからすると、

直後に書かれた内容が、カッコ内に記述したパターンを満たしている事を
チェックする表現らしい。


(?=[a-z])

と書いた場合はa~zのいずれか1文字。つまり、

^(?=[a-z])[0-9a-zA-Z\-]{3}$

と書くと、直後の1文字目だけは、
(?=[a-z])の条件を満たしている必要があり、a~z以外の文字は×となる。

例)
×1aA
○aA1

この例だと1文字目だけが条件の対象だが、
以下のように書き換えると全体に対して有効になる。

^(?=.*[a-z])[0-9a-zA-Z\-]{3}$


(?=.*[a-z])は
任意の文字が0文字以上繰り返された後にa~zのいずれか1文字、
つまり文字列のどっかにa~zのいずれかがあることを意味するので、

”a~zのいずれかを含む”、0~9、a~z、A~Z、ハイフンのいずれかで構成された3文字となる。

例)
○1aA
×12A

そして、これを応用すると、
最初の答えにたどり着く。

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z\-]{6,}$"

”0~9のいずれかを含む”かつ
”a~zのいずれかを含む”かつ
”A~Zのいずれかを含む”、
0~9、a~z、A~Z、ハイフンのいずれかで構成された6文字以上の文字列。


う~む、今まで簡単な正規表現しか使ってなかったですが、
一行でここまで出来るとは。
まだまだ色々記述方法があるようだし、なかなか奥が深いです。


ただ、問題はみんなが理解してないと、
あとから見た人が判らない事ですかね・・・
プログラムと違って、なんとなくじゃ読めないし。