源程序简单分析器

 【难度系数】3级

任务描述】从文件读入C程序,统计其中的代码行、注释和空行数;并统计程序中的函数个数、函数的平均行数,以及规模最大和最小的函数及其开始行号。

功能要求】(1)用户指定要读取的C源程序文件名,从文件中读入C语言源程序。(2)分析内容包括:代码行数,注释行数,空行数,函数个数,函数平均行数,规模最大/最小函数的函数名、代码行数、开始行号。

/*源程序简单分析器问题
 从文件读入C程序,统计其中的代码行、注释和空行数;并统计程序中的函数个数、函数的平均行数,
 以及规模最大和最小的函数及其开始行号
 思路:创建结构体来保存信息,通过读取每一行代码保存在字符串中进行判断
 难点:读取每一行,文件的操作。
 注意:本代码基于个人的书写习惯以及符合规定的代码习惯而编写,并不适用于全部代码风格*/ 
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
struct item//创建结构体保存程序数据 
{
	int code_line;//代码行 
	int code_annotation;//代码注释 
	int code_space;//空行数 
	int number_fun;//函数个数 
	int fun_line[1024];//每个函数行 
	int fun_ave_line;//函数平均行数 
	int fun_max;//最大函数编号 
	int fun_min;//最小函数编号 
	int max_fun_line;//最大函数开始行 
	int min_fun_line; //最小函数开始行
	char max_fun_name[1024];//最大函数名 
	char min_fun_name[1024];//最小函数名 
	 
}; 
int StrFind(char *c1,char *c2);//比较两个字符串是否完全相等,这里用来增加注释数 
void t_file(struct item project,int bHs);//写入文件 
int main()
{
	struct item project;
	struct item *p;
	printf("-----------------------------------------------------\n");
 	printf(" 计算机科学与技术五班*-----*张洪荣*--*学号12110990619\n");
 	printf("-----------------------------------------------------\n");
	//1.创建文件流,文件指针名=fopen(文件名,使用文件方式)打开失败则返回NULL;
	FILE *fp=fopen("design.c","r");
	 //2:检测文件是否打开成功;
    if(!fp)
	{
       printf("打开失败!\n");
       return -1; //返回异常
    }
    //     储存行        最大函数名    最小函数名
    char s,c[1024],max_fun_name[1024],min_fun_name[1024]; 
    //  双引号 斜引号 函数   注释  空行 代码行 每个函数的行数  最大函数 最小函数  最大函数开始行 最小函数开始行 函数平均行 
    int bSyh=0,bXgx=0,bHs=0,bZs=0,nKh=0,nLine=0,fun_line[2555],max_fun,min_fun,  max_fun_line,min_fun_line,    fun_ave_line; 
    //  ""     /*     {}       // 
    memset(fun_line,0,sizeof(int)*2555);//将数组全部定义为0 
    int i=0,j=0,k,flag1,flag2,flag3=0,flag4=0; 
	 while((fgets(c,sizeof(c),fp))!=NULL)//一行一行读取,当到文件末尾时返回NULL 
	{
		nLine++;//用于记录此时在哪一行和总行数 
		if(c[0]=='\0'||c[0]=='\n')//判断空行,请注意如果\t不算空行! 
			nKh++;	
			char x[3]="//";//定义注释字符串 	
		if(StrFind(c,x)!=-1)//寻找"//"类注释 
			bZs++;
		for(i=0;i<sizeof(c);i++)//寻找'/* '类注释 
		{
			int j=i+1;//后一个 
			if(c[i]=='/'&&c[j]=='*')
			bZs++;		
		}	
		if(c[0]=='{'||c[0]==' '&&c[1]=='{')//通过函数开始的花括号来判断是否为函数 
		{
			bHs++;
			flag1=nLine;//记下函数开始的行数 
		}
		if(c[0]=='}'||c[0]==' '&&c[1]=='}')
		{
			flag2=nLine;//记下函数结束的行数
			fun_line[j++]=flag2-flag1+2;//加2是为了将函数头保存下来 	
		}		
	}
		k=0;
		for(j=1;j<bHs;j++)//寻找最大函数 
		{
			if(fun_line[k]<fun_line[j])
			k=j; 
		}
			max_fun=k+1;
		for(j=1;j<bHs;j++)//寻找最小函数 
		{
			if(fun_line[k]>fun_line[j])
			k=j;
		}
			min_fun=k+1;
		int sum,ave;
		for(i=0;i<bHs;i++)//记录函数平均行数 
			sum+=fun_line[i];
		ave=sum/bHs;
	rewind(fp);//返回文件头部 
	int nLine2=0;//标记新一个总行数 
	while((fgets(c,sizeof(c),fp))!=NULL)//一行一行读取,当到文件末尾时返回NULL 
	{
		
		nLine2++;//用于记录此时在哪一行和总行数 
		if(c[0]=='{'||c[0]==' '&&c[1]=='{')//通过函数开始的花括号来判断是否为函数 
		{
			flag3++;//标记最小函数 
			flag4++;//标记最大函数 
		}
		if(flag3==min_fun)
			min_fun_line=nLine2;
		if(flag4==max_fun-1)
			max_fun_line=nLine2;	
	}
	rewind(fp);//返回文件头部 
	nLine2=0; 
	while((fgets(c,sizeof(c),fp))!=NULL)//一行一行读取,当到文件末尾时返回NULL 
	{
		
		nLine2++;//用于记录此时在哪一行和总行数 
		if(nLine2==max_fun_line)
		strcpy(max_fun_name,c);//记录最大函数名 
		if(nLine2==min_fun_line)
		strcpy(min_fun_name,c);//记录最小函数名 
	}
	fclose(fp);
	printf("代码总行数=%d\n",nLine); 
	printf("代码总空行=%d\n",nKh);
	printf("代码总注释=%d\n",bZs);
	printf("代码中函数个数=%d\n",bHs);
	printf("代码中函数的行数\n"); 
	for(i=0;i<bHs;i++)
		printf("%d ",fun_line[i]);
		printf("\n"); 
	printf("最大函数编号=%d 最小函数编号=%d\n",max_fun,min_fun);
	printf("最大函数开始行数=%d\n",max_fun_line); 
	printf("最小函数开始行数=%d\n",min_fun_line);
	printf("最大函数名\n"); 
	puts(max_fun_name);
	printf("最小函数名\n");
	puts(min_fun_name);
	printf("函数平均行=%d",ave);
	project.code_line=nLine;
	project.code_space=nKh;
	project.code_annotation=bZs;
	project.fun_ave_line=ave;
	project.fun_max=max_fun;
	project.fun_min=min_fun;
	project.max_fun_line=max_fun_line;
	project.min_fun_line=min_fun_line;
	project.number_fun=bHs;
	strcpy(project.max_fun_name,max_fun_name);
	strcpy(project.min_fun_name,min_fun_name);
	for(i=0;i<bHs;i++)
		project.fun_line[i]=fun_line[i];	
	t_file(project,bHs);
	return 0;
}
int StrFind(char *c1,char *c2)
{
	int i,j,len1=strlen(c1),len2=strlen(c2);
	int flag=0;//当flag为2时即为//注释 
	for(i=0;i<len1;i++)
	{
		for(j=0;j<len2;j++)
		{
			if(c1[i]==c2[j])
			flag++;
			break;
		}
	}
	if(flag==len2)
	return 0;
	else
	return -1;
}
void t_file(struct item project,int bHs)
{
	 FILE *fpWrite=fopen("E:\\C\\C_mission\\code_analysis.txt","w");  
    if(fpWrite==NULL)   
        exit(0);  
    int i=0;
	fprintf(fpWrite,"代码总行数=%d\n",project.code_line);
	fprintf(fpWrite,"代码总空行=%d\n",project.code_line);
	fprintf(fpWrite,"代码总注释=%d\n",project.code_line);
	fprintf(fpWrite,"代码中函数个数=%d\n",project.code_line);
	fprintf(fpWrite,"函数中的行数\n");
	for(i=0;i<bHs;i++)
		fprintf(fpWrite,"%d ",project.fun_line[i]); 
	fprintf(fpWrite,"最大函数编号=%d 最小函数编号=%d\n",project.fun_max,project.fun_min);
	fprintf(fpWrite,"最大函数开始行数=%d\n",project.max_fun_line); 
	fprintf(fpWrite,"最小函数开始行数=%d\n",project.min_fun_line);
	fprintf(fpWrite,"最大函数名\n"); 
	fputs(project.max_fun_name,fpWrite);
	fprintf(fpWrite,"最小函数名\n");
	fputs(project.min_fun_name,fpWrite);
	fprintf(fpWrite,"函数平均行=%d",project.fun_ave_line);
    fclose(fpWrite);  
}

