表や能等の下位コード5cに当たる文字と\との区別方法 – プログラミング – Home

表や能等の下位コード5cに当たる文字と...
 
通知
すべてクリア

表や能等の下位コード5cに当たる文字と\との区別方法

固定ページ 1 / 2

みかん
 みかん
(@みかん)
ゲスト
結合: 16年前
投稿: 12
Topic starter  

いつもお世話になっております。初質問になりますが宜しくお願いします。

開発はVC6.0のMFCにて行っております。

CString strPath = _T(C:\DATA\表.txt) ;
CString strFileName ;
_splitpath( strPath, NULL, NULL, strFileName.GetBuffer(_MAX_FNAME), NULL)) ;
strFileName.ReleaseBuffer() ;

を実行した場合にstrFileNameには何も入っていない状態になります。
この現象はReleaseで実行した際にのみ発生し、debugでは正常に表が取得できます。

原因としては表の下位コードが\と同じの5cとなっているというところまでは分かってい
ます。

このように\と同じ文字コードの文字が入っているフルパスをフォルダ名やファイル名に
分割する場合、どの様な手法を取ると分割が行えるのでしょうか?

色々検索はしてみたのですが、自分の調べ方が悪いのか解決方法が見つからず困ってお
ります。

どうか宜しくお願い致します。


引用解決済
トピックタグ
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

setlocale( LC_ALL, jpn);
を試してみましたか。


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

C:\DATA\表.txt はC:\\DATA\\表.txt ですね。


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

ごめん、
> CString strPath = _T(C:\DATA\表.txt) ;
って、本来のコードでは
> CString strPath = _T(C:\\DATA\\表.txt) ;
になってますよね(確認)。


返信引用
みかん
 みかん
(@みかん)
ゲスト
結合: 16年前
投稿: 12
Topic starter  

返信遅れてしまい申し訳ありません。

情報ありがとうございます。

setlocaleについてはどういうものか理解して使用を検討してみたいと思います。

ファイルパスについてはC:\\DATA\\表.txtとなっております。


返信引用
AR2
 AR2
(@ar2)
Estimable Member
結合: 4年前
投稿: 110
 

 パス文字の分解で、2バイト文字の処理は結構めんどくさいので私はUNICODEに変換し
て処理しています。(邪道かもしれませんし、速度的な優位性はありません)
 CW2A、CA2W(VC6だとW2A、A2Wだったかも)マクロを使うとかなり安易に使えますので、
参考までにどうぞ。


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2659
 

ご質問の内容は、0x5cが出てきた時に'\'なのかトレイルバイトなのかを調べる方法で
しょうか?

上記の話なら文字列をバイト単位で先頭から順番に検査するしかないと思います。
トレイルバイトに0x5cが来ている場合、直前のバイトは必ず2バイトコードのリードバイトの
コードが存在していますから、1バイトずつ検査してリードバイトだった時は、次の1バイトを
トレイルバイトと認識して'\'ではないと判断すれば良いという話だと思います。
リードバイトかどうかを判定する関数はあったはずなので調べてみてください。

そういう話では無いという事でしたら、スルーしてください。


返信引用
maru
 maru
(@maru)
ゲスト
結合: 17年前
投稿: 358
 

ポイントは
> この現象はReleaseで実行した際にのみ発生し、debugでは正常に表が取得できます。

ですよね。

以下のコードでRelease/debugとも「表」が表示されました。
void func()
{
CString strPath = _T(C:\\DATA\\表.txt);
CString strFileName;
_splitpath(strPath, NULL, NULL, strFileName.GetBuffer(_MAX_FNAME),
NULL);
strFileName.ReleaseBuffer();
AfxMessageBox(strFileName);
}
つまりやり方は間違っていないはず。
みかんさんのコードで気になるところは_splitpath()の最後に余分な)がついている
点。
実際には提示されたコードとは別のコードでやっているんですよね。
(エスケープ文字も抜けていたし。)
原因は提示されていない部分にあるのではないでしょうか?
現象が発生するコードをそのまま提示したら如何でしょう。


返信引用
みかん
 みかん
(@みかん)
ゲスト
結合: 16年前
投稿: 12
Topic starter  

皆様、色々とありがとうございます。

setlocaleについてまだ把握し切れていませんが、軽くテストした結果では変化はありま
せんでした。

CW2A、CA2Wについてはまだ理解しきれていない為引き続き調査していこうと思います。

PATIO様の意見ですが、内容的にはそうなるわけですが、今回はファイルのフルパ
スからフォルダ名、ファイル名が分割するというのが目的になっています。
最終的には先頭から一つずつ調査していって分割する関数を作成するという事も視野に
いれて検討してみます。
リードバイトであった場合次のバイトを見てという方法は大変参考になったので是非使
用してみたいと思います。

maru様の意見通り、ReleaseとDebugでの違いもポイントになり、例文もかなり簡単なも
のに変換してあります。
以下実際のコードの流れが分かる様に一部抜き出したものになります。

