アプリ版:「スタンプのみでお礼する」機能のリリースについて

boostスマートポインタ(shared_ptr)を使用した、簡単なファイルの読み込みとループ処理で困っています。
以下に示すような、テキストファイルから情報を読み取って構造体のvectorをつくる処理をshared_ptrを使って行おうとしています。

input.txt--

>Taro
/boy
/8 years old

>Hanako
/girl
/6 years old
/likes candy
-----

このファイルの'>'で始まる行は'名前'として、それ以外の '/ 'で始まる行はvectorに入れて、このふたつを個人ごとにまとめて構造体として管理するという形をとりたいと考えています。
つまり構造体の要素は <名前の行> <それ以外の行が入ったベクター> となります。
ファイル読み込みの過程で '>' を認識したらこれらのメモリ領域を確保し、shared_ptrで管理したいと考えています。
出来た構造体をベクターに入れ、ファイル読み込みのあとに出力する、という形でプログラムを以下のように書きました。 

#include <string>
#include <fstream>
#include <iostream>
#include <boost/shared_ptr.hpp>
using namespace std;

//構造体定義 
struct my_struct{
std::string name;   
std::vector<std::string> vector_of_string; 

} ;

int main(void){

std::ifstream ifs("input.txt");
//構造体を入れるベクター
std::vector<my_struct>vector_of_my_struct;
std::string buf;
boost::shared_ptr<my_struct>SMARTptr_my_struct(new my_struct);
boost::shared_ptr<vector<string>> SMARTptr_vector_of_string(new vector<string>);

while(ifs && std::getline(ifs, buf)) {

if(buf[0] == '>'){  

//構造体の領域を作成
boost::shared_ptr<my_struct>SMARTptr_my_struct(new my_struct);

//'/'で始まる行を格納しておくベクター領域の作成
boost::shared_ptr<vector<string>> SMARTptr_vector_of_string(new vector<string>);
//構造体に作成されたベクターを入れる
(*SMARTptr_my_struct).vector_of_string = *SMARTptr_vector_of_string;
//構造体にこの行ををnameとして入れる
(*SMARTptr_my_struct).name = buf;

//ここで新たに作られた構造体をベクターに入れる
vector_of_my_struct.push_back(*SMARTptr_my_struct);
}


if(buf[0] == '/'){

//この行をstring格納用のベクター(if(buf[0]=='>') ですでに作られている)に入れる
(*SMARTptr_vector_of_string).push_back(buf);
}

この後、構造体のベクターのループから情報を出力しますが字数制限のため省略させていただきます。
input.txtと同じ内容が出力されることを期待したのですが、実際は'>'で始まる名前の行しか出力されません。 どうやらベクターへのpush_backができていないか、そもそもshared_ptrの扱いに根本的な間違いがあるのでは?と思っているのですが、原因がわかりません。環境はVC++2008 express edition, boost 1.38です。
解決方法、原因、アドバイスなど分かりましたらよろしくお願いします。

A 回答 (3件)

「ベクターへのpush_back」はできていますし, 「shared_ptrの扱いに根本的な間違いがある」わけでもありません. はっきりいえば, 「それ以前の問題」です.



本質的には
int a, *b;
b = new int;
*b = 5;
a = *b;
*b = 4;
としたときに「a と *b が同じ値にならない」と悩んでいるのと同じです.

あと, いろんなところで「同じ名前の変数」を定義しているので, その結果として「どの変数がどこで可視なのか」が混乱しているようにも見えます.
//'/'で始まる行を格納しておくベクター領域の作成
boost::shared_ptr<vector<string>> SMARTptr_vector_of_string(new vector<string>);
で定義した SMARTptr_vector_of_string は,
//この行をstring格納用のベクター(if(buf[0]=='>') ですでに作られている)に入れる
(*SMARTptr_vector_of_string).push_back(buf);
では見えないし有効でもありません.
    • good
    • 0
この回答へのお礼

>で定義した SMARTptr_vector_of_string は,
>//この行をstring格納用のベクター(if(buf[0]=='>') ですでに作られている)に入れる
>(*SMARTptr_vector_of_string).push_back(buf);
>では見えないし有効でもありません.

(if(buf[0]=='/'){}のブロックのpush_backは (if(buf[0]=='>'){}で作ったベクターではなく、
whileループの外側ではじめにつくっていたベクターに入れられていたわけですね。で、(if(buf[0]=='>'){}
のブロックのベクターには何も入れられていないので出力がないということのようです。
スコープが全く理解できていなかったようです。
(if(buf[0]=='>'){}の部分でほかのブロックからも可視になるように(グローバル変数?)ベクターを作ってやれば
よさそうです。

ありがとうございました。

お礼日時:2010/06/16 23:26

このプログラムにおいてポインタを使う意味はほとんどありません. 特に, '>' で始まる行の処理のうち


//'/'で始まる行を格納しておくベクター領域の作成
boost::shared_ptr<vector<string>> SMARTptr_vector_of_string(new vector<string>);
//構造体に作成されたベクターを入れる
(*SMARTptr_my_struct).vector_of_string = *SMARTptr_vector_of_string;
の部分は完全に無意味で, ない方がよほどましです.

もうちょっというと
//構造体の領域を作成
boost::shared_ptr<my_struct>SMARTptr_my_struct(new my_struct);
の部分も有効ではありません. ベクタを
vector<boost::shared_ptr<my_struct> >
で定義していればいいのですが, 現状では「ポインタとしての値」を代入してなんかするということがないので shared_ptr を使う必然性がありません. むしろ
my_struct *ptr_my_struct = new my_struct;
なら「まだ」わからなくもないです... が, 「まだ」レベルであってやはり意味があるとは思えないなぁ.

'>' で始まる行の処理はもっと単純に
my_struct theStruct;
theStruct.name = buf;
vector_of_my_struct.push_back(theStruct);
で終わらせて, '/' で始まる行に対しては
vector_of_my_struct.rbegin()->vector_of_string.push_back(buf);
とすればいい.
    • good
    • 0
この回答へのお礼

いろいろとアドバイスありがとうございました。
問題のプログラムは、結局スコープに気をつけつつ、構造体のベクターをつくり、構造体を毎回指定して呼び出すことで解決しました。

お礼日時:2010/06/19 09:09

それほど単純じゃないですよ~. #1 の前半が何をさしているのか, 理解できていますか~?

この回答への補足

やはりポインタの振る舞いやスコープの理解が決定的に不足していることを痛感しました。自分のコーディングが悪い、というのは分かってきたのですが、それでどう書けばいいというのが思いつきません。
一から勉強して出直してきますと言うべきところなのですが、「こうした方がいい」というような方法、方向性だけでも教えていただけないでしょうか。

補足日時:2010/06/17 01:59
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!