列表

详情


722. 删除注释

给一个 C++ 程序,删除程序中的注释。这个程序source是一个数组,其中source[i]表示第 i 行源码。 这表示每行源码由 '\n' 分隔。

在 C++ 中有两种注释风格,行内注释和块注释。

第一个有效注释优先于其他注释。

如果一行在删除注释之后变为空字符串,那么不要输出该行。即,答案列表中的每个字符串都是非空的。

样例中没有控制字符,单引号或双引号字符。

此外,没有其他内容(如定义或宏)会干扰注释。

我们保证每一个块注释最终都会被闭合, 所以在行或块注释之外的/*总是开始新的注释。

最后,隐式换行符可以通过块注释删除。 有关详细信息,请参阅下面的示例。

从源代码中删除注释后,需要以相同的格式返回源代码。

 

示例 1:

输入: source = ["/*Test program */", "int main()", "{ ", "  // variable declaration ", "int a, b, c;", "/* This is a test", "   multiline  ", "   comment for ", "   testing */", "a = b + c;", "}"]
输出: ["int main()","{ ","  ","int a, b, c;","a = b + c;","}"]
解释: 示例代码可以编排成这样:
/*Test program */
int main()
{ 
  // variable declaration 
int a, b, c;
/* This is a test
   multiline  
   comment for 
   testing */
a = b + c;
}
第 1 行和第 6-9 行的字符串 /* 表示块注释。第 4 行的字符串 // 表示行注释。
编排后: 
int main()
{ 
  
int a, b, c;
a = b + c;
}

示例 2:

输入: source = ["a/*comment", "line", "more_comment*/b"]
输出: ["ab"]
解释: 原始的 source 字符串是 "a/*comment\nline\nmore_comment*/b", 其中我们用粗体显示了换行符。删除注释后,隐含的换行符被删除,留下字符串 "ab" 用换行符分隔成数组时就是 ["ab"].

 

提示:

 ​​​​​​

相似题目

迷你语法分析器

三元表达式解析器

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: vector<string> removeComments(vector<string>& source) { } };

golang 解法, 执行用时: 0 ms, 内存消耗: 2 MB, 提交时间: 2023-07-23 11:08:45

func removeComments(source []string) []string {
	var strArr []string
	isBlock, str :=  false, ""
	for i := 0; i < len(source); i++ {
		isComment, index := false, 0
		if len(source[i]) >= 2 {
			for j := 0; j < len(source[i]) - 1; j++  {
				// 判断有效的注释行
				if source[i][j:j + 2] == "//" && !isBlock && j >= index {
					isComment = true
					str += source[i][index:j]
					index = len(source[i]) // 下一个有效位置
					break
				}

				// 判断有效的注释块开始
				if source[i][j:j + 2] == "/*" && !isBlock && j >= index{
					isComment, isBlock = true, true
					str += source[i][index:j]
					fmt.Printf("'`%s'\n", str)
					index = j + 2 // 下一个有效位置
				}

				// 判断有效的注释块结束
				if source[i][j:j + 2] == "*/" && isBlock && j >= index {
					isComment, isBlock = true, false
					index = j + 2 // 下一个有效位置
				}
			}
		}

		//不在注释块中才写入
		if !isBlock {
			if !isComment {
				strArr = append(strArr, source[i])
			} else {
				if 0 < index && index < len(source[i]) {
					str += source[i][index:len(source[i])]
				}
				if str != "" {
					strArr = append(strArr, str)
					str = ""
				}
			}
		}
	}
	return strArr
}

golang 解法, 执行用时: 0 ms, 内存消耗: 2 MB, 提交时间: 2023-07-23 11:08:17

func removeComments(source []string) []string {
	var ret []string
	isBlockComm := false
	var buf []byte
	for i := 0; i < len(source); i++ {
		s := source[i]
		j := 0
		for j < len(s) {
			if !isBlockComm && j+1 < len(s) && s[j] == '/' && s[j+1] == '*' {
				isBlockComm = true
				j += 2
				continue
			}
			if !isBlockComm && j+1 < len(s) && s[j] == '/' && s[j+1] == '/' {
				break
			}
			if isBlockComm && j+1 < len(s) && s[j] == '*' && s[j+1] == '/' {
				isBlockComm = false
				j += 2
				continue
			}
			if !isBlockComm {
				buf = append(buf, s[j])
			}
			j++
		}
		if len(buf) == 0 {
			continue
		}
		if !isBlockComm {
			ret = append(ret, string(buf))
			buf = []byte{}
		}
	}
	return ret
}

python3 解法, 执行用时: 48 ms, 内存消耗: 16.1 MB, 提交时间: 2023-07-23 11:07:23

