文字列演算子&定数について

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

文字列演算子&定数について

#1 投稿記事 by yu0627 »

ABのバージョンを4.11.03に上げて使ってから気が付いて、ABだけの問題だけではないと思うのですが、lstrcpy関数の「lpString2 As BytePtr」の部分で文字列演算子の+が無効になってしまっています。
例えば、

コード: 全て選択

lstrcpy(lpszFileName, lpszFileName & "." & lpszExt)
なら文字列演算子が有効になるのですが、

コード: 全て選択

lstrcpy(lpszFileName, lpszFileName + "." + lpszExt)
では無効になってしまいます。どうしてでしょうか。同じ現象の人は返信ください。

「api_system.sbp」に記述されている定数のことですが、その中ではファイル属性の定数は以下のようになっています。

コード: 全て選択

Const FILE_ATTRIBUTE_READONLY =            &H00000001
Const FILE_ATTRIBUTE_HIDDEN =              &H00000002
Const FILE_ATTRIBUTE_SYSTEM =              &H00000004
Const FILE_ATTRIBUTE_DIRECTORY =           &H00000010
Const FILE_ATTRIBUTE_ARCHIVE =             &H00000020
Const FILE_ATTRIBUTE_ENCRYPTED =           &H00000040
Const FILE_ATTRIBUTE_NORMAL =              &H00000080
Const FILE_ATTRIBUTE_TEMPORARY =           &H00000100
Const FILE_ATTRIBUTE_SPARSE_FILE =         &H00000200
Const FILE_ATTRIBUTE_REPARSE_POINT =       &H00000400
Const FILE_ATTRIBUTE_COMPRESSED =          &H00000800
Const FILE_ATTRIBUTE_OFFLINE =             &H00001000
しかし、この定数を使いGetFileAttributes関数の戻り値をAnd演算子で判定してみてもうまく出来ません。そこで、

コード: 全て選択

FILE_ATTRIBUTE_READONLY =            &H1
FILE_ATTRIBUTE_HIDDEN =              &H2
FILE_ATTRIBUTE_SYSTEM =              &H4
FILE_ATTRIBUTE_DIRECTORY =           &H10
FILE_ATTRIBUTE_ARCHIVE =             &H20
FILE_ATTRIBUTE_ENCRYPTED =           &H40
FILE_ATTRIBUTE_NORMAL =              &H80
FILE_ATTRIBUTE_TEMPORARY =           &H100
FILE_ATTRIBUTE_SPARSE_FILE =         &H200
FILE_ATTRIBUTE_REPARSE_POINT =       &H400
FILE_ATTRIBUTE_COMPRESSED =          &H800
FILE_ATTRIBUTE_OFFLINE =             &H1000
このように読み替えてやってみるとうまくいきます。例:

コード: 全て選択

	dwFileAttributes=GetFileAttributes(lpszFilePath)
	If (dwFileAttributes And FILE_ATTRIBUTE_READONLY)=&H1 Then
		EnableWindow(GetDlgItem(hDivideDlg, Static_ReadOnlyAttrib), 1)
	End If
	If (dwFileAttributes And FILE_ATTRIBUTE_HIDDEN)=&H2 Then
		EnableWindow(GetDlgItem(hDivideDlg, Static_HidAttrib), 1)
	End If
	If (dwFileAttributes And FILE_ATTRIBUTE_SYSTEM)=&H4 Then
		EnableWindow(GetDlgItem(hDivideDlg, Static_SystemAttrib), 1)
	End If
	If (dwFileAttributes And FILE_ATTRIBUTE_ARCHIVE)=&H20 Then
		EnableWindow(GetDlgItem(hDivideDlg, Static_ArcAttrib), 1)
	End If
	If (dwFileAttributes And FILE_ATTRIBUTE_ENCRYPTED)=&H40 Then
		EnableWindow(GetDlgItem(hDivideDlg, Static_EncryptAttrib), 1)
	End If
	If (dwFileAttributes And FILE_ATTRIBUTE_NORMAL)=&H80 Then
		EnableWindow(GetDlgItem(hDivideDlg, Static_NoAttrib), 1)
	End If
	If (dwFileAttributes And FILE_ATTRIBUTE_TEMPORARY)=&H100 Then
		EnableWindow(GetDlgItem(hDivideDlg, Static_TempAttrib), 1)
	End If
	If (dwFileAttributes And FILE_ATTRIBUTE_SPARSE_FILE)=&H200 Then
		EnableWindow(GetDlgItem(hDivideDlg, Static_SparceAttrib), 1)
	End If
	If (dwFileAttributes And FILE_ATTRIBUTE_REPARSE_POINT)=&H400 Then
		EnableWindow(GetDlgItem(hDivideDlg, Static_ReparceAttrib), 1)
	End If
	If (dwFileAttributes And FILE_ATTRIBUTE_COMPRESSED)=&H800 Then
		EnableWindow(GetDlgItem(hDivideDlg, Static_CompAttrib), 1)
	End If
	If (dwFileAttributes And FILE_ATTRIBUTE_OFFLINE)=&H1000 Then
		EnableWindow(GetDlgItem(hDivideDlg, Static_OfflineAttrib), 1)
	End If
