Remove Comments
Problem
Given a list of source code lines, remove all // line comments and /* */ block comments. Block comments may span multiple lines; concatenate surviving fragments across lines and drop empty resulting lines.
["/*Test*/","int a;","//x","b/*c*/d"]["int a;","bd"]def removeComments(source):
res, buf, inblock = [], [], False
for line in source:
i, n = 0, len(line)
if not inblock: buf = []
while i < n:
if not inblock and i + 1 < n and line[i:i+2] == '/*':
inblock = True; i += 2
elif inblock and i + 1 < n and line[i:i+2] == '*/':
inblock = False; i += 2
elif not inblock and i + 1 < n and line[i:i+2] == '//':
break
else:
if not inblock: buf.append(line[i])
i += 1
if not inblock and buf: res.append(''.join(buf))
return res
function removeComments(source) {
const res = []; let buf = '', inblock = false;
for (const line of source) {
let i = 0, n = line.length;
if (!inblock) buf = '';
while (i < n) {
if (!inblock && line.slice(i, i+2) === '/*') { inblock = true; i += 2; }
else if (inblock && line.slice(i, i+2) === '*/') { inblock = false; i += 2; }
else if (!inblock && line.slice(i, i+2) === '//') break;
else { if (!inblock) buf += line[i]; i++; }
}
if (!inblock && buf.length) res.push(buf);
}
return res;
}
class Solution {
public List<String> removeComments(String[] source) {
List<String> res = new ArrayList<>();
StringBuilder buf = new StringBuilder();
boolean inblock = false;
for (String line : source) {
int i = 0, n = line.length();
if (!inblock) buf.setLength(0);
while (i < n) {
if (!inblock && i + 1 < n && line.charAt(i)=='/' && line.charAt(i+1)=='*') { inblock = true; i += 2; }
else if (inblock && i + 1 < n && line.charAt(i)=='*' && line.charAt(i+1)=='/') { inblock = false; i += 2; }
else if (!inblock && i + 1 < n && line.charAt(i)=='/' && line.charAt(i+1)=='/') break;
else { if (!inblock) buf.append(line.charAt(i)); i++; }
}
if (!inblock && buf.length() > 0) res.add(buf.toString());
}
return res;
}
}
class Solution {
public:
vector<string> removeComments(vector<string>& source) {
vector<string> res; string buf; bool inblock = false;
for (auto& line : source) {
int i = 0, n = line.size();
if (!inblock) buf.clear();
while (i < n) {
if (!inblock && i+1 < n && line[i]=='/' && line[i+1]=='*') { inblock = true; i += 2; }
else if (inblock && i+1 < n && line[i]=='*' && line[i+1]=='/') { inblock = false; i += 2; }
else if (!inblock && i+1 < n && line[i]=='/' && line[i+1]=='/') break;
else { if (!inblock) buf.push_back(line[i]); i++; }
}
if (!inblock && !buf.empty()) res.push_back(buf);
}
return res;
}
};
Explanation
This is a careful character-by-character scan across all the source lines, where a single boolean inblock remembers whether we are currently inside a /* ... */ block comment. Because a block comment can span multiple lines, that flag must persist as we move from one line to the next.
At each position we look at the two characters starting there. If we are not in a block and see /*, we enter block mode. If we are in a block and see */, we leave it. If we are not in a block and see //, the rest of that line is a line comment, so we break out of it. Any other character that is outside a block gets appended to buf.
The buffer buf collects surviving text. We only reset it at the start of a line when we are not mid-block, which lets code fragments before and after a comment join together. When a line finishes and we are not inside a block and buf is non-empty, we flush it to the result, dropping lines that became empty.
Example: ["/*Test*/", "int a;", "//x", "b/*c*/d"]. The first line is entirely a block comment (empty result, dropped). "int a;" survives as is. "//x" is a line comment (dropped). In "b/*c*/d" the /*c*/ is removed, leaving "b" and "d" joined into "bd". Output: ["int a;", "bd"].