構造体のメンバにCStringを使用する方法 – 固定ページ 2 – プログラミング – Home

構造体のメンバにCStringを使用す...
 
通知
すべてクリア

[解決済] 構造体のメンバにCStringを使用する方法

固定ページ 2 / 2

チョーヤ
 チョーヤ
(@チョーヤ)
ゲスト
結合: 18年前
投稿: 5
 

επιστημηさん。

>「pccc++ する意味がなくなる」だけじゃね?
おお、その通りです。

ぴかりんさん、すみませんうそ書きました。
私の発言は無視してください。m(__)m


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

うーん、C++言語の勉強をちゃんとした方が良いのではと言う気が・・・。

newを使わないとコンスタラクタが動かないとかこの辺は入門書にも
書いてある話なので、一足飛びに使おうとしないで基礎を一通り勉強
されたほうが良いと思いますよ。

あと、ステップ・バイ・ステップで進めていくつもりなら
ソースを書くときもそれを考慮して書かないとへんな所ではまります。
今回の例から行くと複数の配列確保をどうするのかまで
考えきれて無いのにループにしてしまっている時点で既に問題かと。


返信引用
ぴかりん
 ぴかりん
(@ぴかりん)
ゲスト
結合: 18年前
投稿: 5
Topic starter  

みなさん 色々なご指摘ありがとうございます

もう一度基礎から見直してみることにします

ありがとうございました


返信引用
bbbb
 bbbb
(@bbbb)
ゲスト
結合: 18年前
投稿: 8
 

これってこういうことじゃ?

typedef struct{
CString AAA;
CString BBB;
}CCC;

--------------------------------
void ddd()
{
ccc* pccc;

while(1)
{
pccc = (CCC*)malloc(sizeof(CCC));

pccc->AAA = new CString();
pccc->AAA = 1234
pccc++;

}
追加終わったら
delete pccc->AAA
free(pccc );

}


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

>これってこういうことじゃ?
>pccc->AAA = new CString();
AAA は CString*型でないですよ。


返信引用
Ban
 Ban
(@ban)
Prominent Member
結合: 5年前
投稿: 776
 

仮に、AAAがCString*型でも、今度はこっちがバグってますし。
pccc->AAA = 1234
ポインタの参照先を直接書き換えてるだけで、CString::operator =は動かない。

# 配置newとか駆使してごにょごにょとか考えるよりは、
# 素直にstd::vectorやC~Arrayの類を使うことを考えるという方向でよいと思います。


返信引用
Ban
 Ban
(@ban)
Prominent Member
結合: 5年前
投稿: 776
 

> ポインタの参照先を直接書き換えてるだけで
# 書き換えも無理やりキャストが必要。


返信引用
bbbb
 bbbb
(@bbbb)
ゲスト
結合: 18年前
投稿: 8
 

失礼。ではこれではだめですか?

typedef struct{
CString* AAA;
CString* BBB;
}CCC;

