Good programmers write fabulous comments. Igor is a programmer and he likes the old C-style comments in /* ... */
blocks. For him, it would be ideal if he could use this style as a uniform comment format for all programming languages or even documents, for example Python, Haskell or HTML/XML documents.
Making this happen doesn't seem too difficult to Igor. What he will need is a comment pre-processor that removes all the comment blocks in /*
, followed by comment text, and by another */
. Then the processed text can be handed over to the compiler/document renderer to which it belongs—whatever it is.
Igor's pre-processor isn't quite that simple, though. Here are some cool things it does:
printf("Hello /* a comment /* a comment inside comment */ inside /* another comment inside comment */ string */ world");After the pre-process step, it becomes:
printf("Hello world");
"/*...*/"
, a constant number 12/*...*/34
or even in a character escape \/*...*/n
Or more formally:
text: text-piece text-piece remaining-text text-piece: char-sequence-without-/* empty-string remaining-text: comment-block text comment-block: /* comment-content */ comment-content: comment-piece comment-piece remaining-comment comment-piece: char-sequence-without-/*-or-*/ empty-string remaining-comment: comment-block comment-content char: letters digits punctuations whitespaces
Our pre-processor, given a text
, removes all comment-block
instances as specified.
//*no recursion*/* file header */should generate:
/* file header */
*
character in any /*
or /*
cannot be re-used in another /*
or */
. For example the following does NOT form a proper comment block /*/
A text document with comment blocks in /*
and */
. The input file is valid. It follows the specification of text
in the problem statement. The input file always terminates with a newline symbol.
We only have one test case for this problem. First we need to output the following line.
Case #1:Then, print the document with all comments removed, in the way specified in the problem statements. Don't remove any spaces or empty lines outside comments.
The input program contains only:
a-z, A-Z,
0-9
~ ! @ # % ^ & * ( ) - + = : ; " ' < > , . ? | / \ { } [ ] _
The small input contains a program of less than 2k bytes.
The large input contains a program of less than 100k bytes.
Input |
|
//*no recursion*/* file header ***********/************ * Sample input program * **********/************* */ int spawn_workers(int worker_count) { /* The block below is supposed to spawn 100 workers. But it creates many more. Commented until I figure out why. for (int i = 0; i < worker_count; ++i) { if(!fork()) { /* This is the worker. Start working. */ do_work(); } } */ return 0; /* successfully spawned 100 workers */ } int main() { printf("Hello /*a comment inside string*/ world"); int worker_count = 0/*octal number*/144; if (spawn_workers(worker_count) != 0) { exit(-1); } return 0; } |
|
|
|
Output |
|
Case #1: /* file header ************************ */ int spawn_workers(int worker_count) { return 0; } int main() { printf("Hello world"); int worker_count = 0144; if (spawn_workers(worker_count) != 0) { exit(-1); } return 0; } |
类型:字符串 难度:2
题意:给一段文本(多行),文本中包含/* ... */的注释段,要求把注释内容去掉,输出结果。但是这个注释和一般的略有不同,有两个特点:
(1)能够嵌套,类似括号的用法
(2)可能出现在文本任何地方,如"/*...*/",12/*...*/34
还有两点要注意的是:
(1)去掉注释文本后形成的/*或*/不算注释,如
//*no recursion*/* file header */
去掉注释后为:
/* file header */
(2)注释中的*只能被一个/*或*/所用,如/*/不是合法的注释
分析:题目本身看似难度不大,但是通过率很低,归根结底还是细节问题较多(其实总体看google的笔试,都不是需要很难的算法才能解出的,考察的都是细节的把握)
基本思路:
(1)遍历文本,用一个栈nest存储/*的位置,遇到/*则入栈,遇到*/则将nest顶端的/*出栈
(2)用另一个栈del记录互不包含重叠的最外层/*..*/对的位置,即当nest出栈后,栈为空,证明最后出栈的是最外层的/*...*/,将它们的位置入del栈
(3)遍历结束后,del内位置对依次出栈,删除对应范围的文本(先删后边的保证前面的位置下标不变,这也是用栈del的原因)
两个细节:
(1)遍历时先找'/',再找前一个是不是'*',即找*/,因为要先和前面的/*匹配。再找后一个是不是'*'
(2)注意标记用过的'*',防止/*/情况中'*'被前一个'/'用完又被后一个'/'用。
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<vector> using namespace std; typedef struct { int l,r; }range; int main() { freopen("E-large-practice.in","r",stdin); freopen("E-large-practice.out","w",stdout); string tmp,text; while(getline(cin,tmp,'\n')) { text+=tmp; text+="\n"; } vector<int> nest; vector<range> del; nest.clear(); del.clear(); int pos = -1; for(int i=0; i<text.size(); i++) { if(text[i]=='/') { if(i>0 && text[i-1]=='*' && !nest.empty() && pos!=(i-1)) { int left = nest.back(); nest.pop_back(); if(nest.empty()) { range tn; tn.l = left; tn.r = i; del.push_back(tn); } } else if(i<text.size()-1 && text[i+1]=='*') { nest.push_back(i); pos = i+1; } } } while(!del.empty()) { range td = del.back(); text.erase(td.l,td.r-td.l+1); del.pop_back(); } cout<<"Case #1:\n"<<text; }