« 2009年02月 | メイン | 2009年04月 »

2009年03月 アーカイブ

2009年03月01日

エラトステネスの篩をC++で実装してみた

エラトステネスの篩をC++で実装してみました。

エラトステネスは、紀元前275年~紀元前194年の人です。
これほど昔の人が、こんなに優れたアルゴリズムを考え出していることに驚きます。

ソースコード中の「ステップ 1」から「ステップ 4」のコメントは、
Wikipediaのエラトステネスの篩の文章に対応しています。

//コンストラクタの引数startから始まり1ずつ増える数値を返す
struct gen1 {
  int val;
  gen1(int start) : val(start) {};
  int operator()() { return val++; };
};

int _tmain(int argc, _TCHAR* argv[])
{
  list<int> search_list(99); //探索リスト(2~100まで)
  vector<int> prime_number; //素数リスト

  //ステップ 1
  //整数を最初の素数である 2 から昇順で探索リストに羅列する。
  generate(search_list.begin(), search_list.end(), gen1(2));

  while (1)
  {
    //ステップ 2
    //リストの先頭の数を素数リストに記録する。
    int num = search_list.front();
    search_list.pop_front();
    prime_number.push_back(num);

    //ステップ 3
    //前のステップで素数リストに加えられた数の全ての倍数を、探索リストから削除する。
    search_list.erase(remove_if(search_list.begin(),
                                search_list.end(),
                                bind2nd(not2(modulus<int>()), num)),
                      search_list.end());

    //ステップ 4
    //探索リストの最大値が素数リストの最大値の平方よりも小さい場合、
    //素数リストおよび探索リストに残っている数が素数となる。
    //探索リストの最大値が素数リストの最大値の平方よりも大きい場合、
    //ステップ 2 に戻る。
    int search_max_num = *search_list.rbegin(); //探索リストの最大値
    int prime_max = *prime_number.rbegin();
    int prime_max_pow = prime_max * prime_max; //素数リストの最大値の平方
    if (search_max_num < prime_max_pow)
    {
      copy(search_list.begin(), search_list.end(), back_inserter(prime_number));
      break;
    }
  }

  //出力
  copy(prime_number.begin(), prime_number.end(), ostream_iterator<int>(cout, " "));
  return 0;
}

出力結果

2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

2009年03月02日

コンテナ中の最大の要素を取得する(std::max_element)

std::max_elementはコンテナ中の最大の要素を返します。

#include <vector>
#include <algorithm>

//コンテナにランダムな要素を設定する
std::vector<int> numbers(10);
std::generate(numbers.begin(), numbers.end(), rand);

//最大の要素
int max = *max_element(numbers.begin(), numbers.end());

コンテナ中の最小の要素を取得する(std::min_element)

std::min_elementはコンテナ中の最小の要素を返します。

#include <vector>
#include <algorithm>

//コンテナにランダムな要素を設定する
std::vector<int> numbers(10);
std::generate(numbers.begin(), numbers.end(), rand);

//最小の要素
int min = *min_element(numbers.begin(), numbers.end());

TIdFTP.DirectoryListingで「No IdFTPListParse classes have been registered.」の例外が発生するときの対処方法

C++Builder 2009にはIndy10が付属しています。
このIndy10のコンポーネントの一つであるTIdFTPを使い、FTPサーバのファイルの一覧を取得したかったのですが…

次のコードを実行すると、例外が発生します。

IdFTP1->Host = EditHost->Text; //サーバ名
IdFTP1->Username = EditUser->Text; //ユーザ名
IdFTP1->Password = EditPassword->Text; //パスワード
IdFTP1->Port = EditPort->Text.ToInt(); //ポート番号
IdFTP1->Connect(); //接続
IdFTP1->List();
TIdFTPListItems* items = IdFTP1->DirectoryListing; //ここで例外が発生

例外のメッセージは次のようなものです。

No IdFTPListParse classes have been registered. Check your uses clause!

ヘルプをよく読むと、解説があります。

