文字列の「Ex」表記に'\0'が含まれている場合

ActiveBasicのバグと思われる不具合を発見された方は、こちらから知らせていただけると助かります。
返信する
メッセージ
作成者
Sinryow
記事: 141
登録日時: 2005年5月31日(火) 09:34
お住まい: 北海道
連絡する:

文字列の「Ex」表記に'\0'が含まれている場合

#1 投稿記事 by Sinryow »

以前も問題になりましたが,文字列のEx表記に'\0'が含まれている場合文字列への代入がうまくできません。

コード: 全て選択

Dim H As String
H=Ex"\r\0\n\0\r\n\0 \0\t\0\0"
MsgBox 0, Str$(H[2]) ' H[2]は関係のない値が出る
BytePtr型に代入(というかポインタを合わせる)場合はうまく出ます。
しかしEx表記の文字列をConst定義したものをBytePtr型に当ててやった場合はうまくいきません。

コード: 全て選択

Dim H As BytePtr
H=Ex"\r\0\n\0\r\n\0 \0\t\0\0"
MsgBox 0, Str$(Len(H))+","+Str$(H[2]) ' H[2]は「10」になる

Const SPACECHAR = Ex"\r\0\n\0\r\n\0 \0\t\0\0"
Dim I As BytePtr
I=SPACECHAR
MsgBox 0, Str$(Len(I))+","+Str$(I[2]) ' I[2]はは関係のない値が出る
このような場合にも対応していただけないでしょうか。
' ============================================================
' Sinryow Game Home Page - http://www.sinryow.net/
' Sinryow ActiveBasic Center - http://ab.sinryow.net/
' ============================================================
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

Re: 文字列の「Ex」表記に'\0'が含まれている場合

#2 投稿記事 by イグトランス »

> 以前も問題になりましたが,文字列のEx表記に'\0'が含まれている場合文字列への代入がうまくできません。
>

コード: 全て選択

Dim H As String
> H=Ex"\r\0\n\0\r\n\0 \0\t\0\0"
> MsgBox 0, Str$(H[2]) ' H[2]は関係のない値が出る
> BytePtr型に代入(というかポインタを合わせる)場合はうまく出ます。
これはStringが内部でlstrlenを呼んでそれを元に確保するサイズなどを決めている都合上仕方がないと思います。
tak
記事: 162
登録日時: 2005年5月31日(火) 07:49

Re: 文字列の「Ex」表記に'\0'が含まれている場合

#3 投稿記事 by tak »

> > 以前も問題になりましたが,文字列のEx表記に'\0'が含まれている場合文字列への代入がうまくできません。
> > BytePtr型に代入(というかポインタを合わせる)場合はうまく出ます。

> これはStringが内部でlstrlenを呼んでそれを元に確保するサイズなどを決めている都合上仕方がないと思います。

しかしながら、この場合"\r\0\n\0\r\n\0 \0\t\0\0"値はString型のリテラル定数ということになりますので、String型の変数に正しく代入されるべきではないでしょうか。
特に、今回のように'\0'で区切り"\0\0"で終端を表すような形式はよく見かけますので、正常に扱えないと厄介です。

もっとも、BytePtr型を使用すれば難なく解決できる問題ですが。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

Re: 文字列の「Ex」表記に'\0'が含まれている場合

#4 投稿記事 by イグトランス »

> しかしながら、この場合"\r\0\n\0\r\n\0 \0\t\0\0"値はString型のリテラル定数ということになりますので、String型の変数に正しく代入されるべきではないでしょうか。

私は文字列リテラルはBytePtrだと思っています。
\0を含んだ文字がStringでうまく扱えないとしてもStringにそこまで求めるほうがまずいのであって、
別に'\0'区切り"\0\0"終端の文字列の並びを扱うクラスを用意すべきではと思っています。

もちろんこれは個人的な意見であり、山本様はtak様のように文字列リテラルはString型とおっしゃるかもしれませんが。
tak
記事: 162
登録日時: 2005年5月31日(火) 07:49

文字列リテラルの型

#5 投稿記事 by tak »

イグトランス様の仰るとおり、文字列直定数はString型よりもむしろBytePtr型と考える方が妥当であることが判明しましたので、報告いたします。

・根拠
 次の2つのコードをコンパイルしたとき、ほぼ同様のコードが生成される。

コード: 全て選択

