一个公司的上机面试题。
有一个c语言写的简单代码文件input.c,要求写一个java程序,读取input.c文件的内容然后去掉注释,包括\\和\**\,注意不能删除引号里边的注释,然后保存到output.c文件。
input.c文件如下:
#include<iostream.h>
struct a {
char a /*2392839238923 /*kasdlfj*/asld*/;
char b; //23232392839
};
/*
askdashfla'
asdfalskdfhlksafdhla
fasdjfhalsdjfhlasdf
askjdfhlkajds
* /
*/
void Function(int param /*232323* / */)
{
//*2323234234l
int i = 1;//2923939
char str[] = "/*232323";
int j = 0;
i = i / j * i;
strcpy(str, "/*lakjslkdflksd*/");
}
main()
{
}
用正则表达式解决如下:
public class CommentTest extends TestCase{
@Test
public void testDeleteComent(){
BufferedReader reader = null;
PrintWriter writer = null;
try {
reader = new BufferedReader(new FileReader("c:/input.c"));
writer = new PrintWriter("c:/output.c");
Map<String, String> map = new HashMap<String, String>();
Pattern pattern = null;
String line = "";
StringBuffer content = new StringBuffer();
pattern = Pattern.compile("\".*?\"");//引号
while((line=reader.readLine())!=null){
StringBuffer sb = new StringBuffer();
Matcher matcher = pattern.matcher(line);
//找到引号,用唯一标识符替换掉引号及其内容,并且保存在map中
while(matcher.find()){
String key = UUID.randomUUID().toString().toUpperCase();
map.put(key, matcher.group());
matcher.appendReplacement(sb, key);//逐一替换
}
matcher.appendTail(sb);
//替换一行中的//和/**/注释
line = sb.toString().replaceAll("/\\*.*\\*/|//.*", "");
if (!line.isEmpty()){
content.append(line).append("\n");
}
}
//替换跨行的/**/注释 (?s)为启用 dotall 模式,把换行符\n也一块删掉
String result = content.toString().replaceAll("(?s)/\\*.*\\*/", "");
//还原引号及其内容
for(Map.Entry<String, String> entry:map.entrySet()){
result = result.replace(entry.getKey(), entry.getValue());
}
writer.println(result);//写入新的文件中
writer.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
if (null != reader) reader.close();
if (null != writer) writer.close();
} catch (IOException e) {
}
}
}
}
输入结果out.c
#include<iostream.h>
struct a {
char a ;
char b;
};
void Function(int param )
{
int i = 1;
char str[] = "/*232323";
int j = 0;
i = i / j * i;
strcpy(str, "/*lakjslkdflksd*/");
}
main()
{
}
最近在看Matcher的源码,以下的替换方法与Matcher.replaceAll方法很相似,看来多看点源码还是很有用的。
//找到引号,用唯一标识符替换掉引号及其内容,并且保存在map中
while(matcher.find()){
String key = UUID.randomUUID().toString().toUpperCase();
map.put(key, matcher.group());
matcher.appendReplacement(sb, key);//逐一替换
}
matcher.appendTail(sb);
其中Matcher.replaceAll方法的源码如下
public String replaceAll(String replacement) {
reset();
boolean result = find();
if (result) {
StringBuffer sb = new StringBuffer();
do {
appendReplacement(sb, replacement);
result = find();
} while (result);
appendTail(sb);
return sb.toString();
}
return text.toString();
}