大岛丈所有作品番号:问题描述]读入一个C程序,统计程序中代码、注释

来源:百度文库 编辑:高校问答 时间:2024/04/28 04:50:00
问题描述]读入一个C程序,统计程序中代码、注释和空行的行数以及函数的个数和平均数,并利用统计信息分析评价程序的风格。为方便,作以下约定:第一个字符是‘{’的行数为注释行(该行不含语句)。除了空行注释外,其余均为行代码,每个函数都是全局的,没有嵌套函数。

[基本要求]把C程序文件作为TEXT文件读入源程序:边读入程序,边识别统计代码行、注释行和空行,还要识别过程和函数的开始和结束,以便统计其个数和平均数。

评价分为代码、注释和空行3方面。分为A、B、C和D4个等级,等级的划分标准是:

A级
B级
C级
D级

代码(过程平均长度)
10~15行
8~9行或者说16~20行
5~7行或21~24行
〈5或〉24行

注释(占总行数比率)
10~25%
10~14%或20~30%
5~9%或是31~35%
〈5%或〉35%

空行(占总行数比率)
15~25%
10~14%或26~30%
5~9%或31~35%
〈5%或〉35%

以下是对程序文件ProgAnal.C分析的输出结果示例:

The result of analysing program file “ProAnal.c”:

Line of code :180 Lines of comments:63 Blanklines:52 Code Comments Space 61% 21% 18%

The program include 9 procedures and 4 functions.

The average length of a section of code is 12.9 lines.

Grade A.Excellent roution Size Style.Grade A:Excellent commenting style.

Grade B.Excellent white space style.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define TRUE 1
#define FALSE 0
#define BOOL int
#define MAXSIZE 5000
#define COUNT 20 // 可以统计的最大的文件个数
#define LEN 20 // 文件名的最大长度

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>

voidcheckfile(char *filename,int i);
voidanaly(char filename[COUNT][LEN],int n);
BOOLGetIn(int *n);
//函数属性结构
typedefstruct {
char filename[20]; //每一个函数的名字
int length; //每一个函数的长度
int pos; //每一个函数的位置
}Fun;
//统计结构的声明
typedefstruct {
int comments; //纯注释的个数
int comment; //混合注释个数
int blank; //空行的个数
Fun fun[MAXSIZE]; //函数的属性
int others; //除去函数中代码外其余的代码个数
int funcount; //函数的个数
}Analy;
//串的基本操作ADT
//检测是否为空串
BOOLStrEmpty(char *s)
{
if(s[0]=='\0')
return TRUE;
return FALSE;
}
//查看S1中是否有值为S2的子串,若有则返回第一个子串的位置,若无则返回-1;
intFind(char *s1,char *s2)
{
int i = 0,j = 0;
if(strlen(s1) < strlen(s2))
return -1;
while (s1[i]!='\0')
{
if(s1[i] == s2[j])
{
i++;
j++;
if(s2[j]=='\0')
return i-j;
continue;
}
i++;
j=0;
}
return -1;

}
//读取文件中的一行字符
voidHaveLine(FILE *fp,char *s)
{
while(!feof(fp))
{
*s = fgetc(fp);
if(*s=='\n'){ //若是一行的结尾则表示取完了一行
*s='\0';
return;
}
s++;
}
*s = '\0';
}
//忽略一行字符开头的空格和tab,返回截断后上的串指针
char*IgnoreB(char *s)
{
while (*s== ' ' || *s== ' ')
s++;
return s;
}
//判断一行字符是不是注释
intIsCom(char *s)
{
int posc,pos1,pos2;
s= IgnoreB(s);
posc = Find(s,"//");
if(posc == 0)//此行仅有注释,无代码;
return 1;
if(posc == -1)
return 0;
pos1 = Find(s,"\"");
pos2 =Find(&s[pos1+1],"\"");
if(posc > pos1 && posc < pos2)
return 0;
return 2;
}
//判断一行字符是不是空白
BOOLIsBlank(char *s)
{
s= IgnoreB(s);
if(*s== '\0')
return TRUE;
return FALSE;
}
intIsFunB(char *s)
{
int i,j,pos,pos2;
//有分号,if while for的不是函数开头
if(Find(s,";") != -1 ||Find(s,"if") != -1 || Find(s,"for") != -1 ||Find(s,"while") != -1||Find(s,"switch") != -1)
return FALSE;
//没有小括号的不是函数开头
if((pos = Find(s,"(")) == -1)
return FALSE;
s = IgnoreB(s);
i = Find(s," ");
j = Find(s," ");
if (i != -1 && j != -1)
i = i > j ? j : i;
else if (i == -1)
i = j;
else if (1 == -1 && j == -1)
return FALSE;
if (i > pos)
return FALSE;
s = &s[i];
s = IgnoreB(s);
pos2 = Find(s,"(");
if(*s == '\0' || *s == '(' ||pos2 > pos)
return FALSE;
return TRUE;
}

voidprintR(int aver ,int comc,int blanks )
{
//按代码级别判定标准输出分析结果
int i;
char Grade[4][15] = {"A:Excellent","B: Good","C: just So-So","D:Bad"};//定义四个级别段
//判定代码的级别
if (aver <= 15 && aver >=10)
i = 0;
else if((aver <=20 && aver >=16) || aver <= 9 && aver >= 8)
i = 1;
else if((aver <=7 && aver >=5) || aver <= 24 && aver >=21)
i = 2;
else if ((aver <5) || (aver > 24))
i = 3;
printf(" Grade %s routine code style\n",Grade[i]);
//判定注释的级别
if (comc<= 25 && comc >= 15)
i = 0;
else if((comc <=14 && comc >=10) || comc <= 30 && comc >=26)
i = 1;
else if((comc <=9 && comc >=5) || comc <= 35 && comc >=31)
i = 2;
else if((comc <5) || (comc > 35))
i = 3;
printf(" Grade %s routine commenting style\n",Grade[i]);
//判定空行的级别
if (blanks <= 25 && blanks >=15)
i = 0;
else if((blanks <=14 && blanks>= 10) || blanks <= 30 && blanks >=26)
i = 1;
else if((blanks <=9 && blanks>= 5) || blanks <= 35 && blanks >=31)
i = 2;
else if((blanks <5) || (blanks > 35))
i = 3;
printf(" Grade %s white spacestyle\n",Grade[i]);
}
//打印输出结果
voidprint(Analy *An)
{
int sum = 0,funcode = 0;
int i, comc , blanks, aver ,code;
for(i = 0;i < An->funcount ;i++)//求函数的代码总数
funcode += An->fun[i].length;
//求所有的代码总数
sum += An->blank;
sum += An->comments;
sum += An->comment;
sum += An->others;
sum += funcode;
if(sum == 0)//防止除数sum为0
sum = 1;
if(An->funcount == 0)//防止除数m为0
aver = 0;
else
aver = funcode/An->funcount;
comc = (An->comments +An->comment)*100/sum;
blanks = ((An->blank)*100)/sum;
code = 100 - comc - blanks; //((funcode + An->others)*100)/sum;
printf(" 程序源代码分析结果如下所示\n\n");
printf(" 代码行数: %d\n",sum -An->blank - An->comment - An->comments);
printf(" 注释行数: %d\n",An->comments +An->comment);
printf(" 空行数: %d\n",An->blank);
printf(" 代码 注释 空行\n");
printf(" ***** ****** ******\n");
printf(" ***** ****** ******\n");
printf(" %d%% %d%% %d%%\n",code,comc,blanks);
printf(" The program includes %d functions\n",An->funcount);
printf(" The average length of section of function is %d\n",aver);
printf("\n");
//按代码级别判定标准输出分析结果
printR(aver,comc,blanks);
}

voidcheckfile(char *filename,int i)
{
FILE *fp;
while((fp = fopen(filename,"r"))== NULL)
{
printf("对不起!文件不存在%s\n",filename);
printf("\n请重新输入第%d个源文件: ",i+1);
scanf("%s",filename);
}
}
BOOLGetIn(int *n)//规范输入的数据,只能为数字
{
char c;
*n = 0;
fflush(stdin);
c = getchar();//当输入一串数据并按回车后,getchar()取出缓存队列中的第一个字符
while(c != '\n'){
if(c == '0' && n == 0)
printf("输入有误!请重新输入....\n");
if(c >= '0' && c <= '9')
*n = (*n) * 10 +c - 48;
else{
printf("输入有误!请重新输入....\n");
fflush(stdin);//清空(刷新)缓存里的内容,以防被下次getchar()取用
return FALSE;
}
c = getchar();
}
return TRUE;
}
voidanaly(char filename[COUNT][LEN],int n)
{
FILE *fp;//分析源文件指针
FILE *fpp;//日志文件指针
Analy An;//程序统计结构体
char s[200];//存储每行的文件
BOOL begin = 0,start = 0;//设置函数开始标记
int i,j = -1,pos = 0;//函数的位置 长度信息
//c检测函数内大括号的匹配,comtype是注释的类型
int c=0,comtype;
An.blank = 0;
An.comments = 0;
An.comment = 0;
An.others = 0;
An.funcount = 0;
if((fpp =fopen("log.txt","w")) == NULL)//建立日志文件
printf("cannot open the file%s\n");
for (i = 0 ;i < n; i++)//遍历所有的文件
{
if((fp =fopen(filename[i],"r")) == NULL)
{
printf("cannot open the file%s\n",filename[i]); //输出filename[i]
getchar();
exit(0);
}
pos = 0; //函数在新一个文件中的位置初始化
while (!feof(fp))
{
HaveLine(fp,s); //从文件中读取一行数据
pos++; //每个函数在文件中开始的位置
//分类统计文件中的代码个数
comtype = IsCom(s);
if (comtype ==1)
{
An.comment++;
continue;
}
if (comtype == 2)
An.comments++;
if (IsFunB(s))
{
fprintf(fpp,"%s\n",s);//提取每个函数的名字写入到文件

j++; //j为函数的个数-1;
c = 0;//大括号个数初始化为0
begin = TRUE;
strcpy(An.fun[j].filename,filename[i]);//记录函数在哪个文件中
An.fun[j].pos = pos;
An.fun[j].length = 1;
}
else if(IsBlank(s))
An.blank++;
else if(begin){
An.fun[j].length++;
if (Find(s,"{") !=-1) //检测是否进入到了函数体内
{
c++;
start = TRUE;
}
if (Find(s,"}") != -1)//检测是否一个函数的结束
c--;
if (c==0 && start)
{
begin = FALSE;
start = FALSE;
}
}
else
An.others++;
}
fclose(fp);//关闭分析文件
}
fclose(fpp);//关闭日志文件
An.funcount= j+1; //把函数的个数保存
print(&An); //打印分析结果
}

voidmain()
{
int n,i;
char c;
char filename[COUNT][LEN];
printf("\t-------------------------------------------------------------\n");
printf("\t 程序源代码分析软件 BY 沈航电子信息工程学院--王盼 \n");
printf("\t--------------------------------------------------------------\n");
while(1){
n=0;
printf("\t\t\t**********程序分析*********\n");
printf("请输入您要分析的源文件的个数: ");
while(!GetIn(&n) || n <= 0){
printf("请输入您要分析的源文件个数:");
}
for(i = 0 ;i < n ;i++)
{
printf("\n请输入第%d个源文件: ",i+1);
scanf("%s",filename[i]);
checkfile(filename[i],i);
fflush(stdin);
}
analy(filename,n);
printf("\t********您需要继续使用本软件吗?Y/N***********\n");
c =getchar();
if(c == 'Y' || c == 'y')
continue;
break;
}
}

问题描述]读入一个C程序,统计程序中代码、注释和空行的行数以及函数的个数和平均数,并利用统计信息分析评价程序的风格。为方便,作以下约定:第一个字符是‘{’的行数为注释行(该行不含语句)。除了空行注释外,其余均为行代码,每个函数都是全局的,没有嵌套函数。

[基本要求]把C程序文件作为TEXT文件读入源程序:边读入程序,边识别统计代码行、注释行和空行,还要识别过程和函数的开始和结束,以便统计其个数和平均数。

评价分为代码、注释和空行3方面。分为A、B、C和D4个等级,等级的划分标准是:

A级
B级
C级
D级

代码(过程平均长度)
10~15行
8~9行或者说16~20行
5~7行或21~24行
〈5或〉24行

注释(占总行数比率)
10~25%
10~14%或20~30%
5~9%或是31~35%
〈5%或〉35%

空行(占总行数比率)
15~25%
10~14%或26~30%
5~9%或31~35%
〈5%或〉35%

以下是对程序文件ProgAnal.C分析的输出结果示例:

The result of analysing program file “ProAnal.c”:

Line of code :180 Lines of comments:63 Blanklines:52 Code Comments Space 61% 21% 18%

The program include 9 procedures and 4 functions.

The average length of a section of code is 12.9 lines.

Grade A.Excellent roution Size Style.Grade A:Excellent commenting style.

Grade B.Excellent white space style.