« 2008年09月 | メイン | 2008年11月 »

2008年10月 アーカイブ

2008年10月04日

Delphi 2009/C++Builder 2009で導入された新しい文字列型の不具合

Delphi 2009/C++Builder 2009で導入された新しい文字列型の不具合について、Embarcadero Discussion Forumsで話題になっていました。

マルチバイト言語圏の特有の問題のようです。

Delphi 2009/C++Builder 2009の開発者の方はぜび、Voteを

IBM developerWorks:CodeIgniter入門

IBM developerWorksでCodeIgniter入門という記事が公開されています。

CodeIgniterは以前にも使用したことがあり、使い方を間違わなければ、便利なフレームワークだと思います。

おすすめは小規模なWebアプリケーションです。

その理由。

その1。学習コストが低いこと。
フレームワーク自体の規模が小さいので学ぶことが少なくてすみます。
また、CodeIgniter ユーザガイド 日本語版という非常に優れたオンラインドキュメントがあります。
ファイルの設置場所はRuby on Railsに似ていますので、Ruby on Railsを知っている人は理解しやすいと思います。

その2。安価なレンタルサーバーでも動作すること。
PHP4とPHP5の両方に対応しています。
インストールはコピーするだけ。
フレームワークは軽量でサーバーのスペックを要求しません。
要するに、ロリポップなどの安価なレンタルサーバーでも問題なく動作します。

欠点は、Active Recordが貧弱なこと。
データベースの処理が多いアプリケーションだと、面倒かもしれません。

2008年10月05日

気がついたら Ruby on Rails 2.0.4 がリリースされていた

気がついたら Ruby on Rails 2.0.4 がリリースされていた。

Ruby on Rails 2.1系が出ているので、放置されているかと思ってた。

Maintenance releaseとあるけど、互換性を失う変更が行われていないか、心配だ。

System.Abs 関数とSystem.Sqr 関数が使えない

System.Abs 関数とSystem.Sqr 関数が使えない。
C++Builder 2007とC++Builder2009の両方で確認。
どちらの関数もちゃんとヘルプには記載されているのに。

#include <System.hpp>
Abs(1);
Sqr(1);

とすると、エラーになる。

[BCC32 エラー] File1.cpp(11): E2268 未定義の関数 'Abs' を呼び出した
[BCC32 エラー] File1.cpp(12): E2268 未定義の関数 'Sqr' を呼び出した

何か間違えているのかな。

2008年10月06日

統計ソフト(仮)

『その数学が戦略を決める』

データと統計分析が、専門家の勘や経験よりも優れた結果を出す。
大変おもしろい本でした。

統計学っておもしろそうだな、と思ったので、
学習をかねて作ってみました。

2008年10月08日

Delphi 2009/C++Builder 2009の新しい文字列型の問題

Embarcadero Discussion Forums: Delphiで、新しい文字列型(AnsiString)の話題が盛り上がっています。

新しい文字列型(AnsiString)は、実装上の理由により、仕様が複雑でわかりにくくなっているという印象を受けます。
さらにヘルプの記述が不十分で混乱を増しています。

文字列という基本的な部分であるだけに、わかりやすく直感的な仕様にしてもらいたいものです。

複数の文字コードを扱うプログラムを書くときは、まだしばらくの間はC++Builder 2009ではなく、C++Builder 2007を使おうと思います。

がんばれ、Embarcadero。

C++0x unique_ptr

C++0x: auto_ptr から unique_ptr への記事でunique_ptrの存在を知りしました。
試しに使ってみたところ、C++Builder 2009で使えました。
ちゃんとサポートされているのですね。

unique_ptrは、auto_ptrの所有権の問題を解決したスマートポインタ。

Wikipeidaの記述によると、

unique_ptrがauto_ptrの代わりとして導入され、auto_ptrは非推奨とされる。

とありました。

既存のコードも少しずつunique_ptrへ書き換えていきたいです。

添付ファイルの日本語ファイル名

添付ファイルにおける日本語のファイル名に関して」のページがよくまとまっており、参考になります。
このページの最終更新日が2001年となっていますが、現在でも使える情報です。

添付ファイルのファイル名は、RFC 2231によって定義されています。
しかし現実には、今でもMIME B encodingが大半を占めているようです。

日本語添付ファイル名の対応について、いくつかのメールソフトの挙動を調べたところ、ほとんどのソフトはRFC 2231で定められている記述方法を読み込むことができました。
ただし、Eudora 7J for Windows(Eudora 6.2J for Windowsも)とOutlook 2003は、正しく読み込むことができませんでした。

Eudoraは、ソフトウェアの販売が終了して1年以上たちます。
D2では、Eudoraのサポートを打ち切る方向で検討します。

2008年10月09日

D2 バージョン 2.0.5(ベータ版) 公開

D2 バージョン 2.0.5(ベータ版) を公開しました。

今回の変更では、添付ファイルのファイル名を取得する機能を追加しました。

使い方は簡単です。
パラメータ入力画面パラメータ文字入力欄で、「[添付ファイル名]」を選択してください。

C++Builder 2009への移植作業 その1

既存のコードをC++Builder 2009へ移植してして、文字列関連の処理の変更が大きいかもしれないことに気づいた。

AnsiString text = "あいうえお";
return text.AnsiPos("う");

C++Builder 2007では「5」を返すが、
C++Builder 2009では「3」を返す。

C++Builder 2007はバイト数で計算しているのに対し、
C++Builder 2009は文字数で計算している。

文字列関連の処理は、すべて見直しが必要かも…

2009年5月28日追記
Update3で修正されました。
C++Builder 2009 Update3では「5」を返します。

2008年10月10日

C++Builder 2009への移植作業 その2 C++Builder 2007と2009のAnsiStringの動作の違いの調査

C++Builder 2007と2009のAnsiStringの動作の違いを検証した。
比較の対象としてC++Builder 2009のUnicodeStringも比較した。

AnsiString s = "あいうえお";

として、各動作を確認した。

結論から言うと、動作が異なったのはAnsiString#AnsiPos()だけ。

C++Builder 2007から2009へ移植するときは、AnsiPos()に注意すればよさそうだ。

WideStringの動作は変更が無く、UnicodeStringと同じ挙動らしい。

C++Builder2007C++Builder2009(AnsiString)C++Builder2009(UnicodeString)C++Builder2007(WideString)C++Builder2009(WideString)
s.AnsiPos("うえ");53
s.Pos("うえ");55333
s.Delete(3, 2);あうえおあうえおあいおあいおあいお
s.Insert("ん", 3);あんいうえおあんいうえおあいんうえおあいんうえおあいんうえお
s.Length();1010555
s.SubString(3, 2);うえうえうえ
s.LastDelimiter("え");944

追記
AnsiString::LastDelimiterの挙動も異なるようです。

2009年5月28日追記
C++Builder 2009 Update3でAnsiStringの挙動が修正されました。

C++Builder2007C++Builder2009 Update3(AnsiString)C++Builder2009 Update3(UnicodeString)C++Builder2007(WideString)C++Builder2009(WideString)
s.AnsiPos("うえ");55
s.Pos("うえ");55333
s.Delete(3, 2);あうえおあうえおあいおあいおあいお
s.Insert("ん", 3);あんいうえおあんいうえおあいんうえおあいんうえおあいんうえお
s.Length();1010555
s.SubString(3, 2);うえうえうえ
s.LastDelimiter("え");994

2008年10月12日

AnsiDequotedStrの不具合

C++Builderには、引用符付き文字列から引用符を削除する「AnsiDequotedStr」という便利な関数が用意されています。

AnsiDequotedStr("\"abc\"", '"'); //=> abc
AnsiDequotedStr("\"あいう\"", '"'); //=> あいう

