1

演習用のコードを書いているときに、この奇妙な問題が発生しました。

最初に最初のオプションを選択するときに、誤ったエントリを入力します。それは私のコードのブランチに行くことになってelseいますが、代わりにそこでスタックします。理由はよくわかりません。これは、間にスペースを入れて「ゲームタイトル」を入力した場合にも発生します。

次に、削除ブランチでコメントアウトした行:

iter = gameTitles.erase(iter);

...まったく機能しません。私がやろうとしているのは、エントリを入力して削除し、その後、エントリと比較して、何を削除するかがわかるようにすることです。そのため、私もイテレータを使用しています。

// Exercise 1
/*
Write a program using vectors and iterators that allows a user to maintain a list of
his or her favorite games. The program should allow the user to list all game titles,
add a game title, and remove a game title.
*/

#include <iostream>
#include <windows.h>
#include <string>
#include <vector>

using namespace std;

int main(){
    bool    bLoop   = true;
    int     nChoice;
    char    cChoice;
    string  sInput;

    vector<string>::const_iterator iter;
    vector<string> gameTitles;

    while(bLoop){
        // -Head
        cout << "///////////////////////////////////\n// My Favorite Games\n\n";
        cout << "1. Add title\n2. Delete title\n3. Clear list\n\n";

        // -List
        if(!gameTitles.empty()){
            for(iter = gameTitles.begin(); iter!=gameTitles.end(); ++iter){
                cout << "-" << *iter << endl;
            }
        }

        cout << "\n:: ";
        cin  >> nChoice;

        // 1. Add
        if(nChoice == 1){
            cout << "\nGame Title: ";
            cin >> sInput;
            gameTitles.push_back(sInput);
        }

        // 2. Delete
        else if(nChoice == 2) {
            cout << "Delete Title: ";
            cin >> sInput;

            for(iter = gameTitles.begin(); iter!=gameTitles.end(); ++iter){
                if(*iter == sInput){
                    cout << "erased";
                    //iter = gameTitles.erase(iter);
                }
            }
        }

        // 3. Clear
        else if(nChoice == 3){
            cout << "Are you sure? (y/n) ";
            cin >> cChoice;
            if(cChoice == 'y'){
                gameTitles.clear();
            }
        } else {
            cout << "\nInvalid Choice, Please try again.\n";
        }

        // -Clean
        system("PAUSE");
        system("cls");
    }
}

編集:最初の問題を解決しました。定数の代わりに通常のイテレータを使用しました

EDIT2:2番目の問題を解決しました、これが私の修正されたコードです:

// Exercise 1
/*
Write a program using vectors and iterators that allows a user to maintain a list of
his or her favorite games. The program should allow the user to list all game titles,
add a game title, and remove a game title.
*/

#include <iostream>
#include <windows.h>
#include <string>
#include <vector>

using namespace std;

int main(){
    bool    bLoop   = true;
    int     nChoice;
    char    cChoice;
    string  sInput;

    vector<string>::iterator iter;
    vector<string> gameTitles;

    while(bLoop){
        // -Head
        cout << "///////////////////////////////////\n// My Favorite Games\n\n";
        cout << "1. Add title\n2. Delete title\n3. Clear list\n\n";

        // -List
        if(!gameTitles.empty()){
            for(iter = gameTitles.begin(); iter!=gameTitles.end(); ++iter){
                cout << "-" << *iter << endl;
            }
        }

        cout << "\n:: ";
        cin >> nChoice;

        if(cin.fail()){
            cin.clear();
            cin.ignore();
        }

        // 1. Add
        if(nChoice == 1){
            cout << "\nGame Title: ";
            cin >> sInput;
            gameTitles.push_back(sInput);
        }

        // 2. Delete
        else if(nChoice == 2) {
            cout << "Delete Title: ";
            cin >> sInput;

            for(iter = gameTitles.begin(); iter!=gameTitles.end(); ){
                if(*iter == sInput){
                    cout << "erased";
                    iter = gameTitles.erase(iter);
                } else {
                    ++iter;
                }
            }
        }

        // 3. Clear
        else if(nChoice == 3){
            cout << "Are you sure? (y/n) ";
            cin >> cChoice;
            if(cChoice == 'y'){
                gameTitles.clear();
            }
        } else {
            cout << "\nInvalid Choice, Please try again.\n";
        }

        // -Clean
        system("PAUSE");
        system("cls");
    }
}
4

2 に答える 2

2

実際には2つの質問があります。

  1. 何か間違ったものを入力すると、入力がスタックするのはなぜですか?のようなものを使用して、入力が成功したことを確認する必要がありますif (std::cin >> nChoice) { /* actual processing */ }nChoice入力が失敗しても、の値は変更されないことに注意してください。入力が失敗した場合は、エラー回復を行う必要があります。ストリームは失敗状態になり(つまり、エラーフラグに設定され)、編集std::ios_base::failbitされるまでそれ以上の入力を拒否しません。clear()これでも、入力に問題のある文字が残りますignore()
  2. ループがerase()誤動作を使用しているのはなぜですか?実際にerase()値を実行するときは、ループの最後でイテレータを再度インクリメントしたくありません。そうした場合、イテレータが最後を超えて移動し、未定義の動作が発生する可能性があります。つまり、ループは次のようになります。

    for(iter = gameTitles.begin(); iter!=gameTitles.end(); ) {
        if (*iter == sInput) {
             cout << "erased";
             iter = gameTitles.erase(iter);
        }
        else {
            ++iter;
        }
    }
    

    もちろん、同じロジックの短いバージョンは次のとおりです。

    gamesTitles.erase(std::remove(gamesTitles.begin(), games.Titles.end(),
                                  sInput),
                      games.Titles.end());
    
于 2012-10-28T20:16:24.917 に答える
0

間違っていると思いますが、コンテナのメソッドiteratorから返されたeraseものは、そのコンテナから消去された値を指すことはありません。次のように仮定します。

std::vector<std::string> v;
// push some items to v
v.push_back( "1" );
v.push_back( "2" );
v.push_back( "3" );
auto i = v.erase( v.end() - 1 );
// Now i point to end of v and you can't derefrence it

vector代わりに、以前は値が含まれていた位置を指します。

auto i = v.erase( v.begin() );
assert( *i == "2" );
于 2012-10-28T20:14:47.410 に答える