/**************************************/
void CFileName::Main()
{
CString strProg = _T(") ;
// ここで取得したデータは.\\DATA\\WORK\\1表.TXTとなっています
GetPrivateProfileString( セクション名, キー名, _T("), strProg.GetBuffer
(MAX_PATH), MAX_PATH, パス ) ;

// 関数へ飛ぶ
GetData( strProg ) ;
}

BOOL CFileName::GetWorkSize( CString strProg )
{
// dllにて拡張子を変更する
CString strCalcFile = GetChangeExt( strProg, INI ) ;

// 以下拡張子を変換したファイルを処理
~~~~
return( FALSE ) ;
}

// string = 元ファイル名 ext=変更拡張子
CString FAR PASCAL EXPORT GetChangeExt( CString *string, char *ext )
{
// ファイル名を取り出す
CString strDrive ;
CString strDir ;
CString strFName ;
CString strExt ;
_splitpath( *string, strDrive.GetBuffer( _MAX_DRIVE ),
strDir.GetBuffer( _MAX_DIR ), strFName.GetBuffer( _MAX_FNAME), strExt.GetBuffer
( _MAX_EXT ) ) ;
strDrive.ReleaseBuffer() ;
strDir.ReleaseBuffer() ;
strFName.ReleaseBuffer() ;
strExt.ReleaseBuffer() ;

// 拡張子とファイル名をくっつける
CString retSt = _T(") ;
retSt.Format( _T(%s%s%s.%s), strDrive, strDir, caFName, ext ) ;

return( retSt ) ;
}

/**************************************/


返信引用
みかん
 みかん
(@みかん)
ゲスト
結合: 16年前
投稿: 12
Topic starter  

申し訳ありません、コードを書き込む前に読み直したつもりでしたが再度読み直すと最
初の関数へ飛ぶ部分の関数名が間違っていました。

GetDataではなくGetWorkSizeになりますのでご了承ください。


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

なんだか判断に困るコードだ・・・ツッコミどころ多杉

MBCS なのか UNICODE なのか一度も発言中に明記されていないし
※GetChangeExt の引数は CString* なのか CString なのか判断に困るし
_MAX_PATH と MAX_PATH は意図して使い分けているのかどうか同上
TCHAR と char が混在しているし

警告レベルを上げて警告のある箇所を見直すだけで直る可能性が大とみた。
(発言内容から判断するに MBCS なのだろうから) UNICODE にしてみてエラー・警告の
出る部分を修正するともっとよいと思われる。


返信引用
みかん
 みかん
(@みかん)
ゲスト
結合: 16年前
投稿: 12
Topic starter  

tetrapod様の発言通り間違いが多くて申し訳ありません。

文字コードはMBCSで、警告レベルは4になっており、最適化は無効(デバッグ時)にして
います。
ブラウザ情報やデバッグ情報は残さないように設定してあります。

問題の発生しているdllにてテストコードを書いても同様の結果になったのでそのコード
そのままコピーさせて頂きます。

/**************************************/
CString strString = _T(C:\\DATA\\表.txt) ;
// ファイル名を取り出す
CString strDrive ;
CString strDir ;
CString strFName ;
CString strExt ;
CString strData = *string ;

USES_CONVERSION ;
CString strUString = A2W( strString ) ;

_splitpath( strUString, strDrive.GetBuffer( _MAX_DRIVE ),
strDir.GetBuffer( _MAX_DIR ), strFName.GetBuffer( _MAX_FNAME ),
strExt.GetBuffer( _MAX_EXT ) ) ;
strDrive.ReleaseBuffer() ;
strDir.ReleaseBuffer() ;
strFName.ReleaseBuffer() ;
strExt.ReleaseBuffer() ;
/**************************************/

Releaseモードでの取得データ
strDrive=C:
strDir=\DATA\表
strFName=
strExt=.txt

Debugモードでの取得データ
strDrive=C:
strDir=\DATA\
strFName=表
strExt=.txt


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

UNICODEとMBCSが混ざっちゃってますね。
元のstrStringを、そのまんま_splitpath()に渡せば、
原理的には正しく動くはずです。

// USES_CONVERSION ; いらない
// CString strUString = A2W( strString ) ;いらない
//元の文字列を渡す↓
_splitpath( strString, strDrive.GetBuffer( _MAX_DRIVE ), ・・・


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

っつうか、CStringの使い方がアウトなので、
リリースの場合ソースのまんまじゃ確かめようがないですね(笑)。
素直に、char配列にしてから試してくださいね。


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

> 素直に、char配列にしてから試してくださいね。
これに賛成ですね。
MBCSでいいんですよね。
だと、最後にCStringに転送すればいいのですよね。
MBCSでいいのなら文字操作はchar配列のほうがいいように思います。
ただ、char配列は文字数を固定して扱ったほうがいいです。
(余った部分は'\0'で)


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

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