The Indy library recognizes these defacto standards, and makes provisions for the IETF draft standards. TIdFTP provides the capabilitiy to parse the various formats for the textual content in the ListResult property into a structured representation of the directory stored in the DirectoryListing property. At the present time, Indy offers parsers for 30 different host-specific directory listing formats. Additional parsers are offered as new directory listing formats are encountered and codified. Use the IdAllFTPListParser.pas unit to include and register the known directory listing parsers for the Indy library.

要するに、「IdAllFTPListParser.pasをincludeしてください」ということです。

そこで、ソースコードに次の行を追加することにしました。

#include <IdAllFTPListParsers.hpp>

ところが、これでも状況は変わりません。

検索エンジンで調べてみると、同じような問題で困っている人が見つかりました。

For some reason, IdFTP1->DirectoryListing->Count is always 0.

Problem using TIdFTP in C++ Builder 2007. List() doesn't work

環境がC++Builder 2007のためでしょうか、現象が多少異なります。
ですが、同じような原因だと考えられます。

次のようなアドバイスがあります。

You have to include the appropriate IdFTPListParse...hpp header files for the specific parser(s) that you want to use. Or alternatively include the IdAllFTPListParsers.hpp header file to enable them all.

これはヘルプに記載されている方法と同じで、私も試した方法です。
案の定、この方法に従っても、問題は解決していません。

質問者は、最新版のIndyをインストールし直したようですが、それでも状況はいっこうに改善せず。
結局、問題は解決していないようです。

TIdFTP.DirectoryListingはC++Builderでは使用できないのかも。
と半分諦めつつ試行錯誤していると、解決策が見つかりました。

わかってしまえば簡単なことですが、でも、わからずに困っている人がたくさんいるのではないでしょうか。

その解決策ですが、次の行を追加するだけです。

#pragma link "IdAllFTPListParsers"

これでうまくいきます。

追記
TIdFTP.DirectoryListingの使い方をまとめました。

2009年03月06日

VCL Fix Pack 1.2

VCL Fix Pack 1.2がリリースされています。

VCLの数多くの問題が修正されるようです。
詳しくはホームページをご覧下さい。

使い方は、ユニットをプロジェクトに追加するだけです。

IDE Fix Pack 2009 2.5

IDE Fix Pack 2009 2.5がリリースされています。

Delphi/C++Builder 2009のバグを修正してくれます。
詳しくはホームページをご覧下さい。

インストーラが付いていますので、簡単にインストール・アンインストールができます。

2009年03月11日

C++Builder2009で扱える画像形式のまとめ

Delphi 2009/C++Builder 2009では、標準で扱える画像形式が増えています。

次の形式を扱うことができます。

  • Graphics Interchange Format(gif)
  • JPEG(jpg)
  • Portable Network Graphics(png)
  • Windows bitmap(bmp)
  • Windows Metafile(wmf,emf)
  • Windows アイコンファイル(ico)

他にもありますか?

C++Builder2009の画像を扱うクラスと必要なヘッダファイルをまとめました。

2009年03月17日

フォームの重なり順序を変更する方法は?

フォームの重なり順序を変更する方法は?」という質問を発見して、まだ解決していないようなので調べてみました。

Form1とForm2の2つを作成し、Form1を表示するときにForm2を表示するようにします。

void __fastcall TForm1::FormShow(TObject *Sender)
{
  Form2->Show();
}

プログラムを実行すると、Form1とForm2の2つのフォームが表示されます。

ここで、Form1をクリックしてアクティブにしても、Form2がForm1の上に表示されたままになります。

form.gif

この現象はC++Builder2007とC++Builder2009の両方で確認できました。

調べてみたところ、TApplication.MainFormOnTaskBarが影響しているようです。

C++Builder2009ではProject1.cppの次の行をコメントアウトすれば、期待する動作になります。

Application->MainFormOnTaskBar = true;

C++Builder2007ではProject1.cppの次の行をコメントアウトします。

SetApplicationMainFormOnTaskBar(Application, true);

SetApplicationMainFormOnTaskBarはApplication.MainFormOnTaskBarの値を設定するだけの関数です。

TApplication.MainFormOnTaskBarはWindows Vista Aero 効果のための機能です。

ヘルプを見るとTApplication.MainFormOnTaskBarの項目には、

このプロパティに依存するアプリケーションでは、このプロパティが MainForm の Z オーダーに影響を与える点に注意してください。

