C++ 去除代码注释

42 篇文章 4 订阅
14 篇文章 2 订阅

输入一段代码,去除其中的注释和空行

支持去除以下形式的注释:

//这是一条注释

/*这是一条注释*/

/*这是一条注释*//*这是一条注释*/

/*这是

一条

注释*/

伪代码

读取一行(str,readpos,startpos,endpos,status)
如果状态是1 正常读取

如果是2 跨行匹配
那么说明正在读取多行注释的中间部分

:跨行匹配
如果该行没有*/
则直接丢弃
如果有*/
将/前面的丢弃
恢复状态1

:正常读取
从该行的readpos位置开始读
初始readpos为0

如果这行出现//
则丢弃//后面的内容

如果这行有/*
标记/位置为起始截取位置
标记为同行待匹配状态2

:单行匹配
继续读,如果读到*/
标记/为终止位置
截取,不换行输出
恢复为正常状态

:一直读到末尾才换行,去除所有注释
如果没读完,标记readpos,重新调用函数再读一次
如果读完了,readpos=len,之前读到了/*,但仍然没有读取到*/
那么标记为状态2 跨行匹配,读取下一行

(注:只是草稿)

流程图

代码

#include<iostream>
#include<fstream>
#include<cstring>
#include<cmath>
using namespace std; 

int Check(string readline)
{
	//非空串判断
	for(int n=0;n<readline.length();n++)
	{	
		//如果有元素不是空格或者回车,该串非空 
		if(readline[n]!=9&&readline[n]!=32&&readline[n]!=13) 
		{
			//cout<<readline+"非空"<<endl;
			return 1;
		}
	}
	return 0; 
} 

int LineProcess(string readline,int &readpos,int &startpos,int &endpos,int& status)
{
	//写入文件 
	fstream out;
	out.open("temp.txt",fstream::out | ios_base::app);
	
	//status 1正常读取 2同行待匹配 3异行待匹配 
	int j=readline.length();
	int flag=0;//没有注释
    //cout<<"当前状态:"<<status<<" 当前行:"<<readline<<endl; 
    //cout<<"当前行:"<<readline<<"当前读取位置:"<<readpos<<readline[readpos]<<endl; 
    //cout<<" 当前行:"<<readline<<endl; 
    
    //跳过空行
	if(0==j)
	{
		//cout<<"空行"<<endl;
		return 0; 
	}

    //逐字符读取 
	for(int n=readpos;n<j;n++)
	{	
		//cout<<"当前状态:"<<status<<"当前读取位置:"<<n<<endl; 
		//cout<<"进入循环"<<endl;
		//cout<<"当前行:"<<readline<<"当前读取位置:"<<readline[n]<<endl; 
		//读取到// 
		if(readline[n]=='/'&&readline[n+1]=='/') 
		{
			//cout<<"当前行:"<<readline<<"当前读取位置:"<<readline[n]<<endl; 
			startpos=n;
			//输出/之前的内容
			//cout<<"//输出:"<<endl; 
			//cout<<"//前注释长度:"<<readline.substr(0,n).length()<<endl;
			//输出非空字符串 
			if(Check(readline.substr(0,n)))
			{
				out<<readline.substr(0,n)<<endl;
				cout<<readline.substr(0,n)<<endl;
			}
			//读取下一行
			readpos=0;
			return 0; 
		}    
		//读取到/* 
		if(readline[n]=='/'&&readline[n+1]=='*') 
		{
			//cout<<"当前行:"<<readline<<"当前读取位置:"<<readline[n]<<endl; 
			//标记 
			//startpos=n; 
			//输出/之前的内容,不换行,一次只输出一部分 
			//cout<<"/*输出:"<<endl; 
			out<<readline.substr(startpos,n-startpos);//0,n 
			cout<<readline.substr(startpos,n-startpos);//n-startpos
			//暂不换行
			//状态变更为同行待匹配 
			status=2;
			//标记读取位置为*的下一位
			readpos=n+2; 
			//继续读本行 
			return 1;
			 
			//old 
			//cout<<"发现注释/*:"<<readline<<endl; 
			//cout<<startpos<<readline[startpos]<<endpos<<readline[endpos]<<endl; 
			//system("pause");
			//break;
		}  
		//读取到*/ 
		if(readline[n]=='*'&&readline[n+1]=='/') 
		{
			//cout<<"readpos:"<<readpos<<endl;
			
			//恢复正常状态
			status=1; 
			
			//标记readpos为/的后一位 
			if(n<j-2)
			{
					//如果还有,从此开始输出 
					startpos=n+2; 
					readpos=n+2; 
					//cout<<"readpos:"<<readpos<<endl;				
					//继续读本行
					return 1; 			
			}
			else
			{
				//读取下一行 
				return 0;
			}

			//if(n!=j-2)return 1;
			//else if(j-2==n)return 0;//读取下一行 
			
			//old
			//flag=3; 
			//endpos=n+1; 
			//cout<<"发现注释*/:"<<readline<<endl; 
			//cout<<startpos<<readline[startpos]<<endpos<<readline[endpos]<<endl; 
			//system("pause");
			//想继续读第二个注释,就不能break 
			//break;
		}    
		//读取到本行末尾 
		if(n==j-1)//▲出错点 n==j进入死循环 
		{
			//cout<<"读取到本行末尾"<<endl;
			//cout<<"当前状态:"<<status<<endl; 
			
			//如果同行待匹配没匹配到,就变成异行待匹配 
			if(2==status)
			{
				//cout<<"同行待匹配没匹配到,变成异行待匹配 "<<endl; 
				status=3;
				//读取下一行
				readpos=0;
				return 0; 
			}
			else if(3==status) //▲出错点 status=3 修改了变量的值 
			{
				//cout<<""<<endl;
				//cout<<"是异行待匹配状态,现在读取下一行"<<endl;				
				//读取下一行 
				readpos=0;
				return 0; 				
			}
			else if(1==status) 
			{
				//正常状态
				//输出本行未输出过的字符,换行
				//cout<<"是正常状态,输出本行,换行,再读取下一行"<<endl;
				out<<readline.substr(startpos)<<endl;
				cout<<readline.substr(startpos)<<endl;
				//读取下一行 
				readpos=0;
				return 0; 
			}
		}
	}
	//system("pause");
}

