
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です。
解決方法、原因、アドバイスなど分かりましたらよろしくお願いします。
No.1ベストアンサー
- 回答日時:
「ベクターへの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);
では見えないし有効でもありません.
>で定義した 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]=='>'){}の部分でほかのブロックからも可視になるように(グローバル変数?)ベクターを作ってやれば
よさそうです。
ありがとうございました。
No.3
- 回答日時:
このプログラムにおいてポインタを使う意味はほとんどありません. 特に, '>' で始まる行の処理のうち
//'/'で始まる行を格納しておくベクター領域の作成
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);
とすればいい.
いろいろとアドバイスありがとうございました。
問題のプログラムは、結局スコープに気をつけつつ、構造体のベクターをつくり、構造体を毎回指定して呼び出すことで解決しました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# このプログラミング誰か教えてください 9 2022/04/22 18:50
- C言語・C++・C# このプログラミング誰か教えてください。 2 2022/04/22 18:48
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- Excel(エクセル) エクセル VBA For Next 繰り返しの書き方を教えてください 6 2022/09/01 14:11
- C言語・C++・C# C++プログラミングコードにポリモーフィズムを取り入れ方を教えてください。 2 2023/06/09 11:17
- C言語・C++・C# C++初心者です stirng 2 2022/09/20 20:43
- C言語・C++・C# プログラムが書けません。 4 2023/01/22 22:57
- CGI perlで書いたcgiでsqliteの使い方を教えてください 2 2023/05/08 21:29
- C言語・C++・C# このプログラミング誰か教えてくれませんか 3 2022/05/13 17:27
- C言語・C++・C# このプログラミング誰か教えてくれませんか 2 2022/05/14 09:45
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
string→CStringの型変換について
-
strtokでの空文字への置き換え
-
C#での関数テーブルの作り方
-
C言語単方向リストのメモリリー...
-
C++/CLI 関数がインポートでき...
-
C# JSONについて
-
C#でIPアドレスの取得について
-
c#で(",")区切りのcsvファイル...
-
特定の文字列が一致する行から...
-
jap実行時のTomcatのエラーに困...
-
2つのリストのマージ方法について
-
GDI+ DrawString() で指定範囲...
-
Javaで文字と数字が混ざったも...
-
動的配列が存在(要素が有る)か...
-
System.err. printlnとSystem.o...
-
C言語のポインターに関する警告
-
ORA-01858: 数値を指定する箇所...
-
一定のスペースを空けて端を揃...
-
ループ処理の際、最後だけ","を...
-
配列で、値の入っている要素数...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C# ListBoxのアイテムをユーザ...
-
C#でIPアドレスの取得について
-
string→CStringの型変換について
-
「指定されたキャストは有効で...
-
【Java8以降】csvファイルの複...
-
jap実行時のTomcatのエラーに困...
-
特定の文字列が一致する行から...
-
C#での関数テーブルの作り方
-
PHPのSHA256変換について
-
Delphiで改行文字の置換がうま...
-
GDI+ DrawString() で指定範囲...
-
strcmp関数などでの複数の文字...
-
C# 他のアプリケーションから複...
-
c#で(",")区切りのcsvファイル...
-
SQLインジェクション
-
ArrayListを改良したい
-
HTML文書の文字コードの判定法
-
phpマニュアルの見方
-
2つのリストのマージ方法について
-
strncpy後のatoiがおかしい
おすすめ情報