ディレクトリの取得方法

解決


aki  2006-01-18 18:46:40  No: 60340

GetCurrentDirectory  で取得したディレクトリのひとつ上位にあるディレクトリを取得する方法を教えて下さい。

プロジェクトの場所が
E:\AA\BB\CC\DD\EE.sln
とある場合、GetCurrentDirectory  でもとめられるのは
E:\AA\BB\CC\DD  だが、
E:\AA\BB\CC     までを求めたい。


Blue  2006-01-18 18:58:57  No: 60341

普通に文字列処理ではダメなのでしょうか?

例えば、
_tsplitpath関数を使って、"E:\AA\BB\CC" を分割する
とか。


aki  2006-01-18 19:11:41  No: 60342

その後の処理上、CString  形式ではなく
char  Buff[]  という形で求めたいので、

#define  MAX_PATH   260
char Buff[MAX_PATH], Buff2[MAX_PATH]
GetCurrentDirectory (sizeof(Buff), Buff);
int Code = 0;
for (int i=0; i<MAX_PATH; i++) {
    if (Buff[i] == '\\')  Code = i;
}
for (i=0; i<Code; i++) {
    Buff2[i] = Buff[i];
}

という形で試みてみましたが、Buff2の値が
E:\AA\BB\CCフフフフフフフフフフフフフフフフフフフフフ………
となってしまい、できませんでした。
Buff2のサイズをBuff2[Code]とできればそれでいいのでしょうが、
配列を変数で定義する方法がわからず、
何より、無駄な処理をしているように思えるので質問させていただきました。


Blue  2006-01-18 19:27:28  No: 60343

まず初期化されていない文字列に対して、
バッファサイズ分の要素を比較しないほうがいいです。
>for (int i=0; i<MAX_PATH; i++) {
でなく
for ( int i = 0; Buff[ i ] != '\0'; i++ )
としましょう。
> for (i=0; i<Code; i++) {
>     Buff2[i] = Buff[i];
> }
では、最後の \ の手前までコピーしているだけでなので、
文字列の終端を示す '\0' が入っていません。
Buff2[ Code ] = '\0';
と、ちゃんと入れてあげましょう。
もっとも、文字列の複写ならば、string.hにstrncpyというのがありますので、
strncpy( Buff2, Buff, Code - 1 );
Buff2[ Code ] ='\0';
で同様の処理になります。

ところで、パス文字列には全角文字が含まれるので、'\' の検索では致命的なバグがあります。
Shift_JISでは、1バイトが全角文字を表すコードで2バイト目が '\' のコードという文字が存在します。(ソ とか 能 とかがそう)
'\' 検索時に全角文字を意識して検索しないといけません。
# MFCのCStringのReverseFindメソッドのソースをみると、うまいこと検索しているのが分かります。

こういうめんどくさいことがあったので、最初に
> _tsplitpath関数を使って
といったわけです。

下は _tsplitpath と _tmakepath の例です。
void GetCurrentParentDirectory( LPTSTR lpBuffer )
{
    TCHAR szCurrentDirectory[ _MAX_DIR ];
    TCHAR szDrive[ _MAX_DRIVE ], szDirectory[ _MAX_DIR ];

    GetCurrentDirectory( _MAX_DIR, szCurrentDirectory );
    _tsplitpath( szCurrentDirectory, szDrive, szDirectory, NULL, NULL );
    _tmakepath( lpBuffer, szDrive, szDirectory, NULL, NULL );
}

int main( void )
{
    TCHAR szCurrentParentDir[ _MAX_DIR ];
    GetCurrentParentDirectory( szCurrentParentDir );
    MessageBox( NULL, szCurrentParentDir, _T( "" ), MB_OK );
    return 0;
}

ただ、_tmakepathを使うと、末尾に '\' がつくので注意してください。


Toshi  2006-01-18 19:32:51  No: 60344

余りに初歩的なので回答を躊躇しちゃいますが、今後の「応用」に期待して書きます。

ちなみにVCなら _MAX_PATH は定義済みなのでそれを使う事にします。
もし元のパスも残しておきたいなら・・

char currentPath[_MAX_PATH], parentPath[_MAX_PATH];
GetCurrentDirectory(sizeof(currentPath), currentPath);
strcpy(parentPath, currentPath);
for (size_t p = strlen(parentPath)-1; p >= 0; p--){
    if (parentPath[p] == '\\'){
        parentPath[p] = 0;
        break;
     }
}


Blue  2006-01-18 19:38:28  No: 60345

> 下は _tsplitpath と _tmakepath の例です。
バッファサイズ間違っていました。
_MAX_DIR は ドライブ名 + ':' の文字数を含んでいないですから
_MAX_PATH を指定しないといけなかったです。

> int main( void )
TCHAR 意識するなら
int _tmain( void )
のほうがよかったかな。


aki  2006-01-18 20:04:46  No: 60346

解決しました。
今年度プログラミング会社に入社したばかりで初めての仕事だったので、
とても初歩的な質問でしたが、ありがとうございました。
これからの仕事にも応用できると思います。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加