• ベストアンサー

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の領域確保の方法も怪しいという感じがします。 解決策、アドバイスありましたらよろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.5

#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; }

hydrozoa
質問者

お礼

具体的なコードを書いていただいて、非常にありがたいです。 ですが、Debug Errorで Run-time Check Failure #3 - the variable 'ptr_eachvector' is being used without being initialized. となってしまうようです。 VC++環境特異的な問題でしょうか??

その他の回答 (6)

  • Yanch
  • ベストアンサー率50% (114/225)
回答No.7

少し、手直しをして、サンプル作ってみました。 ---------------------------------------------------------------------- #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の使い方がわからないと言う 事でもないでしょうしね・・・ アルゴリズムとデータ構造から見直す習慣を付けると良いのではないでしょうか。

hydrozoa
質問者

お礼

コードを書いていただきありがとうございました。 こちらの環境で正しく動きました。 また bool boFirstuse = true; の使い方なども非常に参考になりました。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.6

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) ;  } という感じになる, かな. いくつかの仮定ができればもうちょっと簡単になるけど....

hydrozoa
質問者

お礼

ありがとうございました。 こちらの環境でビルド、実行で確認ができました。 if の条件の書き方なども参考になりました。

  • Yanch
  • ベストアンサー率50% (114/225)
回答No.4

> ですが、、そのあとイテレータを使って > 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:  } ---------------------------------------------------------------------- と言う感じの動作になります。

hydrozoa
質問者

お礼

>each_vector = *ptr_eachvector ; // 空のvector<string>をeach_vector に複製している。(ここで、each_vectorは空になる) その部分は自分でも怪しいと思っていた部分でした。 ここが問題のようですね。 each_vectorの定義とnewに関して全く理解不足だったようです。もしよろしければ 正解のコード または参考になるサイトなど教えていただけないでしょうか。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

う~ん,,,, 「vector のポインタの vector」を使う理由がわからん.... vector の vector ではいけない理由があるんだろうか.

hydrozoa
質問者

お礼

>vector の vector ではいけない理由があるんだろうか. vectorのvectorという発想はありませんでした。そういう方法でも試してみようと思います。

回答No.2

 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;  }

hydrozoa
質問者

お礼

具体的なコードありがとうございます。 エラーは出なくなりました。 しかし、 cout << *it_c << endl; の部分による出力がなにもされません。これはeach_vectorを作るあたりに問題があるのでしょうか???

  • Yanch
  • ベストアンサー率50% (114/225)
回答No.1

まずは、コンパイルエラーの対応から、 //   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>のイテレータは取れません。 他にも、あやしいコーディングがあるような気がしますが、 各個、対応してみてください。

hydrozoa
質問者

お礼

ありがとうございます。 (*it_b)->begin(); かっこで囲まなければいけなかったのですね。 おかげでエラーは出なくなりました。 ですが、、そのあとイテレータを使って cout << *it_c << endl; としているのですが、何も出力されません。 これはまた別の原因がありそうです。。。。

関連するQ&A