お世話になります。
void foo()
{
char* pchr;
CString CSt;
CSt = "44EEB262";
pchr = foo1( CSt );
.
.
}
char* foo1( CString CSt )
{
char* p = new char[ CSt.GetLength() ];
.
.
return p;
}
文字列長が不定の引数を扱う関数foo1()を作りたいんですが、
上のコードでは動的変数pがdeleteできないのでエラーになリます。
char* pchr = new char[ CSt.GetLength()];
void foo1( CString CSt, char* pchr )
{
.
.
}
delete pchr;
こうすれば良いのでしょうが、文字列長を気にしないで使えるような関数foo1()は
できないものでのでしょうか?
下のchar* pchrの替わりにvectorを使う手も有ると思いますが、vectorでは大げさすぎるので
それ以外の方法で
よろしく、お願い致します。
new[]で配列を確保したなら、使用後にどこかでdelete[]で削除する処理を書
くしかありません。
new, deleteのメモリ管理を隠したいなら、可変長文字列のクラスを定義する
ことになるでしょう。
しかし、可変長文字列ならCStringをそのまま使うか、std::stringを使えば
事足ります。
あえて複雑な処理をしようとする意図が良く分かりません。
> char* pchr = new char[ CSt.GetLength()];
-- snip --
> delete pchr;
既にiijimaさんもご指摘済みですが、この処理はバグってますね。
私なら、std::stringを使います。そのために用意されたクラスですから。
以下、想定しうる代案。
boost::shared_array<char> foo();
これなら、呼び元でdeleteしなくてもchar配列は自動破棄されます。
ただし、std::stringの方が適切な用途だと思いますし、意図がわからないのは同様です。
そもそも、CStringのGetLengthは文字数を返すはずです。
char *p = new char[CString.GetLength]とすると、
最後に付与すべき'\0'の領域が無い為にdeleteエラーを起こすはず
です。また、2バイト文字が入っている場合にもメモリ
確保領域が足りなくなるはず(GetLengthが文字数なので)なので
deleteエラーを起こすはずです。
2バイト文字は入る事を考慮するならメモリ確保は最大で
char *p = new char[CString.GetLength() * 2 + 1];
とすべきなのでは?間違っていたら職者の方フォローよろしくです。
> char *p = new char[CString.GetLength]とすると、
> 最後に付与すべき'\0'の領域が無い為にdeleteエラーを起こすはず
このpにCStringの内容をコピーするだなんて、元発言には一言も書いてありません。
なのでその指摘は「勇み足」
> また、2バイト文字が入っている場合にもメモリ
> 確保領域が足りなくなるはず(GetLengthが文字数なので)なので
マルチバイトの場合8bit単位でカウントするので大丈夫です。
みなさま、ご回答いただきありがとうございました。
std::stringと言うのが有るんですね。
初めて、知りましたので勉強して見ます。
それと、foo1()の中で、余裕を見た文字配列chr[256]を宣言定義し
必要な文字列+1を\n処理し、chrを返した場合はどのような結果に
なるんでしょうか?
foo1()は終了しているのでスコープとしては、見えないと思いますが、
ポインタで見れば、そのアドレスの内容が書き替えられる前なら
データは拾えるものなのでしょうか?
やはり、こう言うのは邪道でしょうか?
いままで、ポインタをなるべく使わないようにしてましたので、
どうも知識があやふやですので、的を射た質問ではないかと思いますが
よろしくお願いいたします。
> それと、foo1()の中で、余裕を見た文字配列chr[256]を宣言定義し
> 必要な文字列+1を\n処理し、chrを返した場合はどのような結果に
> なるんでしょうか?
char* foo1() {
char result[256];
...
return result;
}
こんなやつ?
やってはいけません。ローカル変数のポインタを返してはなりません。
なので「結果どうなるか」を語るのは無意味です。
> いままで、ポインタをなるべく使わないようにしてましたので、
それが正解。これからもなるべく使わないように。
# ただでさえポインタを使わざるを得ないシチュエーションがあるのだから
# それ以上に使うのはトラブルの元。
> std::stringと言うのが有るんですね。
> 初めて、知りましたので勉強して見ます。
それが吉^^
納得できました。
std::stringを使う方向で勉強いたします。
どうも、ありがとうございました。
>std::stringを使う方向で勉強いたします。
なんで CString のままじゃダメなんだろうと思ふ。
char*型にキャストできないからという理由から?(std::stringもできなかったような。。。)
上記の理由であれば、
GetBufferやGetBufferSetLength,もしくは場合によってはconst_castでもいいような気がするんだけど。
その手の類似スレ)
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200606/06060020.txt
え〜、まだstd::stringの勉強してませんので、Blueさんの疑問が良く分かりません
とりあえず、もともと、テキストボックスの16進0からFを2文字づつとりだして
1文字のcharにしたかった
テキストボックスのメンバ変数をCStringにしていただけのことなんです。
その後、テキストボックスの文字列を全部引数で渡して、char文字配列で返せないか
と思って、この質問になりました。
可変長のデータを引数にして、処理結果の可変データを返す関数を作る場合、
何か常套句があるんじゃないかと思ったしだいです。
で、std::stringを教えていただいたので、勉強してみようと思うんですが、
この方向であってますでしょうか?
CStringとstd::stringは、どちらも文字列のクラスです。
CStringはマイクロソフト社が定義したもので、std::stringはC++言語の標準
ライブラリで定義されているものです。
どちらを使うかは自由です。
最初に掲げられたコードでCStringクラスが使われているので、そのままCStringクラスだけで全て処理しても良いのに、というのがBlueさんの疑問だ
と思います。
私の最初の投稿でも、CStringまたはstd::stringで事足りることを指摘しま
した。
今回の場合はどちらを使ってもおそらくたいした違いはないと思いますが、
std::stringはVC++以外の環境でも使えますので、この機会に勉強しておいて
損はありません。
やっと、おぼろげに分かってきました。
とりあえず、std::stringを勉強してみます
ありがとうございました。
ツイート | ![]() |