引用:
メリットといえば、確保、解放が自動というあたりでしょうか。あまり神経質にならずに文字列を扱えます。ですから、WinAPI関連ではなく、文字列自体を操作したいときに使いますね。
なるほど。文字列自体を操作したい時ですか。確かに「str = str + "aiueo"」なんて処理はString型だと簡単にできますね。
BytePtr型だとサイズが小さい場合、メモリの再確保をしなくちゃいけないなど、ちょっと煩わしいですね。
引用:
API関数については、GetWindowTextで言えばGetWindowTextLengthのような存在がある、
つまり事前に文字数がわかる場合にはまず間違いなくString型でAPI関数を包み込んでいます。
そうでない場合はByte配列を使うことも止むを得ませんが。
自分は逆で、GetWindowTextLength()関数のような事前に文字数が分かる場合には間違いなくBytePtr型で処理しています。
そういえば、事前に文字数が分からないっていう状況になったことがないですね。
文字数を把握できないっていう状況になってないからString型の利便性が分からないんでしょうか...?
引用:
> しかし、String型の仕様って凄く曖昧なんですよね。
これがABのかなり痛い点の1つだと思っています。
直接VoidPtrへ変換したときの妙な挙動、配列で要素数の制限、New[]も使えないetc……。
事ある度に言ってきましたが、これに対する私の案は「演算子多重定義をできるようにしてStringを単なるクラスにする」というものです。
特別扱いをやめてしまえば少しは素直になってくれないかというわけです。
クリティカルセクションの処理だとかどういうことをやってるかほとんど分からないんですけど、HeapAlloc()関数とかmemcpy()関数を使ってるみたいなのでBytePtr型をクラスにしちゃえばよさそうですよね。
[ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]コード:
Class CStringBasic
Protected
c_lpString As BytePtr
c_lstLen As Long
c_stSize As SIZE_T
' メモリに関する関数は隠蔽(?)。
' 確保されているメモリのサイズを返す
Function getSize() As SIZE_T
getSize=c_stSize
End Function
' メモリが確保されているなら解放する
Sub release()
If isAlloc()=TRUE Then
free(c_lpString)
c_lstLen=NULL
End If
c_lpString=NULL
c_stSize=NULL
End Sub
' 確保されているならTRUEを返す
Function isAlloc() As BOOL
isAlloc=FALSE
If c_lpString<>NULL Then
isAlloc=TRUE
End If
End Function
' 解放されているならTRUEを返す
Function isRelease() As BOOL
isRelease=TRUE Xor isAlloc()
End Function
Public
Sub CStringBasic()
c_lstLen=NULL
c_stSize=NULL
c_lpString=NULL
End Sub
Sub ~CStringBasic()
release()
End Sub
' メモリ確保の関数も隠蔽した方がいい?
' でもAPI関数を使うときにユーザーがメモリを確保できないと困る。
Sub zeroString(ByVal stSize As SIZE_T)
release()
c_stSize=stSize
c_lpString=calloc(getSize())
End Sub
' 文字列の長さをバイト数で返す
Function length() As Long
length=c_lstLen
End Function
End Class
Class CString
Inherits CStringBasic
Public
Sub CString()
CStringBasic()
End Sub
Sub CString(ByVal lpString As BytePtr)
CStringBasic()
cpy(lpString)
End Sub
Sub CString(ByVal lpString As String)
CStringBasic()
cpy(lpString)
End Sub
' 文字列から指定された位置の文字コードを返す
Function charAt(ByVal nIndex As Long) As Char
charAt=c_lpString[nIndex]
End Function
' 文字列バッファに文字列をコピー
Sub cpy(ByVal lpString As BytePtr)
c_lstLen=lstrlen(lpString)
If isAlloc()=TRUE Then
If getSize()<=length() Then
c_stSize=(length() As SIZE_T)+1
c_lpString=realloc(c_lpString,getSize())
lstrcpy(c_lpString,lpString)
Else
lstrcpy(c_lpString,lpString)
End If
Else
c_stSize=(length() As SIZE_T)+1
zeroString(getSize())
lstrcpy(c_lpString,lpString)
End If
End Sub
' 文字列バッファに文字列をコピー
Sub cpy(ByVal lpString As String)
cpy(StrPtr(lpString))
End Sub
' 文字列バッファに数値を文字列に変換したものをコピー
Sub cpy(ByVal lpString As Double)
Dim _str As CString(Str$(lpString))
cpy(_str.toBytePtr())
End Sub
' 文字列バッファに文字列を追加
Sub cat(ByVal lpString As BytePtr)
If length()<>0 Then
c_lstLen+=lstrlen(lpString)
If getSize()<=length() Then
c_stSize=(length() As SIZE_T)+1
c_lpString=realloc(c_lpString,getSize())
lstrcat(c_lpString,lpString)
Else
lstrcat(c_lpString,lpString)
End If
Else
cpy(lpString)
End If
End Sub
' 文字列バッファをString型に変換
Function toString() As String
toString=MakeStr(c_lpString)
End Function
' 文字列バッファをBytePtr型に変換する、訳じゃなくポインタを返す
' getStr にでも変更するか?
Function toBytePtr() As BytePtr
toBytePtr=c_lpString
End Function
Function toVal() As Double
toVal=Val(c_lpString)
End Function
Function toInt() As Long
toInt=Int(toVal())
End Function
Function toFix() As Long
toFix=Fix(toVal())
End Function
' 文字列から特定の位置の文字列を取り出す。
Function slice(ByVal startPos As Long,ByVal endPos As Long) As BytePtr
Dim len As Long
If startPos < endPos Then
If endPos>length() Then
endPos=length()
End If
len=endPos-startPos
Else
If startPos>length() Then
startPos=length()
End If
len=startPos-endPos
End If
slice=calloc(len+1)
memcpy(slice,VarPtr(c_lpString[startPos]),len)
' slice[len]=0
End Function
' 文字列の長さを文字数で返す。必ずではないかも...。
Function lengthEx() As Long
Dim cnt As Long
For cnt=0 To length()
If IsDBCSLeadByte(charAt(cnt)) Then
cnt++ '早くループを終わらせる為の処理
lengthEx++
End If
Next
End Function
End Class
弄くりだしたら結構面白くてクラスが継承し始めました...。
使い方 [ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]コード:
Dim str As CString(Ex"あいうえお\r\n")
str.cat(Ex"なにやってんの\r\n")
str.cat(Ex"しらね\r\n")
MessageBox(hMainWnd,str.toBytePtr(),Str$(str.lengthEx())+"文字",MB_OK)
str.cpy(120 As Double)
str.cpy(str.toVal()*2 As Double)
MessageBox(hMainWnd,str.toBytePtr(),"",MB_OK)
引用:
自分はBytePtr型は使わずString型ばかり使っています。
(確保・解放を気にせず使えるからです。)
確保・解放を気にせず使えるのは便利ですよね。
でも、自分はBytePtr(バイタープターと呼んでます)に慣れすぎちゃって、確保・解放を自分で管理してないと不安になります...(笑