飴屋ぷろじぇくと

 ちょっとカテゴリを分けてみようかなっと。

--.--.--[--] スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

2014.11.07[金] FreeBASICのワイド文字列が使いにくい件(その2

まず前回のこの件ですが、
Windows版FreeBASICでの話ですが、Print命令等、コンソールに出力するステートメントには不具合があってWStringをまともに表示できません。出力文字数の計算に間違いがあるようで、漢字ひらがなカタカナ等多バイト文字を出そうとすると文字列が途中で途切れてしまいます。多分、ワイド文字での文字数分のバイト数(WindowsなのでSJISのバイト数)しか出力してないんだと思います。
 コンソールのフォントをラスターフォントにしてあるとこの症状が出て、MS ゴシックに変えると直りました。
cmdfont.png
その因果関係がよく判りませんが、内部処理の文字数取得とかがコンソールの状態に影響されるのでしょう。後で時間があったらFBのソースコードを見てみるつもりですが、とりあえず対処法が判ったので良しとします。

さて、本題のMyStringの実装の話になります。
「異常系が弱い」と書きましたが、案の定、初期状態のWStringを代入しようとしたり、MyStringが初期状態で何かしようとすると実行時にアクセス違反を起こして落ちてしまいました。
要はNULLポインタ問題ですね。
なのでその辺の対処をしました。
mystring.bi
Type MyString
Private:
    st As WString Ptr
Public:
    Declare Constructor
    Declare Constructor(s As WString)
    Declare Constructor(m As MyString)
    Declare Destructor
    Declare Operator Let(s As WString)
    Declare Operator Let(m As MyString)
    Declare Operator Cast ByRef As WString
    Declare Operator @ As WString Ptr
    Declare Operator [](i As Integer) As Integer
End Type
'Len()のオーバーロード
Declare Operator Len(m As MyString) As Integer

mystring.bas
#include "mystring.bi"

Constructor MyString
    st = 0
End Constructor

Constructor MyString(s As WString)
    This = s
End Constructor

Constructor MyString(m As MyString)
    This = m
End Constructor

Destructor MyString
    if st <> 0 Then
        Deallocate(st)
    End If
End Destructor

Operator MyString.Let(s As WString)
    Dim n As Integer = Len(*st)
    Dim ln As Integer = Len(s)
    If n < ln Then
        Dim p As WString Ptr = Reallocate(st, (Len(s) + 1) * Len(WString))
        if p <> 0 Then
            *p = s
            st = p
        Else
            *st = Left(s, n) '確保に失敗したら引数の方を切る
        End If
    ElseIf st <> 0 Then '自身がNULLでない
        if ln = 0 Then  '引数がNULLまたは空文字列
            (*st)[0] = 0
        Else
            *st = s
        End If
    End If
End Operator

Operator MyString.Let(m As MyString)
    This = *m.st
End Operator

Operator MyString.Cast ByRef As WString
    return *st
End Operator

Operator MyString.@ As WString Ptr
    return st
End Operator

Operator MyString.[](i As Integer) As Integer
    return (*st)[i]
End Operator

Operator Len(m As MyString) As Integer
    Return Len(*@m)
End Operator


あと、MidLeftRightの文字化け問題ですが、LeftRightに関しては第一引数がWStringとWString Ptrのどちらにも対応していて、こんな風に
Dim w As MyString = "文字列テスト1234"
Print Left(@w, 3)
Print Right(@w, 4)

変数の前に@(ポインタ演算子)をひとつ入れておけば問題を回避できることが判りました。
※前にも書きましたが、このMyStringは@を付けるとWStringのポインタを返すようになってます。

MidはWString Ptrではダメみたいです。
Dim value As MyString = "すとりんぐ"
Print Mid(*@value, 2, 2)
Print Mid(value & "", 2, 2)

このように*@を付けるか、結合演算をして明示的にWStringに変換させるしかありません。

今回はここまでです。

Comment






(編集・削除用)

Trackback

http://utau2009.blog114.fc2.com/tb.php/29-8124b8b0

この記事にトラックバック(FC2Blog User)

Copyright © 飴屋/菖蒲

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。