You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

字符串迭代器传参触发EXCEPTION_WRONG_SHIP_TYPE异常求助

问题:舰队击沉游戏中addShips函数触发舰船类型错误异常

我开发了一款舰队击沉(Sink the Fleet)小游戏,其中Player类的addShips函数接收字符串输入来创建舰船。输入格式固定为「B-A3-S」,代表战列舰(Battleship)、起始坐标A3、朝向南方(S);多组舰船信息用至少一个空格分隔(例:B-A3-S C-D8-N)。舰船类型对应枚举值:Battleship、Destroyer、Cruiser、Submarine。

我尝试用string::iterator遍历字符串,把当前字符传入Ship::typeFromChar获取ShipType,但始终触发EXCEPTION_WRONG_SHIP_TYPE异常。刚学指针与类,找不到问题根源,相关代码如下:

Player类addShips方法

void Player::addShips(string ships) {
    string::iterator it; //iterator to go through string
    //ship attributes 
    ShipType type;
    Coordinate pos; 
    Orientation o;

    for (it = ships.begin(); it != ships.end(); it++) {
        if ((*it == ships.at(0) && isalpha(ships[*it])) || (isalpha(ships[*it]) && isspace(ships[*it-1]))) { 
            type = Ship::typeFromChar(ships[*it]);  
        } else if (ships[*it] == '-') {
         ...//more conditions for different situations
        } 
    }
}    

Ship类typeFromChar方法

ShipType Ship::typeFromChar(char type) {
    ShipType st;
    if (type == 'B') { 
        st = BATTLESHIP;
    } else if (type == 'D') {
        st = DESTROYER;
    } else if (type == 'C') {
        st = CRUISE;
    } else if (type == 'S') {
        st = SUBMARINE;
    } else { 
        throw EXCEPTION_WRONG_SHIP_TYPE; //
    }
    return st;
}

main函数调用

Player player1("Jack");
try {
        string ships="B-B3-E S-J10-N   C-D7-W  D-A1-S";
        player1.addShips(ships);
    }
    catch (Exception e) {
        Util::error(ERR_SHIPS);
        Util::debug(e);
        return;
    }

错误根源分析

代码里有两个致命逻辑错误,直接导致传入typeFromChar的字符不是预期的'B'/'C'/'D'/'S':

  1. 混淆迭代器的*it含义:
    *it是迭代器指向的字符值(比如'B'的ASCII码是66),但你用ships[*it]去访问字符串索引——相当于用字符的ASCII值作为下标,完全超出字符串有效索引范围,拿到的是随机垃圾值,必然触发异常。

  2. 条件判断逻辑混乱:
    第一个if的判断逻辑完全错误:

    • *it == ships.at(0):只有第一个字符会满足,后续舰船类型字符(比如输入里的'S'/'C'/'D')根本不满足
    • isalpha(ships[*it]):同样是用ASCII值当索引,无意义
    • 正确逻辑应该是:判断当前字符是字母,且要么是字符串第一个字符,要么前一个字符是空格(代表新舰船的开始)

修复后的代码

修正后的Player::addShips方法

void Player::addShips(string ships) {
    string::iterator it;
    ShipType type;
    Coordinate pos; 
    Orientation o;

    for (it = ships.begin(); it != ships.end(); ++it) {
        // 判断当前字符是字母,且是新舰船的起始(开头或前一个是空格)
        if (isalpha(*it) && (it == ships.begin() || isspace(*(it - 1)))) { 
            // 直接传入当前迭代器指向的字符,而非用*it当索引取ships的元素
            type = Ship::typeFromChar(*it);  
        } else if (*it == '-') {
            // 处理后续的坐标和朝向逻辑
            ...
        } 
    }
}    

额外优化建议

  • 遍历迭代器时用++it替代it++,效率更高(对string迭代器影响不大,但养成好习惯)
  • 可以用stringstream分割输入字符串,按空格拆分每个舰船信息串(比如"B-B3-E"),再单独解析子串,比逐个字符遍历更清晰易维护:
    #include <sstream>
    #include <string>
    
    void Player::addShips(string ships) {
        std::stringstream ss(ships);
        std::string shipStr;
        while (ss >> shipStr) { // 自动按空格分割
            // 解析单个shipStr,比如"B-B3-E"
            char typeChar = shipStr[0];
            ShipType type = Ship::typeFromChar(typeChar);
            // 后续解析坐标和朝向...
        }
    }
    

内容的提问来源于stack exchange,提问作者Lnyka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 22:34:57