void Readin()
{
	//读入 :过滤单行的注释,将注释内容全部截取 
	fstream in;
 	in.open("InFile.txt",ios::in);
 	
	//写入文件 
	fstream out;
	out.open("temp.txt",fstream::out | ios_base::trunc);
    
    int n=0;//当前读取位置 
    int endpos=0; //用后记得初始化 
    int startpos=0;
    int status=1;
    int readpos=0;
    string readline;
    while (getline(in, readline))
    {
    	//cout<<"读取下一行"<<endl;
    	int res=0;
    	startpos=0; 
    	//读取下一行0,继续读本行1 
    	while(res=LineProcess(readline,readpos,startpos,endpos,status))
    	{
    		//cout<<"继续读本行"<<endl;
    		res=0;
    		//system("pause");
		}
	} 
	in.close();
	out.close(); 
	return;
}

int main()
{
	Readin();
	return 0;
}

总结:

先写伪代码,再画流程图,最后写程序,这样可以使得代码逻辑结构清晰,减少出错,节省大量时间。

如果不写伪代码,不画流程图,上来直接就敲,写出来的可能是一座屎山。

虽然能跑,但是逻辑混乱,可读性低,维护困难。

输入

本代码

输出

#include<iostream>
#include<fstream>
#include<cstring>
#include<cmath>
using namespace std; 
int Check(string readline)
{
	for(int n=0;n<readline.length();n++)
	{	
		if(readline[n]!=9&&readline[n]!=32&&readline[n]!=13) 
		{
			return 1;
		}
	}
	return 0; 
} 
int LineProcess(string readline,int &readpos,int &startpos,int &endpos,int& status)
{
	fstream out;
	out.open("temp.txt",fstream::out | ios_base::app);
	
	int j=readline.length();
	int flag=0;
    
	if(0==j)
	{
		return 0; 
	}
	for(int n=readpos;n<j;n++)
	{	
		if(readline[n]=='/'&&readline[n+1]=='/') 
		{
			startpos=n;
			if(Check(readline.substr(0,n)))
			{
				out<<readline.substr(0,n)<<endl;
				cout<<readline.substr(0,n)<<endl;
			}
			readpos=0;
			return 0; 
		}    
		if(readline[n]=='/'&&readline[n+1]=='*') 
		{
			out<<readline.substr(startpos,n-startpos);
			cout<<readline.substr(startpos,n-startpos);
			status=2;
			readpos=n+2; 
			return 1;
			 
		}  
		if(readline[n]=='*'&&readline[n+1]=='/') 
		{
			
			status=1; 
			
			if(n<j-2)
			{
					startpos=n+2; 
					readpos=n+2; 
					return 1; 			
			}
			else
			{
				return 0;
			}
			
		}    
		if(n==j-1)
		{
			
			if(2==status)
			{
				status=3;
				readpos=0;
				return 0; 
			}
			else if(3==status) 
			{
				readpos=0;
				return 0; 				
			}
			else if(1==status) 
			{
				out<<readline.substr(startpos)<<endl;
				cout<<readline.substr(startpos)<<endl;
				readpos=0;
				return 0; 
			}
		}
	}
}
void Readin()
{
	fstream in;
 	in.open("InFile.txt",ios::in);
 	
	fstream out;
	out.open("temp.txt",fstream::out | ios_base::trunc);
    
    int n=0;
    int endpos=0; 
    int startpos=0;
    int status=1;
    int readpos=0;
    string readline;
    while (getline(in, readline))
    {
    	int res=0;
    	startpos=0; 
    	while(res=LineProcess(readline,readpos,startpos,endpos,status))
    	{
    		res=0;
		}
	} 
	in.close();
	out.close(); 
	return;
}
int main()
{
	Readin();
	return 0;
}

最初,没重构之前的代码结构

原先用了一堆flag值,先读取完一行,再跳出来处理

已经读完了一行,就不好继续处理了,这样就很局限了,有很多操作无法实现,比如前面已经读取到了一个注释,后面还有一个,这就没办法了

没用流程图把逻辑关系理顺,这样的逻辑关系过于混乱,自己也不清楚运行到哪一步了,只能一步步慢慢调试修改,甚至有时候修改操作之间会互斥,令人崩溃

此外,这样的代码的复用率低,就比如读取一行,其实可以写一个函数来复用,没有必要在一个函数中写很多重复操作,因为这将大大提高出错的概率

void Readin()
{
    while (getline(in, readline))
    {
    	for(n=0;n<j;n++)
    	{	
			//过滤单行注释 
			if(readline[n]=='/'&&readline[n+1]=='/') 
			{
			
			}    
			//过滤多行注释 
			if(readline[n]=='/'&&readline[n+1]=='*') 
			{
			
			}  
			if(readline[n]=='*'&&readline[n+1]=='/') 
			{
			
			}    
		}
		if(flag==1)//有单行注释,截取 
		{

		}
		else if(flag==0)//没注释,直接输出 
		{

		} 
		else if(flag==2)//有多行注释,这是第一行 
		{

		} 
		else if(flag==4)//有多行注释,该行全部为注释 
		{

		} 
		else if(flag==3)//注释为单行中的/**/ 
		{

		} 
	} 
	in.close();
	out.close(); 
	return;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值