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?
3 に答える
一連の要素を保持するソースからコンテナを構築する最も簡単な方法は、イテレータのペアを取るコンストラクタを使用することです。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;
}
ファイルを文字列に読み取ったと仮定すると、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++ で文字列を分割しますか?
#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';
}