首页 > 编程 > C++ > 正文

去除C/C++中的注释

2019-11-06 07:53:32
字体:
来源:转载
供稿:网友
/******************************************************** 功能: 输入:指向C/C++程序代码的指针及长度 来源:程序员面试宝典第45页

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

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

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

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

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

“”中的“//”“/*”

''中的“//”“/*”

“//”与“/*”的嵌套关系,比如///* 、/*  //*/ *********************************************************/

#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <string.h>#include <unistd.h>#include <sys/types.h>void remove_comment(char *buf, size_t size){ char *p, *end, c;                //p-动态移动的字符指针,end-指向文件末尾的字符指针,c-存储没一个p指向的字符 char *sq_start, *dq_start;   //sq_start-单引号开始位置(single),dq_start-双引号开始(double) char *lc_start, *bc_start;    //lc_start-//的开始位置,bc_start-/*的开始位置 size_t len;                         //记录某符号结束和开始的位置之差(长度,偏移量)  p = buf; end = p + size; sq_start = dq_start = NULL; lc_start = bc_start = NULL;  while (p < end)      /*当指针没有到达文件末尾 */ {  c = *p;                //用字符变量c存储指针指向的字符    switch (c)             //根据c的值做相应处理  {   case '/'':              /*处理单引号*/   {    if (dq_start || lc_start || bc_start)          //当遇到过双引号、//或/*的时候,则不需要再判断'//'的情况了。    {     p++;     continue;                          //继续下一个,对while而言的    }    /*******************************以下是没有遇到过双引号或//或/*的时候*******************************/    if (sq_start == NULL)     /****如果未遇到单引号****/    {     sq_start = p++;            //start指向单引号的开始位置,p指向下一个</p><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:tahoma,arial,宋体,sans-serif; font-size:15px; line-height:18px">    }    else                              /*如果遇到过单引号,sq_start指向单引号开始位置*/    {     len = (p++) -sq_start;        if (len == 2 && *(sq_start+1) == '//'){     /*若遇到 “  '/''   ”这种情况则两个单引号并未匹配,遇到的“'”是“/' ”中的,而不是与sq_start所指向单引号匹配*/      continue;     }          sq_start = NULL;      //否则将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) =='//')     /*若遇到 “" ab/''cd"   ”这种情况则两个双引号并未匹配,遇到的“"”是“/"”中的,而不是与dq_start所指向双引号匹配*/     continue;    }    dq_start = NULL;                 //如果双引号中不是//,标记为NULL    /*****************以上是没有遇到过单引号或//或/*的时候*****************/   }      case '/':            //斜杠,注意这个斜杠也可以是'//',"//",//,/*/中的第二个斜杠,但会在下面第二行代码中被忽略掉   {    if (sq_start || dq_start || lc_start || bc_start) //如果是单引号、双引号、斜杠、/*的后面    {     p++;     continue;    }    /***********************下面是遇到注释//或/*的时候****************************/    c = *(p + 1);         //否则c取p指向字符的下一个字符    if (c == '/')            //遇到了双斜杠    {     lc_start = p;         //标记双斜杠的开始     p += 2;                //p指向双斜杠后面的字符    }    else if (c == '*')     //遇到了/*    {     bc_start = p;       //标记/*的开始     p += 2;              //p指向/*后面的字符    }    /*************************上面是遇到注释//或/*的时候**************************/    else    {     p++;     }   }      case '*': //星号,同斜杠,但少了如果遇到/*的情况,因为遇到这种情况后,要判断是不是遇到结束的地方*/了   {    if (sq_start || dq_start || lc_start) //如果是单引号、双引号、斜杠、/*的后面    {     p++;     continue;     }        if (*(p + 1) != '/') //如果星号后面紧跟的不是斜杠,那么忽略过。    {     p++;     continue;    }        p += 2; //否则p指向斜杠后面那个字符。注意下面的清空语句,p指向的那个字符并不会被清除。    memset(bc_start, ' ', p-bc_start); //清空/* …… */中间的内容包括注释符号本身。    bc_start = NULL;    break;   }      case '/n': /*换行符,主要处理遇到双斜杠时,需要清除双斜杠到/n的前面的字符*/   {    if (lc_start == NULL) //如果还没有遇到双斜杠,那么忽略    {     p++;     continue;     }        c = *(p - 1);    /*如果遇到过双斜杠,清空双斜杠本身和到/n前面的那个字符,p指向下一个字符,/r是回车符(光标退回到最前面),这里要判断</p><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:tahoma,arial,宋体,sans-serif; font-size:15px; line-height:18px">   c == '/r'是因为在UNIX系统下文件结尾的换行只有/n,而windows系统下文件结尾的换行为/r/n   */</p><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:tahoma,arial,宋体,sans-serif; font-size:15px; line-height:18px">    memset(lc_start, ' ', (c == '/r'? ((p++) -1) : p++) - lc_start);     lc_start = NULL;    break;   }      default:    p++;    break;  }  /****************************************************  如果遇到双斜杠,这个if语句存在的意义在于万一最后  一行代码是带有双斜杠但没有给换行符/n的,也要清除掉。    *****************************************************/  if (lc_start)   {   memset(lc_start, ' ', p - lc_start);  } }}/**********************************************   main函数的开始***********************************************/int main (int argc, char *argv[]){ int fd, n; char buf[102400];  if (argc != 2) {  PRintf("command error: Input as ./command <file>/n"); }  fd = open(argv[1], O_RDONLY); /*只读打开*/ 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("%s", buf); close(fd);  return 0;}


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选