ところが、引用符が連続するとき、空の文字列を返してしまうようです。

AnsiDequotedStr("\"\"abc\"\"", '"'); //=> 
AnsiDequotedStr("\"\"あいう\"\"", '"'); //=>

C++Builder 2007とC++Builder 2009で現象を確認しました。

C++Builder 2009への移植作業 その3 C++Builder 2009におけるTStringList#LoadFromFileの挙動の変化

C++Builder 2007からC++Builder 2009への変更でTStringList#LoadFromFileの動作が変わりました。
文字コードがシフトJIS以外のファイルをTStringList#LoadFromFileで読み込むと、動作の違いにとまどうことになります。

挙動が変わった理由は、TStringListが内部でUnicodeStringでデータを保持するようになったため。
C++Builder 2009では、TStringList#TextやTStringList#StringsがUnicodeStringを返すようになりました。
そのためUnicodeの変換が行われます。

例えば以下のコードでは、次のような文字コード変換が行われます。
# デフォルトANSIコードページがシフトJISと仮定します。

TStringList* file = new TStringList();

// ファイルの文字コードをシフトJISとして読み込み、Unicodeに変換する
file->LoadFromFile("C:\\sample.txt");

// UnicodeをシフトJISに変換する
AnsiString text = file->Text;

2行目の文字コード変換が問題です。
文字列がシフトJIS以外だとしても、シフトJISとして変換されてしまいます。

C++Builder 2009ではLoadFromFileの引数で、ファイルのコードページが指定できるようになっています。

TStringList* list = new TStringList();
TEncoding* encoding = TEncoding::GetEncoding(20932); //euc-jp
list->LoadFromFile("C:\\sample.txt", encoding);

ただし、この方法はあらかじめコードページがわかっている場合にしか使えません。
ファイルを読み込んでから文字コードを判別して…、という場合には違う方法が必要です。

C++Builder 2009のTStringList#LoadFromFileには、BOMでコードページを自動判別する機能が追加されている

Delphi 2009では(C++Builder 2009も)BOMでコードページを自動判別する機能が追加されているそうです。

BOMからLE UTF-16/BE UTF-16/UTF-8を自動判別してくれます。
BOMがなければANSIのデフォルトのコードページになります。

UTF8とUTF-16のファイルが扱いやすくなりそう。

トラックボールについて

ASCII.jpのサイトにトラックボールの記事が掲載されていました。

私もトラックボールを愛用しています。
マウスよりも使いやすいですし、もっとユーザーが増えても良いと思っています。

使い始めた理由は手の痛み。軽い腱鞘炎のような症状でしょうか。
トラックボールは手に優しいということで、使い始めました。
実際に、トラックボールは手に優しいと思います。
マウスが駄目でも、トラックボールなら使えます。

使い始めてわかったのは、トラックボールは場所をとらないということ。
マウスのように動かしたりしないので、トラックボールを置くスペースだけあればいいのです。
机のスペースが有効に利用できます。

最初に買ったのは、KENSINGTON 64327 Orbit Optical
この製品がとても良かったので、トラックボールユーザーになりました。

今使っているのが、Logicool マーブルマウス ST-45UPi
この製品も満足しています。

いつかは、KENSINGTON 64325 EXPERT MOUSE OPTICALのようなハイエンド商品を使ってみたい。
でも、この値段なのでなかなか手が出せません。

ついでに書いておくと、キーボードはPFU Happy Hacking Keyboard Lite2
日本語配列かな無刻印がポイントです。かな無刻印なのが、ちょっと格好いい。
いつかはProfessional2にしたいと思っています。

2008年10月13日

C++Builder 2009のTMemIniFileとエンコードの挙動を調べた

C++Builder 2009のTMemIniFileとエンコードの挙動を調べた。

結論から先に言うと、エンコードを指定する場合は「TEncoding::Unicode」を使うこと。
TEncoding::UTF8やEncoding:UTF7を使うと、不可思議な挙動に悩まされる。