class Solution:
        def removeComments(self, source: List[str]) -> List[str]:
                    
            string = '\n'.join(source) + '\n'
            
            while '//' in string or '/*' in string:
                multiInd = string.find('/*')
                oneInd = string.find('//')
                
                # 如果单行注释的那一行还有多行注释 就直接忽略掉
                if(oneInd < multiInd and oneInd != -1) or (multiInd == -1 and oneInd != -1):
                    oneEnd = string[oneInd+2:].find('\n') + oneInd + 2
                    string = string[:oneInd] + string[oneEnd:]
                    continue
                # 如果是单行注释被包在多行注释里
                if(multiInd < oneInd and multiInd != -1) or (multiInd != -1 and oneInd == -1):
                    multiEnd = string[multiInd+2:].find('*/') + multiInd + 2
                    string = string[:multiInd] + string[multiEnd+2:]
                    
            result = []
            for s in string.split('\n'):
                if s != '':
                    result.append(s)
            return result

cpp 解法, 执行用时: 4 ms, 内存消耗: 7.7 MB, 提交时间: 2023-07-23 11:06:18

class Solution {
public:
    vector<string> removeComments(vector<string>& source) {
        bool comment = false;
        vector<string> res;
        string tmp;
        for(auto& s : source){            
            int i = 0, len = s.size();
            //开头不在多行注释中,新起一行,否则追加到之前的字符串
            if(!comment) tmp.clear();
            while(i < len){
                //开始块注释
                if(!comment && i < len - 1 && s[i] == '/' && s[i + 1] == '*' ){
                    comment = true;
                    ++i;
                }
                //结束块注释
                else if(comment && i < len - 1 && s[i] == '*' && s[i + 1] == '/'){
                    comment = false;
                    ++i;
                }
                //开始行注释
                else if(!comment && i < len - 1 && s[i] == '/' && s[i + 1] == '/'){
                    break;
                }
                //非注释
                else if(!comment){
                    tmp += s[i];
                }
                ++i;            
            }  
            //非注释且非空,则保存到结果集合
            if(!comment && !tmp.empty()){
                res.emplace_back(tmp);
            }        
        }
        return res;
    }
};

java 解法, 执行用时: 1 ms, 内存消耗: 40.1 MB, 提交时间: 2023-07-23 11:05:29

class Solution {
    public List<String> removeComments(String[] source) {
        boolean inBlock = false;
        StringBuilder newline = new StringBuilder();
        List<String> ans = new ArrayList();
        for (String line: source) {
            int i = 0;
            char[] chars = line.toCharArray();
            if (!inBlock) newline = new StringBuilder();
            while (i < line.length()) {
                if (!inBlock && i+1 < line.length() && chars[i] == '/' && chars[i+1] == '*') {
                    inBlock = true;
                    i++;
                } else if (inBlock && i+1 < line.length() && chars[i] == '*' && chars[i+1] == '/') {
                    inBlock = false;
                    i++;
                } else if (!inBlock && i+1 < line.length() && chars[i] == '/' && chars[i+1] == '/') {
                    break;
                } else if (!inBlock) {
                    newline.append(chars[i]);
                }
                i++;
            }
            if (!inBlock && newline.length() > 0) {
                ans.add(new String(newline));
            }
        }
        return ans;
    }
}

python3 解法, 执行用时: 44 ms, 内存消耗: 16.1 MB, 提交时间: 2023-07-23 11:05:01

'''
我们需要逐行分析源代码。有两种情况,要么在一个注释内或者不在。
如果我们遇到注释块符号,而我们不在注释中,那么我们将跳过接下来的两个字符,并将状态更改为在注释中。
如果我们遇到注释块符号并且我们在注释中,那么我们将跳过接下来的两个字符并将状态更改为不在注释中。
如果我们遇到一个行注释且我们不在注释中,那么我们将忽略该行的其余部分。
如果我们不在注释中(并且它不是注释的开头),我们将记录所遇到的字符。
在每行的末尾,如果我们不在注释中,我们将记录该行。
'''
class Solution:
    def removeComments(self, source: List[str]) -> List[str]:
        in_block = False
        ans = []
        for line in source:
            i = 0
            if not in_block:
                newline = []
            while i < len(line):
                if line[i:i+2] == '/*' and not in_block:
                    in_block = True
                    i += 1
                elif line[i:i+2] == '*/' and in_block:
                    in_block = False
                    i += 1
                elif not in_block and line[i:i+2] == '//':
                    break
                elif not in_block:
                    newline.append(line[i])
                i += 1
            if newline and not in_block:
                ans.append(''.join(newline))

        return ans

上一题