代码之家  ›  专栏  ›  技术社区  ›  k0ala Xing

C++:文本处理不正确,第一个\r\n未解析

  •  0
  • k0ala Xing  · 技术社区  · 1 年前

    我正在将一个开源游戏客户端从PC移植到Android,但在处理NPC聊天时,有些行没有正确解析:

    来自服务器的原始文本:

    formatted_text_ = "Now...ask me any questions you may have on traveling!!\r\n#L0##bHow do I move?#l\r\n#L1#How do I take down the monsters?#l\r\n#L2#How can I pick up an item?#l\r\n#L3#What happens when I die?#l\r\n#L4#When can I choose a job?#l\r\n#L5#Tell me more about this island!#l\r\n#L6#What should I do to become a Warrior?#l\r\n#L7#What should I do to become a Bowman?#l\r\n#L8#What should I do to become a Magician?#l\r\n#L9#What should I do to become a Thief?#l\r\n#L10#How do I raise the character stats? (S)#l\r\n#L11#How do I check the items that I just picked up?#l\r\n#L12#How do I put on an item?#l\r\n#L13#How do I check out the items that I'm wearing?#l\r\n#L14#What are skills? (K)#l\r\n#L15#How do I get to Victoria Island?#l\r\n#L16#What are mesos?#l#k"
    

    第二行 “我该如何移动” 未作为新行开始,以结尾的其他行\r\n将通过跟随新行进行正常分析。

    如何处理和:

                switch (text[first]) {
                    case '\\':
                        if (first + 1 < last) {
                            switch (text[first + 1]) {
                                case 'n':
                                    linebreak = true;
                                    break;
                                case 'r':
                                    linebreak = ax_ > 0;
                                    break;
                            }
    
                            skip++;
                        }
    
                        skip++;
                        break;
    

    当换行符为true或长度超过最大宽度时,应添加新行:

            bool newword = skip > 0;
            bool newline = linebreak || ax_ + wordwidth > max_width_;
    
            if (newword || newline) {
                add_word(prev, first, last_font, last_color);
            }
    
            if (newline) {
                add_line();
    
                endy_ = ay_;
                ax_ = 0;
                ay_ += font_.linespace();
    
                if (!lines_.empty()) {
                    ay_ -= line_adj_;
                }
            }
    

    enter image description here 如何处理formatted_text_:

    https://github.com/speedyHKjournalist/OpenMapleClient/blob/521af535bb65fb231296d02f1d19a6f38e77673d/app/src/main/cpp/src/IO/UITypes/UINpcTalk.cpp#L141

    https://github.com/speedyHKjournalist/OpenMapleClient/blob/73ddd15f443cc0ab9f796ce362a67d73e5e453ad/app/src/main/cpp/src/Graphics/GraphicsGL.cpp#L617

    https://github.com/speedyHKjournalist/OpenMapleClient/blob/73ddd15f443cc0ab9f796ce362a67d73e5e453ad/app/src/main/cpp/src/Graphics/GraphicsGL.cpp#L657

    1 回复  |  直到 1 年前
        1
  •  1
  •   selbie    1 年前

    那些 \r\n 序列是两个字节。 \r 是回车。和 \n 是换行字符。Windows偏好 \\r\n 用于行尾。Unix和其他任何地方(包括Android)只喜欢 n 用于行尾。

    最简单的事情就是请客 r , n \\r\n 作为有效的行尾标记。因此,让我们将格式化的字符串标准化,使\n成为实际的行尾标记:

        std::string s = formatted_text_;
        std::string t;
    
        for (size_t i = 0; i < s.size(); i++) {
            if (s[i] == '\r') {
                t += '\n';
                if ((i + 1 < s.size()) && (s[i + 1] == '\n')) {
                    i++;
                }
            }
            else {
                t += s[i];
            }
        }
    

    结果是 t 现在是以下形式的字符串:

    "Now...ask me any questions you may have on traveling!!\n#L0##bHow do I move?#l\n#L1#How do I take down the monsters?#l\n#L2#How can I pick up an item?#l\n#L3#What happens when I die?#l\n#L4#When can I choose a job?#l\n..."
    

    由于我们现在有一个分隔符来指示行的末尾,我们可以使用 getline 以解析为行列表。

        std::istringstream iss(t);
        std::string line;
        while (std::getline(iss, line, '\n')) {
            lines.push_back(line);
        }
    

    lines 是字符串的数组(矢量),如下所示:

    #L0##bHow do I move?#l
    #L1#How do I take down the monsters?#l
    #L2#How can I pick up an item?#l
    #L3#What happens when I die?#l
    #L4#When can I choose a job?#l
    #L5#Tell me more about this island!#l
    #L6#What should I do to become a Warrior?#l
    #L7#What should I do to become a Bowman?#l
    #L8#What should I do to become a Magician?#l
    #L9#What should I do to become a Thief?#l
    #L10#How do I raise the character stats? (S)#l
    #L11#How do I check the items that I just picked up?#l
    #L12#How do I put on an item?#l
    #L13#How do I check out the items that I'm wearing?#l
    #L14#What are skills? (K)#l
    #L15#How do I get to Victoria Island?#l
    #L16#What are mesos?#l#k
    

    例如 line[2] 等于 #L2#How can I pick up an item?#l 。的那些格式说明符 #L2 #l 为了你的比赛——我把它留给你练习。

    笔记 #include <string> #include <vector> and #include <sstream> 以便上述代码工作。