とあります。

Quality Centralにもありました。

この挙動がWindows Vista Aeroの仕様なのか、VCLの仕様なのかはわかりません。

2009年03月18日

C++Builder Tipsに日付関連の記事を追加

C++ Builder Tipsの「日数の計算」の記事を加筆しました。

ついでに、「有効な日付や時刻かどうかを調べる」と「年初、月初の日付を取得する」の記事も追加しました。

DateUtilsユニットには他にも便利な関数がたくさんあります。
プログラムで日付を扱うなら、ヘルプに目を通しておくと効率が上がります。

Python Tipsに日付の処理を追加

Python Tipsに「日付の処理いろいろ」を追加しました。

Python ライブラリリファレンス 5.1 datetime -- 基本的な日付型および時間型を見るとわかりますが、
Pythonは日付関連の処理も充実しています。

今回の「日付の処理いろいろ」では、よく使いそうなものを取り上げました。

2009年03月20日

DELPHI 2009 HANDBOOK

DELPHI 2009 HANDBOOKがAmazonで予約注文できるようになっていました。

追記
DELPHI 2009 HANDBOOKを購入しました

2009年03月23日

高度経済成長は復活できる

豊富なデータに裏付けられた説得力のある主張は、とても刺激的だった。

常識と思っていたものが実は幻想であり、事実は全く異なるものであった。

例えば、県別に収入を比較するとき、通勤時間も考慮すると意外な事実が浮かび落ちる。

一人あたりの県民所得が1位の東京都は、通勤時間ロス引き後勤労世帯成員1人当たり実収入では17位にまで下がる。

大阪府は一人あたりの県民所得は6位だが、通勤時間ロス引き後勤労世帯成員1人当たり実収入では41位だ。

通勤時間ロス引き後勤労世帯成員1人当たり実収入を見ると、41位大阪府、42位埼玉県、44位千葉県、45位兵庫県と、都市圏が最下位争いをしている。

これは大都市圏の社会基盤整備が冷遇され続けてきたためである。

「所得の高い大都市圏から所得の低い地方に富を再分配するのは当然だ」という常識的な主張は、実は大間違いなのである。

多くの人がこの本を読んで、日本の本当の姿を知って欲しいと思う。

2009年03月25日

DELPHI 2009 HANDBOOKはどこで買える?

DELPHI 2009 HANDBOOKが発売されたようです。
購入できるオンライン書店を探しました。

購入可能

売り切れ・在庫なし

書籍情報なし

追記
DELPHI 2009 HANDBOOKを購入しました。

Python で Win32API プログラミング入門

Perl で Win32::API プログラミング入門 を参考にしました。

Python 2.5以降には、ctypes が付属しているので、 今日からすぐに Win32API を利用したプログラミングが出来ます。

# ctypesは、動的リンク/共有ライブラリ内の関数呼び出しを可能にします。
# Linuxなど、Windows以外のOSでも使用することができます。

簡単なメッセージボックスを表示するPythonプログラムは以下になります。

#!C:\Python26\python
# -*- coding: cp932 -*-
import ctypes
ctypes.windll.user32.MessageBoxA(0, 'Hello, World!', 'Message', 0)
# ユニコード版
# ctypes.windll.user32.MessageBoxW(0, u'Hello, World!', u'Message', 0)

このプログラム実行すると、「Hello, World!」と書かれたWindowsメッセージボックスが表示されます。

任意のDLLを扱う場合は、ctypes.windll.LoadLibraryを使用します。

test.dllのソースコード

#include <windows.h>
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
  return 1;
}
__declspec(dllexport) int WINAPI Add(int x, int y)
{
  return x + y;
}

test.dllを扱うPythonスクリプト

#!C:\Python26\python
# -*- coding: cp932 -*-
from ctypes import windll
from ctypes.util import find_library
# dllのパスの取得
path = find_library("test")
# dllの読み込み
dll = windll.LoadLibrary(path)
# dll内の関数の実行
print dll.Add(1, 2) #=> 3

ctypes はとっても便利なモジュールですね。

C++ Builder 2009で、DLLのデバッグにPythonを利用する

