ファイル名の連結 – プログラミング – Home

通知
すべてクリア

[解決済] ファイル名の連結


カナタ
 カナタ
(@カナタ)
ゲスト
結合: 19年前
投稿: 3
Topic starter  

こんばんわ、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で作っています。


引用未解決
トピックタグ
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 21年前
投稿: 1301
 

> デバックで見る限り、FoldernameにはD:\123456789という値が入っていて、

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

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


返信引用
tib
 tib
(@tib)
ゲスト
結合: 22年前
投稿: 468
 

勘ですが、+演算子よりもCString::Format()を使うといいかも。

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

という感じに。


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

str2 を ReleaseBuffer してないようだけど。
ReleaseBuffer しないうちに、他のオブジェクトにコピーしても大丈夫なんだっけ?

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


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 19年前
投稿: 59
 

> 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


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 21年前
投稿: 1301
 

わざわざ CString 使ったのが敗因かな。
しれっと TCHAR str2[MAX_PATH]; で十分でわないかと。


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 19年前
投稿: 59
 

> TCHAR
よくみたら微妙ですな。

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

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


返信引用
カナタ
 カナタ
(@カナタ)
ゲスト
結合: 19年前
投稿: 3
Topic starter  

皆様、レスどうもです。

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

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

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

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


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 21年前
投稿: 1301
 

# どーでもいーけど「裏覚え」ってナニ?
# 「うる覚え」のこと?
# どっちも間違い。 正しくは「うろ覚え」

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

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


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 19年前
投稿: 59
 

> strcore.cppの512行
CString::ReleaseBuffer(int nNewLength)の

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

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


返信引用
カナタ
 カナタ
(@カナタ)
ゲスト
結合: 19年前
投稿: 3
Topic starter  

皆様のアドバイスで無事解決いたしました。

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

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


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 19年前
投稿: 59
 

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
 Blue
(@Blue)
ゲスト
結合: 19年前
投稿: 59
 

> 式がTRUEならば、Debug Assertion Failed! のメッセージボックスを出す。
めちゃくちゃちがってました。逆ですた。

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


返信引用
RAPT
 RAPT
(@RAPT)
ゲスト
結合: 22年前
投稿: 310
 

> しかしなぜ、ReleaseBufferしないうちに代入したらいけないのかが
> まだわかりません。
そういう仕様だから。
# 厳密なところはソースを読めば良い。

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

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


返信引用
とおり
 とおり
(@とおり)
ゲスト
結合: 20年前
投稿: 43
 

仕様外のことをしたら、何が起こるかわからない。何も保証されない。
だって、設計者の想定外のことをしているのだから。
PCが爆発しても文句は言えない。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました