【C】C语言写的给C语言源代码去掉注释的程序
作用就是去掉注释。别小看这个程序了,因为去掉注释并不像大家想的那么简单——因为//和/*不一定都是注释,比如下面的代码: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;
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='\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='\0';//结尾
if(pLineLength)//返回行长度
*pLineLength=cbLineLen;
return pChNewLine;
}
//=============================================================================
//函数:RightTrim
//描述:把字符串右边的空格、TAB去掉
//-----------------------------------------------------------------------------
void RightTrim(char*szLine)
{
size_t cbLine;
char*pChr;
cbLine=strlen(szLine);
pChr=&szLine;
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:"defconst");
return 1;
}
fp=fopen(argv,"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='\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='\0';
pStr--;
continue;
}
else
{
*pStr='\0';//直接把/*开始的内容全删
break;//这一行处理结束
}
}
else
{
*pStr='\0';
InComment=1;
break;
}
}
if(*pStr=='\\')//如果找到斜杠
{
if(!pStr)//并且后面是空,这个斜杠是续行符
{
char*szNextLine;//追加下一行的数据
szNextLine=ReadLine(fp,&cbLine);
if(!szNextLine)
{
if(feof(fp))
{
fprintf(stderr,
"%s(%u):unexpected end of file found\n",
argv,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,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,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:
SRC: 6666666666666666
页:
[1]