よろしくお願いします。
VB6.0sp6,Windows2000professionalsp4です。
VBでのディレクトリの有無の判別方法を検索していて、サンプルをひとつ見つけたのですが・・・↓がコードです。
------------------------------------------------
Private Declare Function PathIsDirectory Lib "SHLWAPI.DLL" Alias "PathIsDirectoryA" _
(ByVal pszPath As String) As Long
'
' ディレクトリであるかどうか
'
Private Function IsDirectory(ByVal strFileName As String) As Boolean
' strFilename : チェックしたいディレクトリ名
' 戻り値 : ディレクトリであればTrueを返す。
Dim lngResult As Long
lngResult = PathIsDirectory(strFileName)
IsDirectory = Not (lngResult = 0) 'ここが理解できません
End Function
Private Sub Command1_Click()
Dim strFileName As String
strFileName = "C:\WINNT\Profiles\Administrator\My Documents\HEROPA\TestCls\SHLWAPI"
Msgbox IsDirectory(strFileName)
End Sub
--------------------------------------------
IsDirectory関数は、PathIsDirectoryの戻り値がLong型のため、それをBooleanに直すためのものだと思うのですが、
IsDirectory = Not (lngResult = 0)はどういう原理なのでしょうか?
これだとlngResultにどんな値が入ろうがIsDirectoryに返されるのはTrueになってしまうと思うのですが(lngResultに0が代入され、それがNotされるから)、しかし実際に実行してみるとちゃんとTrueとFalseを判定しています。いったいどうしてなのでしょうか?
それと、PathIsDirectoryの宣言で、関数の戻り値がLongになっていますが、他に見つけたサンプルではBooleanとなっていました。どちらが正しいのでしょうか?
No.9ベストアンサー
- 回答日時:
>VBでのTrueは-1という理解でいいのでしょうか?それとも0以外という理解が正しいのでしょうか?
値としては、-1です。
ただ、Trueを固定値概念で持つ必要はありません。
False(0)でなければ、Trueの分岐部が走ります。
だから「VBでのTrueは」というより「VBでのTrue値は」であれば、確かに-1です^^;
そういう認識を持っていれば、言語を意識しないで済むと思いますよー
最初の発言に戻りますが、
>PathIsDirectoryの宣言で、関数の戻り値がLongになっていますが、他に見つけたサンプルではBooleanとなっていました。どちらが正しいのでしょうか?
PathIsDirectory自体は、DLLに用意されれある関数ですよね?
自分で作成したものではなく、既に用意されているDLLの関数を、どのように利用するかというのがAPIの宣言です。
他の例ですが(ちょっと例えが悪いかもしれませんが)、
Declare Function API関数 Lib "HOGEHOGE.DLL" (ByRef パラメータ As 構造体) As Long
と切る場合もあれば
Declare Function API関数 Lib "HOGEHOGE.DLL" (ByVal パラメータ As Long) As Long
と切るパターンもあります
結果としては、どっちでもいいです。
この例のAPI関数においてはパラメータ部で、構造体の先頭ポインタさえ渡れば、どっちでもいいわけです。
この関数を利用する人の利用したいように宣言ができます。
戻り値部分にいたっては、もっと融通が利きます。
Cに渡す部分であれば、DLLが欲しているパラメータなので、ある程度の制約が発生しますが、戻り値はこっちが受ける部分なので、DLLがその戻り値に対し、メモリを参照することはありません。
私の持っているMSDNでは
BOOL PathIsDirectory(
LPCTSTR pszPath
);
と書いてあるので、2つの固定値を返す関数のようですね。
さらに0と16を返すようです。
16が返るからといって、わざわざこれをLongで受けて、
If (Long戻り値=16) Then
なんてやる人はいませんよね^^;
そこでキャストして受けるようにしてあげれば、Longの概念が打ち消せるわけです。
ちなみにCで利用するパターン(参考までにです)
http://nienie.com/~masapico/api_PathIsDirectory. …
(確か海外のVBのサイトだったと思うけど)Win32APIタイプライブラリというのが存在しています。
それを参照すると、APIの宣言をしなくてもよいという代物です。
そのタイプライブラリはAPIビューワと、結構違います^^;
APIビューワだけが正ではありません。
たくさんAPI利用のサイトを見たらわかると思いますが、みんな結構バラバラですよね^^;
私に限らず、結構オリジナルでやる人が、今では多いと思いますよー
IN/OUT/戻り値を意識していれば、正しいパターンは複数あります。
計算ドリルと違って、正解は一つじゃないのです。
結果、PathIsDirectoryの戻りは、BooleanであろうとLongであろうと、間違いはありません。
どういう宣言が、一番目的に適しているかで、自分で扱いやすい方を選択したらいいと思いますよ。
ほぼ理解できました。何度も回答していただき本当にありがとうございます!
ところで、最近のプログラミング雑誌には、VB6.0の記事はほぼ見られなくなりました。.netを購入する財布も、気力もない私としてはつらいです。6.0もまだまともに使えないのに.netに移ってもしかたありませんしね。
思えばこれまでいろいろな言語を、つついては放り、放ってはつつきとなんだかうじうじやってきました。結果、あまりにも自分の持つ知識が使い物にならないかを実感する毎日です。
もっとがんばらねば、と思いました。
どうもありがとうございました!
No.8
- 回答日時:
>>>C/C++やAPI関数の戻り値では基本的に「False=0」「True=0以外」です。
>>とありますが、VBでも一緒です。
>VBは違いますよ(^^;
例えばですが
If 9999 Then
MsgBox "True 処理"
Else
MsgBox "False 処理"
End If
とすると、TRUE処理が走ります
9999に限らず0以外ならTRUE処理となります。
>確かに、CBool()ではゼロ以外をTrueと判定してくれますが、
>試しにイミディエイトウインドウで
>?Cint(true)
>?Clng(True)
>としてみてください。
>この場合のイコールは「一対一」という意味です。
それを言うと、キリがないのですが、
CではTrueをintにキャストしたら、1なのですが。。。
CやVBに限らず、[FALSE=0] というのは、私の知る限りでは「プログラミング言語」全体的にそうなのではないでしょうか?
Trueを判定するより、Falseを判定する方が処理ステップが少なく済む場合が多いです。(直近の業務がアセンブラだったので^^;)
簡素な言語レベルでそうなので、その上をいく近代言語でも、基本的なルールは変わらないと思います。
上記例でも
If 9999 Then
の中では
[9999]は[0]ではないから
という処理が予想できます。
if (9999) {
MessageBox (0,"true処理","",MB_OK);
} else {
MessageBox (0,"false処理","",MB_OK);
}
これはCでも一緒ですよね^^;
さらに別例も揚げておきます。
Cでの永久ループ
while (《0以外の整数値》) {
};
VBでの永久ループ
Do While (《0以外の整数値》)
Loop
>これを「気持ち悪い(Boolean型への暗黙のキャストなので)」と取るか、「使えればOK」と取るかはその人次第なのかもしれませんが、私個人としては「基本をきっちり押さえること」が大事だと思ってます。
はい、それは非常にわかります。私も当初は「暗黙のキャスト」は非常に疑問を覚えました。
しかしそれを利用する事で、ステップ数の削減を行えるので、VBの利点として逆手に取ることもできます。
>ですから、「誉められない」と書いたのです。
もう、これは価値観かな^^;
>Trueを判定するより、Falseを判定する方が処理ステップが少なく済む場合が多いです
貴重な情報をありがとうございます。脳に刻みました。
すみません。混乱してきました。VBでのTrueは-1という理解でいいのでしょうか?それとも0以外という理解が正しいのでしょうか?
No.7
- 回答日時:
#6さんは、結構お出来になる方みたいですね(^^;
>私も、宣言はオリジナルでやっちゃいます。
私も、個人で作っているプログラム(で、かつソースを公開しない)ならそうすると思います。
ただ、仕事で使ったり他の人にソースを流用される可能性がある場合は、少なくともコメントは入れると思います。
実際に、tochanxさんが「なぜここはBooleanなのだろう」と疑問をもたれてますよね。これは可読性を失った結果・・・だと思うのです。
>>C/C++やAPI関数の戻り値では基本的に「False=0」「True=0以外」です。
>とありますが、VBでも一緒です。
VBは違いますよ(^^;
確かに、CBool()ではゼロ以外をTrueと判定してくれますが、
試しにイミディエイトウインドウで
?Cint(true)
?Clng(True)
としてみてください。
この場合のイコールは「一対一」という意味です。
MS-Basicで良く、論理式でTrueの場合は-1を返すということを利用して
i = (k > 0)*(-20) + 80
みたいな式を書いたことがある人は、BasicでのTrue(真)は-1ということを良く知っているんですけどね(^^;
# もっとも、今こんな式を書いたら怒られてしまいますけど(^^;
前に戻って、もしPathIsDirectoryが「0か-1か」を返す関数であればBooleanで全く問題ないですね。
# BOOLなので0か1か、かもしれませんけど
ですが実際に(Longで宣言した上で)
debug.print PathIsDirectory("C:\")
としてみてください。
# 私の環境では16が出力されました
これを「気持ち悪い(Boolean型への暗黙のキャストなので)」と取るか、「使えればOK」と取るかはその人次第なのかもしれませんが、私個人としては「基本をきっちり押さえること」が大事だと思ってます。
ですから、「誉められない」と書いたのです。
ちょっとキツイ内容になってしまいましたが、私も敵意があるわけではないのでご容赦を(^^;
お礼が遅れてしまい申し訳ありません。
なるほど!理解が少し深まりました。ありがとうござます!
確かにCint(true),Clng(true)の結果はともに-1になりますね。VBではTrueは-1ということですね。
すみません。ちょっとわからないのですが、
>この場合のイコールは「一対一」という意味です
というのはどういう意味なのでしょうか?
私の環境でも16が出力されました。
No.6
- 回答日時:
#5さんに一部賛同で一部反論(敵意ではないのでご容赦を)
>PathIsDirectoryの宣言で、関数の戻り値がLongになっていますが、他に見つけたサンプルではBooleanとなっていました。
>どちらが正しいのでしょうか?
まず、どちらが正しいという考えはありません。
APIの宣言は、関数ではなく「宣言」です。
それよりLongかBooleanかを問いてますが、その部分は返し値部分なので、
「返す値の範囲を理解する事」
「どのような利用の仕方をするか」
というのが大事だと思います。
APIにまだ不慣れなら、#5さんが述べられているような方法をお勧めいたします。
でも慣れたら、教科書通りのやり方をする必要はありません。私も、宣言はオリジナルでやっちゃいます。
ただ、ここの掲示板で書くときは、APIビューワの宣言から利用します。
#5さんの発言どおり、掲示板なので
>可読性
を重視した内容にするためです。
突然ですが、APIサンプルの超有名なURL
vbvbvb.com
http://www.vbvbvb.com/
ぱぱんぶいびぃ
http://www.mitene.or.jp/~sugisita/
Visual Basic Station
http://www1.harenet.ne.jp/~unaap/
かなりヘビーなAPI使い師です。
各サンプルは、パラメータであればほとんど一緒ですが、戻り値にいたっては宣言方法がみんな一緒とは限りません。
またvbvbvb.com運営者とぱぱんぶいびぃ運営者が登録しているVBのメーリングリストが存在しています。
これまたヘビーなメーリングリストで、回答がC++で返ってくることもあるようなところです。
そこでも、戻り値の型を意識するより、APIの特性に意識するように結論が出ていました。
要は「せっかくのVBなんだから、使えればOK」って感じだと思います。
パラメータではないので、PathIsDirectoryの戻り値の取る範囲から、メモリリークを意識しないでもいい事は明らかです。
あと#5さんへの補足
>また#2さんが指摘されていらっしゃるように
>VBでは「True=-1」「False=0」なわけですが
>C/C++やAPI関数の戻り値では基本的に「False=0」「True=0以外」です。
とありますが、VBでも一緒です。
#2さんが
>しかし、実際には
>Not 0→True
と言っている部分があります。その部分のことですね。
vbvbvb.com のサンプルの多くは、これを意識したAPI関数の利用になっていると思います。
お礼が遅れて申し訳ありません。
どうもありがとうございます!
非常に勉強になります。教科書に書いていないことばかりで、とてもわくわくします。
リンクまでたくさん提示していただき、本当に助かります。
vbvbvb.comには以前いったことがあるのですが、挫折してしまいました・・・
すみません。一ヶ所理解できないところがあります。もしよろしければ補足をお願いしたいです。
>パラメータではないので、PathIsDirectoryの戻り値の取る範囲から、メモリリークを意識しないでもいい事は明らかです。
ここが理解できません。戻り値の取る範囲から、メモリリークを意識する必要がないとはどういうことなのでしょうか?
回答ありがとうございました!
No.5
- 回答日時:
>どちらが正しいのでしょうか?
#1さんが#3で指摘されておられるように「Long」です。
というより、API関数の殆どの戻り値はHANDLEにしろポインタにしろ(VB内部では)Longで帰ってきます。
>他に見つけたサンプルではBooleanとなっていました。
は、単にこのケースで言うと「Declare宣言だけでIsDirectoryと同じ事を実現する」為だと思います。
手抜きといっては手抜きですが、こういうのはあまり誉められませんね(^^;
まあ、イミディエイトウインドウで
?CBool(1)
?Cbool(0)
とでもしてみれば分かると思いますが、この関数に関しては0なら失敗、それ以外なら成功なので実害はありませんけど。
また#2さんが指摘されていらっしゃるように
VBでは「True=-1」「False=0」なわけですが
C/C++やAPI関数の戻り値では基本的に「False=0」「True=0以外」です。
IsDirectory = Not (lngResult = 0)
という表現は、これを意識してのことだと思いますよ(^^;
# C/C++で良く
# if (!hoge()){...
# と書くのと一緒かと。
#1さんが「Boolean型のサイズが変わるかもという話」をされていますが、これはC/C++では考慮しないといけない話ではありますが、VB6ということであれば考える必要は全くありませんね。
そもそも64BitプラットフォームではVB6なんて使えないでしょうし・・・(^^;
>計算量が少なくて効率的な気がするのですが
現在のコーディングでは、効率より可読性を大事にするケースのほうが多いと思いますし、そうすべきだと思います。
(lngResult <> False)
では、もしlngResultがBooleanだったらそんな書き方はせずに
(lngResult)
または
(lngResult = True)
と書きますよね。
それに、そもそもlngResultはLong、True/FalseはBooleanですから、違う型で比較するのは直感的に嫌な感じがします(^^;
No.4
- 回答日時:
「<>」
私もそうなのですが、一部の人が嫌います。
これはおそらく、他の言語ではあまり見かけないからじゃないかなー
Cやオラクルのストアドプロシージャでは
!(A=B)
と書いて同じ意味を持ちます。
IsDirectoryはAPIを内部で利用しているだけのオリジナル関数だから、返しの型は結局何でもいいです。
ただIsDirectory関数の特性として
・ある
・ない
を返すだけなので、Boolean特性にしているのでしょう。
また、
Not (lngResult = 0)
この表現はよく用いられる書き方です。
APIの定数で
API_FALSE = 0
です。
API関数の戻り値のパターンをあげておきます
(1)存在チェック系など
・[0]存在しない
・[-1]存在する
(2)実行系など1
・[0]失敗
・[正値]成功(1以上の長整数)
(3)実行系など2
・[負値]失敗(エラー番号)
・[正値]成功(1以上の長整数)
(4)実行系など3
・[正値]失敗(1以上の長整数で特定のエラー番号)
・[正値]成功(1以上の長整数で特定の正常ステータス値)
などなど、いっぱいあります。
(1)のパターンのAPIであれば、全て
Not (lngResult = 0)
でステータスを、わかりやすいBoolean型に置き換えることが可能です。
No.3
- 回答日時:
>プログラミング的にはVBにおけるPathIsDirectoryの宣言では、戻り値の型はBooleanにする方がよいというのは…
すみません、ちょっと調べてみたのですが、
VB6での
Boolean型は、サイズが2バイトで
Long型は、4バイト
SHLWAPI.DLLでの戻り値
BOOL型は、4バイトですので、
型を合わせるということで言えば、Long型の方がいいですね。ごめんなさい。
>Booleanが将来的に他の型を使われる可能性
紛らわしい表現だったかもしれません。
他の型というのは、Boolean型のサイズが変わるかもという話です。(よく考えてみればLong型にしても同じことが言えますね^^;)
Boolean型は、VB6では、前述したように、2バイトサイズですけど、将来的に、(例えば64ビットマシンが基本的なコンピュータとなった時に?、)4バイトになったりあるいは、1バイトになったりする可能性があります。なので、そうした物理的なサイズを指定するより、抽象的な型名を使う方が良いというような意味でした。(今回の質問の場合逆になってしまいました(;^_^A )
ちなみに、VCでは、
BOOL型はint(4バイト)で
BOOLEAN型は、char(1バイト)になっていました。
No.2
- 回答日時:
0→False
です
-1→True
です
しかし、実際には
Not0→True
です
Not (lngResult = 0)
↓
Not (lngResult = False)
↓
(lngResult <> False)
という意味です。
ありがとうござます。
しかしどうして、
Not (lngResult = 0)
と
(lngResult <> False)
が同じ式なのにNotの方を採用しているのでしょうか?
Not (lngResult = 0)
と
(lngResult <> False)
なら、
(lngResult <> False)
の方が計算量が少なくて効率的な気がするのですが・・・
No.1
- 回答日時:
VB言語では、
lngResult = 0
は、位置によって代入の場合と論理式の場合があります。
質問文の場合、論理式として評価されます。
なので、代入されるのではなく、0かどうかを調べて、true か falseになります。
IF文で0かどうか調べるときXXX = 0と条件の部分にかきますよね、それと同じです。
>PathIsDirectoryの宣言で、…
APIの説明を観るとBOOL型となっていました。
結局BOOL型の実体がLONG(VBでの)ということなのでしょう
同じコト(最終的に同じものになる場合)でも、
プログラミング的には、Booleanの方がいいのだと思います。(Booleanが将来的に他の型を使われる可能性がありますから)
ありがとうございます。
位置によって論理式として評価されるのですか!なるほど!納得です。
ですが、BLUEPIXY様の回答の後半部分が理解できません。
プログラミング的にはVBにおけるPathIsDirectoryの宣言では、戻り値の型はBooleanにする方がよいというのはわかりましたが、()の中の「Booleanが将来的に他の型を使われる可能性がありますから」というのがわかりません。
よろしければもう少しわかりやすく教えていただけないでしょうか?ヒントだけでもお願いします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) 【Excel VBA】自動メール送信の機能追加 5 2022/09/29 12:53
- Visual Basic(VBA) batからexeを実行し戻り値を受け取る EXEの実行内容の結果によって、戻り値を0か1かで返したい 1 2023/07/04 16:40
- Visual Basic(VBA) 別シートから年齢別の件数をカウントしたいの続き 5 2023/01/24 00:16
- Visual Basic(VBA) 【変更】ファイルを閉じてダイアログで保存した時、更新したシートだけの処理の実行をする 5 2022/03/26 18:31
- Visual Basic(VBA) 【追加】ファイルを閉じてダイアログで保存した時だけ処理の実行をする 3 2022/03/23 15:43
- Visual Basic(VBA) batからexeを実行し戻り値を受け取る バッチからEXEの結果を受け取りたいのですが、 下記のバッ 1 2023/07/04 15:13
- Access(アクセス) Vba Userformを前面に出すについて 3 2022/04/15 12:29
- Visual Basic(VBA) Vbaで数式をポーランド記法に変換するコードを作って実行しようとするとフリーズします。 1 2022/05/24 17:53
- Visual Basic(VBA) 【VBA】写真の貼り付けコードがうまく機能しません。 5 2022/09/01 18:43
- Visual Basic(VBA) outlook マクロが終了しません。 1 2022/09/02 11:14
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・プリン+醤油=ウニみたいな組み合わせメニューを教えて!
- ・タイムマシーンがあったら、過去と未来どちらに行く?
- ・遅刻の「言い訳」選手権
- ・【大喜利】【投稿~11/12】 急に朝起こしてきた母親に言われた一言とは?
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・好きな「お肉」は?
- ・あなたは何にトキメキますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・ハマっている「お菓子」を教えて!
- ・【大喜利】【投稿~11/1】 存在しそうで存在しないモノマネ芸人の名前を教えてください
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・つい集めてしまうものはなんですか?
- ・自分のセンスや笑いの好みに影響を受けた作品を教えて
- ・【お題】引っかけ問題(締め切り10月27日(日)23時)
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・【大喜利】【投稿~10/21(月)】買ったばかりの自転車を分解してひと言
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBAのプログラムで、DIAG = 1# ...
-
「#undef」と「#define」の使い...
-
Integer変数をカラにしたいので...
-
C++ 構造体の一括初期化 {0}
-
long型のデータをバイト型の配...
-
VBAの変数のデータ型を変更する...
-
異なる構造体のデータのコピー
-
値が代入されてない時
-
構造体にする理由・利点・使用例
-
Pro*C NUMBER型の...
-
C言語 構造体の中に共用体を定...
-
日付チェック関数について
-
構造体の初期化方法について
-
構造体のポインタにNULLが入らない
-
整数から16進数への変換 現在c...
-
C言語 配列の長さの上限
-
関数から配列を返すには?
-
C言語のポインタに直接アドレス...
-
構造体のextern方法
-
セグメントエラー
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBAのプログラムで、DIAG = 1# ...
-
Integer変数をカラにしたいので...
-
C++ 構造体の一括初期化 {0}
-
「#undef」と「#define」の使い...
-
C言語 構造体の中に共用体を定...
-
構造体のデータを丸ごとコピー...
-
値が代入されてない時
-
typedefをプログラム中で解除す...
-
charとucharの違い
-
異なる構造体のデータのコピー
-
構造体のポインタにNULLが入らない
-
VBAにてcolorindexを変数に格納...
-
VBAの変数のデータ型を変更する...
-
long型のデータをバイト型の配...
-
整数から16進数への変換 現在c...
-
構造体の初期化方法について
-
日付チェック関数について
-
1バイトデータの読み出しについて
-
命名規則 VB 構造体
-
GTKプログラミングで型宣言する...
おすすめ情報