找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 6068|回复: 1

【C】C语言写的给C语言源代码去掉注释的程序

[复制链接]

1112

主题

1653

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
245
威望
744 点
宅币
24254 个
贡献
46222 次
宅之契约
0 份
在线时间
2298 小时
注册时间
2014-1-26
发表于 2014-11-17 08:38:57 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
作用就是去掉注释。别小看这个程序了,因为去掉注释并不像大家想的那么简单——因为//和/*不一定都是注释,比如下面的代码:
char szUrl[]="http://www.0xaa55.com/";
看见没有?这里就不能简单地把“//www.0xaa55.com/";”去掉了。
解决的方法是对"和'进行识别,把引号内的//和/*无视掉,仅对“正常”的//和/*进行判定。这样就能保证不会错误地删除不是注释的部分了。

我写的这个控制台程序用法很简单,它只有一个参数:文件名。然后经过处理的代码直接输出到stdout,如果你要把内容写入文件,请使用重定向命令:cmntkill a.c>a.txt
  1. //=============================================================================
  2. //作者:0xAA55
  3. //论坛:http://0xaa55.com
  4. //版权所有(C) 2013-2014 技术宅的结界
  5. //
  6. //用途:
  7. //将C、C艹文件中的注释去掉
  8. //-----------------------------------------------------------------------------
  9. #include<stdio.h>
  10. #include<stdlib.h>
  11. #include<string.h>

  12. //=============================================================================
  13. //函数:Usage
  14. //描述:打印程序的用法。
  15. //-----------------------------------------------------------------------------
  16. void Usage(char*argv0)
  17. {
  18.         fprintf(stderr,
  19. "cmntkill: This tool is used to remove the comments in a C\\C++ source file.\n"
  20. "Usage:\n"
  21. "%s inputfile\n",
  22.         argv0);
  23. }

  24. #define        LineLen        80

  25. //=============================================================================
  26. //函数:ReadLine
  27. //描述:读取完整的一行
  28. //返回分配了内存的一行字符串,pLineLength返回行长度(不包括结尾的0)
  29. //-----------------------------------------------------------------------------
  30. char*ReadLine(FILE*fp,size_t*pLineLength)
  31. {
  32.         char szLineBuf[LineLen];
  33.         char*pChNewLine;
  34.         size_t cbLineLen=0;
  35.         long pCurPos;
  36.        
  37.         pCurPos=ftell(fp);
  38.         while(!feof(fp))
  39.         {
  40.                 //连续读取文件,直到找到换行符
  41.                 fread(szLineBuf,1,LineLen,fp);
  42.                 pChNewLine=strchr(szLineBuf,'\n');
  43.                 if(pChNewLine)//如果找到换行符
  44.                 {
  45.                         cbLineLen+=(size_t)pChNewLine+1-(size_t)szLineBuf;//计算行长度

  46.                         //转到读取的位置
  47.                         fseek(fp,pCurPos,SEEK_SET);

  48.                         //分配内存来存放字符串
  49.                         pChNewLine=(char*)malloc(cbLineLen);
  50.                         if(!pChNewLine)
  51.                                 return NULL;

  52.                         //读取行
  53.                         fread(pChNewLine,1,cbLineLen,fp);
  54.                         pChNewLine[cbLineLen-1]='\0';//去掉结尾的换行符
  55.                         if(pLineLength)//返回行长度
  56.                                 *pLineLength=cbLineLen-1;
  57.                         return pChNewLine;
  58.                 }
  59.                 else
  60.                         cbLineLen+=LineLen;
  61.         }
  62.        
  63.         //如果读到文件尾都没遇到换行符,则这个文件只有一行
  64.         fseek(fp,0,SEEK_END);
  65.         cbLineLen=(size_t)ftell(fp)-(size_t)pCurPos;
  66.         if(!cbLineLen)
  67.         {
  68.                 fgetc(fp);//使feof返回非零
  69.                 return NULL;
  70.         }

  71.         //转到读取的位置
  72.         fseek(fp,pCurPos,SEEK_SET);

  73.         //分配内存
  74.         pChNewLine=(char*)malloc(cbLineLen+1);
  75.         if(!pChNewLine)
  76.                 return NULL;

  77.         //读取行
  78.         fread(pChNewLine,1,cbLineLen,fp);
  79.         pChNewLine[cbLineLen]='\0';//结尾
  80.         if(pLineLength)//返回行长度
  81.                 *pLineLength=cbLineLen;
  82.         return pChNewLine;
  83. }


  84. //=============================================================================
  85. //函数:RightTrim
  86. //描述:把字符串右边的空格、TAB去掉
  87. //-----------------------------------------------------------------------------
  88. void RightTrim(char*szLine)
  89. {
  90.         size_t cbLine;
  91.         char*pChr;

  92.         cbLine=strlen(szLine);
  93.         pChr=&szLine[cbLine-1];

  94.         while(cbLine--)
  95.         {
  96.                 switch(*pChr)//判断字符
  97.                 {
  98.                 case' ':
  99.                 case'\t':
  100.                         *pChr='\0';//去掉空格或TAB
  101.                         pChr--;
  102.                         continue;
  103.                 default://遇到其它字符,则返回
  104.                         return;
  105.                 }
  106.         }
  107. }

  108. //=============================================================================
  109. //函数:main
  110. //描述:程序入口点
  111. //-----------------------------------------------------------------------------
  112. int main(int argc,char**argv)
  113. {
  114.         FILE        *fp;
  115.         char        *szLine;
  116.         size_t        cbLine;
  117.         int                InComment=0;//是否在注释内
  118.         size_t        LineNo=1;

  119.         if(argc<2)
  120.         {
  121.                 Usage(argc?argv[0]:"defconst");
  122.                 return 1;
  123.         }

  124.         fp=fopen(argv[1],"r");
  125.         if(!fp)
  126.         {
  127.                 fputs("Could not read file.\n",stderr);
  128.                 return 2;
  129.         }

  130.         while(!feof(fp))
  131.         {

  132.                 szLine=ReadLine(fp,&cbLine);
  133.                 if(!szLine)
  134.                 {
  135.                         if(feof(fp))
  136.                                 break;
  137.                         fputs("Insufficient memory.\n",stderr);
  138.                         goto Cleanup;
  139.                 }

  140.                 RightTrim(szLine);

  141.                 //如果是在/**/的注释内
  142.                 if(InComment)
  143.                 {
  144.                         char*pEnd;//直接找结尾
  145.                         pEnd=strstr(szLine,"*/");
  146.                         if(pEnd)//找到了结尾
  147.                         {
  148.                                 InComment=0;//在注释外了
  149.                                 pEnd+=2;//看后面有没有内容
  150.                                 if(*pEnd)//有的话把后面的内容覆盖到前面
  151.                                 {
  152.                                         size_t cbRemains;
  153.                                         cbRemains=strlen(pEnd);
  154.                                         memmove(szLine,pEnd,cbRemains);//覆盖到前面
  155.                                         szLine[cbRemains]='\0';
  156.                                         //接着就会跳到if(!InComment)那里继续处理
  157.                                 }
  158.                                 else//后面没内容,这是空行
  159.                                 {
  160.                                         fputc('\n',stdout);//输出一个空行
  161.                                         free(szLine);
  162.                                         continue;
  163.                                 }
  164.                         }
  165.                         else//没找到结尾,整行都是注释
  166.                         {
  167.                                 fputc('\n',stdout);//输出一个空行
  168.                                 free(szLine);
  169.                                 continue;
  170.                         }
  171.                 }

  172.                 //如果是在/**/的注释外
  173.                 if(!InComment)
  174.                 {
  175.                         char*pStr;

  176.                         //遍历这行字符串
  177. ParseStr:        for(pStr=szLine;*pStr;pStr++)
  178.                         {
  179.                                 if(!strncmp(pStr,"//",2))//如果找到了单行注释
  180.                                 {
  181.                                         *pStr='\0';//直接将其干掉
  182.                                         break;//这一行处理结束
  183.                                 }
  184.                                 if(!strncmp(pStr,"/*",2))//如果找到了多行注释
  185.                                 {
  186.                                         char*pEnd;//直接找结尾
  187.                                         pEnd=strstr(pStr,"*/");
  188.                                         if(pEnd)//如果找到了说明这个多行注释只在一行内
  189.                                         {
  190.                                                 pEnd+=2;//跳过注释结束的标识
  191.                                                 if(*pEnd)//后面有内容
  192.                                                 {
  193.                                                         size_t cbRemains;
  194.                                                         cbRemains=strlen(pEnd);
  195.                                                         memmove(pStr,pEnd,cbRemains);//覆盖到前面
  196.                                                         pStr[cbRemains]='\0';
  197.                                                         pStr--;
  198.                                                         continue;
  199.                                                 }
  200.                                                 else
  201.                                                 {
  202.                                                         *pStr='\0';//直接把/*开始的内容全删
  203.                                                         break;//这一行处理结束
  204.                                                 }
  205.                                         }
  206.                                         else
  207.                                         {
  208.                                                 *pStr='\0';
  209.                                                 InComment=1;
  210.                                                 break;
  211.                                         }
  212.                                 }

  213.                                 if(*pStr=='\\')//如果找到斜杠
  214.                                 {
  215.                                         if(!pStr[1])//并且后面是空,这个斜杠是续行符
  216.                                         {
  217.                                                 char*szNextLine;//追加下一行的数据
  218.                                                 szNextLine=ReadLine(fp,&cbLine);
  219.                                                 if(!szNextLine)
  220.                                                 {
  221.                                                         if(feof(fp))
  222.                                                         {
  223.                                                                 fprintf(stderr,
  224.                                                                         "%s(%u):unexpected end of file found\n",
  225.                                                                         argv[1],LineNo);
  226.                                                                 goto Cleanup;
  227.                                                         }
  228.                                                         fputs("Insufficient memory.\n",stderr);
  229.                                                         goto Cleanup;
  230.                                                 }
  231.                                                 RightTrim(szNextLine);//去掉最右边空格
  232.                                                 strcpy(pStr,szNextLine);//复制到斜杠所在位置
  233.                                                 free(szNextLine);
  234.                                                 goto ParseStr;//返回前面重新遍历这个字符串
  235.                                         }
  236.                                 }
  237.                                 if(*pStr=='"')//如果找到双引号
  238.                                 {
  239.                                         pStr++;
  240.                                         while(*pStr)//向后查找对应的双引号
  241.                                         {
  242.                                                 if(*pStr=='\\')//如果是斜杠就跳过这个字符
  243.                                                 {
  244.                                                         pStr+=2;
  245.                                                         continue;
  246.                                                 }
  247.                                                 if(*pStr=='"')//找到对应的双引号了
  248.                                                         break;//跳出
  249.                                                 pStr++;
  250.                                         }
  251.                                         if(!(*pStr))//没找到则双引号不平衡
  252.                                         {
  253.                                                 fprintf(stderr,
  254.                                                         "%s(%u):Unbalanced quote\n",
  255.                                                         argv[1],LineNo);
  256.                                                 goto Cleanup;
  257.                                         }
  258.                                 }
  259.                                 if(*pStr=='\'')//如果找到单引号
  260.                                 {
  261.                                         pStr++;
  262.                                         while(*pStr)//向后查找对应的单引号
  263.                                         {
  264.                                                 if(*pStr=='\\')//如果是斜杠就跳过这个字符
  265.                                                 {
  266.                                                         pStr+=2;
  267.                                                         continue;
  268.                                                 }
  269.                                                 if(*pStr=='\'')//找到对应的单引号了
  270.                                                         break;//跳出
  271.                                                 pStr++;
  272.                                         }
  273.                                         if(!(*pStr))//没找到则双引号不平衡
  274.                                         {
  275.                                                 fprintf(stderr,
  276.                                                         "%s(%u):Unbalanced quote\n",
  277.                                                         argv[1],LineNo);
  278.                                                 goto Cleanup;
  279.                                         }
  280.                                 }
  281.                         }


  282.                         fputs(szLine,stdout);
  283.                         fputc('\n',stdout);
  284.                         free(szLine);
  285.                 }
  286.                 LineNo++;
  287.         }

  288.         fclose(fp);
  289.         free(szLine);
  290.         return 0;
  291. Cleanup:
  292.         fclose(fp);
  293.         free(szLine);
  294.         return 2;
  295. }
复制代码
BIN: cmntkill.exe (44 KB, 下载次数: 10)
SRC: cmntkill.7z (3.42 KB, 下载次数: 9, 售价: 10 个宅币)

本帖被以下淘专辑推荐:

回复

使用道具 举报

0

主题

25

回帖

22

积分

用户组: 初·技术宅

UID
3072
精华
0
威望
0 点
宅币
-3 个
贡献
0 次
宅之契约
0 份
在线时间
8 小时
注册时间
2017-11-10
发表于 2017-11-12 21:26:02 | 显示全部楼层
6666666666666666
回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-4-27 05:36 , Processed in 0.039844 second(s), 38 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表