String型の使用頻度。
String型の使用頻度。
皆さん、標準データ型である String ってどのくらい使ってますか?
また、どういった時に使いますか?
自分は皆無と言っていい程String型を使ったことがなくて、String型の使用目的が分かりません...。
むしろ、「String型って要らなくね?要らねぇろ?」、の域です。
String型のメリットって...?
また、どういった時に使いますか?
自分は皆無と言っていい程String型を使ったことがなくて、String型の使用目的が分かりません...。
むしろ、「String型って要らなくね?要らねぇろ?」、の域です。
String型のメリットって...?
ヘルプファイルにはこう書かれてますね。
私は最初に扱った言語が、このActiveBasicなので、Basic以外のときもよく使用します。しかし、String型の仕様って凄く曖昧なんですよね。長い間String型を扱っていないと、なかなかうまく扱えないと思います。
ヘルプファイルに書かれているように、無理に使う必要もないでしょう。
メリットといえば、確保、解放が自動というあたりでしょうか。あまり神経質にならずに文字列を扱えます。ですから、WinAPI関連ではなく、文字列自体を操作したいときに使いますね。String型は従来のBasic言語との互換性をとるために存在します。文字列 / バイナリデータを扱う場合は、特に理由がない限り、プログラマーが任意的にメモリ確保、解放を行い、BytePtr型として文字列データを管理する手法を推奨します。
私は最初に扱った言語が、このActiveBasicなので、Basic以外のときもよく使用します。しかし、String型の仕様って凄く曖昧なんですよね。長い間String型を扱っていないと、なかなかうまく扱えないと思います。
ヘルプファイルに書かれているように、無理に使う必要もないでしょう。
私はその文を完全無視するつもりでいます。時代に逆行しているとしか思えないからです。
今時文字列を単なるByte配列(に相当するもの)として扱う言語と言えばCとアセンブリ言語くらいです。
うっかりメモリ確保で誤ってしまったり解放し忘れていたりバッファオーバーフローを起こしそうになったり、何と面倒です。
というのは私が文字列型のある言語に慣れてしまったからでしょうか。
しかしそんなことに頭を振り回している暇があったら、プログラムのアルゴリズムや見た目(UI)を凝りたいです。
API関数については、GetWindowTextで言えばGetWindowTextLengthのような存在がある、
つまり事前に文字数がわかる場合にはまず間違いなくString型でAPI関数を包み込んでいます。
そうでない場合はByte配列を使うことも止むを得ませんが。
> しかし、String型の仕様って凄く曖昧なんですよね。
これがABのかなり痛い点の1つだと思っています。
直接VoidPtrへ変換したときの妙な挙動、配列で要素数の制限、New[]も使えないetc……。
事ある度に言ってきましたが、これに対する私の案は「演算子多重定義をできるようにしてStringを単なるクラスにする」というものです。
特別扱いをやめてしまえば少しは素直になってくれないかというわけです。
勿論バイナリデータにはStringを使う気は毛頭ありません。
上記は全て文字列に対しての話です。
今時文字列を単なるByte配列(に相当するもの)として扱う言語と言えばCとアセンブリ言語くらいです。
うっかりメモリ確保で誤ってしまったり解放し忘れていたりバッファオーバーフローを起こしそうになったり、何と面倒です。
というのは私が文字列型のある言語に慣れてしまったからでしょうか。
しかしそんなことに頭を振り回している暇があったら、プログラムのアルゴリズムや見た目(UI)を凝りたいです。
API関数については、GetWindowTextで言えばGetWindowTextLengthのような存在がある、
つまり事前に文字数がわかる場合にはまず間違いなくString型でAPI関数を包み込んでいます。
そうでない場合はByte配列を使うことも止むを得ませんが。
> しかし、String型の仕様って凄く曖昧なんですよね。
これがABのかなり痛い点の1つだと思っています。
直接VoidPtrへ変換したときの妙な挙動、配列で要素数の制限、New[]も使えないetc……。
事ある度に言ってきましたが、これに対する私の案は「演算子多重定義をできるようにしてStringを単なるクラスにする」というものです。
特別扱いをやめてしまえば少しは素直になってくれないかというわけです。
勿論バイナリデータにはStringを使う気は毛頭ありません。
上記は全て文字列に対しての話です。
なるほど。文字列自体を操作したい時ですか。確かに「str = str + "aiueo"」なんて処理はString型だと簡単にできますね。OverTakerさん さんが書きました:メリットといえば、確保、解放が自動というあたりでしょうか。あまり神経質にならずに文字列を扱えます。ですから、WinAPI関連ではなく、文字列自体を操作したいときに使いますね。
BytePtr型だとサイズが小さい場合、メモリの再確保をしなくちゃいけないなど、ちょっと煩わしいですね。
自分は逆で、GetWindowTextLength()関数のような事前に文字数が分かる場合には間違いなくBytePtr型で処理しています。イグトランスさん さんが書きました: API関数については、GetWindowTextで言えばGetWindowTextLengthのような存在がある、
つまり事前に文字数がわかる場合にはまず間違いなくString型でAPI関数を包み込んでいます。
そうでない場合はByte配列を使うことも止むを得ませんが。
そういえば、事前に文字数が分からないっていう状況になったことがないですね。
文字数を把握できないっていう状況になってないからString型の利便性が分からないんでしょうか...?
クリティカルセクションの処理だとかどういうことをやってるかほとんど分からないんですけど、HeapAlloc()関数とかmemcpy()関数を使ってるみたいなのでBytePtr型をクラスにしちゃえばよさそうですよね。> しかし、String型の仕様って凄く曖昧なんですよね。
これがABのかなり痛い点の1つだと思っています。
直接VoidPtrへ変換したときの妙な挙動、配列で要素数の制限、New[]も使えないetc……。
事ある度に言ってきましたが、これに対する私の案は「演算子多重定義をできるようにしてStringを単なるクラスにする」というものです。
特別扱いをやめてしまえば少しは素直になってくれないかというわけです。
[ここをクリックすると内容が表示されます]
弄くりだしたら結構面白くてクラスが継承し始めました...。
コード: 全て選択
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)
確保・解放を気にせず使えるのは便利ですよね。C1000さん さんが書きました:自分はBytePtr型は使わずString型ばかり使っています。
(確保・解放を気にせず使えるからです。)
でも、自分はBytePtr(バイタープターと呼んでます)に慣れすぎちゃって、確保・解放を自分で管理してないと不安になります...(笑
最後に編集したユーザー 7 [ 2006年5月03日(水) 16:38 ], 累計 3 回
僕はString型は使いまくってます。
理由は確保とか解放とかする必要性がなくなりますからね。
しかし、イグトランスさんが言ったようにCやアセンブリだと配列を使っているわけで、現在アセンブリ言語を勉強している僕にとってString型を含む関数は移植が面倒なだけです。
やっぱりBytePtr(個人的にバイトプターと読んでる。)に慣れていたほうがいいのでしょうか?
理由は確保とか解放とかする必要性がなくなりますからね。
しかし、イグトランスさんが言ったようにCやアセンブリだと配列を使っているわけで、現在アセンブリ言語を勉強している僕にとってString型を含む関数は移植が面倒なだけです。
やっぱりBytePtr(個人的にバイトプターと読んでる。)に慣れていたほうがいいのでしょうか?
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。
に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。
ここ以外の場所では「暇人13世」というHNを主として使用。
に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。
私はスクリプティング言語や関数型言語など専ら高級言語路線を歩んでいます。
そういうわけでABでもString型を多用したくなるのは当然の事なのです。
> そういえば、事前に文字数が分からないっていう状況になったことがないですね。
これはたとえばGetOpenFileNameの場合です。
フックプロシージャを使えば文字数もわかるらしいのですが、
そこまで手間をかけるつもりはありませんから、このようにByte配列を率直に使うという程度のことです。
ちなみに私のStringクラスの構想はString(書換不可)とStringBuilder(書換可)という2本立てというJava/C#的にするというものです。
Stringは参照カウント式にして、現Stringで頻繁に行われる値渡しでも速度低下を抑えられるようにし、
StringBuilderはAPIからの文字列受け取りや数値型変数の書式化もできるようにするという具合です。
実現できるかどうかはともかくですが。
#ところでSingleのほうで山本様が好意的な回答を寄せていただけました。
#ありがとうございます。
そういうわけでABでもString型を多用したくなるのは当然の事なのです。
> そういえば、事前に文字数が分からないっていう状況になったことがないですね。
これはたとえばGetOpenFileNameの場合です。
フックプロシージャを使えば文字数もわかるらしいのですが、
そこまで手間をかけるつもりはありませんから、このようにByte配列を率直に使うという程度のことです。
コード: 全て選択
Dim file[ELM(MAX_PATH)] As Byte
Dim ofn As OPENFILENAME
With ofn
.lpstrFile = file
.nMaxFile = MAX_PATH
'その他は省略
Wnd With
Stringは参照カウント式にして、現Stringで頻繁に行われる値渡しでも速度低下を抑えられるようにし、
StringBuilderはAPIからの文字列受け取りや数値型変数の書式化もできるようにするという具合です。
実現できるかどうかはともかくですが。
#ところでSingleのほうで山本様が好意的な回答を寄せていただけました。
#ありがとうございます。
> 私はスクリプティング言語や関数型言語など専ら高級言語路線を歩んでいます。
> そういうわけでABでもString型を多用したくなるのは当然の事なのです。
僕は主に x86 のアセンブリ言語を扱うことが多いため、低い次元で手軽に扱えてC言語との親和性も高い BytePtr 文字列に偏りがちになっています。
イグトランスさんとの対比で、おもわず「なるほど」と頷いてしまいました (^^;
> ちなみに私のStringクラスの構想はString(書換不可)とStringBuilder(書換可)という2本立てというJava/C#的にするというものです。
> Stringは参照カウント式にして、現Stringで頻繁に行われる値渡しでも速度低下を抑えられるようにし、
> StringBuilderはAPIからの文字列受け取りや数値型変数の書式化もできるようにするという具合です。
僕がイマイチ C# に馴染めないのはそこなんですよね。頭の中で「文字列=バイトの列」という固定観念が完成してしまっているので、わざわざ2種類の文字列型を準備することに抵抗を感じるのです。うーん…
おなじプログラミングの世界、さらには言語すら同じなのに、自分と対称的な立場に立って、対称的に考える人がいるということを改めて実感し、感動を覚えつつ。。。
> そういうわけでABでもString型を多用したくなるのは当然の事なのです。
僕は主に x86 のアセンブリ言語を扱うことが多いため、低い次元で手軽に扱えてC言語との親和性も高い BytePtr 文字列に偏りがちになっています。
イグトランスさんとの対比で、おもわず「なるほど」と頷いてしまいました (^^;
> ちなみに私のStringクラスの構想はString(書換不可)とStringBuilder(書換可)という2本立てというJava/C#的にするというものです。
> Stringは参照カウント式にして、現Stringで頻繁に行われる値渡しでも速度低下を抑えられるようにし、
> StringBuilderはAPIからの文字列受け取りや数値型変数の書式化もできるようにするという具合です。
僕がイマイチ C# に馴染めないのはそこなんですよね。頭の中で「文字列=バイトの列」という固定観念が完成してしまっているので、わざわざ2種類の文字列型を準備することに抵抗を感じるのです。うーん…
おなじプログラミングの世界、さらには言語すら同じなのに、自分と対称的な立場に立って、対称的に考える人がいるということを改めて実感し、感動を覚えつつ。。。
> > そういえば、事前に文字数が分からないっていう状況になったことがないですね。
> これはたとえばGetOpenFileNameの場合です。
> フックプロシージャを使えば文字数もわかるらしいのですが、
> そこまで手間をかけるつもりはありませんから、このようにByte配列を率直に使うという程度のことです。
>
言われてみたら確かな文字数は分からないですね。でも、MAX_PATHよりも小さいだろうってことで自分もByte配列を使います。
> #ところでSingleのほうで山本様が好意的な回答を寄せていただけました。
楽しみですね!
> これはたとえばGetOpenFileNameの場合です。
> フックプロシージャを使えば文字数もわかるらしいのですが、
> そこまで手間をかけるつもりはありませんから、このようにByte配列を率直に使うという程度のことです。
>
コード: 全て選択
Dim file[ELM(MAX_PATH)] As Byte
> Dim ofn As OPENFILENAME
> With ofn
> .lpstrFile = file
> .nMaxFile = MAX_PATH
> 'その他は省略
> Wnd With
> #ところでSingleのほうで山本様が好意的な回答を寄せていただけました。
楽しみですね!
memcpy()関数も覚えておくと便利ですよ。C1000さん さんが書きました:最近は自分もまともにAPIなどを使うのでBytePtrを使い始めました。BytePtr型は文字列判定などもしっかりできるのでけっこう使いやすいですね。
よく分からない場合、Left$, Right$, Mid$関数の定義を覗いてみると勉強になります。
String型でもできるのかもしれませんけど、以下のように書けるのがなんとなく嬉しいです。
コード: 全て選択
Dim lpStr As LPSTR
Dim cc As Long
lpStr=calloc(26)
' "ABCDEFG..."という文字列を作る
For cc=0 To 25
lpStr[cc]=Asc("A")+cc
Next
MessageBox(0,lpStr,"英大文字",MB_OK)
free(lpStr)
String型でも
とすれば同等の事が出来ますよ。
メモリの開放が必要ありませんし。
コード: 全て選択
Dim Str As String
Dim cc As Long
Str=ZeroString(26)
' "ABCDEFG..."という文字列を作る
For cc=0 To 25
Str[cc]=Asc("A")+cc
Next
MessageBox(0,Str,"英大文字",MB_OK)
メモリの開放が必要ありませんし。
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。
に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。
ここ以外の場所では「暇人13世」というHNを主として使用。
に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。