C# の文字列ソート

August 17, 2008
つい忘れてしまうのでメモっておきます。

.NET Framework の String.CompareTo(String) は Char.CompareTo(Char) と異なる基準で文字を比較します。List<String> と List<Char> に ASCII 文字をつっこんで List<T>.Sort() すると一目瞭然です。List<T>.Sort() はデフォルトで CompareTo 使うため、これで違いを確認できます。


using System;
using System.Collections.Generic;
...
List c_list = new List();
List s_list = new List();

for (int i = 0; ' ' + i <= '~'; i++) {
char c = (char)(' ' + i);
c_list.Add(c);
s_list.Add(new string(c, 1));
}

c_list.Sort();
foreach (char c in c_list) {
Console.Write(c);
}
Console.WriteLine();

s_list.Sort();
foreach (string s in s_list) {
Console.Write(s);
}
Console.WriteLine();




結果は以下です。


!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
'- !"#$%&()*,./:;?@[]^_`{|}~+<=>\0123456789aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ




List<Char> のほうは ASCII コード順にソートされていますが、List<String> のほうはなにやら愉快なことになっています。

String.CompareOrdinal() という Char.CompareTo(Char) と同じ基準で比較をするスタティックメソッドがあるので、これを delegate にして渡してやると同じ結果になります。


s_list.Sort(delegate(string a, string b) { return string.CompareOrdinal(a, b); });





!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~



MinGW で64bit整数を printf するときの注意

September 14, 2007
MinGW は Windows の C Library (MSVCR) を使うので普通は %lld を解釈してくれません。Cygwin から開発をしていると、この事を忘れてはまり易いので注意。
(環境 : Windows 2000 + gcc 3.4.5 (mingw special))

VC++ と同じように %I64u, %I64d を使えば大丈夫です。C++ コードならストリームを使えばとりあえず問題ないとのこと。

Google:MinGW lld I64d で関連情報がたくさん出てきます。

これは使用するランタイムを選択することでも解決できます。最新の MinGW Runtime をインストールし、Wrapper として libmsvcr80.a をリンクすることで MSVCR 8.0 を使えば %lld も正常に解釈されます。libmsvcr71.a 以前はだめです。



printf の話題なのでついでに

%llf は多くの C Library で結果的に拡張倍精度長浮動小数点数 (long double) の format として機能しますが、本来 long double の変換修飾子は L です。日頃から %Lf を使うようにした方が無難かと思います。

これはたとえば GNU C Library なら vfprintf.c のソースから is_long_double 周辺を見ればよくわかります。

MSVCR は %Lf も解釈してくれませんが。(だめじゃん)

LXRのbaseurl

June 20, 2007
LXR (Linux Cross Reference)は設定ファイルの項目baseurlをもとに、
HTMLのbase要素を通じてスクリプトへのパスをブラウザに伝える。

もし、LXRを閉じたネットワークに設置して内部から利用し、
さらに外部からもSSHのポートフォワーディングなどで
利用する場合、色々なホスト名でアクセスされることになる。

しかし、単にbaseurlに"/lxr/"などと相対パスを書いても
base要素のhref属性としてはブラウザに正しく解釈されず、
おかしな挙動が起きてしまう。

この場合は、LXRのlib/LXR/Common.pmのbaseurlサブルーチンを

sub baseurl {
return('http://'.$ENV{'SERVER_NAME'}.
':'.$ENV{'SERVER_PORT'}.
$Conf->baseurl);
}


などと書き換えて絶対パスにしてやればよい。

Camomile

December 08, 2006
CamomileはOCaml用のUnicode処理ライブラリです。
GODIにも入っていて簡単に取得して使い始めることができます(今は0.6系の模様)。
このソフト、APIマニュアルは公開されているのですが、以前からあんまり
サンプルコードやチュートリアルがなくてとっつきにくかったので、
ちょっとサンプルコードつきの説明を書いてみました。

Camomile

前5件

次5件