Dim b As BytePtr, s As String
b = "Literal"
s = b

コード: 全て選択

Dim s As String
s = "Literal"
前者はポインタ変数bの値が利用されるのに対し、後者はリテラルが格納されているアドレスが直接利用されます。
(僕の予想に大きく反して)これだけの違いしかありませんでした。
結局、コンパイラは文字列直定数をByte型の配列としか認識せず、通常はBytePtr型を使うようです。

文字列直定数、例えば、"\r\0\n\0\r\n\0 \0\t\0\0"の場合 0F 00 00 00 0D 00 0D 0A 00 0D 0D 0A 00 20 00 09 00 00 00 といった具合に、文字列リテラルの前には必ずサイズを保持する32ビット値がついていると思っていたのですが、コンパイラは僕の期待したように扱ってはくれず、ただ単に最初に現れる 00 を文字列の終端と見なしてしまうために予期しない動作をしてしまいます。

> \0を含んだ文字がStringでうまく扱えないとしてもStringにそこまで求めるほうがまずいのであって、
イグトランス様のこの発言は見事に的を射ています。
> 別に'\0'区切り"\0\0"終端の文字列の並びを扱うクラスを用意すべきではと思っています。
もっともです。僕はまだオブジェクト指向の本質が見えていないので、この発想は出てきませんでした。
なるほど、と頷くことしかできないのが悔しいです。
Sinryow
記事: 141
登録日時: 2005年5月31日(火) 09:34
お住まい: 北海道
連絡する:

Re: 文字列の「Ex」表記に'\0'が含まれている場合

#6 投稿記事 by Sinryow »

イグトランス さんが書きました:私は文字列リテラルはBytePtrだと思っています。
\0を含んだ文字がStringでうまく扱えないとしてもStringにそこまで求めるほうがまずいのであって、
別に'\0'区切り"\0\0"終端の文字列の並びを扱うクラスを用意すべきではと思っています。
というか私がもともと何をしたかったかというと,Constで'\0'を含む文字列が定義できたらいいな,ということだったのです。
それに「別に'\0'区切り"\0\0"終端の文字列の並びを扱うクラスを用意すべきではと思っています。」とか言ってもそれは一般的な「'\0'を含む文字列」に対する解決にはなりませんし。
' ============================================================
' Sinryow Game Home Page - http://www.sinryow.net/
' Sinryow ActiveBasic Center - http://ab.sinryow.net/
' ============================================================
山本
Site Admin
記事: 535
登録日時: 2005年5月30日(月) 15:08
連絡する:

#7 投稿記事 by 山本 »

'\0'文字コードとString型の問題についてお答えします。

まず、リテラル文字列というのは、ダブルクォート""で囲まれた文字列データ、またはEx表記の拡張文字列データのことをいいますが、こちらは\0を終端コードとして認識しています。

それにたいしてString型データというのは、バイナリデータ部とデータ長を併せ持つ、少し特殊な型となります。

コード: 全て選択

Dim s As String
s=Ex"\0"
このようなコードで、String型変数sに'\0'がバイナリデータとして挿入できないというのは、上記の理由により、リテラル文字列の終端コードを認識してしまうところにあります。

もともと、Ex表記は拡張仕様であり、従来のString型を重視して設計されたものではありません。よって、Ex表記に限り、バイナリデータ部とデータ長を併せ持つ演算を考慮するというのは、速度的な面、生成されるネイティブコードの品質上、あまり好ましいものではないと私は捕らえています。

では、'\0'という文字コードをString型にどのように埋め込めばいいかというと、単純に、String型に対する従来のやり方を適応してやるのが一番自然な形です。

コード: 全て選択

Dim s As String
s="test"+Chr$(0)+"test"
このような表記はN88BASIC互換のString型では最も抵抗のない書き方だと思います。

Sinryow さんが書きました:というか私がもともと何をしたかったかというと,Constで'\0'を含む文字列が定義できたらいいな,ということだったのです。
Constで定義されたリテラル文字列に'\0'が含まれていると、以降のデータが無効になってしまうのは、AB側の不具合ですので、次回のバージョンアップで修正します。
xsb007

#8 投稿記事 by xsb007 »

 ついでなんですが、次のバージョンで \x[文字コード] エスケープシーケンスが使えるようになったらいいなぁと思っています。
(1や2のとかの文字コードRPGのスクリプト制御に使いたいので)
返信する