VisualStudio2005 MFCでの開発です。
すでに作成してあるプログラムで、LPBYTE型の文字を使用して処理を行っているのです
が、その途中で一部分を抜き出したLPBYTE型にする・・という機能を追加しています。
追加した機能では、LPBYTE型の文字列がはいっているデータをうけとり、
一部分を抜き出したものをCString型の変数に入れました。
その後、CString型の文字列をLPBYTE型の変数におきかえてあげるにはどうすればいいの
でしょうか。
(もともとのプログラムのLPBYTE型データから一部分を抜き出したLPBYTE型を渡して
そのまま処理を行わせたいのです)
初心者のため、表現方法が適切ではないかもしれません。
宜しくお願いします。
BYTE ch[] = abcd;
LPBYTE x = ch ;
CString str;
str = (LPCTSTR)x;
+さん、回答ありがとうございます。
すみません。書き方が悪かったようです。
CString型への変更はできたのですが、
できあがったCStringの変数の中身をLPBYTEに渡してあげたいのです。
+さんの例のあとに、strの中身を変更したものを、再度xに渡してあげる
ということは可能でしょうか。
むぅ。。。。
TCHARに変換した後、どうするかによる。
TCHARに変換した後、文字列操作しないなら。
CString str;
TCHAR x = (TCHAR)(LPCTSTR)str;//無理やりバージョン
TCHARに変換した後、文字列操作するなら。
CString str;
TCHAR x = str.GetBuffer(str.GetLength() + 1);
::strcat(x,0123);
str.ReleaseBuffer();//だったかな?
TCHARじゃなかった。LPBYTEと読み替えてね^^;
コンパイラに叱られたらキャストを。。。
とりあえず、
>LPBYTE型の文字
とは?
文字コードはShift_JISなのか?Unicodeなのか?
また、LPBYTE型の文字列の領域は誰が面倒みるのか?
CStringT::GetBufferではCString変数が寿命が尽きると使えなくなります。
+さん、度々ありがとうございます。
無理やりバージョンのほうで、なんとかデータをLPBYTEに移すことはできたのですが、
引き続き伺いたいことがあります。
-----------------------------------------------------------
-----------------------------------------------------------
AAA::BBB( LPBYTE x ) { //この時点でxに文字が入っている
CCC ( x );
}
AAA::CCC ( LPBYTE x ) {
xの文字を操作し、変更した内容でxに入れてあげる
}
-----------------------------------------------------------
-----------------------------------------------------------
↑のようなことを行っており、AAA::CCCの中で、xに変更した値が入っていることを
デバッグで確認しました。
ただ、呼ばれた先(AAA::BBB)に戻ったときにxの値が元の値(AAA::CCCに入る前)
に戻ってしまいます。
CCC ( &x ) とするとコンパイルで
「error C2664: ~ 1 番目の引数を 'LPBYTE *__w64 ' から 'LPBYTE' に変換できませ
ん」とエラーが出てしまいます。
全くの素人のような質問で申し訳ありません・・。
Blueさん、
文字コードはShift_JIS です。
>また、LPBYTE型の文字列の領域は誰が面倒みるのか?
この質問の回答ですが、すみません・・。理解不足で回答ができません。
行っていることは+さんへの変身に書いたようなことです。
(すでにAAA::BBBに引数として渡されている)
アドバイスなどあればよろしくお願いいたします。
呼び元で領域をちゃんと確保していないと、バッファーオーバーフローしそうです
が・・・
AAA::CCC ( LPBYTE x )で、
以下のどちらを行っているかによる。
x[0] = 'a';
x = a;
後者はxの内容を変えているわけじゃないので
変わりません。
LPBYTEは好きではないのでBYTEで書きますね。
AAA::CCC ( BYTE** x );
ならば
CCC(&x)と書けるようになる。
しかし
他の方が指摘しているように
文字列を格納するメモリを誰が確保して誰が解放するのかが
ごっちゃになって動作しなくなりますよ。
AAA::CCC ( LPBYTE x )で、
x[0]='a';
x[1]='b';
みたいなことをするなら
x[n]のnはいくつまで使用可能か分かっている上で行わないといけません。
バイト数が増える可能性があるなら
AAA::CCC ( LPBYTE x )では無理ですね。
AAA::CCC ( BYTE** x )にした場合
x = new BYTE[増やしたサイズ];
とすると、もともとのxは
- 解放してはいけない
- freeしなければいけない
- deleteしなければいけない
のどれなのか不明である。
それと
大本のCString str;のstrは変わらないので
AAA::BBB( BYTE** x )も変えて
・・・
あーメンドクセ
AAA::BBB( std::vector<BYTE>& x );
AAA::CCC( std::vector<BYTE>& x );
こうしちゃえよ。
でも、これで上手く行くのかは知りません。
C/C++の文字列って面倒だな。
chamaroさん、ご指摘ありがとうございます。
勉強不足で、現状の動きをおいかけるのがやっとの状態のため
そこまで気がまわっていませんでした。
もう少し、他の方の回答も参考に見直しをしてみます。
wclrp ( 'o')さん、めんどくさいことをありがとうございます。
なかなかやっかいそうですね。。
教えていただいた方法を試しつつ、
他の手段がないかを検討してみます。
ひとまず、解決済みとします。
ありがとうございました。
時間がゆるすなら、一度今の作業をストップさせて、
「ポインタ」を勉強したほうがいいと思う
まず
「LPBYTE型の文字列」
これがおかしい。
かなり大雑把にすすめますが
LPBYTE型は、扱いたいデータ本体ではなく、
データが保持されている場所を示すものです。
+さんの書かれた例でいえば
BYTE ch[] = abcd; ←このchが文字列の本体。
LPBYTE x = ch ; ←chが保存されている場所を示す情報をxに入れておくだけ
つまり、
x自体が[abcd]を持ってるわけじゃないし、
chのサイズやその生存期間を、xからは管理できない。
開放などして、chがなくなってしまったりすると、
xの値が入ったままだとしても、その情報は意味が無くなります。
例えて書くと
abcd 住人
ch[] 家そのもの
x 住所
こんな感じ
んでもって
==============================
AAA::BBB( LPBYTE x ) { //この時点でxに文字が入っている
CCC ( x );
}
AAA::CCC ( LPBYTE x ) {
xの文字を操作し、変更した内容でxに入れてあげる
}
==============================
これだが、
まず、CCC(LPBYTE x)のxは、CCC内だけで通じるローカルの変数でしかなく、
BBBのxとは別物です(CCCのほうをyに変えても成立するでしょ)。
BBBから呼ばれるときに、「住所情報」を貰ってるだけです
その上で、CCC内でxに何かの値を上書きするということは
「別の住所」が上書きされるということになります。
ここでは「住所情報」が失われるだけで大元の文字列はなんら変更されないのです。
ウォッチなどをみると、xは「新しく上書きされた別の住所」
を示しますから、CCC内のxでは情報が更新されてみえますが、
BBBに戻ったとき、BBBのxが指し示す住所は変わってないため、
値が戻ったように見えるのです
で、最後に
wclrp ( 'o')さんが書かれているのが
「xが指し示す大元のデータにアクセスする」方法。
これをつかえば、大元のデータが変更できます。
#間違いがあったら指摘お願いいたします
自分ならきっとこんな実装するだろう。
つまり、BBB関数のへ入る前と後では、xは別物にする。
//この時点でxに文字が入っている
⇒xは誰かがnewしてるハズと(勝手に)仮定ww
void AAA::BBB( LPBYTE x )
{
x = CCC ( &x );
}
LPBYTE AAA::CCC ( LPBYTE *tmp )
{
//xの文字を操作し、変更した内容でxに入れてあげる
⇒ってことは文字の長さが短くなるのかな?まぁいいや
・
(略)
・
int newLength = strlen( 新しい文字 );
PBYTE ret = new BYTE [newLength];
memcpy( ret , 新しい文字 , newLength );
delete [] *tmp;//仮定が外れてるならキケンな香りww
return ret;
}