ファイル名の連結

[戻る]
カナタ 2005/09/01(木) 21:24:07
こんばんわ、VC勉強中の初心者+です。
ある画像を自動で保存できるようなプログラムを作ろうと思っています。
その前段階として、フォルダ選択ダイアログでフォルダのパスを取得し、
コードの中で適当なファイル名をフォルダのパスと連結させて画像を保存させようと
おもいましたが、うまくセーブするファイル名ができません。
コードは以下のとうりです。

//フォルダ選択ダイアログのコード

CString Foldername;//フォルダのパスを入れる。

void Caaa::bbb(){
BROWSEINFO bInfo;
    LPITEMIDLIST pIDList;
    CString str;
    CString str2;
    
    // BROWSEINFO構造体に値を設定
    bInfo.hwndOwner             = AfxGetMainWnd()->m_hWnd;
    bInfo.pidlRoot              = NULL;
    bInfo.pszDisplayName        = str.GetBuffer(MAX_PATH);
    bInfo.lpszTitle             = _T("フォルダの選択");
    bInfo.ulFlags               = BIF_RETURNONLYFSDIRS;
    bInfo.lpfn                  = NULL;
    bInfo.lParam                = (LPARAM)0;
    
    pIDList = ::SHBrowseForFolder(&bInfo);
    if(!(pIDList == NULL))
    {
        ::SHGetPathFromIDList(pIDList, str2.GetBuffer(MAX_PATH))
        Foldername = str2;

        str.ReleaseBuffer();
        ::CoTaskMemFree( pIDList );
    }
}

//ファイル名連結
void Caaa::ccc(){
    CString Filename = "001.bmp";
    CString Savename;


    Savename = Foldername + "\\" + Filename;

...略
}

デバックで見る限り、Foldernameには"D:\123456789"という値が
入っていて、Savenameは"D:\123456789\001.bmp"となる予定が
"\001.bmp"になり、Foldernameが連結されませんでした。

なにが悪いのかわからず困っています。
どうかご教授のほどお願いします。

環境は VC++6.0SP4 WinXP_SP1 SDIで作っています。

επιστημη 2005/09/01(木) 21:29:22
> デバックで見る限り、Foldernameには"D:\123456789"という値が入っていて、

どこで見ました? 連結の直前?

# デバックではありません。デバッグ(debug)です。

tib 2005/09/01(木) 21:50:35
勘ですが、+演算子よりもCString::Format()を使うといいかも。

  Savename.Format( "%s\\03d.bmp", Foldername, cnt );

という感じに。

シャノン 2005/09/01(木) 22:51:02
str2 を ReleaseBuffer してないようだけど。
ReleaseBuffer しないうちに、他のオブジェクトにコピーしても大丈夫なんだっけ?

あと、パス名の連結には PathCombine とか PathAppend が便利。

Blue [E-Mail] 2005/09/01(木) 23:25:44
> ReleaseBuffer しないうちに、他のオブジェクトにコピーしても大丈夫なんだっけ?
文字列長を確定していないので、operator+等のメソッドが正確に動かなくなっていま
す。
operator=はOKぽい。(文字列長不確定の情報もコピーするがw)

CString::GetBuffer-MSDN
http://www.microsoft.com/japan/msdn/library/default.asp?
url=/japan/msdn/library/ja/wcemfc/htm/cstring_14.asp

επιστημη 2005/09/01(木) 23:34:31
わざわざ CString 使ったのが敗因かな。
しれっと TCHAR str2[MAX_PATH]; で十分でわないかと。

Blue [E-Mail] 2005/09/01(木) 23:39:28
> TCHAR 
よくみたら微妙ですな。

>    bInfo.lpszTitle             = _T("フォルダの選択");
>    CString Filename = "001.bmp";
>    Savename = Foldername + "\\" + Filename;
_Tマクロ使うんだか使わないんだか。

> あと、パス名の連結には PathCombine とか PathAppend が便利。
私は_splitpath,_makepathつかってました。(しかもCString::GetBuffer使ってw)

カナタ 2005/09/02(金) 00:55:37
皆様、レスどうもです。

