文字列処理は重要です。ポインタが理解出来ているかどうかの重要な見極めにもなります。

基本
"今日は○○する気分ではない"
という文字列は最後に0(ナル文字)がつきます。

ナル文字とヌルとヌルポインタの違いはその意味にあり、
ナル文字(NUL)はゼロ終端系文字列(*1)に於ける文字の終了
nullは無効な値
null pointerは無効なポインタ
をそれぞれ意味します。

補足

1)ゼロ終端系でない文字列にはPASCAL文字列等があり、PASCAL文字列は処理速度に優れた特性があるため、Excel内部等で用いられている。


実際に使ってみよう

Sting型に慣れている人は面倒だと思うけど、ついてきて欲しい。

1 byte型配列を使おう!

#N88BASIC
Dim mes[123] As Byte'123バイト確保
lstrcpy(mes, "平井公彦")'mesに文字列をコピー
lstrcat(mes," 私は彼が好きです")'mesに連結
wsprintf(mes+lstrlen(mes), "%d",100)'100を文字列にして追加
Print MakeStr(mes)
なんということのないコードだが、配列にデータをコピーしているのであふれにように中尉。
おしりがNULなのでmes[8]=0などと直接値を代入しててもおk

2 ポインタ

#N88BASIC
Dim p As *Byte

Const A="平井公彦"
Const B="松嶋絵美"

p=A
Print MakeStr(p)
p=B
Print MakeStr(p)
エラーメッセージなどすでに文字列が確保されているようなときは、ポインタを使えばいい。
アドレスを渡すだけなので、バッファオーバーフローとかないし、速い。
しかし、ポインタの指した先がリテラルの場合は変更できないと思え。


Ex

文字列の先頭にExをつけると(例:Ex"asdf")エスケープ文字列が有効になります。
例えば\nが改行、\tがタブ、\qがクオートです。

昔のBASICのように"asd"+Chr$(&H0D)+"qwe"でもコンパイルは通りますが、
Ex"asd\nqwe"と書いたほうが、文字が少なくて住みます…。
お好みにあわせてどうぞ。


文字、文字列の種類と変数型の注意点

文字列を扱う場合、通常は

"BASIC"

などとしてプログラム内ではクオーテーションで囲む。変数に代入する場合は、

Dim str1 As String
str1="BASIC"

としてDim文で定義したString型変数に文字列を代入することが出来る。
String型は標準的なBASIC言語に準拠した文字列型で、その使い方はBASIC言語として一般性と汎用性がある。

文字列とは別に、1文字だけを扱う事も可能。英字アルファベットを表記するASCIIコードは
英字で255文字に収まる事から、数値的に255が表現できれば良いので1Byteの範囲に収まる。
Byte型変数は255までの数値表現が可能だから、Byte型の変数一つでASCII英字コード一文字を表す事が出来る。

Dim c As Byte

c=97
print c '数値として表示
print Chr$(a) '文字として表示

このByte型を配列とすれば複数の文字を代入でき、文字列として扱う事も可能になる。
文字を扱う場合、一つの文字のByte変数とその集合であるByte型配列があり、一字以上の文字列を扱うString型がある。
普段BASICを使う場合はString型を用いる事が多い。

String型は内部でメモリーを確保して文字列を保存するので、LongやDoubleとは異なり可変長の変数型として処理
される。String型文字列のメモリーブロックはプログラムが終了すると自動的に開放される。


NULL(NUL)終端文字列


Byte文字、String型文字列とは別に、Win32APIを利用する場合にはC/C++と互換性のあるNull(NUL)文字終端の文字列を
使う。これはByte型変数の配列と等しく、異なるのは文字終端がNull(NUL,ゼロ)で終わると規定されている所。
Byte配列の文字列は標準的なBASICには無い型で多くのBASIC処理系では扱えない事が多いが、Win32APIを利用する場合には
C/C++と互換性があり、Win32APIを利用する事が多いabでは多用される。
見た目はByte型文字配列と何ら変わらない。

Dim nstr(20) As Byte

lstrcpy(nstr,"hello null string") 'Null終端Byte配列文字列を作成
print MakeStr(nstr) '文字列を表示

Null終端文字列は、文字列の最後にNull(数字のゼロ)が来るが、普通はAPI文字列関数を利用して作成する事が多い。
文字列を作成するときに利用したlstrcpy()関数は、標準的なBASIC言語の関数ではなくてWindows環境のC/C++関数。
lstrcpy()関数を用いてString型からByte配列型Null終端文字列を作るのである。

