- ベストアンサー
Vectorのポインタが入ったvector
windows Vista sp1, Visual C++ 2008でC++の勉強をしています。 Vectorへのポインタが入ったvectorを使うプログラムを書いているのですがうまくいかず、困っています。 どういうプログラムかというと、 入力ファイルの">"という記号を区切りとして、その間にある各行をひとまとめのグループとしてvectorにいれます。 さらに各vectorのポインタをべつのvectorに入れます。 最終的に区切りの数だけvectorができ、入力ファイルを読み終わった後に すべてのvectorを"各グループのポインタが入ったvector"からループ処理ですべて出力する、というものです。 /入力ファイル input.txt/ > human cat dog > beetle dragonfly spider > salmon saury catfish > vector1には human cat dog vector2にはbeetle dragonfly spider vector3にはsalmon saury catfish が入り、 別のvectorにそれぞれのvectorのポインタをいれ、 最後にこのvectorをつかって全ファイル内容を出力するというものです。 具体的に書くと、 ">"の区切りごとの各行のstringを入れるvectorとしてeach_vector。 each_vectorのポインタを入れるvectorをvector_of_ptr_each_vectorとします。 ">"を認識するごとに new で each_vectorの領域を確保し、そのポインタをvector_of_ptr_each_vectorに追加していき、">"のない行のstringを each_vectorに入れます。 ファイルの読み込みが終わった後でvector_of_ptr_each_vectorからイテレータを使って各vector(each_vector)の全要素をそれぞれ出力する、というものです。 以下のようにコードを書きました。 #include <fstream> #include <string> #include <vector> #include <iostream> using namespace std; int main( ) { ifstream ifs("input.txt"); string buf; std::vector<string> each_vector; std::vector<std::vector<string> *> vector_of_ptr_each_vector; while(ifs && getline(ifs, buf)) { if(buf[0] == '>'){ std::vector<string>* ptr_eachvector ; ptr_eachvector = new std::vector<string>; each_vector = *ptr_eachvector ; vector_of_ptr_each_vector.push_back(ptr_eachvector) ; } each_vector.push_back(buf) ; } printf("\n output from vector of ptr of vector\n"); std::vector<std::vector<string> *>::iterator it_b = vector_of_ptr_each_vector.begin(); while( it_b != vector_of_ptr_each_vector.end() ) { std::vector<string>::iterator it_c = it_b->begin(); //エラー1 while( it_c != it_b->end() ) //エラー2 { cout << *it_c << endl; ++it_c; } ++it_b; } return 0; } ですが、エラーでビルドされず、 std::vector<string>::iterator it_c = it_b->begin(); の行に関して error C2839: invalid return type 'std::vector<_Ty> **' for overloaded 'operator ->' error C2039: 'begin' : is not a member of 'std::_Vector_iterator<_Ty,_Alloc>' while( it_c != it_b->end() ) の行に関して error C2839: invalid return type 'std::vector<_Ty> **' for overloaded 'operator ->' 1> with 1> [ 1> _Ty=std::string 1> ] error C2039: 'end' : is not a member of 'std::_Vector_iterator<_Ty,_Alloc>' 1> with 1> [ 1> _Ty=std::vector<std::string> , 1> _Alloc=std::allocator<std::vector<std::string> > 1> ] fatal error C1903: unable to recover from previous error(s); stopping compilation というようなエラーが出ます。 vectorのポインタを入れたvectorの扱い、特にイテレータに関して問題があると思うのですが原因が分かりません。 また、new でのeach_vectorの領域確保の方法も怪しいという感じがします。 解決策、アドバイスありましたらよろしくお願いします。
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
#include <fstream> #include <string> #include <vector> #include <iostream> using namespace std; int main() { ifstream ifs("input.txt"); string buf; std::vector<std::vector<string> *> vector_of_ptr_each_vector; while(ifs && getline(ifs, buf)) { std::vector<string>* ptr_eachvector ; if(buf[0] == '>'){ ptr_eachvector = new std::vector<string>; vector_of_ptr_each_vector.push_back(ptr_eachvector) ; } else { ptr_eachvector->push_back(buf) ; } } cout << "\n output from vector of ptr of vector\n"; std::vector<std::vector<string> *>::iterator it_b = vector_of_ptr_each_vector.begin(); while( it_b != vector_of_ptr_each_vector.end() ) { std::vector<string>::iterator it_c = (*it_b)->begin(); while( it_c != (*it_b)->end() ) { cout << '[' << *it_c << "] "; ++it_c; } cout << endl; ++it_b; } return 0; }
その他の回答 (6)
- Yanch
- ベストアンサー率50% (114/225)
少し、手直しをして、サンプル作ってみました。 ---------------------------------------------------------------------- #include <iostream> #include <fstream> #include <string> #include <vector> // using namespace std; int main() { std::ifstream ifs("input.txt"); std::string buf; // std::vector<string> each_vector; // std::vector<std::vector<string> *> vector_of_ptr_each_vector; std::vector< std::vector<std::string> > vector_of_string_vector; std::vector<std::string> string_vector; bool boFirstuse = true; while (ifs && std::getline(ifs, buf)) { if ((buf[0] == '>')) { // std::vector<string>* ptr_eachvector ; // ptr_eachvector = new std::vector<string>; // each_vector = *ptr_eachvector ; // vector_of_ptr_each_vector.push_back(ptr_eachvector) ; if (!boFirstuse) { vector_of_string_vector.push_back(string_vector); } else { boFirstuse = false; } string_vector.clear(); // } // each_vector.push_back(buf) ; } else { string_vector.push_back(std::string(buf)); } } printf("\n output from vector of ptr of vector\n"); // std::vector<std::vector<string> *>::iterator it_b = vector_of_ptr_each_vector.begin(); // while( it_b != vector_of_ptr_each_vector.end() ) // { // std::vector<string>::iterator it_c = (*it_b)->begin(); // while( it_c != (*it_b)->end() ) // { // cout << *it_c << endl; // ++it_c; // } // // ++it_b; // } std::vector< std::vector<std::string> >::iterator ite_a = vector_of_string_vector.begin(); int i = 0; while (ite_a != vector_of_string_vector.end()) { std::cout << "vector[" << i << "]:" << std::endl; std::vector<std::string>::iterator ite_b = ite_a->begin(); while (ite_b != ite_a->end()) { std::cout << *ite_b << std::endl; ite_b++; } ite_a++; i++; } return 0; } ---------------------------------------------------------------------- > each_vectorの定義とnewに関して全く理解不足だったようです。もしよろしければ 正解のコード または参考になるサイトなど教えていただけないでしょうか。 > vector の使い方を解説したウェブサイトなら、検索すれば いくつか見つかると思いますが、たぶん、vectorの使い方がわからないと言う 事でもないでしょうしね・・・ アルゴリズムとデータ構造から見直す習慣を付けると良いのではないでしょうか。
お礼
コードを書いていただきありがとうございました。 こちらの環境で正しく動きました。 また bool boFirstuse = true; の使い方なども非常に参考になりました。
- Tacosan
- ベストアンサー率23% (3656/15482)
ptr_eachvector の定義位置が間違ってる気がする>#5. あと, 最後のブロックが入らない気がする (これは元のコードも同じかな). たぶん, 最初の while ループ (+ 関連する変数の定義) は string buf; std::vector<std::vector<string> *> vector_of_ptr_each_vector; std::vector<string>* ptr_eachvector = 0; while(ifs && getline(ifs, buf)) { if(buf[0] == '>'){ if (ptr_eachvector) { vector_of_ptr_each_vector.push_back(ptr_eachvector) ; } ptr_eachvector = new std::vector<string>; } else if (ptr_eachvector) { ptr_eachvector->push_back(buf) ; } } if (ptr_eachvector) { vector_of_ptr_each_vector.push_back(ptr_eachvector) ; } という感じになる, かな. いくつかの仮定ができればもうちょっと簡単になるけど....
お礼
ありがとうございました。 こちらの環境でビルド、実行で確認ができました。 if の条件の書き方なども参考になりました。
- Yanch
- ベストアンサー率50% (114/225)
> ですが、、そのあとイテレータを使って > cout << *it_c << endl; > としているのですが、何も出力されません。 何も出力されない理由としては、何も*it_cに入っていないからなのですが、 問題は、データをvectorに入れている次のコードにあります。 (問題のコード) ---------------------------------------------------------------------- 15: while(ifs && getline(ifs, buf)) { 16: 17: if(buf[0] == '>'){ 18: std::vector<string>* ptr_eachvector ; 19: ptr_eachvector = new std::vector<string>; 20: each_vector = *ptr_eachvector ; 21: 22: vector_of_ptr_each_vector.push_back(ptr_eachvector) ; 23: } 24: 25: each_vector.push_back(buf) ; 26: } ---------------------------------------------------------------------- vectorコンテナの特徴をよく理解して、トレースすれば、明かなのですが、 ---------------------------------------------------------------------- 15: while(ifs && getline(ifs, buf)) { 16: 17: if(buf[0] == '>'){ 18: std::vector<string>* ptr_eachvector ; 19: ptr_eachvector = new std::vector<string>; // 空のvector<string>を作成している 20: each_vector = *ptr_eachvector ; // 空のvector<string>をeach_vector に複製している。(ここで、each_vectorは空になる) 21: 22: vector_of_ptr_each_vector.push_back(ptr_eachvector) ; // vector_of_ptr_each_vectorに空のvector<string>を追加 23: } 24: 25: each_vector.push_back(buf) ; // 空のeach_vectorにbufを追加。 26: } ---------------------------------------------------------------------- と言う感じの動作になります。
お礼
>each_vector = *ptr_eachvector ; // 空のvector<string>をeach_vector に複製している。(ここで、each_vectorは空になる) その部分は自分でも怪しいと思っていた部分でした。 ここが問題のようですね。 each_vectorの定義とnewに関して全く理解不足だったようです。もしよろしければ 正解のコード または参考になるサイトなど教えていただけないでしょうか。
- Tacosan
- ベストアンサー率23% (3656/15482)
う~ん,,,, 「vector のポインタの vector」を使う理由がわからん.... vector の vector ではいけない理由があるんだろうか.
お礼
>vector の vector ではいけない理由があるんだろうか. vectorのvectorという発想はありませんでした。そういう方法でも試してみようと思います。
- επιστημη(@episteme)
- ベストアンサー率46% (546/1184)
std::vector<std::vector<string> *>::iterator it_b = vector_of_ptr_each_vector.begin(); while( it_b != vector_of_ptr_each_vector.end() ) { std::vector<string>::iterator it_c = (*it_b)->begin(); while( it_c != (*it_b)->end() ) { cout << *it_c << endl; ++it_c; } ++it_b; }
お礼
具体的なコードありがとうございます。 エラーは出なくなりました。 しかし、 cout << *it_c << endl; の部分による出力がなにもされません。これはeach_vectorを作るあたりに問題があるのでしょうか???
- Yanch
- ベストアンサー率50% (114/225)
まずは、コンパイルエラーの対応から、 // std::vector<string>::iterator it_c = it_b->begin(); //エラー1 std::vector<string>::iterator it_c = (*it_b)->begin(); //エラー1 // while( it_c != *it_b->end() ) //エラー2 while( it_c != (*it_b)->end() ) //エラー2 (*it_b) が「std::vector<string> *」 ですから、 it_b->begin()では、std::vector<string>のイテレータは取れません。 他にも、あやしいコーディングがあるような気がしますが、 各個、対応してみてください。
お礼
ありがとうございます。 (*it_b)->begin(); かっこで囲まなければいけなかったのですね。 おかげでエラーは出なくなりました。 ですが、、そのあとイテレータを使って cout << *it_c << endl; としているのですが、何も出力されません。 これはまた別の原因がありそうです。。。。
お礼
具体的なコードを書いていただいて、非常にありがたいです。 ですが、Debug Errorで Run-time Check Failure #3 - the variable 'ptr_eachvector' is being used without being initialized. となってしまうようです。 VC++環境特異的な問題でしょうか??