フォルダ選択ダイアログのコードは他のサイトからの引用です。お許し願います。
初心者なもので、文字列等はCStringを多用しています。

str2のReleaseBufferは入れるとエラーになってしまいます。
「strcore.cppの512行?(裏覚え)でエラー」みたいなのですが、何がなんだかです。
ReleaseBufferを削除したらエラーが出なくなったので必要ないとおもいました。
そこが原因なのでしょうか?

あとデバッグは連結の後で見ています。

以上です。また今日すこしがんばってみます。

επιστημη 2005/09/02(金) 01:05:39
# どーでもいーけど「裏覚え」ってナニ?
# 「うる覚え」のこと?
# どっちも間違い。 正しくは「うろ覚え」

> ReleaseBufferを削除したらエラーが出なくなったので必要ないとおもいました。

それはヒドイ。
エラーが出なくなった=正しくなった ではありません。
取りあえず食ってくれた だけのこと。 オナカ壊すかもしんないけど。

Blue [E-Mail] 2005/09/02(金) 01:16:38
> strcore.cppの512行
CString::ReleaseBuffer(int nNewLength)の

>     ASSERT(nNewLength <= GetData()->nAllocLength);
ですかね。
(そこらへんでASSERTIONが出そうなところはここぐらい。)

ReleaseBufferの引数にMAX_PATHより大きな値または-2以下の値を設定しているのでしょ
うか?

カナタ 2005/09/05(月) 23:14:57
[[解決]]
皆様のアドバイスで無事解決いたしました。

ReleaseBufferしないうちに代入したのがいけないみたいです。
ReleaseBufferしてから代入したらうまくいきました。
しかしなぜ、ReleaseBufferしないうちに代入したらいけないのかが
まだわかりません。

追伸、Wincore.cppの2666行でエラーがでます。
原因は何なのでしょうか?

Blue [E-Mail] 2005/09/06(火) 00:30:19
CString s1, s2;
strcpy( s1.GetBuffer( 10 ), "test" );
s2 = s1;
s2.ReleaseBuffer();

みたいなことをするとアサートがでました。
> CString::ReleaseBuffer(int nNewLength)の
> >     ASSERT(nNewLength <= GetData()->nAllocLength);
で GetData()->nAllocLengthの値が0でした。

CString::operator=の中で、
>m_pchData = stringSrc.m_pchData;
>InterlockedIncrement(&GetData()->nRefs);
の処理の時に文字列長が不確定でのままの状態が悪さをしているようです。

> 追伸、Wincore.cppの2666行でエラーがでます。
これは、ここに書かれているソースでは判断が付きません。(Wndクラス関連)
> ASSERT(hWndStop == NULL || ::IsWindow(hWndStop));
がなにを示しているか読み取ってください。


ASSERT(式)
 式がTRUEならば、Debug Assertion Failed! のメッセージボックスを出す。
 (デバッグモードのみ)
 詳しくはMSDN引いてください。

Blue [E-Mail] 2005/09/06(火) 00:32:01
>  式がTRUEならば、Debug Assertion Failed! のメッセージボックスを出す。
めちゃくちゃちがってました。逆ですた。

式がFALSE(偽)ならば、Debug Assertion Failed! のメッセージボックスを出す。

RAPT 2005/09/06(火) 00:41:53
> しかしなぜ、ReleaseBufferしないうちに代入したらいけないのかが
> まだわかりません。
そういう仕様だから。
# 厳密なところはソースを読めば良い。

ちゃんとMSDNに、CString::GetBuffer()/GetBufferSetLength()を使ったら、
他のCStringクラスのメソッドを使用する前にReleaseBuffer()しろと
書いてあります。


> 追伸、Wincore.cppの2666行でエラーがでます。
> 原因は何なのでしょうか?
不正なコードを書いたから。

とおり 2005/09/06(火) 00:59:00
仕様外のことをしたら、何が起こるかわからない。何も保証されない。
だって、設計者の想定外のことをしているのだから。
PCが爆発しても文句は言えない。

古いスレッドには追加発言できません。