分析程序:

/*回文数问题,难度4级
思路:先转换进制,再判断是否为回文数
二进制,八进制本来的算法便要倒叙,直接看倒叙和正序是否相即可判断*/  
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int judge_ten(long x);//判断十进制是否为回文数 
int numeration_change_judge_two(long x,long *s1);//转为二进制判断是否为回文数 
int numeration_change_judge_eight(long x,long *s2);//转为八进制判断是否为回文数 
int numeration_change_judge_sixteen(long x,long *s3);//转为十六进制判断是否为回文数
int main()
 {
 	char ch;
 	long x;
 	long s1[30],s2[30],s3[30];//用于存放二进制,八进制,十六进制 
	printf("请输入一个十进制正整数\n");
	scanf("%ld",&x);
	judge_ten(x); 
	numeration_change_judge_two(x,s1);
	numeration_change_judge_eight(x,s2);
	numeration_change_judge_sixteen(x,s3);
	printf("是否继续使用? Y/N\n"); 
	scanf("%s",&ch);
	if(ch=='N'||ch=='n')
	return 0;
	else if(ch=='Y'||ch=='y')
	main();//递归调用主函数 
	printf("-----------------------------------------------------\n");
 	printf(" 计算机科学与技术五班*-----*张洪荣*--*学号12110990619\n");
 	printf("-----------------------------------------------------\n");
	return 0;
 }