エンコードを指定しないC++Builder 2007と同じ書き方。

//書き込み
std::unique_ptr<TMemIniFile> ini(new TMemIniFile(path));
ini->WriteString(L"日本語", L"こんにちは", L"こんにちは");
ini->WriteString(L"中国語", L"こんにちは", L"你好");
ini->UpdateFile();

ファイルには、ANSIのデフォルトのコードページ(Shift_JIS)で保存される。
したがって、文字化けする。

//読み込み
std::unique_ptr<TMemIniFile> ini(new TMemIniFile(path));
ini->ReadString(L"日本語", L"こんにちは", "no data"); //=> こんにちは
ini->ReadString(L"中国語", L"こんにちは", "no data"); //=> ?好

エンコードにTEncoding.Unicodeを指定する書き方。
リトルエンディアンバイトオーダーのUTF-16で保存される。
ファイルには16進数 FFFE のバイトオーダーマークが付く。

//書き込み
std::unique_ptr<TMemIniFile> ini(new TMemIniFile(path, TEncoding::Unicode));
ini->WriteString(L"日本語", L"こんにちは", L"こんにちは");
ini->WriteString(L"中国語", L"こんにちは", L"你好");
ini->UpdateFile();

//読み込み
std::unique_ptr<TMemIniFile> ini(new TMemIniFile(path, TEncoding::Unicode));
ini->ReadString(L"日本語", L"こんにちは", "no data"); //=> こんにちは
ini->ReadString(L"中国語", L"こんにちは", "no data"); //=> 你好

書き込み、読み込みともに問題なく動作する。

なお、ファイルにバイトオーダーマークが付いているので、エンコードを指定しなくても、自動的に識別してくれる。

std::unique_ptr<TMemIniFile> ini(new TMemIniFile(path));
ini->ReadString(L"日本語", L"こんにちは", "no data"); //=> こんにちは
ini->ReadString(L"中国語", L"こんにちは", "no data"); //=> 你好

エンコードにTEncoding::UTF8を指定する書き方。
UTF-8形式で保存される。
ファイルには、16進数 EFBBBF のバイトオーダーマークが付く。

//書き込み
std::unique_ptr<TMemIniFile> ini(new TMemIniFile(path, TEncoding::UTF8));
ini->WriteString(L"日本語", L"こんにちは", L"こんにちは");
ini->WriteString(L"中国語", L"こんにちは", L"你好");
ini->UpdateFile();

//読み込み
std::unique_ptr<TMemIniFile> ini(new TMemIniFile(path, TEncoding::UTF8));
Memo1->Lines->Add(ini->ReadString(L"日本語", L"こんにちは", "no data")); //=> こんにちは
Memo1->Lines->Add(ini->ReadString(L"中国語", L"こんにちは", "no data")); //=> 你好 / ?好

ここで、奇妙な動作になる。

ファイルが存在しないとき、つまり新規保存になるときは正しく、UTF-8で保存される。
ところが、すでにファイルが存在するときには、ANSIのデフォルトのコードページ(Shift_JIS)で保存されてしまう。

TEncoding::UTF8ではなくTEncoding::UTF7を使っても、同様の現象が起こる。

2008年10月14日

D2 バージョン 2.0.6 公開

D2 バージョン 2.0.6 を公開しました。

今回の変更点

  • 添付ファイルのファイル名を取得する機能を追加しました。
  • Base64とQuoted-Printableのデコード処理を修正しました。
  • マルチパートのメールの処理を修正しました。

C++0x final属性

C++0xに新しく追加された機能の一つに「final属性」があります。
Javaなどの言語でおなじみの属性です。
サブクラスでの継承やオーバーライドを禁止します。

C++Builder 2009で、次のコードをコンパイルすると、エラーになります。

class TFoo
{
  virtual void f() {};
};
class TBar : public TFoo
{
  //仮想メンバ関数宣言のオーバーライドを禁止する
  void f [[final]] () {};
};
class TBaz : public TBar
{
  void f() {};
};

