Description

以字符串数组的形式给出一份C++程序源码,求去除注释后的源码。注释包括///**/两种形式。

Constraints

  • \(1 \le source.length \le 100\)
  • \(0 \le source[i].length \le 80\)

Solution

构建出正确的状态机即可。口述让GPT帮画出来了。

               +--------+  "//"   +--------+
               | NORMAL | ------> |  LINE  |
               +--------+         +--------+
                  |                  |
                 "/*"               '\n'
                  |                  |
                  v                  v
               +--------+  "*/"   +--------+
               | BLOCK  | ------> | NORMAL |
               +--------+         +--------+

                        - ChatGPT

一个技巧是同时判断两个字符,而不要单字符作为状态。

同时为了代码整洁,加上一个cmp可对比单个字符或者两个字符。

(其实也整洁不到哪里去。)

之前还写过一份很OOP的多态实现,那叫一个又长又容易错。

对比之下,这一份代码的核心部分就没几行。

Code

class Solution {
public:
    vector<string> removeComments(vector<string>& source) {
        enum {
            NORMAL,
            LINE,
            BLOCK,
        } state {NORMAL};
        vector<string> ans;
        string tmp;

        auto flush = [&] {
            if(!tmp.empty()) ans.emplace_back(std::move(tmp));
        };

        for(auto &line : source) line += '\n';
        for(auto &line : source) {
            for(int i = 0; i < line.size(); ++i) {
                auto cmp = [&]<size_t N>(const char (&cs)[N]) {
                    if constexpr (N == 2) {
                        return line[i] == cs[0];
                    } else {
                        static_assert(N == 3);
                        auto a = line[i];
                        auto b = (a == '\n') ? '\0' : line[i+1];
                        return tie(a, b) == tie(cs[0], cs[1]);
                    }
                };

                if(state == NORMAL) {
                    if(cmp("//")) state = LINE, i++;
                    else if(cmp("/*")) state = BLOCK, i++;
                    else if(cmp("\n")) flush(), i++;
                    else tmp += line[i];
                    continue;
                }
                if(state == LINE) {
                    if(cmp("\n")) state = NORMAL, flush(), i++;
                    continue;
                }
                if(state == BLOCK) {
                    if(cmp("*/")) state = NORMAL, i++;
                    continue;
                }
            }
        }
        flush();
        return ans;
    }
};

LeetCode-722 Remove Comments