デバッグしてGetFileAttributes関数の戻り値を見ると「&H20」「&H24」のように先頭の0はついていないので0をつけたのが原因だと思います。
これは僕の環境だけでしょうか。
もし違うならよければ修正をお願いいたします。

WindowsXPSP2
AB 4.11.03
マティ
記事: 161
登録日時: 2005年8月23日(火) 00:15
お住まい: 沖縄県
連絡する:

#2 投稿記事 by マティ »

以下のコードではちゃんと表示できました。
Windows2000 SP4
AB 4.11.03
yu0627さん、dwFileAttributesDWordで定義していますよね!
yu0627
記事: 154
登録日時: 2005年5月31日(火) 14:53

返信@yu0627

#3 投稿記事 by yu0627 »

yu0627さん、dwFileAttributesはDWordで定義していますよね!
もちろんです。

コード: 全て選択

Dim dwFileAttributes As DWord
と、いうように宣言しています。

文字列演算子についてはどうでしょうか?
マティ
記事: 161
登録日時: 2005年8月23日(火) 00:15
お住まい: 沖縄県
連絡する:

#4 投稿記事 by マティ »

文字列連結もOKでした。

コード: 全て選択


Dim lpszFileName As String
Dim lpszExt      As String
lpszFileName = "aa"
lpszExt="bb"
lstrcpy(lpszFileName, lpszFileName + "." + lpszExt)
ただし、このコードではバッファーがあふれてしまいますので、正しい処理ではないです・・・

PS.AB4.11.03ですが、ファイル名はab411r03_.zipですか?(アンダーバーが付いています?)
最後に編集したユーザー マティ [ 2005年11月24日(木) 21:00 ], 累計 2 回
yu0627
記事: 154
登録日時: 2005年5月31日(火) 14:53

返信@yu0627

#5 投稿記事 by yu0627 »

> PS.AB4.11.03ですが、ファイル名はab411r03_.zipですか?(アンダーバーが付いています?)
はい。ついております。しかし「+」は使えません。
マティ
記事: 161
登録日時: 2005年8月23日(火) 00:15
お住まい: 沖縄県
連絡する:

#6 投稿記事 by マティ »

確認したいのですがご協力下さい。
新規の.abpを作成して、下記のコードのみを実行しても同様な結果になります?

コード: 全て選択


Dim lpszFileName As String
Dim lpszExt      As String
lpszFileName = "aa"
lpszExt="bb"
lstrcpy(lpszFileName, lpszFileName + "." + lpszExt)
MessageBox(0,lpszFileName,"",MB_OK)     'メッセージボックスを追加
ちなみに、このプログラムは、MessageBoxを出した後、HeapFreeでエラーになります。
yu0627
記事: 154
登録日時: 2005年5月31日(火) 14:53

#7 投稿記事 by yu0627 »

> 確認したいのですがご協力下さい。
> 新規の.abpを作成して、下記のコードのみを実行しても同様な結果になります?
>

コード: 全て選択


> Dim lpszFileName As String
> Dim lpszExt      As String
> lpszFileName = "aa"
> lpszExt="bb"
> lstrcpy(lpszFileName, lpszFileName + "." + lpszExt)
> MessageBox(0,lpszFileName,"",MB_OK)     'メッセージボックスを追加
> 
> ちなみに、このプログラムは、MessageBoxを出した後、HeapFreeでエラーになります。
いえ、これではちゃんと「aa.bb」と表示されますし、デバッグモードでHeapfreeでエラーになります。

Heap block at 001439C8 modified at 001439D7 past requested size of 7

しかし、問題のコードでやるとまだ直りません。lstrcpy関数の中で「+」が機能しません。
「&」なら機能します。あと、lstrcat関数でも起こりました。
二つの関数を呼び出しているDLL「kernel32.dll」のバージョンは5.1.2600.2180 (xpsp_sp2_rtm.040803-2158)です。

というわけで問題のコードの一部分をお見せいたします。

コード: 全て選択


	Dim lpszFileName[MAX_PATH] As Byte
	Dim lpszExt[10] As Byte
	lstrcpy(lpszFileName, lpszFileName + "." + lpszExt)
このようなコードになっております。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

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

私は左辺・右辺のどちらかにString型のものがないと+演算子で文字列連結はできないものと思っています。
あるいはそれを満たしていてもその演算の結果をBytePtr型の引数へ渡すのもまずいと思っています。
(String型の変数へ代入するかString型の引数へ渡すだけ)

