`
qqchinaok
  • 浏览: 213423 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论
阅读更多

   
程序员面试宝典上面的题目有很多是很经典的问题,可供我们思考,而且会对我们面试有很大好处。

下面是第45页的一个题目:编写一个函数,实现把C/C++程序代码中的注释去掉,我开始看的时候总是看不懂,后来在网上看到一个网友详细的分析了其代码,但是我看了之后觉得有好多地方他分析的都不对,于是,我自己又花了半天的时间分析了一遍,觉得自己理解了,下面给出我的分析语句。如果还有不严谨的部分,请指教!

/********************************************************<br>
功能:去除C/C++中的注释<br>
输入:指向C/C++程序代码的指针及长度<br>
来源:程序员面试宝典第45页

分析:一次读取一行,分两种情况,因为有两种注释:

(1)在读取到的一行中查找“//”,如果找到,则把“//”及其后的部分扔掉。

(2)在读取到的一行中查找“/*”,记录位置pos1,然后再在这行中查找“*/”,如果找到,也记录位置pos2,扔掉它们与其中的内容,以pos2开始,继续查找“/*”;如果在当前行中没有找到,则去掉当前行中“/*”及其后的内容,读取新的一行,查找“*/”,如没有。则去掉读取到的这一行,再读一行,查找“*/”,如找到,记录位置pos2,去掉这一行的0到pos2之间的字符。

(3)进行步骤1、步骤2,直到程序结束。

编程时要考虑的特殊情况i:

<img src="http://img.baidu.com/hi/babycat/C_0002.gif" alt="" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-color: initial;">“”中的“//”“/*”

<img src="http://img.baidu.com/hi/babycat/C_0012.gif" alt="" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-color: initial;">''中的“//”“/*”

<img src="http://img.baidu.com/hi/babycat/C_0004.gif" alt="" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-color: initial;">“//”与“/*”的嵌套关系,比如///* 、/* //*/<br>
*********************************************************/

#include <stdio.h><br>
#include <stdlib.h><br>
#include <fcntl.h><br>
#include <string.h><br>
#include <unistd.h><br>
#include <sys/types.h>

void remove_comment(char *buf, size_t size)<br>
{<br>
char *p, *end, c; //p-动态移动的字符指针,end-指向文件末尾的字符指针,c-存储没一个p指向的字符<br>
char *sq_start, *dq_start; //sq_start-单引号开始位置(single),dq_start-双引号开始(double)<br>
char *lc_start, *bc_start; //lc_start-//的开始位置,bc_start-/*的开始位置<br>
size_t len; //记录某符号结束和开始的位置之差(长度,偏移量)<br><br>
p = buf;<br>
end = p + size;<br>
sq_start = dq_start = NULL;<br>
lc_start = bc_start = NULL;<br><br>
while (p < end) /*当指针没有到达文件末尾*/<br>
{<br>
c = *p; //用字符变量c存储指针指向的字符<br><br>
switch (c) //根据c的值做相应处理<br>
{<br>
case '\'': /*处理单引号*/<br>
{<br>
if (dq_start || lc_start || bc_start) //当遇到过双引号、//或/*的时候,则不需要再判断'//'的情况了。<br>
{<br>
p++;<br>
continue; //继续下一个,对while而言的<br>
}<br>
/*******************************以下是没有遇到过双引号或//或/*的时候*******************************/<br>
if (sq_start == NULL) /****如果未遇到单引号****/<br>
{<br>
sq_start = p++; //start指向单引号的开始位置,p指向下一个

}<br>
else /*如果遇到过单引号,sq_start指向单引号开始位置*/<br>
{<br>
len = (p++) -sq_start;

if (len == 2 &amp;&amp; *(sq_start+1) == '\\')

{

/*若遇到 “ '\'' ”这种情况则两个单引号并未匹配,遇到的“'”是“\' ”中的,而不是与sq_start所指向单引号匹配*/<br>
continue;<br>
}<br><br>
sq_start = NULL; //否则将sq_start置位为NULL

}<br>
/*******************************以上是没有遇到过双引号或//或/*的时候*******************************/<br>
break;<br>
}<br><br>
case '\"': /*处理双引号*/<br>
{<br>
if (sq_start || lc_start || bc_start) //当遇到过单引号、//或/*的时候,则不需要处理<br>
{<br>
p++;<br>
continue;<br>
}<br>
/*****************以下是没有遇到过单引号或//或/*的时候*****************/<br>
if (dq_start == NULL) /*如果没有遇到过双引号*/<br>
{<br>
dq_start = p++; //标记遇到了双引号<br>
}<br>
else if (*((p++) -1) =='\\')

{

/*若遇到 “"ab\''cd" ”这种情况则两个双引号并未匹配,遇到的“"”是“\"”中的,而不是与dq_start所指向双引号匹配*/<br>
continue;<br>
}<br>
dq_start = NULL; //如果双引号中不是//,标记为NULL<br>
/*****************以上是没有遇到过单引号或//或/*的时候*****************/<br>
}<br><br>
case '/': //斜杠,注意这个斜杠也可以是'//',"//",//,/*/中的第二个斜杠,但会在下面第二行代码中被忽略掉<br>
{<br>
if (sq_start || dq_start || lc_start || bc_start) //如果是单引号、双引号、斜杠、/*的后面<br>
{<br>
p++;<br>
continue;<br>
}<br>
/***********************下面是遇到注释//或/*的时候****************************/<br>
c = *(p + 1); //否则c取p指向字符的下一个字符<br>
if (c == '/') //遇到了双斜杠<br>
{<br>
lc_start = p; //标记双斜杠的开始<br>
p += 2; //p指向双斜杠后面的字符<br>
}<br>
else if (c == '*') //遇到了/*<br>
{<br>
bc_start = p; //标记/*的开始<br>
p += 2; //p指向/*后面的字符<br>
}<br>
/*************************上面是遇到注释//或/*的时候**************************/<br>
else<br>
{

p++;<br>
}<br>
}<br><br>
case '*': //星号,同斜杠,但少了如果遇到/*的情况,因为遇到这种情况后,要判断是不是遇到结束的地方*/了<br>
{<br>
if (sq_start || dq_start || lc_start) //如果是单引号、双引号、斜杠、/*的后面<br>
{<br>
p++;<br>
continue;<br>
}<br><br>
if (*(p + 1) != '/') //如果星号后面紧跟的不是斜杠,那么忽略过。<br>
{<br>
p++;<br>
continue;<br>
}<br><br>
p += 2; //否则p指向斜杠后面那个字符。注意下面的清空语句,p指向的那个字符并不会被清除。<br>
memset(bc_start, ' ', p-bc_start); //清空/* …… */中间的内容包括注释符号本身。<br>
bc_start = NULL;<br>
break;<br>
}<br><br>
case '\n': /*换行符,主要处理遇到双斜杠时,需要清除双斜杠到\n的前面的字符*/<br>
{<br>
if (lc_start == NULL) //如果还没有遇到双斜杠,那么忽略<br>
{<br>
p++;<br>
continue;

}<br><br>
c = *(p - 1);<br>
/*如果遇到过双斜杠,清空双斜杠本身和到\n前面的那个字符,p指向下一个字符,/r是回车符(光标退回到最前面),这里要判断

c == '\r'是因为在UNIX系统下文件结尾的换行只有\n,而windows系统下文件结尾的换行为\r\n */

memset(lc_start, ' ', (c == '\r'? ((p++) -1) : p++) - lc_start);<br>
lc_start = NULL;<br>
break;<br>
}<br><br>
default:<br>
p++;<br>
break;<br>
}<br>
/****************************************************<br>
如果遇到双斜杠,这个if语句存在的意义在于万一最后<br>
一行代码是带有双斜杠但没有给换行符\n的,也要清除掉。<br>
*****************************************************/<br>
if (lc_start)<br>
{<br>
memset(lc_start, ' ', p - lc_start);<br>
}<br>
}<br>
}

/**********************************************<br>
main函数的开始<br>
***********************************************/<br>
int main (int argc, char *argv[])<br>
{<br>
int fd, n;<br>
char buf[102400];<br><br>
if (argc != 2)<br>
{<br>
printf("command error: Input as ./command <file>\n");<br>
}<br><br>
fd = open(argv[1], O_RDONLY); /*只读打开*/<br>
if (fd == -1)<br>
{<br>
return -1;<br>
}<br><br>
n = read(fd, buf, sizeof(buf));<br>
if (n == -1 || n == 0)<br>
{<br>
close(fd);<br>
return -1;<br>
}<br>
printf("test\n");<br>
remove_comment(buf, n);<br>
*(buf + n) = '\0';<br>
printf("%s", buf);<br>
close(fd);<br><br>
return 0;<br>
}
 
0
0
分享到:
评论

相关推荐

    C/C++源程序注释的删除

    C语言注释删除程序 [程序功能] 1、删除注释,包括块注释(/**/)和行注释(//) 2、删除空白行 3、用指定数量的空格替换TAB字符 [使用方法] 1、在WINDOWS的CMD窗口中键入行命令 2、使用WINDOWS的批处理文件(.BAT...

    清除c/c++代码中条件编译部分的程序,帮助阅读源代码,生成好的tags

    网上众多的开源C/C++代码,因为跨平台的需要,参杂了许多的条件编译语句,对阅读源代码造成了不方便,而且用ctags等工具生成源代码的tags文件时会有些妨碍,本工具就是用来预处理这些条件编译的,将未定义的区域自动...

    原程序注释

    给定 C/C++ 源程序的源代码,要求去掉所有的注释代码并输出去除注释后的代码。已知 C/C++ 代码的注释有两种:单行注释和多行注释,前者稳以“ // ”引导的行;后者则是由“ /* ”和“ */ ”包含的部分,可以在同一...

    去除C++源文件注释

    完美去除C++注释 包括 行注释 与 块注释

    c/c++词法分析预处理

    c/c++词法分析预处理cpp源代码,将同目录下"abc.cpp"去除跳格回车换行注释和不必要的空格,输出文件"abc_chuli.cpp",因为具体要求不同,这处理出来的文件还是能继续编译运行。

    去除源程序注释

    给定 C/C++源程序的源代码,要求去掉所有的注释代码并输出去除注释后的代码。已知 C/C++ 代码的注释有两种:单行注释和多行注释,前者稳以“//”引导的行;后者则是由“/*”和 “*/”包含的部分,可以在同一行内,也...

    源代码注释清理器(清除C++源码中的所有注释内容,简单易用)

    1.功能:此程序能够去除 C++程序源文件中的所有注释,能识别“//”与“/**/”两种注释 2.用法:将待清理的 C++源代码 存为纯文本形式“test.txt”,将文本文件copy到CommentCleaner.exe同一个文件夹内,运行 ...

    Qt编写移除C++代码注释源码

    Qt5编写的移除代码注释源码,Qt5编写的移除代码注释源码,

    c/c++课程设计学生成绩管理系统

    关于c语言和c++的课程成绩信息管理系统,共有将近6000行代码,建议使用vs2012或2010便于管理也可使用VC6.0++环境修改运行但查找麻烦,所有的语言没有脱离c和c++,主要采用模块思想,也可以转换成面向对象型的语言,...

    C8051程序注释

    C8051单片机编程例程注释,帮助初学者更好的了解程序编写过程,熟悉程序。以便于在此基础上进行更改,开发自己的程序。

    计算机视觉OpenCV CLAHE C++源代码详细注释版

    本资源为OpenCV CLAHE源代码改造而成: 1、去除了OPENCL处理相关的代码; 2、将其改造成了一个可以独立执行的程序; 3、增加了详细注释,在现有网上公开资料中没有如此详细透彻的注释。

    C和C++头文件对比一览

    很多C++程序代码依赖那些已经存在很多年的C++ “准”标准程序库(C++迟迟未标准化才导致这些情况的发生),例如iosteam.h,complex.h等等。 为了解决这个新出现的问题,标准化委员会决定设计一些新的头文件名,给...

    c++面试大全文档(很全的哦)

    一、请你就C/C++或者JAVA代码行数、注释行数统计工具的实现,描述一下: 1、 需要考虑哪些过滤条件?你如何处理? 答:过滤条件:(取得每行并去掉两头的空格后) ⑴空行,行的长度为0;⑵如果是以//开头,为注释...

    删除代码注释

    我写的一个能够删除C、C++代码中注释的程序,删除JAVA代码的注释应该也是可以的^_^

    新手学习C++入门资料

    这些关键字能作为函数和变量的标识符在C程序中使用,尽管C++包含了所有的C,但显然没有任何C++编译器能编译这样的C程序。 C程序员可以省略函数原型,而C++不可以,一个不带参数的C函数原型必须把void写出来。而C++...

    简单编译器 编译技术课程设计源代码及文档

    (2)用C/C++语言编写词法分析程序(应考虑能被语法分析程序调用) (3)预处理,去除注释、多余空格、回车换行符等 (3)设计实现语法分析程序(调用上述词法程序分析单词) (4)设计构造属性文法及中间代码序列结构 (5)采用...

    各种开发语言注释清理工具

    C++, C#,Java代码批量清理注释工具,支持自定义文件类型清理。

    C++网络爬虫项目

    WEBCRAWLER 网络爬虫实训项目 1 WEBCRAWLER 网 络 爬 虫 实 训 项 目 文档版本: 1.0.0.1 编写单位: 达内IT培训集团 C++教学研发部 编写人员: 闵卫 ...本框架,但代码中的注释和teacher目录下对应的部分...

    Visual C++开发经验技巧宝典(第1章)

    0072 为什么在程序中广泛使用STL 30 0073 如何在STL中使用容器 30 0074 STL算法的优点 31 0075 如何设计和使用STL迭代器 31 0076 使用STL需要包含哪些头文件 32 0077 STL简单应用 32 1.10 C++.NET语法...

    图像抠图DIS-自然图像中高精度二分图像抠图的方法(C++推理代码)

    二分图像分割(DIS),旨在从自然图像中分割高精度的对象。为此,我们收集了第一个大规模DIS数据集,称为DIS5K,其中包含5470张高分辨率(例如2K、4K或更大)图像,涵盖各种背景中的伪装、突出或精细物体。DIS使用极...

Global site tag (gtag.js) - Google Analytics