アーカイブ | 22:26

書式設定

4 12月

さーて、本日のC#たんは?

文字列処理シリーズ3本目、書式設定についての話です。

サンプル コード: 書式設定サンプル.cs

書式設定とは

数値をそのまま表示するんじゃなくて、整形してから出力しましょうという話です。例えば、同じ19800という数字であっても、

  • そのまま: 19800
  • 3ケタごとにコンマ区切り: 19,800
  • 指数表記: 1.98e4

など、いろいろな書式があります。

書式設定には、ToStringメソッドやstringクラスのFormat静的メソッドを使います。

また、WPFやSilverlightのデータ バインディングでも、書式の設定が可能です。

書式の書き方は.NET特有です。最近だと、Pythonでも似た書き方ができるそうですが、完全一致じゃないです。

書式設定に関する詳細は以下のページで確認できます。

http://msdn.microsoft.com/ja-jp/library/26etazsy.aspx

ToString

C#では、数値などから文字列への型変換は、そのままではできません。しかし、objectクラスがToStringというメソッドを持っていて、これで文字列化できます。

自作の型を文字列化したい場合は、以下のように、ToStringメソッドをオーバーライドして使います。

class Point
{
    public int X { get; set; }
    public int Y { get; set; }

public override string ToString()
    {
        return "(" + X + ", " + Y + ")";
    }
}

例えば、

var p = new Point { X = 10, Y = 20 };
Console.WriteLine(p);

このコードからは以下のような結果が得られます。

(10, 20)

書式付きToString

intDateTimeなど、主要な型には、書式設定が可能なバージョンのToStringメソッドが提供されています。書式を、ToStringの引数として渡します。

var n = 1980;
Console.WriteLine(n.ToString("d")); // 1980
Console.WriteLine(n.ToString("x")); // 7bc

var x = 0.12;
Console.WriteLine(x.ToString("f")); // 0.12
Console.WriteLine(x.ToString("e")); // 1.200000e-001

書式の書き方については後程改めて説明します。

複合書式: string.Format

stringクラスのFormat静的メソッドで、複数の値をまとめて書式設定することができます。

var x = 7;
var y = 13;
var line = string.Format("{0} × {1} = {2}", x, y, x * y);
Console.WriteLine(line); // 7 × 13 = 91

1つ目の引数が書式で、2つ目以降の引数を、それぞれ、{0}, {1}, {2} の部分に展開します。{} 内の数字は、何番目の引数を参照するかのインデックス(0始まり)を表します。

Console.Writeや、StreamWriter.Writeなど、内部的にstring.Formatを呼び出してくれるものもあります。

Console.WriteLine("({0}, {1})", 1, 2); // (1, 2)

インデックスに続けて、,(コンマ)で区切って幅を指定することもできます。この時、正の数を指定すると右詰め、負の数を指定すると左詰めになります。

Console.WriteLine("({0,-5}) ({1,5})", 1, 1); // (1    ) (    1)

また、インデックスに続けて、: (コロン)で区切って、個別の書式を指定できます。

Console.WriteLine("{0:x}, {1:c}", 123, 123); // 7b, \123
//↑ "{0}, {1}", 123.ToString("x"), 123.ToString("c")
と同じ扱い

それでは、個別の書式についてみていきましょう。

数値(標準)

dは10進数、xは16進数を表します。xを大文字にするか小文字にするかで、16進数のa~fの大小を選べます。

// d10進数、0詰め桁数指定
Console.WriteLine("{0:d}, {0:d4}", 5); // 5, 0005
// x: 16
進数、0詰め桁数指定
Console.WriteLine("{0:x}, {0:X}, {0:x4}, {0:X4}", 140); // 8c, 8C, 008c, 008C

fで固定小数点表示、eで指数表記を表します。また、gで、fとeのどちらか、簡潔な方を自動選択してくれます。

// f: 小数点、小数点以下の桁数指定
Console.WriteLine("{0:f}, {0:f5}", 0.1234); // 0.12, 0.12340
// e:
指数表記、精度指定
Console.WriteLine("{0:e}, {0:e2}, {0:E2}", 0.1234); // 1.234000e-001, 1.23e-001, 1.23E-001
// g: f
e かを自動選択
Console.WriteLine("{0:g}, {1:g}", 1200000000000000.0, 0.12); // 1.2e+15, 0.12

その他、適宜桁区切り、通貨記号などをはさんでくれるn、cや、精度を自動判定してくれるr、パーセント化してくれるpなどが利用できます。

