tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルtostringを改良したい
記事No10885
投稿日: 2012/08/14(Tue) 14:49
投稿者しげちん
はじめまして

WinXPでVB2010ExpressEdtionを使っています.
これまで約10年間VB6.0を使っていましたが,1ヶ月ほど前からVB2010を使っています.

お聞きしたいのは.ToStringを改良したメソッドを作れないかということです.
(123.456).ToString("00.00") = "123.46"
という書き方ができるのは知っていますが,カッコ内の書式を書くのがやや煩雑です.

そこで,
.ToStringF(a,b)
ここでaは文字列化後の数値の文字数,bは小数点以下の桁数
というメソッドに改良したいのです.
例えば
(123.456).ToStringF(8,2)
「  123.46」
となります
(桁が余っているところは半角スペースにするのですが,これは自分でできます)

この.ToStringFを通常のtostringと同じように
Debug.Print (a.ToStringF(6,2) & b.ToStringF(5,3))
などとできたらいいなと考えています.
どこ(モジュール?クラス?)にどのように(桁をあわせる部分ではなく,
メソッドの枠組みをどのように)書いたらいいのか教えていただけないでしょうか?
また,この.tostringFを新しく作成したソリューションでも簡単に利用できる様にする
(リンクとして追加する.vbに書いておくなど?)にはどうすればよいのでしょうか?


よろしくお願い致します

[ツリー表示へ]
タイトルRe: tostringを改良したい
記事No10886
投稿日: 2012/08/14(Tue) 15:21
投稿者VBレスキュー(花ちゃん)
> Debug.Print (a.ToStringF(6,2) & b.ToStringF(5,3))
> などとできたらいいなと考えています.

それなら、FormatNumber メソッドを使ってもいいのでは。  
Debug.Print(FormatNumber("123456.789", 2))

 http://www.hanatyan.sakura.ne.jp/dotnet/kan01_08.htm#StringFormat

[ツリー表示へ]
タイトルRe^2: tostringを改良したい
記事No10887
投稿日: 2012/08/14(Tue) 15:53
投稿者しげちん
早速のコメントありがとうございます.

FormatNumberを使うと
2つの数値を区切る際に 
Debug.Print (FormatNumber(x,3) & "   " & FormatNumber(y,4))
というように「"   " &」を余分に書かねばならないので,
できれば.ToStringF(a,b)というメソッドの改良の方法を教えてくださいませんでしょうか?
(この方法だと,出力する数値全体の長さよりも大きなaを指定しておけば勝手に空白が入るので,
空白を部分の記述を省くことができます)

今のところ,末尾のような関数を作って
Debug.Print (format1(x,10,3) & format1(y,14,3))
のようにしているのですが,メソッドを改良する方法で同じことは実現できないかと思い
質問しました.
初心者には難しい作業なのかもしれませんが,よろしくお願い致します.


  Function format1(ByVal a As Double, ByVal b As Integer, ByVal c As Integer)
    'format number "a":フォーマットを併せる
    'b : length of number including decimal point
    'c : length of decimal place
    Dim fm$ = "", st$
    Dim nl As Integer

    Select Case c
      Case Is > 0       'decimal
        fm$ = "##0."
        For i = 1 To c
          fm$ = fm$ + "0"
        Next i
      Case 0           'long
        fm$ = "##0"
    End Select
    st$ = Format(a, fm$)

    nl = Len(st$)   'length of a
    If nl < b Then
      For i = 1 To b - nl  'add space
        st$ = " " + st$
      Next i
    ElseIf nl > b Then    'delete upper digit
      st$ = Mid$(st$, nl - b + 1, b)
    End If
    format1 = st$

  End Function

[ツリー表示へ]
タイトルRe^3: tostringを改良したい
記事No10891
投稿日: 2012/08/14(Tue) 17:04
投稿者VBレスキュー(花ちゃん)
>   Function format1(ByVal a As Double, ByVal b As Integer, ByVal c As Integer)
>     'format number "a":フォーマットを併せる
>     'b : length of number including decimal point
>     'c : length of decimal place
>     Dim fm$ = "", st$
>     Dim nl As Integer
>
>     Select Case c
>       Case Is > 0       'decimal
>         fm$ = "##0."
>         For i = 1 To c
>           fm$ = fm$ + "0"
>         Next i
>       Case 0           'long
>         fm$ = "##0"
>     End Select
>     st$ = Format(a, fm$)
>
>     nl = Len(st$)   'length of a
>     If nl < b Then
>       For i = 1 To b - nl  'add space
>         st$ = " " + st$
>       Next i
>     ElseIf nl > b Then    'delete upper digit
>       st$ = Mid$(st$, nl - b + 1, b)
>     End If
>     format1 = st$
>
>   End Function

下記のように書く事でもできます。

Debug.Print(ToFormatEx(123.456, 8, 1) & ToFormatEx(123.456, 8, 3))

Private Function ToFormatEx(ByVal d1 As Double, ByVal sp As Integer, ByVal kt As Integer) As String
   ToFormatEx = FormatNumber(d1, kt).PadRight(sp)
End Function

[ツリー表示へ]
タイトルRe^4: tostringを改良したい
記事No10893
投稿日: 2012/08/15(Wed) 09:07
投稿者しげちん
VBレスキュー(花ちゃん)様

ありがとうございます
こんなに簡単にかけてしまうんですね
大変参考になりました
ありがとうございました

