2

C++ で非常に奇妙なセット イテレータの問題が発生しました。

set<string> dict;
dict.insert("hello");
dict.insert("my");

int maxLen = INT_MIN;

set<string>::iterator itr;
for (itr=dict.begin(); itr!=dict.end(); itr++) {
    int len = (*itr).length();
    if ( len > maxLen )
        maxLen = (*itr).length();
}

このコードは、単語セット内の最長の単語の長さである maxLen を 5 に設定するのに役立ちます。

set<string> dict;
dict.insert("hello");
dict.insert("my");

int maxLen = INT_MIN;

set<string>::iterator itr;
for (itr=dict.begin(); itr!=dict.end(); itr++) {
    if ( (*itr).length() > maxLen )
        maxLen = (*itr).length();
}

ただし、このコードでは正しい結果が得られません。コードを実行した後、maxLen は INT_MIN の値のままです。(*itr).length() の値を保持するために変数を使用しないこと以外は、基本的に何も変わりません。

これは私にとって非常に奇妙です。何か不足していますか?イテレータの使用に関する疑問を明確にしたいだけです。

どうもありがとう!

4

1 に答える 1

6

ここでの問題は、使用している型がsignedであるのに関数がunsigned型をstring::length返すことだと思います。符号付きの値と符号なしの値の比較では、常に符号付きの値が最初に符号なしの値に変換されます。あなたの場合、 と のビットパターンが同じであるため、 を符号なしの値に変換すると、可能な最大の符号なしの値になります。intINT_MININT_MINUINT_MAX

これが初めて機能する理由はint、一時変数に割り当てられたときに符号なしの値が s にキャストされたためです。

これを修正するには、キャストを追加します。

for (itr=dict.begin(); itr!=dict.end(); itr++) {
    if ( int((*itr).length()) > maxLen )
        maxLen = (*itr).length();
}

あなたがそれに取り組んでいる限り、ここで行うことができる他の多くのスタイル上の修正があります。

  • ポストインクリメントをプリインクリメント++に切り替え++て効率を高め、
  • ->の代わりに(*).使用する
  • 演算子の周りに空白を追加し、
  • ループ内でローカルに反復子を宣言する

これを次に示します。

for (set<string>::iterator itr = dict.begin(); itr != dict.end(); ++itr) {
    if (int(itr->length()) > maxLen) {
       maxLen = itr->length();
    }
}

あるいは、C++11 準拠のコンパイラを使用している場合は、範囲ベースの for ループを使用します。

for (const auto& val: dict) {
    if (int(val.length()) > maxLen) {
       maxLen = val.length();
    }
}

お役に立てれば!

于 2013-10-22T02:27:47.203 に答える