ab.com コミュニティ
https://www.activebasic.com/forum/

文字列の「Ex」表記に'\0'が含まれている場合
https://www.activebasic.com/forum/viewtopic.php?t=115
ページ 11

作成者:  Sinryow [ 2005年6月15日(水) 19:47 ]
記事の件名:  文字列の「Ex」表記に'\0'が含まれている場合

以前も問題になりましたが,文字列の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]はは関係のない値が出る
このような場合にも対応していただけないでしょうか。

作成者:  イグトランス [ 2005年6月15日(水) 21:08 ]
記事の件名:  Re: 文字列の「Ex」表記に'\0'が含まれている場合

> 以前も問題になりましたが,文字列の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 [ 2005年6月15日(水) 22:31 ]
記事の件名:  Re: 文字列の「Ex」表記に'\0'が含まれている場合

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

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

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

もっとも、BytePtr型を使用すれば難なく解決できる問題ですが。

作成者:  イグトランス [ 2005年6月15日(水) 23:11 ]
記事の件名:  Re: 文字列の「Ex」表記に'\0'が含まれている場合

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

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

もちろんこれは個人的な意見であり、山本様はtak様のように文字列リテラルはString型とおっしゃるかもしれませんが。

作成者:  tak [ 2005年6月16日(木) 21:17 ]
記事の件名:  文字列リテラルの型

イグトランス様の仰るとおり、文字列直定数は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 [ 2005年6月18日(土) 10:23 ]
記事の件名:  Re: 文字列の「Ex」表記に'\0'が含まれている場合

引用:
私は文字列リテラルはBytePtrだと思っています。
\0を含んだ文字がStringでうまく扱えないとしてもStringにそこまで求めるほうがまずいのであって、
別に'\0'区切り"\0\0"終端の文字列の並びを扱うクラスを用意すべきではと思っています。
というか私がもともと何をしたかったかというと,Constで'\0'を含む文字列が定義できたらいいな,ということだったのです。
それに「別に'\0'区切り"\0\0"終端の文字列の並びを扱うクラスを用意すべきではと思っています。」とか言ってもそれは一般的な「'\0'を含む文字列」に対する解決にはなりませんし。

作成者:  山本 [ 2005年6月18日(土) 11:40 ]
記事の件名: 

'\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型では最も抵抗のない書き方だと思います。

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

作成者:  xsb007 [ 2005年6月19日(日) 10:13 ]
記事の件名: 

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

ページ 11 全ての表示時間は UTC+09:00 です
Powered by phpBB® Forum Software © phpBB Limited
https://www.phpbb.com/