- UID
- 1
- 精华
- 积分
- 76365
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
作用就是去掉注释。别小看这个程序了,因为去掉注释并不像大家想的那么简单——因为//和/*不一定都是注释,比如下面的代码:
char szUrl[]="http://www.0xaa55.com/";
看见没有?这里就不能简单地把“//www.0xaa55.com/";”去掉了。
解决的方法是对"和'进行识别,把引号内的//和/*无视掉,仅对“正常”的//和/*进行判定。这样就能保证不会错误地删除不是注释的部分了。
我写的这个控制台程序用法很简单,它只有一个参数:文件名。然后经过处理的代码直接输出到stdout,如果你要把内容写入文件,请使用重定向命令:cmntkill a.c>a.txt- //=============================================================================
- //作者:0xAA55
- //论坛:http://0xaa55.com
- //版权所有(C) 2013-2014 技术宅的结界
- //
- //用途:
- //将C、C艹文件中的注释去掉
- //-----------------------------------------------------------------------------
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
- //=============================================================================
- //函数:Usage
- //描述:打印程序的用法。
- //-----------------------------------------------------------------------------
- void Usage(char*argv0)
- {
- fprintf(stderr,
- "cmntkill: This tool is used to remove the comments in a C\\C++ source file.\n"
- "Usage:\n"
- "%s inputfile\n",
- argv0);
- }
- #define LineLen 80
- //=============================================================================
- //函数:ReadLine
- //描述:读取完整的一行
- //返回分配了内存的一行字符串,pLineLength返回行长度(不包括结尾的0)
- //-----------------------------------------------------------------------------
- char*ReadLine(FILE*fp,size_t*pLineLength)
- {
- char szLineBuf[LineLen];
- char*pChNewLine;
- size_t cbLineLen=0;
- long pCurPos;
-
- pCurPos=ftell(fp);
- while(!feof(fp))
- {
- //连续读取文件,直到找到换行符
- fread(szLineBuf,1,LineLen,fp);
- pChNewLine=strchr(szLineBuf,'\n');
- if(pChNewLine)//如果找到换行符
- {
- cbLineLen+=(size_t)pChNewLine+1-(size_t)szLineBuf;//计算行长度
- //转到读取的位置
- fseek(fp,pCurPos,SEEK_SET);
- //分配内存来存放字符串
- pChNewLine=(char*)malloc(cbLineLen);
- if(!pChNewLine)
- return NULL;
- //读取行
- fread(pChNewLine,1,cbLineLen,fp);
- pChNewLine[cbLineLen-1]='\0';//去掉结尾的换行符
- if(pLineLength)//返回行长度
- *pLineLength=cbLineLen-1;
- return pChNewLine;
- }
- else
- cbLineLen+=LineLen;
- }
-
- //如果读到文件尾都没遇到换行符,则这个文件只有一行
- fseek(fp,0,SEEK_END);
- cbLineLen=(size_t)ftell(fp)-(size_t)pCurPos;
- if(!cbLineLen)
- {
- fgetc(fp);//使feof返回非零
- return NULL;
- }
- //转到读取的位置
- fseek(fp,pCurPos,SEEK_SET);
- //分配内存
- pChNewLine=(char*)malloc(cbLineLen+1);
- if(!pChNewLine)
- return NULL;
- //读取行
- fread(pChNewLine,1,cbLineLen,fp);
- pChNewLine[cbLineLen]='\0';//结尾
- if(pLineLength)//返回行长度
- *pLineLength=cbLineLen;
- return pChNewLine;
- }
- //=============================================================================
- //函数:RightTrim
- //描述:把字符串右边的空格、TAB去掉
- //-----------------------------------------------------------------------------
- void RightTrim(char*szLine)
- {
- size_t cbLine;
- char*pChr;
- cbLine=strlen(szLine);
- pChr=&szLine[cbLine-1];
- while(cbLine--)
- {
- switch(*pChr)//判断字符
- {
- case' ':
- case'\t':
- *pChr='\0';//去掉空格或TAB
- pChr--;
- continue;
- default://遇到其它字符,则返回
- return;
- }
- }
- }
- //=============================================================================
- //函数:main
- //描述:程序入口点
- //-----------------------------------------------------------------------------
- int main(int argc,char**argv)
- {
- FILE *fp;
- char *szLine;
- size_t cbLine;
- int InComment=0;//是否在注释内
- size_t LineNo=1;
- if(argc<2)
- {
- Usage(argc?argv[0]:"defconst");
- return 1;
- }
- fp=fopen(argv[1],"r");
- if(!fp)
- {
- fputs("Could not read file.\n",stderr);
- return 2;
- }
- while(!feof(fp))
- {
- szLine=ReadLine(fp,&cbLine);
- if(!szLine)
- {
- if(feof(fp))
- break;
- fputs("Insufficient memory.\n",stderr);
- goto Cleanup;
- }
- RightTrim(szLine);
- //如果是在/**/的注释内
- if(InComment)
- {
- char*pEnd;//直接找结尾
- pEnd=strstr(szLine,"*/");
- if(pEnd)//找到了结尾
- {
- InComment=0;//在注释外了
- pEnd+=2;//看后面有没有内容
- if(*pEnd)//有的话把后面的内容覆盖到前面
- {
- size_t cbRemains;
- cbRemains=strlen(pEnd);
- memmove(szLine,pEnd,cbRemains);//覆盖到前面
- szLine[cbRemains]='\0';
- //接着就会跳到if(!InComment)那里继续处理
- }
- else//后面没内容,这是空行
- {
- fputc('\n',stdout);//输出一个空行
- free(szLine);
- continue;
- }
- }
- else//没找到结尾,整行都是注释
- {
- fputc('\n',stdout);//输出一个空行
- free(szLine);
- continue;
- }
- }
- //如果是在/**/的注释外
- if(!InComment)
- {
- char*pStr;
- //遍历这行字符串
- ParseStr: for(pStr=szLine;*pStr;pStr++)
- {
- if(!strncmp(pStr,"//",2))//如果找到了单行注释
- {
- *pStr='\0';//直接将其干掉
- break;//这一行处理结束
- }
- if(!strncmp(pStr,"/*",2))//如果找到了多行注释
- {
- char*pEnd;//直接找结尾
- pEnd=strstr(pStr,"*/");
- if(pEnd)//如果找到了说明这个多行注释只在一行内
- {
- pEnd+=2;//跳过注释结束的标识
- if(*pEnd)//后面有内容
- {
- size_t cbRemains;
- cbRemains=strlen(pEnd);
- memmove(pStr,pEnd,cbRemains);//覆盖到前面
- pStr[cbRemains]='\0';
- pStr--;
- continue;
- }
- else
- {
- *pStr='\0';//直接把/*开始的内容全删
- break;//这一行处理结束
- }
- }
- else
- {
- *pStr='\0';
- InComment=1;
- break;
- }
- }
- if(*pStr=='\\')//如果找到斜杠
- {
- if(!pStr[1])//并且后面是空,这个斜杠是续行符
- {
- char*szNextLine;//追加下一行的数据
- szNextLine=ReadLine(fp,&cbLine);
- if(!szNextLine)
- {
- if(feof(fp))
- {
- fprintf(stderr,
- "%s(%u):unexpected end of file found\n",
- argv[1],LineNo);
- goto Cleanup;
- }
- fputs("Insufficient memory.\n",stderr);
- goto Cleanup;
- }
- RightTrim(szNextLine);//去掉最右边空格
- strcpy(pStr,szNextLine);//复制到斜杠所在位置
- free(szNextLine);
- goto ParseStr;//返回前面重新遍历这个字符串
- }
- }
- if(*pStr=='"')//如果找到双引号
- {
- pStr++;
- while(*pStr)//向后查找对应的双引号
- {
- if(*pStr=='\\')//如果是斜杠就跳过这个字符
- {
- pStr+=2;
- continue;
- }
- if(*pStr=='"')//找到对应的双引号了
- break;//跳出
- pStr++;
- }
- if(!(*pStr))//没找到则双引号不平衡
- {
- fprintf(stderr,
- "%s(%u):Unbalanced quote\n",
- argv[1],LineNo);
- goto Cleanup;
- }
- }
- if(*pStr=='\'')//如果找到单引号
- {
- pStr++;
- while(*pStr)//向后查找对应的单引号
- {
- if(*pStr=='\\')//如果是斜杠就跳过这个字符
- {
- pStr+=2;
- continue;
- }
- if(*pStr=='\'')//找到对应的单引号了
- break;//跳出
- pStr++;
- }
- if(!(*pStr))//没找到则双引号不平衡
- {
- fprintf(stderr,
- "%s(%u):Unbalanced quote\n",
- argv[1],LineNo);
- goto Cleanup;
- }
- }
- }
- fputs(szLine,stdout);
- fputc('\n',stdout);
- free(szLine);
- }
- LineNo++;
- }
- fclose(fp);
- free(szLine);
- return 0;
- Cleanup:
- fclose(fp);
- free(szLine);
- return 2;
- }
复制代码 BIN:
cmntkill.exe
(44 KB, 下载次数: 10)
SRC:
cmntkill.7z
(3.42 KB, 下载次数: 9, 售价: 10 个宅币)
|
|