print文で文字列を表示する場合は変換が必要で、MakeStr()関数にてByte配列のNull文字列をString型に変換しておく。
BASIC標準のPrint文は、引数がString型だからである。

lstrcpy()関数などを用いないで同等のByte型Null終端文字列を作る場合は、下記のようにする。

nstr(0)=97
nstr(1)=98
nstr(2)=99
nstr(3)=0
print MakeStr(nstr)

Print文では引数がString型なので変換が必要だが、Msgbox等では元々Win32APIの関数なのでByte配列Null終端文字列
をそのまま扱え、String型へ変換する必要がない。

lstrcpy(nstr,"MessageBox")
Msgbox 0,nstr

Byte型配列Null終端文字列と、String型文字列との相互変換は、MakeStr(),StrPtr()関数などを使う事が出来る。


Byte型配列の文字列の初期化時の注意点


Byte型配列の文字列では、String型とは異なりDim文などで確保されたメモリー内容についてきちんと初期化
されている保証がないので、配列やメモリー領域を確保したりする場合は初期化が必要になる。
32個のByte配列を初期化する場合、For文を使う例を示す。

Dim nstr(31) As Byte

For i=0 to 31
nstr(i)=0
next i

String型ではZeroString()関数が用意されているが、ここではByte型配列の文字列なので、
同等の処理は、ZeroMemory()関数を用いて行う事が出来る。

ZeroMemory(nstr,32)

ZeroMemory()では要素数を与える。配列の添え字と要素数が一致しないので注意。


文字列のエスケープ記号処理の注意点


abの文字列は、C/C++のようなエスケープ記号をサポートしない。標準的なBASIC文字列は"\r\n"のような改行を
扱う事は出来ない。String型の文字列は、"\r\n"を4文字の文字列として処理する。

Print "abcdef\r\n" 'エスケープしない文字列

abの文字列はAPIのwsprintf()関数やlstrcpy()関数内でもエスケープ記号は処理されないので注意が必要。
しかし、Ex修飾するとエスケープ記号が利用でき、"abc\ndef"という文字列が利用可能。

Print Ex"abc\r\ndef" 'エスケープ記号が有効

エスケープ記号はC/C++において多用される記法だが、同等のコードは、
従来のBASIC型の記法を用いてChr$()関数を用いて改行コードを追加することも可能。

Print "abc"+Chr$(13)+Chr$(10)+"def"

lstrcpy(nstr,"abc"+Chr$(13)+Chr$(10))


ワイド文字列の扱いについての注意


日本語など国際化された文字列は、英数字ASCII文字列の255文字では扱えない。多国語対応では1Byte以上を使って
1文字を表す文字コードがマルチバイト文字、ワイド文字等が使われ、漢字も1Byte以上で表記される。
abで用意されている文字列関数は基本的に1Byte処理を行いこれで十分な場合もあるが、場合によっては問題が起きる。
そのためInStr2()関数が提案されている。
http://hira.hopto.org/tips/activebasic/memory/instr_multibyte.xhtml


String文字列へのポインタについての注意


abでは、Byte/Long/Double型のポインタは存在するがString型へのポインタは無い。String型は内部でメモリーを確保し
文字列作成しているので、String型文字列自体がポインタとして扱われていると表現できる。
abにおいてWin32API関数の文字列引数でString型とByte配列Null終端文字列が等しく扱えて互換性があるように
見えるのは、両方ともポインタアクセスを行っているため。

String文字列をポインタで指して直接文字列を配列操作する場合、内部処理は不明なのでString型で扱わない方が良い。
どうしてもポインタ操作を行う場合は、一旦Byte型配列の文字列に変換して処理するのが良い。
String型を用いる場合は、標準BASICで用意されている文字列関数を使うようにしてポインタ操作は避ける方が良い。

異なる文字列間の相互変換は、http://www.mb.ccnw.ne.jp/garger-studio/gameprog/ab0052.htmlに詳しく記載されている。
String型文字列の詳細は、http://www.mb.ccnw.ne.jp/garger-studio/gameprog/ab0051.htmlに記載されている。

String型文字列として利用されていた領域はabプログラム終了と同時に開放される。

なお、abのポインタの記法は、*Byte/BytePtr双方が可能だが、*Byteと書く記法はC/C++と同じ。Helpに書かれている記事
ではBytePtrと記載されているが同じ意味。

タグ:

+ タグ編集
  • タグ:

このサイトはreCAPTCHAによって保護されており、Googleの プライバシーポリシー利用規約 が適用されます。

最終更新:2010年12月03日 18:34