C++ Builderで、DLLのデバッグにPythonを利用する がすばらしかったので、
C++Builder 2009で同様のことができるか検証しました。

結論から言うと、C++Builder 2009でもPythonを使用することで簡単にDLLのデバッグができました。

以下は作業手順です。

メインメニューから「ファイル」-「新規作成」-「その他」を選択します。

「C++Builderプロジェクト」から「ダイナミックライブラリ」を選択します。

「ソースの種類」は「C」を選択、「マルチスレッド」「VC++スタイルのDLL」はチェックを外します。

「OK」ボタンを押し、プロジェクトを作成します。

プロジェクトを保存、再構築します。

メインメニューから「実行」-「実行時引数」を選択します。

「ホストアプリケーション」にpython.exeを指定します。

C:\Python26\python.exe

ソースコードにブレークポイントを設定します。

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
  return 1; //<= この行にブレークポイントを設定する
}

プロジェクトを実行します。
Pythonインタラクティブシェルが起動します。

次のコードを入力します。

>>> import ctypes
>>> dll = ctypes.windll.LoadLibrary("Project1.dll")

C++Builderで設定していたブレークポイントで、プログラムが止まれば成功です。

プログラムを再開します。

Pythonインタラクティブシェルを終了します。

>>> quit()

次のコードを追加し、ブレークポイントを設定します。

__declspec(dllexport) int WINAPI Add(int x, int y)
{
  return x + y; //<= この行にブレークポイントを設定する
}

再び、プロジェクトを実行します。

次のコードを入力します。

>>> import ctypes
>>> dll = ctypes.windll.LoadLibrary("Project1.dll")
>>> print dll.Add(1, 2)

C++Builderで設定していたブレークポイントで、プログラムが止まれば成功です。

毎回、Pythonインタラクティブシェルで同じコードを入力するのは大変ですので、スクリプトファイルから実行することにします。

プロジェクトのDebugディレクトリにtest.pyを作成し、次のコードを記述します。

#!C:\Python26\python
# -*- coding: cp932 -*-
from ctypes import windll
dll = windll.LoadLibrary("Project1.dll")
print dll.Add(1, 2)
raw_input('') #Enterキーを入力するまで待機する

メインメニューから「実行」-「実行時引数」を選択します。

「パラメータ」に作成したtest.pyのパスを指定します。
パスにスペースが入る場合は、「"」でくくる必要があります。

"C:\Documents and Settings\yamamoto\My Documents\test\Debug\test.py"

プロジェクトを実行すると、test.pyが実行されます。

C++Builderで設定していたブレークポイントで、プログラムが止まれば成功です。

2009年03月30日

TNkDIB/TNkPrinterがDelphi2009に対応

Delphi2009に対応したTNkDIBとTNkPrinterが公開されました。

Delphi2009に対応したTNkDIBとTNkPrinterを、
C++Builder2009でコンパイルできることを確認しました。

以下、確認方法です。

プロジェクトにすべてのpasファイルを追加します。
次に、プロジェクトを再構築します。
pasファイルからhppファイルが作成されます。

以下のコードを追加し、コンパイルします。

#include "NkDIB.hpp"
#include "NkPrinters.hpp"

TNkDIB* dib = new TNkDIB();
TNkPrinter* printer = NkPrinter;

NkDIB.hppでコンパイルエラーになりました。

[BCC32 エラー] NkDIB.hpp(22): E2209 インクルード ファイル 'Nkgraph.hpp' をオープンできない

NkDIB.hppの次の部分を変更することでエラーを回避できます。

//#include <Nkgraph.hpp>    // Pascal unit
#include "Nkgraph.hpp"  // Pascal unit

これでコンパイルに成功しました。

おそらく設計時パッケージにコンポーネントをインストールすれば、
このエラーも発生しないと思います。

DELPHI 2009 HANDBOOK

DELPHI 2009 HANDBOOKを読みました。
この本を読むまでは、Delphi2009はDelphi2007からUnicodeのサポートと小さな修正が行われただけだと思っていました。
実際には、多くの新しい機能が追加された優れた開発環境だったことがわかりました。

