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:解决了第二个问题,这是我更正的代码:

// 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

其实有两个问题:

  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 回答