[ツリー表示へ]
タイトルRe: tostringを改良したい
記事No10888
投稿日: 2012/08/14(Tue) 16:10
投稿者魔界の仮面弁士
> (123.456).ToStringF(8,2)
> 「  123.46」
> となります

個人的にはあまり好きではないのですが、実装自体は可能ですよ。


Public Class Form1
    Private Sub Button1_Click() Handles Button1.Click
        TextBox1.Text = (123.456).ToStringF(8, 2)
        TextBox2.Text = (123456).ToStringF(8, 0)

        Dim a = 12.3456
        Dim b = 9.87654

        Debug.Print("{0,6:N2}と{1,5:N3}", a, b)
        Debug.Print("{0,6:F2}と{1,5:F3}", a, b)
        Debug.Print(a.ToStringF(6, 2) & "と" & b.ToStringF(5, 3))
    End Sub

    Private Sub Form1_Load() Handles MyBase.Load
        Dim f As New Font("Consolas", 15)
        TextBox1.Font = f
        TextBox2.Font = f
    End Sub
End Class

Module Sigechin
    <System.Runtime.CompilerServices.Extension()> _
    Public Function ToStringF(Of T As IFormattable)(value As T, a As Byte, b As Byte) As String
        If b = 0 Then
            Return value.ToString("0", Nothing).PadLeft(a)
        Else
            Return value.ToString("0." & StrDup(b, "0"c), Nothing).PadLeft(a)
        End If
    End Function
End Module



手抜きコードなので、このままだと Now.ToStringF(3, 0) などとも
書けてしまう(しかも実行時エラー)という問題があります。

それを嫌う場合にはジェネリックを使わず、Double/Integer などといった
個々の型に対するオーバーロードを実装してあげてください。

[ツリー表示へ]
タイトルRe^2: tostringを改良したい
記事No10889
投稿日: 2012/08/14(Tue) 16:28
投稿者しげちん
魔界の仮面弁士様

コメントありがとうございます.
やりたいことが実現しました.

もしお手数でなければ
>それを嫌う場合にはジェネリックを使わず、Double/Integer などといった
>個々の型に対するオーバーロードを実装
という方法も教えて頂けないでしょうか?

[ツリー表示へ]
タイトルRe^3: tostringを改良したい
記事No10890
投稿日: 2012/08/14(Tue) 17:02
投稿者魔界の仮面弁士
> Debug.Print (FormatNumber(x,3) & "   " & FormatNumber(y,4))
> というように「"   " &」を余分に書かねばならないので,
Debug.Print(書式, x, y) や Console.WriteLine(書式, x, y)、
String.Format(書式, x, y) などでは駄目なのでしょうか?


>>それを嫌う場合にはジェネリックを使わず、Double/Integer などといった
>>個々の型に対するオーバーロードを実装
> という方法も教えて頂けないでしょうか?

Module Sigechin
    <System.Runtime.CompilerServices.Extension()> _
    Public Function ToStringF(value As Double, a As Byte, b As Byte) As String
        Return String.Format("{0," & CStr(a) & ":F" & CStr(b) & "}", value)
    End Function

    <System.Runtime.CompilerServices.Extension()> _
    Public Function ToStringF(value As Integer, a As Byte, b As Byte) As String
        Return String.Format("{0," & CStr(a) & ":G" & CStr(b) & "}", value)
    End Function

    <System.Runtime.CompilerServices.Extension()> _
    Public Function ToStringF(value As Decimal, ……
    '以下同様に、Decimal, Single, Byte, SByte, Short, UShort,
    '      UInteger, Long, ULong, BigInteger 等のためのメソッドを用意。
End Module

[ツリー表示へ]
タイトルRe^4: tostringを改良したい
記事No10892
投稿日: 2012/08/14(Tue) 17:34
投稿者しげちん
魔界の仮面弁士様

たびたびのコメントありがとうございます.
個々の型に対するオーバーロードを実装についてよくわかりました.

>Debug.Print(書式, x, y) や Console.WriteLine(書式, x, y)、
>String.Format(書式, x, y) などでは駄目なのでしょうか?
試しに次のようにやってみましたがうまくいきませんでした.
    Dim a, b As Double
    a = 1.02005
    b = 2.5678
    Debug.Print("00.00", a, b)
やり方がまずいのでしょうか?

たとえば上記のa,bを
  1.02  2.57
(半角6文字で,小数点2桁)
と表示するには,書式,x,yはどのように書けばいいのでしょうか?

[ツリー表示へ]
タイトルRe^5: tostringを改良したい
記事No10894
投稿日: 2012/08/16(Thu) 15:04
投稿者魔界の仮面弁士
> と表示するには,書式,x,yはどのように書けばいいのでしょうか?
最初のサンプルに Debug.Print のコードも載せていますので、参考にしてみてください。

# 当初は Debug.Print 無しのコードで投稿し、その後、返信がまだ
# ついていなかったので、すぐに Debug.Print 付きのコードに
# 書き直したのですが…どうもタイミングが悪かったようで。

[ツリー表示へ]
タイトルRe^6: tostringを改良したい
記事No10895
投稿日: 2012/08/17(Fri) 14:38
投稿者しげちん
魔界の仮面弁士様

ご連絡ありがとうございます
最初のレスを見落としていました
すいません
debug.printの書式の書き方,わかりました
同じ書式で出力するにしてもいろいろやり方があって,大変勉強になりました
ありがとうございました

[ツリー表示へ]