--------------------------------
void ddd()
{
ccc* pccc;

while(1)
{
pccc = (CCC*)malloc(sizeof(CCC));

pccc->AAA = new CString();
*pccc->AAA = 1234
pccc++;

}
追加終わったら
delete pccc->AAA
free(pccc );


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

これならばOKですが、
元からCStringでもったCCCをmallocせず、newすればいいだけなのであまり意味ないので
は?
(いちいちmallocしてnewする意味あるのかなぁと)


返信引用
Ban
 Ban
(@ban)
Prominent Member
結合: 5年前
投稿: 776
 

ループの中でpcccを更新してしまったら、ループの後にいくら解放処理を書いても、
delete pccc->AAA
free(pccc );
最後のpcccしか解放できず他は全部リークすると思いますが。

> 動的配列使ったほうがよさげ。
> そうすればポインタなんて関係ないかと。

PODが必要ならCStringは諦めるしかないし、
Blueさんの提案どおりにこうにしない理由がよくわからず。

# 配置newってのは最後の手段だと思う…。


返信引用
bbbb
 bbbb
(@bbbb)
ゲスト
結合: 18年前
投稿: 8
 

最終的にはこんな感じで使いたいわけではなく?

typedef struct{
CString* StrAdress;
CString* StrParent;
CString* StrName;
HTREEITEM item;
BOOL bRet;
}S_VIEW_DATA;

typedef struct{
S_VIEW_DATA* pdata;
long count;
}S_VIEW;
//********************************************************************
//
//
//
//
********************************************************************
void CTabDlg::InPutFile(CString StrFileName)
{
//変数定義
S_VIEW s_view;
CString StrLine;
CString StrTemp;
long i,j;
long pos;
long setCount;
CStdioFile file;
CString StrAdress;
CString StrParent;
CString StrName;

//初期化処理
s_view.count = 0;
setCount = 0;

//----------------------------------
// 表示項目全削除
//----------------------------------
m_tree.DeleteAllItems();

//----------------------------------
// ファイル読み出し
//----------------------------------
file.Open(StrFileName,CFile::modeRead);

//----------------------------------
// 項目数取得
//----------------------------------
while(1)
{
file.ReadString(StrLine);
if(StrLine != ")
{
s_view.count++;
}
else
{
break;
}
}
file.Seek(0,0);

//----------------------------------
// データ領域取得
//----------------------------------
s_view.pdata = (S_VIEW_DATA*)malloc(sizeof(S_VIEW_DATA) *
s_view.count);

//----------------------------------
// データの読み取り
//----------------------------------
for(i = 0; i < s_view.count; i++)
{
s_view.pdata[i].StrAdress = new CString();
s_view.pdata[i].StrParent = new CString();
s_view.pdata[i].StrName = new CString();
s_view.pdata[i].bRet = FALSE;
file.ReadString(StrLine);

//1つ目
pos = StrLine.Find(,,0);
StrAdress = StrLine.Left(pos);
*s_view.pdata[i].StrAdress = StrAdress;
StrLine.Delete(0,pos+1);

//2つ目
pos = StrLine.Find(,,0);
StrParent = StrLine.Left(pos);
*s_view.pdata[i].StrParent = StrParent;
StrLine.Delete(0,pos+1);

//3つ目
StrName = StrLine.Left(StrLine.GetLength());
*s_view.pdata[i].StrName = StrName;
}

//----------------------------------
// 先頭ノードの設定
//----------------------------------
for(i = 0; i < s_view.count; i++)
{
if(*s_view.pdata[i].StrParent == 0x00000000)
{
s_view.pdata[i].item = m_tree.InsertItem
(*s_view.pdata[i].StrName,TVI_ROOT);
setCount++;
}
}
if(setCount != s_view.count)
{
while(1)
{
//--------------------------
// 子供ノードの設定
//--------------------------
for(i = 0; i < s_view.count; i++)
{
for(j = 0; j < s_view.count; j++)
{
if(*s_view.pdata[j].StrParent ==
*s_view.pdata[i].StrAdress)
{
s_view.pdata[j].item =
m_tree.InsertItem(*s_view.pdata[j].StrName,s_view.pdata[i].item);
setCount++;
if(setCount ==
s_view.count)
{
break;
}
}
}
}
if(setCount == s_view.count)
{
break;
}
}
}
//----------------------------------
// 領域開放
//----------------------------------
for(i = 0; i < s_view.count; i++)
{
delete s_view.pdata[i].StrAdress;
delete s_view.pdata[i].StrParent;
delete s_view.pdata[i].StrName;
}
free(s_view.pdata);
file.Close();

}


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

ですから、元からnewすれば構造体のメンバをポインタにする必要もないのですが。

struct S_VIEW_DATA
{
CString StrAdress;
CString StrParent;
CString StrName;
HTREEITEM item;
BOOL bRet;
};

//----------------------------------
// データ領域取得
//----------------------------------
s_view.pdata = new S_VIEW_DATA[s_view.count];

//----------------------------------
// 領域開放
//----------------------------------
delete [] s_view.pdata;

んでもって、MFCならCArray<S_VIEW_DATA, S_VIEW_DATA>を使うと便利。
(これなら前もってサイズを求めるために2度ファイルを読む必要がない)


返信引用
bbbb
 bbbb
(@bbbb)
ゲスト
結合: 18年前
投稿: 8
 

そうなんですか?
それは知りませんでした。
ありがとうございます。


返信引用
menba-
 menba-
(@menba-)
ゲスト
結合: 18年前
投稿: 1
 

そんな使い方があったとは、知りませんでした。


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

返信する

投稿者名

投稿者メールアドレス

タイトル *

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