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

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

A 回答 (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;
}
    • good
    • 0
この回答へのお礼

具体的なコードを書いていただいて、非常にありがたいです。

ですが、Debug Errorで
Run-time Check Failure #3 - the variable 'ptr_eachvector' is being used without being initialized.

となってしまうようです。
VC++環境特異的な問題でしょうか??

お礼日時:2009/02/09 06:45

少し、手直しをして、サンプル作ってみました。



----------------------------------------------------------------------
#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の使い方がわからないと言う
事でもないでしょうしね・・・

アルゴリズムとデータ構造から見直す習慣を付けると良いのではないでしょうか。
    • good
    • 0
この回答へのお礼

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

お礼日時:2009/02/10 05:08

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

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

お礼日時:2009/02/10 06:37

> ですが、、そのあとイテレータを使って


> 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:  }
----------------------------------------------------------------------
と言う感じの動作になります。
    • good
    • 0
この回答へのお礼

>each_vector = *ptr_eachvector ; // 空のvector<string>をeach_vector に複製している。(ここで、each_vectorは空になる)
その部分は自分でも怪しいと思っていた部分でした。
ここが問題のようですね。

each_vectorの定義とnewに関して全く理解不足だったようです。もしよろしければ 正解のコード または参考になるサイトなど教えていただけないでしょうか。

お礼日時:2009/02/09 01:55

う~ん,,,,


「vector のポインタの vector」を使う理由がわからん.... vector の vector ではいけない理由があるんだろうか.
    • good
    • 0
この回答へのお礼

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

お礼日時:2009/02/09 01:59

 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;
 }
    • good
    • 0
この回答へのお礼

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

お礼日時:2009/02/09 01:00

まずは、コンパイルエラーの対応から、



//   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>のイテレータは取れません。

他にも、あやしいコーディングがあるような気がしますが、
各個、対応してみてください。
    • good
    • 0
この回答へのお礼

ありがとうございます。
(*it_b)->begin();
かっこで囲まなければいけなかったのですね。
おかげでエラーは出なくなりました。

ですが、、そのあとイテレータを使って
cout << *it_c << endl;
としているのですが、何も出力されません。

これはまた別の原因がありそうです。。。。

お礼日時:2009/02/09 00:56

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