5

As per request of the fantastic fellas over at the C++ chat lounge, what is a good way to break down a file (which in my case contains a string with roughly 100 lines, and about 10 words in each line) and insert all these words into a std::set?

4

3 に答える 3

25

一連の要素を保持するソースからコンテナを構築する最も簡単な方法は、イテレータのペアを取るコンストラクタを使用することです。istream_iteratorストリームを反復処理するために使用します。

#include <set>
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>

using namespace std;

int main()
{
  //I create an iterator that retrieves `string` objects from `cin`
  auto begin = istream_iterator<string>(cin);
  //I create an iterator that represents the end of a stream
  auto end = istream_iterator<string>();
  //and iterate over the file, and copy those elements into my `set`
  set<string> myset(begin, end);

  //this line copies the elements in the set to `cout`
  //I have this to verify that I did it all right
  copy(myset.begin(), myset.end(), ostream_iterator<string>(cout, "\n"));
  return 0;
}

http://ideone.com/iz1q0

于 2012-06-21T20:43:23.980 に答える
3

ファイルを文字列に読み取ったと仮定すると、boost::split がそのトリックを実行します。

#include <set>
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>

std::string astring = "abc 123 abc 123\ndef 456 def 456";  // your string
std::set<std::string> tokens;                              // this will receive the words
boost::split(tokens, astring, boost::is_any_of("\n "));    // split on space & newline

// Print the individual words
BOOST_FOREACH(std::string token, tokens){
    std::cout << "\n" << token << std::endl;
}

必要に応じて、セットの代わりにリストまたはベクトルを使用できます。

また、これはほとんどだまされていることに注意してください: C++ で文字列を分割しますか?

于 2012-06-26T16:07:49.383 に答える
2
#include <set>
#include <iostream>
#include <string>

int main()
{
  std::string temp, mystring;
  std::set<std::string> myset;

  while(std::getline(std::cin, temp))
      mystring += temp + ' ';
  temp = "";      

  for (size_t i = 0; i < mystring.length(); i++)
  {
    if (mystring.at(i) == ' ' || mystring.at(i) == '\n' || mystring.at(i) == '\t')
    {
      myset.insert(temp);
      temp = "";
    }
    else
    {
      temp.push_back(mystring.at(i));
    }
  }
  if (temp != " " || temp != "\n" || temp != "\t")
    myset.insert(temp);

  for (std::set<std::string>::iterator i = myset.begin(); i != myset.end(); i++)
  {
    std::cout << *i << std::endl;
  }
  return 0;
}

上から始めましょう。まず、操作する変数がいくつか必要です。temp解析する文字列の各文字から作成するときの文字列の単なるプレースホルダーです。mystringは分割しようとしている文字列でmyset、分割された文字列を貼り付ける場所です。

次に、ファイルを読み取り (<パイプによる入力)、内容を に挿入しmystringます。

ここで、文字列を分割するスペース、改行、またはタブを検索して、文字列の長さを反復処理したいと考えています。これらの文字のいずれかが見つかった場合はinsert、文字列をセットに追加し、プレースホルダー文字列を空にする必要があります。それ以外の場合は、その文字をプレースホルダーに追加して、文字列を構築します。終了したら、最後の文字列をセットに追加する必要があります。

最後に、セットを反復処理し、各文字列を出力します。これは単純に検証用ですが、それ以外の場合にも役立つ可能性があります。

編集:回答に統合する必要があると考えたコメントで、 Loki Astariによって提供された私のコードの大幅な改善:

#include <set>
#include <iostream>
#include <string>

int main()
{
  std::set<std::string> myset;
  std::string word;

  while(std::cin >> word)
  {
      myset.insert(std::move(word));
  }

  for(std::set<std::string>::const_iterator it=myset.begin(); it!=myset.end(); ++it)
    std::cout << *it << '\n';
}
于 2012-06-21T20:41:06.740 に答える