どのように対して繰り返し処理を実行するstd::地図の文字列はC++
-
21-08-2019 - |
質問
私は、以下の問題を繰り返し処理を行連想配列の文字列を使用して定義され std::map
.
-- snip --
class something
{
//...
private:
std::map<std::string, std::string> table;
//...
}
このコンストラクタでは私の読み込みテーブルのペアの文字列のキーに関連する文字列データです。かかる方法 toString
この文字列を返しますオブジェクトを含むすべてのキーと関連するデータに含まれるテーブルオブジェクト(key=データ形式)になります。
std::string something::toString()
{
std::map<std::string, std::string>::iterator iter;
std::string* strToReturn = new std::string("");
for (iter = table.begin(); iter != table.end(); iter++) {
strToReturn->append(iter->first());
strToReturn->append('=');
strToRetunr->append(iter->second());
//....
}
//...
}
がんのようにコンパイルを取得します以下のようなエラー:
error: "error: no match for call to ‘(std::basic_string<char,
std::char_traits<char>, std::allocator<char> >) ()’".
が誰かに説明しんから、足りないものがありましたら、何なっているが悪いのでしょうか。い一部の議論も同様の問題の場合 hash_map
場所により、ユーザーが定義するハッシュ機能が利用できるように hash_map
と std::string
オブジェクト。このようなものでも私の場合は?
解決
あなたの主な問題は、イテレータにfirst()
というメソッドを呼び出しているということです。あなたは何を行うことを意図していることfirst
と呼ばれるプロパティを使用します。
...append(iter->first) rather than ...append(iter->first())
スタイルの問題として、あなたはその文字列を作成するためにnew
を使用すべきではありません。
std::string something::toString()
{
std::map<std::string, std::string>::iterator iter;
std::string strToReturn; //This is no longer on the heap
for (iter = table.begin(); iter != table.end(); ++iter) {
strToReturn.append(iter->first); //Not a method call
strToReturn.append("=");
strToReturn.append(iter->second);
//....
// Make sure you don't modify table here or the iterators will not work as you expect
}
//...
return strToReturn;
}
の編集のfacildelembrarは、近代的なCであなたが今
ループを書き換えることができ++という(コメントで)指摘しましたfor (auto& item: table) {
...
}
他のヒント
なを書く
toString()
方法。これはJava.実施ストリームのオペレーター用クラスです。好みの標準アルゴリズムを上書き自分のループを実行します。こうした状況の
std::for_each()
提供の素敵なインターフェースだけます。が発生する場合には、利用、ループなしに変更、データ、。
const_iterator
以上iterator
.そのた場合、誤ってみて、価値観を変え、コンパイラの警告を表示します。
その後:
std::ostream& operator<<(std::ostream& str,something const& data)
{
data.print(str)
return str;
}
void something::print(std::ostream& str) const
{
std::for_each(table.begin(),table.end(),PrintData(str));
}
したいときに印刷で、ストリームのオブジェクト:
int main()
{
something bob;
std::cout << bob;
}
ご必要の文字列表現オブジェクトを利用できます lexical_cast
.
int main()
{
something bob;
std::string rope = boost::lexical_cast<std::string>(bob);
}
の詳細を記入してください。
class somthing
{
typedef std::map<std::string,std::string> DataMap;
struct PrintData
{
PrintData(std::ostream& str): m_str(str) {}
void operator()(DataMap::value_type const& data) const
{
m_str << data.first << "=" << data.second << "\n";
}
private: std::ostream& m_str;
};
DataMap table;
public:
void something::print(std::ostream& str);
};
あなたの追記が言って呼び出しを変更します。
...append(iter->first)
と
... append(iter->second)
また、行
std::string* strToReturn = new std::string("");
は、ヒープ上に文字列を割り当てます。あなたが実際にこの動的に割り当てられた文字列へのポインタを返すようにする場合は、リターンははstd ::した文字列を変更する必要があります*。
また、あなたは、ヒープ上にそのオブジェクトを管理心配にローカル宣言を変更したくない場合は、
std::string strToReturn("");
と 'APPEND' を変更する参照構文を使用するために呼び出す...
strToReturn.append(...)
の代わりに
strToReturn->append(...)
これはのコピーは、のそれ戻り変数に、その後、スタック上の文字列を作成することに注意してください。これは、パフォーマンスに影響します。
::イテレータのstd ::マップを間接参照の結果は STDであることに注意してください::ペアに。 first
とsecond
の値は、彼らが変数であり、関数ではありません。
変更:
iter->first()
タグに
iter->first
iter->second
と同上ます。
iter->first
とiter->second
は、あなたはメソッドとしてそれらを呼び出すために、変数しようとしているされます。
使用します。
std::map<std::string, std::string>::const_iterator
の代わりに:
std::map<std::string, std::string>::iterator
for ( auto iter : table ) {
key=iter->first();
value=iter->second();
}
他の価値の最適化は、のLPCTSTRとしての周りに渡すことができる文字列を終了不変NULLを返しSTLの列のクラス、ののc_str()のメンバーでありますを、E。グラム。、LPCTSTRを期待カスタム関数へ。私はそれを確認するためにデストラクタを通じてトレースしていませんが、私は、文字列クラスは、それがコピーを作成しているメモリの後に見えることを疑うます。