// n: 適宜、桁区切りなどを挿入、小数点以下の桁数指定
Console.WriteLine("{0:n}, {0:n0}", 1234567); // 1,234,567.00, 1,234,567
// c:
通貨
Console.WriteLine("{0:c}", 1234567); // \1,234,567
// r:
復元するのに十分な桁数で出力
Console.WriteLine("{0:r}", 0.1234567890123456789f); // 0.123456791
// p:
パーセント表示、小数点以下の桁数指定
Console.WriteLine("{0:p1}", 0.1234); // 12.30%

詳細: http://msdn.microsoft.com/ja-jp/library/dwhawy9k.aspx

数値(カスタム)

数値は、0や#(ナンバー記号)などを使って、かなり自由な書式を作れます。

// 桁数を明示。0. 0 は省略
Console.WriteLine("{0:#.##}", 0.2345); // .23
// 0
詰め4ケタ.4ケタ
Console.WriteLine("{0:0000.0000}", 1.23); // 0001.2300
// 3
ケタ区切り、小数点以下0詰め2ケタ
Console.WriteLine("{0:#,#.00}", 1234567); // 1,234,567.00

詳細: http://msdn.microsoft.com/ja-jp/library/0c899ak8.aspx

日付

DateTime型もしくはDateTimeOffset型に対して、いくつかの書式を指定できます。

var d = new DateTime(2008, 5, 4, 8, 30, 0);
Console.WriteLine(d.ToString("d")); // 2008/05/04
Console.WriteLine(d.ToString("D")); // 2008
54

詳細: http://msdn.microsoft.com/ja-jp/library/az4se3k1.aspx

カスタム書式も指定できます。

var d = new DateTime(2008, 5, 4, 8, 30, 0);
Console.WriteLine(d.ToString("y/M/d h:m:s")); // 8/5/4 8:30:0
Console.WriteLine(d.ToString("hh:mm:ss"));    // 08:30:00
Console.WriteLine(d.ToString("yy/MM/dd"));    // 08/05/04 8:30:0
Console.WriteLine(d.ToString("yyyy/MM/dd"));  // 2008/12/04
Console.WriteLine(d.ToString("ddd dddd"));    //
 日曜日

詳細: http://msdn.microsoft.com/ja-jp/library/8kb3ddd4.aspx

/ や : などは自由に挿入できます。その他、以下の文字は特別な意味を持ちます。

  • y, yy, yyyy: 年。それぞれ、下2桁(2桁目が0なら1ケタ)、下2桁(2桁目は0詰め)、4ケタ表示
  • M, MM: 月。以下、2文字並べた場合、0を挿入して2ケタに
  • d, dd: 日
  • h, hh: 時(12時間形式)
  • H, HH: 時(24時間形式)
  • m, mm: 分
  • s, ss: 秒
  • f: 秒の小数点以下
  • ddd: 曜日。それぞれ、短い形式と長い形式
  • MMM, MMMM: 英語の場合、JunとかJuanaryとか。日本語だと5と5月になる
  • t, tt: amかpmか
  • g: 年号
  • K: タイム ゾーン

書式とカルチャー

さて、ここで1つお題。お値段を表示する書式を考えてください。

Console.WriteLine(@"{0:#,###}", price);

↑これでいいだろうですって?まあ、日本では概ね…

ところで、世界各国の通販、そうですねぇ、Amazonさんのページでも見てください。お値段のところ、どうなっていますか?

  • 小数点以下の有無
  • 小数点に使う記号
  • 3ケタずつの区切りに使う記号
  • 通貨記号
  • 負の数の表し方

何一つ同じ国がない…

ということでですね、お値段の表示には、文化の指定が必要です。C#の場合、たとえば以下のように書きます。

var cultures = new[] { "ja-jp", "zh-cn", "en-us", "en-gb", "fr-fr", "de-de", "pt-br", "tr-tr", "he-il" };
var price = 9800;

foreach (var c in cultures)
{
    var culture = new CultureInfo(c);
    var plus = price.ToString("c", culture);
    var minus = (-price).ToString("c", culture);
    Console.WriteLine("{0,-11} / {1,-12} ({2})", plus, minus, culture.DisplayName);
}

¥9,800 / -¥9,800 (日本語 (日本))
9,800.00 / -9,800.00 (中国語 (中華人民共和国))
$9,800.00 / ($9,800.00) (
英語 (米国))
£9,800.00 / -£9,800.00 (
英語 (英国))
9 800,00
/ -9 800,00 (フランス語 (フランス))
9.800,00
/ -9.800,00 (ドイツ語 (ドイツ))
R$ 9.800,00 / -R$ 9.800,00 (
ポルトガル語 (ブラジル))
9.800,00 TL / -9.800,00 TL (
トルコ語 (トルコ))
9,800.00 / -9,800.00 (ヘブライ語 (イスラエル))

通貨に限らず、小数点や区切り文字、日付の書式などは文化の影響を受けます。

広告