DELPHI 2009 HANDBOOKは、Delphi 2007 HANDBOOK(日本語未翻訳)の続編という位置づけになっています。
そのため、本書の内容はDelphi2009の新機能と変更点に絞られています。
Delphi2009で新たに追加された機能だけで400ページ以上の本になったわけです。

本書のターゲットは、旧バージョンのDelphiからDelphi2009へ移行する開発者です。
これからDelphiを始める初心者には難しすぎると思います。
C++Builder2009ユーザーもObject Pascalの新機能以外は参考になります。

本書の内容を大きく分けると次の4つに分けられます。

  • Unicode
  • IDEの新機能
  • Object Pascalの新機能
  • VCLの新機能

Delphi2009の一番の目玉であるUnicodeについては、多くのページが割かれています。
次の3つに分けられます。

  • Unicodeについての解説
  • UnicodeString型の説明
  • 旧バージョンからの移行方法

たくさんのサンプルコードが掲載されており、実際に動作を確認しながら読み進めることができるようになっています。
サンプルコードはこちらからダウンロードできるようです。

IDEにも、いくつもの新機能が追加されています。
便利になった新しい機能を上手に使い、効率よく開発したいものです。

  • 新しく追加されたプロジェクトオプションの項目について
  • リソース管理の機能
  • ツールパレット検索ボックス
  • プロジェクトマネージャビュー
  • その他いろいろ

Object Pascalの新機能として、2つの機能が説明されています。

  • ジェネリクス
  • 無名メソッド

ジェネリクスと無名メソッドによって、Object Pascalがより生産性の高いプログラミング言語になったことがわかります。
無名メソッドはC++Builderにはない機能ですから、とても羨ましいです。

それから、242~243ページの「オーバーロードにおける変更」は注意が必要です。
特に「あるメソッドを呼び出していたコードが、以前と異なるメソッドを呼び出すようになってしまう」は気がつきにくいだけに問題です。
ただし状況が限られているので、問題を理解していれば何とかなりそうです。

VCLの新機能で説明されているコンポーネント

  • 新しいコンポーネント
    • バルーンヒント
    • ButtonedEdit
    • CategoryPanelGroup
    • Ribbon
  • コモンコントロールの新機能
    • Button
    • Label
    • RadioGroup
    • Edit
    • ComboBox
    • ListView
    • ProgressBar
    • HeaderControl
    • RichEdit

VCLの新機能ですが、4つの新しいコンポーネントとリボンのサポートに加えて、 Windows XPやWindows Vistaで追加されたコモンコントロールの新機能がサポートされました。
リボンコントロールについては、1つの章をまるまる使って説明しています。

# 古いOSで新機能を使用するとどうなるのか、検証しました。
# => C++Builder2009でコモンコントロールに追加された新機能の検証

他にも、COMサポートやdbExpress、DataSnap2009についての解説もあります。

と、盛りだくさんの内容でした。

本書では、Delphi2009の新機能・変更点に内容が絞られています。
Delphi7からDelphi2007までの間に追加された機能、例えばクラスヘルパーなどについては、説明がありません。
Delphi 2007 HANDBOOKの日本語訳も出版してほしいです。

Django×Python

Django×Pythonを読みました。
Djangoについて書かれた希少な本です。

非常にもったいないというか、惜しい本でした。
ターゲットが曖昧なのです。

「Chapter2 Djangoを使いこなすための基礎知識」では、Pythonの入門的な内容になっています。
読者層は、Pythonを使ったことのないまったくの入門者です。

一方、「Chapter4 Djangoをきちんと使う」「Chapter5 Djangoを使いこなす」では、説明が足早に進みます。
読者層は、Djangoに多少触れたことのあるDjangoユーザです。
Python入門者には、難易度が高すぎます。

Appendixの「Djangoチートシート」が100ページ以上もある充実した内容になっています。
本書全体の半分近くを占める分量です。
これほど充実させる必要性を感じません。
Appendixを削り、Chapter4~Cpahter5の内容を充実させ、Python入門者にもわかるレベルにした方が良かったと思います。

うーん、もったいない。

About 2009年03月

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

前のアーカイブは2009年02月です。

次のアーカイブは2009年04月です。

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

Powered by
Movable Type 3.35