统计C/C++有效代码量

一直想分享点方法,却又不知从何入手;正好老大让统计工程有效代码行数,就分享一下相关的经验。前后总共尝试了3种方案

(1)VS2010直接统计

在如下对话框中输入:^:b*[^:b#/]+.*$


(2)sourceinsight 总计

     选择Project->Project Report(勾选如下图),点ok即可

     统计C/C++有效代码量_第1张图片

(3)自己写个脚本

    中秋节熬了一个通宵用perl写了一个脚本,当然主要是perl本身用的也不是很好,带有尝试性的写写,所以可能还有一些问题,但好在此次统计中感觉结果还是很靠谱的,所以本着学习的态度暂且拿出来分享,如有不妥请指正。

# function:本脚本用于统计c/c++代码的有效行数;其他语言暂不支持
# author  :MoreSpeech
# date    :2016/9/17

#参数1:输入代码存放路径
#参数2:输出log文件名

#! /user/bin/perl

use warnings;
use strict;


if(@ARGV != 2)
{
	die"Usage: statistical_line_num.pl src_path info.log\n";
}
my $src_path=$ARGV[0];
my $log_file_name = $ARGV[1];

##支持文件格式
my %formatHash = ('.cpp', 1, '.c', 1, '.h',1, '.hpp', 1,'.cc', 1,);

my %dest_file_hash;
ransack($src_path, \%formatHash, \%dest_file_hash);

my %linenum2file;

my $sumValidline = 0;
while( my ($onefile, $val) = each( %dest_file_hash))
{
	my $validN = processOneFile($onefile);
	$sumValidline += $validN;	
	$linenum2file{$onefile} = $validN; 	
}

writeLog($log_file_name, %linenum2file);

print "$sumValidline\n";





###############sub_function#######################
sub writeLog{
	my ($log_name, %linen2file) = @_;	
	
	open (Handle, ">$log_name") or die "can't create the $log_name\n";
	my %hash=();
	my @key = sort {$linen2file{$a}<=>$linen2file{$b}} keys %linen2file;
	
	foreach my $key(@key)
	{
		print Handle"$key, $linen2file{$key}\n";
	}
	close(Handle);	
}


sub   ransack 
{ 
   my ($dir, $format, $files) = @_; 
   my   @array=glob( "$dir\\* ");   
   foreach my $item (@array)
   {      
		if(-d $item)
		{
			ransack($item, $format, $files); 
		}
		elsif( $item =~ /(.\w{1,10})$/) 
		{			 
			if( exists $format->{$1})
			{
				$files->{$item} = 1;	
			}			
		}
   }   
} 


sub  ParseCommentBegin{
	my $InString = shift;
	my $validchar  = shift;
	my $beginchar = "/*";
	my $endchar = "*/";
	my $beginPos = index($InString, $beginchar);
	my $endPos = index($InString, $endchar);
	my $flag = 0;
	
	if( $beginPos > $endPos && $endPos >= 0) ##another "*/", so skip it
	{
		$endPos = index($InString, $endchar, $endPos + length($endchar));
		$flag = 1;
	}
	
	if($beginPos > 0  && !$flag)
	{
		my $str = substr($InString, 0, $beginPos);		
		$$validchar .= $str;
	}
	
	my $retval = 0;		 	
	if( $beginPos >= 0 && $endPos > 0 )
	{
		my $subString = substr($InString, $endPos + length($endchar));				
		my $len = length($subString);
		if( $len > 0)
		{
			return ParseCommentBegin($subString, $validchar);
		}
	}
	elsif($beginPos <0  && $endPos< 0)
	{
		$$validchar .= $InString;
		return 0;
	}
	elsif($endPos < 0)
	{			 
		return 1;                            ##wait for end		
	}
	else{
		print "Error: without this situation\n"
	}	
	return 0;
}


sub  ParseCommentEnd{
	my $InString = shift;
	my $validchar  = shift;
	my $endchar = "*/";
	my $endPos = index($InString, $endchar);
	if( $endPos < 0 )
	{
		return;
	}	
    my $subString = substr($InString, $endPos + length($endchar));		
	my $tmpStr = $subString;
	$tmpStr =~ s/[\s|\t]*//g;	
	if( length($tmpStr) > 0 )
	{
		$$validchar .= $subString;
		ParseCommentEnd($subString, $validchar);	
	}
}


sub ParseArrayBegin{
	my $InString = shift;
	my $beginchar = "[";
	my $endchar = "]";
	my $beginPos = index($InString, $beginchar);
	my $endPos = index($InString, $endchar);
	my $searchPos = $endPos + 1;
	my $retval = 0; ##ordinary
	if( $beginPos && ($endPos > $beginPos) ) ##array[]
	{		
		if( !(index($InString, "=", $searchPos ) < 0) )
		{
			$searchPos += 1;
			if( !(index($InString ,"{", $searchPos) < 0) )
			{
				$searchPos += 1;
				if( index($InString, "}", $searchPos) < 0 )
				{
					$retval = 1; ##wait for "}"
				}				
			}	
			else
			{
				$retval = 2;    ###wait for "{"
			}			
		}
		elsif( index($InString, ";", $searchPos))
		{
			$retval = 0; ##get array end symbol";"
		}
		else
		{
			$retval = 3;  ##wait for "="
		}
	}
	return $retval;	
}




##校验查到结果是否有效
sub CheckValidFind
{
	my $InString = shift;
	my $forestr = shift;
	my $backstr = shift;
	my $forePos = index($InString, $forestr);
	my $backPos = index($InString, $backstr);  ##dest string
		
	if(($forePos < $backPos) && ($forePos>=0)) ##pairing
	{
		my $subString = substr($InString, $backPos+length($backstr));
		if(CheckValidString($subString))
		{
			
			return CheckValidFind($subString, $forestr, $backstr);
		}		
	}
	elsif( $backPos >= 0 )
	{
	   
		return 1;  ##valid: just one
	}
	else
	{
	  #  die "Error: without this situation\n";
	}
	return 0;      ##invalid
}

sub FindInFile{
	*FILE = shift;
	my $flag = shift;
	my $deststr = shift;
	my $nline = 0;
	
	while( my $line =  )
	{		
		chomp($line);
		if(!CheckValidString($line))
		{
			next;
		}
		$nline++;
		if( $line =~ /$deststr/)
		{			 
			if($flag == 1)
			{
				if(CheckValidFind($line, "{", "}"))
				{					
					last; ##find the valid "}"
				}
			}
			else
			{			
				last;
			}
		}		
	}
	return 1;	
}


sub ParseArrayEnd{
	*FileHandle= shift;
	my $InFlag = shift;
	#print "$InFlag\n";
	my $sumLine = 0;
	while( my $line = )
	{
		chomp($line);
		
		if( $InFlag == 3)
		{		
		 	$sumLine += FindInFile( *FileHandle, $InFlag, "=");
			$InFlag = 2;
			 
		}
		elsif( $InFlag == 2 )
		{
		 	$sumLine += FindInFile(*FileHandle ,$InFlag, "{");
			$InFlag = 1;
			 		
		}
		elsif( $InFlag == 1 )
		{				 
			$sumLine += FindInFile(*FileHandle, $InFlag, "}");			 
			last;
		}		 
	}	
	return $sumLine;
}


sub CheckValidString{
	my $string = shift;
	$string =~ s/[\s|\t]*//g;
	if( length($string) > 0)   #valid string
	{
		return 1;        
	}
	else
	{
		return 0;
	}
}

sub processOneFile
{
	my $file_name = shift;
	open(curHandle, "<$file_name") or die "can't open the $file_name\n";
	my $validlineN = 0;
	my $nLine = 0;
	my $waitforend = 0;
	while(my $line =  )
	{			
		chomp($line);		
		my $validstring="";
		 
		if( $line =~ /^[\s|\t]*\/\//) #"//"
		{
			#print "$line";
		}
		elsif( $line =~ /\/\*/)       #"/*" :begin of comment
		{			    
			if(ParseCommentBegin($line, \$validstring))
			{
				$waitforend = 1;
			}
			else
			{
				$waitforend = 0;       ##get "*/"
			}
			if( CheckValidString($validstring) )
			{				
				$validlineN++;	
			}          
		}
		elsif( $line =~ /\*\//)       #"*/": end of  comment
		{
			ParseCommentEnd($line, \$validstring);				
			if( CheckValidString($validstring))
			{				
				$validlineN++;
			}
			$waitforend = 0;
		}		
		elsif( !$waitforend )
		{		
			if( $line =~ /\[/)
			{			   
				my $retval = ParseArrayBegin($line);					
				if( $retval )
				{					
					$validlineN += ParseArrayEnd(*curHandle, $retval);				 
				}
			}	
            if(CheckValidString($line))
			{				
				$validlineN++;
			}
		}		
	}	 
	close(curHandle);	
	return $validlineN;
}





你可能感兴趣的:(脚本语言)