昨天上午的面试题,大家来做做吧。
时间:2008-05-13 15:22:54
来源:论坛整理 作者: 编辑:chinaitzhe
网友回复:似乎c primer上有这题。
网友回复:这么简单,不就是去掉以//开头的行和/* */之间的文本
网友回复:在单引号和双引号里面是没有注释符号的吧,别的嘛就是找到//就忽略剩下的一行,找到/*就忽略*/中的内容咯,别的都照常输出,还有什么非凡情况么?
网友回复:我比較喜歡用
int id=10 //xxxx
string page=0 // asdf
网友回复:我想應該按字符來比較,不能按行來處理`
网友回复:要按行来处理吧,究竟 // 后面一整行的数据都是注释
网友回复:/*
*/
是可以跨行的
分开来处理
网友回复:假如 /*,*/或则//在串中出现呢?我想应该考虑这个问题
网友回复:我的话会用一些比较机械化点的做法,按位读取字符比较假如连续出现两个'/',那么将//与后面的字符进行删除,直到碰到换行符
假如出现"/*"那么将从此位置开始删除直到出现"*/",在出现"//"与"/*"之前要记录现在所查看的字符是否在引号中,假如碰到"的话可以直接查找匹配的"中间不用进行比较.这样应该就可以删除注释了。
我还是有点疑问~~~你删除注释要做什么?让别人看不懂你的程序???
网友回复:这个我做过,不过当时是去掉java代码的注释,但基本上是一样的。
网友回复:以前有个朋友写过,
当时BUG是,没做好文件尾的判定,一直找// /*下去了。。
网友回复:以前写过这个程序 很麻烦
网友回复:http://topic.csdn.net/t/20050316/17/3856432.html
网友回复:刚刚编的程序,请大家找找BUG,不过基本实现了去除注释,但是,刚刚用黑盒测试法,发现,假如是/***********\\\///////
这种类型的话,就不能实现了,正在解决问题中,不过先放上来共享下
#include <iostream.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void main()
{
FILE* f;
int i=0;
char buffer,tmp;
f=fopen("test.cpp","r b");//在工程的根目录,请保存”test.cpp"这个文件
while((buffer=getc(f))!=EOF)
cout < <buffer;
cout < <endl
< <"处理后的代码"
< <endl;
rewind(f);
while((buffer=getc(f))!=EOF)
{
switch(buffer)
{
case '/': tmp=getc(f);
switch(tmp)
{
case '/': while(getc(f)!='\r')
;
break;
case '*':
while((tmp=getc(f))!=EOF)
{
//这步判定是否为"*/",否就继续取数据
if(tmp=='/'&&buffer=='*')
break;
buffer=tmp;
}
break;
default:
cout < <buffer;
cout < <tmp;
break;
}
break;
default: cout < <buffer;
break;
}
}
fclose(f);
}
网友回复:
- C/C code
Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ #include <iostream.h> #include <stdlib.h> #include <stdio.h> #include <string.h> void main() { FILE* f; int i=0; char buffer,tmp; f=fopen("test.cpp","r b"); while((buffer=getc(f))!=EOF) cout<<buffer; cout<<endl <<"处理后的代码" <<endl; rewind(f); while((buffer=getc(f))!=EOF) { switch(buffer) { case '/': tmp=getc(f); switch(tmp) { case '/': while(getc(f)!='\r') ; break; case '*': while((tmp=getc(f))!=EOF) { if(tmp=='/'&&buffer=='*') break; buffer=tmp; } break; default: cout<<buffer; cout<<tmp; break; } break; default: cout<<buffer; break; } } fclose(f); }
网友回复:可不可以用正则表达式?
可以用的话,可以很简单的了,呵呵。
网友回复:不考虑 "" 吗?假如""中有 // /* */
网友回复:还有 考虑""时还得考虑里面有 \"的情况
网友回复:我以前写的一个
- C/C code
Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ /* C/C source comment removal tool The language: S -> A | B | S A -> C | D | S B -> S | F | B C -> S | C D -> E | D E -> S | D F -> B ----------------------------------- S: start -- '/' -> A, '"' -> B, <?> -> S A: '/' -- '/' -> C, '*' -> D, <?> -> S B: '"' -- '"' -> S, '\' -> F, <?> -> B C: '/' -- <\n> -> S, <?> -> C D: '*' -- '*' -> E, <?> -> D E: '*' -- '/' -> S, <?> -> D F: '\' -- <?> -> B ----------------------------------- S: 0 A: 1 B: 2 C: 3 D: 4 E: 5 F: 6 */ #include <stdio.h> #include <stdlib.h> #define BUFF_COUNT 16 /* memory buffer */ char buff[BUFF_COUNT]; int cur; /* file pointer */ FILE *out; /* reset buffer */ void resetbuff(void) { cur = 0; memset(buff, 0, BUFF_COUNT * sizeof(char)); } /* save output */ void save(void) { if(cur > 0) { fputs(buff, out); } resetbuff(); } /* S */ int fsms(char ch) { if(ch == '/') { return 1; } else if(ch == '"') { return 2; } else { save(); return 0; } } /* A */ int fsma(char ch) { if(ch == '/') { resetbuff(); return 3; } else if(ch == '*') { resetbuff(); return 4; } else { save(); return 0; } } /* B */ int fsmb(char ch) { if(ch == '"') { save(); return 0; } else if(ch == '\\') { save(); return 6; } else { save(); return 2; } } /* C */ int fsmc(char ch) { if(ch == '\n') { resetbuff(); return 0; } else { resetbuff(); return 3; } } /* D */ int fsmd(char ch) { if(ch == '*') { resetbuff(); return 5; } else { resetbuff(); return 4; } } /* E */ int fsme(char ch) { if(ch == '/') { resetbuff(); return 0; } else { resetbuff(); return 4; } } /* F */ int fsmf(char ch) { resetbuff(); return 2; } /* application start */ int main(int argc, char *argv[]) { FILE *in; /* input */ char ch; /* read char */ int (*mt[])(char) = {fsms, fsma, fsmb, fsmc, fsmd, fsme, fsmf}; /* machine table */ int ms = 0; /* current machine */ /* print welcome message */ printf("C/C Code Comment Removal Tool v1.0\n\n"); /* validate arguments */ if(argc != 3) { printf("Usage: rmcmt.exe <input file> <output file>\n"); exit(1); } /* open input file */ in = fopen(argv[1], "r"); if(!in) { printf("Can't open input file %s.\n", argv[1]); exit(2); } /* open output file */ out = fopen(argv[2], "w"); if(!out) { printf("Can't open output file %s.\n", argv[2]); exit(3); } /* run machines with whole file */ while(1) { /* read from input file */ ch = fgetc(in); if(feof(in)) { save(); break; } /* save buffer */ buff[cur ] = ch; /* run machine */ ms = mt[ms](ch); } /* close */ fclose(in); fclose(out); printf("%s -> %s completed.\n", argv[1], argv[2]); return 0; }
网友回复:写看看
网友回复:对字符串流进行处理:
检测字符串是否是 /* :
若是,则忽略后面的字符串直到 */出现;
若否,则判定是否是 //:
若是 , 则忽略后面的字符串到行尾(行尾字符'/n')
若否 , 则正常输出.
像这样判定就可以了
不考虑 "" 吗?假如""中有 // /* */ ---已考虑
假如有'\' 字符a,则字符a按转译后的字符考虑
网友回复:对忽略字符的过程,不进行字符串(/*或//)的判定,只判定*/或结尾符(/n)
网友回复://假设代码是通过编译器检测,注释符合规范
public static String run(String str){
StringBuffer strb = new StringBuffer("");
int pointer = 0;
while(pointer != str.length()){
char c = str.charAt(pointer);
if('/' == c){
pointer;
if(str.charAt(pointer) == '/'){
while(str.charAt( pointer) != '\n');
pointer;
}
else if(str.charAt(pointer) == '*'){
while(!(str.charAt( pointer) == '*'
&& str.charAt(pointer 1) == '/'));
pointer = pointer 2;
}
}
else{
strb.append(c);
pointer;
}
}
return strb.toString();
}
网友回复:用正则表达式。。。最简单不过
网友回复:学习下.
网友回复:其实这个想写全了很难~
不说别的,光#IF 0这类的编译宏嵌套就够你受的
还有在字符串中/*或者//之类的
以及转义字符
想想这些逻辑就头皮发麻~
网友回复:一次读取一行,分两种情况,因为有两种注释,
1. 在读取到的一行中查找 //, 假如找到,则把 // 及其后的部分扔掉
2. 在读取到的一行中查找 /*,记录位置pos1,然后再在这行中查找 */,假如找到,也记录位置如pos2,扔掉他们与其中的内容,以pos2开始,继续查找 /*; 假如在当前行中没有找到,则去掉当前行中/*及其后的内容,读取新的一行,查找 */,如没有查找,去掉读取到的这一行,再读一行,查找 */, 如找到,记录位置pos2,去掉这一行的0到pos2之间的字符.
3. 进行步骤1, 2,直到全文结束.
网友回复:大家都很牛啊 ~~~~~~~学习中!
网友回复:顶个,这里的气氛我喜欢
网友回复:偶不会
你们都N
学学习习
网友回复:学习了…………
网友回复:面试网站建设?
网友回复:wo 也看看
网友回复:mark
网友回复:就算不考虑编译宏,引号里面的字符串中出现//和/*的情况也是很麻烦的。。。。
网友回复:mark
网友回复:下面是我今天早上重新写过的,和我前天早上面试时写的有点不一样,
那时候比较紧张,很多情况都没有考虑到。
大家帮忙看看我现在写的代码,还有没有遗漏的情况。
以下代码在VC6下编译通过,并用该源代码文件测试过,成功地把其中的注释去掉。
- C/C code
Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ #include <string.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <io.h> /** * 功能:移除C/C 程序代码中的注释 * * 输入:指向C/C 程序代码的指针 */ void remove_comment(char *buf, size_t size) { char *p, *end, c; char *sq_start, *dq_start; char *lc_start, *bc_start; size_t len; p = buf; end = p size; sq_start = NULL; dq_start = NULL; lc_start = NULL; bc_start = NULL; while (p < end) { c = *p; switch (c) { case '\'': /* 单引号 */ if (dq_start || lc_start || bc_start) { /* 忽略字符串与注释中的单引号 */ p ; continue; } if (sq_start == NULL) { sq_start = p ; } else { len = p - sq_start; if (len == 2 && *(sq_start 1) == '\\') { /* 忽略字符中的单引号 */ continue; } sq_start = NULL; } break; case '\"': /* 双引号 */ if (sq_start || lc_start || bc_start) { /* 忽略字符或注释中的双引号 */ p ; continue; } if (dq_start == NULL) { dq_start = p ; } else { if (*(p - 1) == '\\') { /* 忽略字符串中的双引号 */ continue; } dq_start = NULL; } break; case '/': /* 斜杆 */ if (sq_start || dq_start || lc_start || bc_start) { /* 忽略字符、字符串或注释中的斜杆 */ p ; continue; } c = *(p 1); if (c == '/') { lc_start = p; p = 2; } else if (c == '*') { bc_start = p; p = 2; } else { /* 忽略除号 */ p ; } break; case '*': /* 星号 */ if (sq_start || dq_start || lc_start || bc_start == NULL) { /* 忽略字符、字符串或行注释中的星号,还有忽略乘号 */ p ; continue; } if (*(p 1) != '/') { /* 忽略块注释中的星号 */ p ; continue; } p = 2; memset(bc_start, ' ', p - bc_start); bc_start = NULL; break; case '\n': /* 换行符 */ if (lc_start == NULL) { p ; continue; } c = *(p - 1); memset(lc_start, ' ', (c == '\r' ? (p - 1) : p ) - lc_start); lc_start = NULL; break; default: p ; break; } } if (lc_start) { memset(lc_start, ' ', p - lc_start); } } int main(int argc, char *argv[]) { int fd, n; char buf[102400]; fd = open("C:\\Documents and Settings\\Administrator\\桌面\\remove_comment.c", _O_RDONLY, 0); if (fd == -1) { return -1; } n = read(fd, buf, sizeof(buf)); if (n == -1 || n == 0) { close(fd); return -1; } //printf("test\n"); remove_comment(buf, n); *(buf n) = '\0'; printf(buf); /***********\\\/////// */ close(fd); return 0; } // dkdkddlsdkkkkkkkkkkkkkkk /* dkdkdk */ // ididiiddddddddddddddddd // dkdkdkkkkkkkkkkkkkkkk /***********\\\////*////
网友回复:MARK!
网友回复:learning....
网友回复:要考虑的非凡情况:
1.“”中的// /*
2. 这个字符'//'
3. // 与 /*的嵌套关系
A。///*
B。/* //*/……
网友回复:mark
网友回复:
这些非凡情况在我写的代码中已经考虑到了!
网友回复:面试题:编写一函数,实现把C/C 程序代码中的注释去掉?
http://blog.csdn.net/ngwsx/archive/2008/04/04/2250186.aspx
网友回复:The C Programming Language 最开始那一章的习题。
网友回复:
误会了,我不是说你的代码有问题。
另外,又想到
#if 与 #endif之间的 /*
网友回复:#if 与 #endif之间的注释是去掉还是保留?
网友回复:lz,你的代码还是有问题。
网友回复:
请说说是在什么情况下?
网友回复:
- C/C code
Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ #include <iostream> #include <stack> #include <fstream> #include <cstdio> int main() { FILE *fp = fopen("main.cpp", "r"); if (!fp) { std::cerr << "Error" << std::endl; return 1; } // Google char ch, nextCh; // Google while ((ch = fgetc(fp)) != EOF) { if ('/' == ch) { nextCh = fgetc(fp); if ('/' == nextCh) { while (((ch = fgetc(fp)) != EOF)) { if ('\n' == ch) { std::cout << std::endl; break; } } } else if ('*' == nextCh) { while ((ch = fgetc(fp)) != EOF) { if ('*' == ch) { nextCh = fgetc(fp); if (nextCh == EOF || '/' == nextCh) { break; } } } } else { std::cout << /**Commentar*/ch << nextCh; } /**Commentar*/ /**Com * mentar*/ } else { std::cout << ch; } } /***********\\\/////// */ ///**// return 0; }
网友回复:mark
-----------------------------------------------------------------------------------------------------------------------------

网友回复:呵呵,题目看似很简单,写起来却不是很顺手
网友回复:xuexi
网友回复:学习中
网友回复:你随便试试,我是随便写了几行,有的注释就没去掉。
网友回复:用自动机吧,我记得我们做过作业的
网友回复:我练习了一下,没考虑宏的影响,只考虑字符串的影响。我的测试用例:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
cout < <"line 1 // hello" < <endl; // line 1
cout < <"line 2 /* haha~ */" < <endl; // line 2
cout < <"line 3 \" /* hehe */" < <endl; /* line 3 */
/* ********\\\\\\\\\\/////////********
this is test program
this is test program
this is test program
*/
return 0;
}
去掉后
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
cout < <"line 1 // hello" < <endl;
cout < <"line 2 /* haha~ */" < <endl;
cout < <"line 3 \" /* hehe */" < <endl;
return 0;
}
宏的影响能不能给个例子,参考一下,好设计测试。。。
网友回复:
麻烦举个例子好吗?
网友回复://dshjhffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
"k//*/sjfkl
sdk
//
//jdklfs
remove_comment.c的内容。
输出:
"k//*/sjfkl
sdk
//
//jdklfsPress any key to continue
网友回复:楼上的输出是对的吧...
网友回复://jdklfsPress any key to continue这行注释没去掉吧。
网友回复:MARK
网友回复:#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
/**
* 功能:移除C/C 程序代码中的注释
*
* 输入:指向C/C 程序代码的指针
*/
void
remove_comment(char *buf, size_t size)
{
char *p, *end, c;
char *sq_start, *dq_start;
char *lc_start, *bc_start;
size_t len;
p = buf;
end = p size;
sq_start = NULL;
dq_start = NULL;
lc_start = NULL;
bc_start = NULL;
while (p < end) {
c = *p;
switch (c) {
case '\'': /* 单引号 */
if (dq_start ¦ ¦ lc_start ¦ ¦ bc_start) {
/* 忽略字符串与注释中的单引号 */
p ;
continue;
}
if (sq_start == NULL) {
sq_start = p ;
} else {
len = p - sq_start;
if (len == 2 && *(sq_start 1) == '\\') {
/* 忽略字符中的单引号 */
continue;
}
sq_start = NULL;
}
break;
case '\"': /* 双引号 */
if (sq_start ¦ ¦ lc_start ¦ ¦ bc_start) {
/* 忽略字符或注释中的双引号 */
p ;
continue;
}
if (dq_start == NULL) {
dq_start = p ;
} else {
if (*(p - 1) == '\\') {
/* 忽略字符串中的双引号 */
continue;
}
dq_start = NULL;
}
break;
case '/': /* 斜杆 */
if (sq_start ¦ ¦ dq_start ¦ ¦ lc_start ¦ ¦ bc_start) {
/* 忽略字符、字符串或注释中的斜杆 */
p ;
continue;
}
c = *(p 1);
if (c == '/') {
lc_start = p;
p = 2;
} else if (c == '*') {
bc_start = p;
p = 2;
} else {
/* 忽略除号 */
p ;
}
break;
case '*': /* 星号 */
if (sq_start ¦ ¦ dq_start ¦ ¦ lc_start ¦ ¦ bc_start == NULL) {
/* 忽略字符、字符串或行注释中的星号,还有忽略乘号 */
p ;
continue;
}
if (*(p 1) != '/') {
/* 忽略块注释中的星号 */
p ;
continue;
}
p = 2;
memset(bc_start, ' ', p - bc_start);
bc_start = NULL;
break;
case '\n': /* 换行符 */
if (lc_start == NULL) {
p ;
continue;
}
c = *(p - 1);
memset(lc_start, ' ',
(c == '\r' ? (p - 1) : p ) - lc_start);
lc_start = NULL;
break;
default:
p ;
break;
}
}
if (lc_start) {
memset(lc_start, ' ', p - lc_start);
}
}
int
main(int argc, char *argv[])
{
int fd, n;
char buf[102400];
fd = open("C:\\Documents and Settings\\Administrator\\桌面\\remove_comment.c",
_O_RDONLY, 0);
if (fd == -1) {
return -1;
}
n = read(fd, buf, sizeof(buf));
if (n == -1 ¦ ¦ n == 0) {
close(fd);
return -1;
}
//printf("test\n");
remove_comment(buf, n);
*(buf n) = '\0';
printf(buf);
/***********\\\/////// */
close(fd);
return 0;
}
网友回复:解决这个问题 是不是要写出 注释语句 的正则表达式,然后按表达式中满足的条件去掉注释
感觉这个问题有点象是写编译器的词法和语法器的一部分。。。
网友回复:学习一下
网友回复:以下是我把lz的改了改,还有一些问题。lz再看看吧。
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
/**
* 功能:移除C/C 程序代码中的注释
*
* 输入:指向C/C 程序代码的指针
*/
void
remove_comment(char *buf, size_t size)
{
char *p, *end, c;
char *sq_start, *dq_start;
char *lc_start, *bc_start;
size_t len;
p = buf;
end = p size;
sq_start = NULL;
dq_start = NULL;
lc_start = NULL;
bc_start = NULL;
while (p < end) {
c = *p;
switch (c) {
case '\'': /* 单引号 */
if (dq_start ¦ ¦ lc_start ¦ ¦ bc_start) {
/* 忽略字符串与注释中的单引号 */
p ;
continue;
}
if (sq_start == NULL) {
sq_start = p ;
} else {
len = p - sq_start;
// if (len == 2 && *(sq_start 1) == '\\') {
/* 忽略字符中的单引号 */
// continue;
// }
sq_start = NULL;
}
break;
case '\"': /* 双引号 */
if (sq_start ¦ ¦ lc_start ¦ ¦ bc_start) {
/* 忽略字符或注释中的双引号 */
p ;
continue;
}
if (dq_start == NULL) {
dq_start = p ;
} else {
dq_start = NULL;
}
break;
case '/': /* 斜杆 */
if (sq_start ¦ ¦ dq_start ¦ ¦ lc_start ¦ ¦ bc_start) {
/* 忽略字符、字符串或注释中的斜杆 */
p ;
continue;
}
c = *(p 1);
if (c == '/') {
lc_start = p;
p = 2;
} else if (c == '*') {
bc_start = p;
p = 2;
} else {
/* 忽略除号 */
p ;
}
break;
case '*': /* 星号 */
if (sq_start ¦ ¦ dq_start ¦ ¦ lc_start ¦ ¦ bc_start == NULL) {
/* 忽略字符、字符串或行注释中的星号,还有忽略乘号 */
p ;
continue;
}
if (*(p 1) != '/') {
/* 忽略块注释中的星号 */
p ;
continue;
}
p = 2;
memset(bc_start, ' ', p - bc_start);
bc_start = NULL;
break;
case '\n': /* 换行符 */
if (sq_start== NULL && dq_start== NULL && lc_start== NULL && bc_start== NULL) {
p ;
continue;
}
// c = *(p - 1);
if (sq_start) {
memset(sq_start, ' ', p - sq_start);
}
if (dq_start) {
memset(dq_start, ' ', p - dq_start);
}
if (lc_start) {
memset(lc_start, ' ', p - lc_start);
}
if (bc_start) {
memset(bc_start, ' ', p - bc_start);
}
lc_start = NULL;
sq_start= NULL;
dq_start= NULL;
bc_start= NULL;
p ;
break;
default:
p ;
break;
}
}
}
int
main(int argc, char *argv[])
{
int fd, n;
char buf[102400];
fd = open("C:\\Documents and Settings\\Administrator\\桌面\\remove_comment.c",
_O_RDONLY, 0);
if (fd == -1) {
return -1;
}
n = read(fd, buf, sizeof(buf));
if (n == -1 ¦ ¦ n == 0) {
close(fd);
return -1;
}
//printf("test\n");
remove_comment(buf, n);
*(buf n) = '\0';
printf(buf);
/***********\\\/////// */
close(fd);
return 0;
}
网友回复:接分是王道!
网友回复:大家都很厉害啊,我正学习中。。。。见识见识!
关键字:昨天上午,试题,做做,
下一篇:下面没有链接了











文章评论
共有 0 位网友发表了评论 此处只显示部分留言 点击查看完整评论页面