マティさんのコードを実行するとyu0627さんと同じエラーになります。
しかし次のようにきちんとメモリを確保した上でMakeStr()を使用するとうまくいきます。
(バージョンはもちろん4.11.03(ab411r03_.zip)です)

コード: 全て選択

#strict

Dim lpszFileName As String
Dim lpszExt      As String
lpszFileName = ZeroString(5)
lstrcpy(lpszFileName, "aa")
lpszExt="bb"
lstrcpy(lpszFileName, MakeStr(lpszFileName) + "." + lpszExt)
MessageBox(0, lpszFileName, "", MB_OK)     'メッセージボックスを追加
MakeStrを使用しないようにするとメッセージボックスの内容はaaだけとなってしまいました。
("."やlpszExtだけにMakeStrをつけても同じでした)
ただこれはlstrcpyのコピー元とコピー先の両方にlpszFileNameを使っているのがまずいのだと私は思います。

追記(H17.11.25 12:54)
lstrcat(lpszFileName, "." + lpszExt)としても問題なく動きます。
yu0627
記事: 154
登録日時: 2005年5月31日(火) 14:53

返信@yu0627@友達の家

#9 投稿記事 by yu0627 »

> 私は左辺・右辺のどちらかにString型のものがないと+演算子で文字列連結はできないものと思っています。
> あるいはそれを満たしていてもその演算の結果をBytePtr型の引数へ渡すのもまずいと思っています。
> (String型の変数へ代入するかString型の引数へ渡すだけ)
>
> マティさんのコードを実行するとyu0627さんと同じエラーになります。
> しかし次のようにきちんとメモリを確保した上でMakeStr()を使用するとうまくいきます。
> (バージョンはもちろん4.11.03(ab411r03_.zip)です)
>

コード: 全て選択

#strict
> 
> Dim lpszFileName As String
> Dim lpszExt      As String
> lpszFileName = ZeroString(5)
> lstrcpy(lpszFileName, "aa")
> lpszExt="bb"
> lstrcpy(lpszFileName, MakeStr(lpszFileName) + "." + lpszExt)
> MessageBox(0, lpszFileName, "", MB_OK)     'メッセージボックスを追加
> MakeStrを使用しないようにするとメッセージボックスの内容はaaだけとなってしまいました。
> ("."やlpszExtだけにMakeStrをつけても同じでした)
> ただこれはlstrcpyのコピー元とコピー先の両方にlpszFileNameを使っているのがまずいのだと私は思います。
>
> 追記(H17.11.25 12:54)
> lstrcat(lpszFileName, "." + lpszExt)としても問題なく動きます。
MakeStr関数を使うんですか。やってみます。
コピー元とコピー先の変数のことですが、別々でもなっていました。
どちらかがString型の変数でなければ「+」が使えないのですか。
前までどちらもByte型でもうまくいっていました。今後は「&」を文字列演算子として使っていこうと思います。
それだったらうまくいきますので(意味違う??)。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

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

私は左辺・右辺のどちらかにString型のものがないと+演算子で文字列連結はできないものと思っています。
あるいはそれを満たしていてもその演算の結果をBytePtr型の引数へ渡すのもまずいと思っています。
(String型の変数へ代入するかString型の引数へ渡すだけ)
いやこれはただ私がコードを書くときの方針でABの仕様とは関係ありません。
ただABの仕様がはっきりとわからないのでこうしておけば安心かと思っているだけです。

誤解を招くような書き方で申し訳ありませんでした。
yu0627
記事: 154
登録日時: 2005年5月31日(火) 14:53

返信@yu0627

#11 投稿記事 by yu0627 »

>
私は左辺・右辺のどちらかにString型のものがないと+演算子で文字列連結はできないものと思っています。
> あるいはそれを満たしていてもその演算の結果をBytePtr型の引数へ渡すのもまずいと思っています。
> (String型の変数へ代入するかString型の引数へ渡すだけ)
> いやこれはただ私がコードを書くときの方針でABの仕様とは関係ありません。
> ただABの仕様がはっきりとわからないのでこうしておけば安心かと思っているだけです。
>
> 誤解を招くような書き方で申し訳ありませんでした。
いえいえ。
あなたのとおりやってみると+演算子でもうまくいきました。
やはりByte型などの同士の結合は&にすることにします。
ですのであとはファイル属性の定数のことだけにします。
マティ
記事: 161
登録日時: 2005年8月23日(火) 00:15
お住まい: 沖縄県
連絡する:

#12 投稿記事 by マティ »

問題が解決してよかったですね

言い訳
yu0627さんが以前に、ハンガリー記法についての投稿をされていたので、lpszから始まる変数はString型と勘違いしていました。
それでString型では+演算子が使用できますって事で前回のサンプルを乗せました。

PS.
&演算子でバイト配列の結合が出来る事を始めて知りました。
自分の環境でのファイル属性については、ちゃんと動作する事で報告済みです。
返信する