エラーメッセージ

[BCC32 エラー] Unit1.h(24): E2542 'f' は 'final' にマークされ、上書きできない

クラスに対しても、final属性を追加できます。

class TFoo
{
  virtual void f() {};
};
//クラスの継承を禁止する
class TBar [[final]] : public TFoo
{
  void f() {};
};
class TBaz : public TBar
{
  void f() {};
};

エラーメッセージ

[BCC32 エラー] Unit1.h(22): E2542 'TBar' は 'final' にマークされ、上書きできない

[[final]]というのがちょっと読みにくく感じますが、
これでC++プログラミングがより堅牢になりました。

C++Builder 2009のコード補完機能

C++Builder 2009のコード補完機能について

エディタのコード補完機能がおかしいような? たとえば、フォームにラベルを配置して「Label1->」と入力しても、ほんのちょっとしか候補が出てきません。

NRTTKR Blog日記のお部屋

私も、最初は同様の現象が起きていました。
候補が少ししか出ない。変だな。と。

でも、今ではC++Builder 2007と同じようにたくさんの候補が表示されます。

いつからちゃんと表示されるようになったのかは不明です。
しばらく使っていると良くなるのかな。

2008年10月18日

C++0x explicit 変換演算子

C++0xの新機能の一つ「explicit 変換演算子」。
暗黙の型変換を禁止します。

class TFoo
{
public:
  TFoo(int i) {};
};

class TBar
{
public:
  explicit TBar(int i) {}; //暗黙の型変換を禁止
};

int _tmain(int argc, _TCHAR* argv[])
{
  TFoo foo = 1;
  TBar bar = 1; //ここでコンパイルエラー

エラーメッセージ

[BCC32 エラー] File1.cpp(25): E2034 'int' 型は 'TBar' 型に変換できない

C++Builder 2009のTIdHTTP::Getの文字コードの処理を検証した

C++Builder 2009のTIdHTTP::Get(URL)はUnicodeStringを返すようになりました。

もしかして、文字コードを自動認識してくれるかも。
と期待して、動作を検証してみたところ、

//UTF-8のページを読み込む
Memo1->Lines->Text = IdHTTP1->Get("http://www.yahoo.co.jp/");

しっかりと、文字化けしました。

自分で文字コードを設定しなければならないようです。

//UTF-8のページを読み込む
std::unique_ptr<TMemoryStream> ms(new TMemoryStream());
IdHTTP1->Get("http://www.yahoo.co.jp/", ms.get());
ms->Position = 0;
Memo1->Lines->LoadFromStream(ms.get(), TEncoding::UTF8);

文字列で取得する場合。

// UTF-8のページを読み込む
std::unique_ptr<TMemoryStream> ms(new TMemoryStream());
IdHTTP1->Get("http://www.yahoo.co.jp/", ms.get());
UTF8String s = reinterpret_cast<char*>(ms->Memory);
//文字コードがShift_JISの場合
//AnsiStringT<932> s = reinterpret_cast<char*>(ms->Memory);
//文字コードがEUC_JPの場合
//AnsiStringT<20932> s = reinterpret_cast<char*>(ms->Memory);

UnicodeStringになって、面倒になったような気がします。

2008年10月26日

業務連絡、引っ越しします

今週末に引っ越しをします。

インターネットの接続環境がなくなるために、メールの確認ができなくなります。
そのためメールによるお問い合わせに、すぐに回答することができません。
引っ越し完了後、速やかに対応させていただきます。

ご了承ください。

なお、シェアウェアのライセンス発行は通常どおり行います。
ご安心ください。

About 2008年10月

2008年10月にブログ「山本隆の開発日誌」に投稿されたすべてのエントリーです。過去のものから新しいものへ順番に並んでいます。

前のアーカイブは2008年09月です。

次のアーカイブは2008年11月です。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。

Powered by
Movable Type 3.35