int judge_ten(long x)
 {
 	long s,y=0;
 	s=x;
 	while(s>0)
 	{
 		y=y*10+s%10;
 		s=s/10;
	}
	if(y==x)
	printf("十进制 %ld\n",x);
	return 0;
 } 
int numeration_change_judge_two(long x,long *s1)
 {
 	long i,j,flag=x,len=0;//存放十进制数 
 	long a[30],flag2,flag3=0;//方便倒叙用的数值a[30],flag2用来在倒叙中标记len flag3用于验证是否为回文数 
 	for(i=0;flag!=0;i++)//转为二进制 
 	{
 		a[i]=flag%2;
		flag/=2;
		len=i;
    }
	flag2=len; 
	for(j=0;j<=len;j++)//倒叙输入在s1数值中 
		s1[j]=a[flag2--];
	for(i=0;i<=len;i++)//判断倒叙与正序是否完全相等 
	{
		if(s1[i]==a[i])
			flag3++;
	}
	if(flag3==len+1)//若符合条件就输出 
	{
		printf("二进制 ");
		for(i=0;i<=len;i++)
			printf("%ld",s1[i]);
		printf("\n");
	}	
	return 0; 
 }
int numeration_change_judge_eight(long x,long *s2)
 {
 	long i,j,flag=x,len=0;//存放十进制数 
 	long a[30],flag2,flag3=0;//方便倒叙用的数值a[30],flag2用来在倒叙中标记len flag3用于验证是否为回文数 
 	for(i=0;flag!=0;i++)//转为八进制 
 	{
 		a[i]=flag%8;
		flag/=8;
		len=i;
	}
	flag2=len; 
	for(j=0;j<=len;j++)//倒叙输入在s1数值中 
		s2[j]=a[flag2--];
	for(i=0;i<=len;i++)//判断倒叙与正序是否完全相等 
	{
		if(s2[i]==a[i])
			flag3++;
	}
	if(flag3==len+1)//若符合条件就输出 
	{
		printf("八进制 ");
		for(i=0;i<=len;i++)
			printf("%ld",s2[i]);
		printf("\n");
	}		
	return 0; 
}
int numeration_change_judge_sixteen(long x,long *s3)
{
		long i,j,flag=x,len=0;//存放十进制数 
 	long a[30],flag2,flag3=0;//方便倒叙用的数值a[30],flag2用来在倒叙中标记len flag3用于验证是否为回文数 
 	for(i=0;flag!=0;i++)//转为十六进制 
 	{
 		a[i]=flag%16;
		flag/=16;
		len=i;
	}
	flag2=len; 
	for(j=0;j<=len;j++)//倒叙输入在s1数值中 
		s3[j]=a[flag2--];
	for(i=0;i<=len;i++)//判断倒叙与正序是否完全相等 
	{
		if(s3[i]==a[i])
			flag3++;
	}
	if(flag3==len+1)//若符合条件就输出 
	{
		printf("十六进制 ");
		for(i=0;i<=len;i++)//十六进制的输出需要进行调整 
		{
			if(s3[i]>9)
			printf("%c",s3[i]+55);//将十六进制大于9的部分输出
			if(s3[i]<=9)
			printf("%d",s3[i]); 
		}
		printf("\n");
	}			
	return 0;

}

结果:

 

包括源程序和详细的使用说明个,同时内付相关的软件 编程环境: 操作系统:Windows XP SP2 开发语言:C++ / MFC 编译环境:MS Visual C++6.0 第3方函数库:Winpcap3.1 使用说明: 1. 启动: 程序启动后首先出现网卡选择对话框,如图1所示,在设备列表中选择需要进行捕获的网卡。 2. 界面: 选择网卡后出现程序主界面,界面设计主要参照了一款比较优秀的网络协议分析工具Iris的图形化界面,采用切分窗口风格,整个程序界面分为三部分:左侧为树形视图,右侧上半部分为列表视图,右侧下半部分为编辑视图 3. 功能: 1) 如果不做任何设置,程序默认为混杂模式,点击按钮① 后,程序开始捕获网络上传输的所有数据包,并将它们显示在列表视图中。点击按钮② 停止捕获。 2) 点击列表视图中的某一行后,对应于该数据包的详细字段分析和原始数据将分别显示在左侧树形视图和右下的编辑视图中,如图2所示。 3) 列表视图中显示的最大数据包数量为2000条,超过后列表视图将清空并重新开始。另外程序还提供了在任意时刻清空当前列表视图中所有数据包的命令(提供该命令的原因是经常会有这样的情况:即列表视图中已经有了很多消息了,但目前只需要关注从即刻起之后到来的消息,这时以前的消息就不再有用并且会影响我们对所要消息的选择)。要使用该命令请在列表视图中任意位置单击鼠标右键,在弹出的菜单中选择“全部清空”
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值