我的程序(2):c源码统计器
这是大二时数据结构的课程设计,要求用vc做一个有用户界面的程序.因为当时还不会用vc,所以在去年寒假用c写了一个没有界面的源码统计器,就算是课程设计的内核吧.
期间又该了多次,添加一些功能,增强安全性,对代码进行优化等,总共又5个版本.贴出来几个有代表性的,希望大家指正.
0.0版 :在键盘上输入程序,然后程序返回结果.
/*统计c中代码行和注释行的数量*/
#include<stdio.h>
void recomment(int c,int *pzhushi,int *phangshu,int *flagzhushi,int *flagzhw);
void in_comment(int *pzhushi,int *phangshu, int *flagzhushi,int *flagzhw);
void echo_quote(int c);
main()
{
int c;
int nzhushi=0, nhangshu=0; /* 记录注释和总行数*/
int *pzhushi=&nzhushi;
int *phangshu=&nhangshu;
int *flagzhushi, *flagzhw; /*标志:是否在注释或代码中*/
*flagzhushi=0, *flagzhw=0;
while( (c=getchar())!=EOF )
recomment(c,pzhushi,phangshu,flagzhushi,flagzhw);
printf("%d,%d\n",*pzhushi,*phangshu);
getch();
return 0;
} /*主函数完成*/
void recomment(int c,int *pzhushi,int *phangshu,int *flagzhushi,int *flagzhw)
{
int d;
if (c == '/'){
if ( (d=getchar()) =='*' )
in_comment(pzhushi,phangshu,flagzhushi,flagzhw);/* 进入注释处理函数*/
else if ( d == '/' )
recomment(d,pzhushi,phangshu,flagzhushi,flagzhw); /*递归*/
}
else if ( c == '\'' || c == '"' )
echo_quote(c); /* 在引号内的注释不算*/
else if ( c == '\n'){ /* 对回车的处理(考虑了各种情况)*/
if(*flagzhushi == 1 ) /*如果此行有注释*/
++ (*pzhushi);
if ( *flagzhw==1 )
++ (*phangshu);
*flagzhw=*flagzhushi=0;
}else if ( *flagzhw == 0 && c !=' ' )
*flagzhw=1;
} /*完成*/
void in_comment(int *pzhushi,int *phangshu, int *flagzhushi,int *flagzhw)
{
int c,d;
c=getchar();
d=getchar();
while ( c != '*' || d != '/' ){
if ( c == '\n' ){
++ (*pzhushi);
if ( *flagzhw == 1 )
++ (*phangshu);
}
c=d;
d=getchar();
}
*flagzhushi=1;
} /* 完成*/
void echo_quote(int c)
{
int d;
while ( (d=getchar()) !=c )
if ( d=='\\')
getchar(); /*忽略转义字符*/
} /*完成*/
1.0版 主要对0.0版本中复杂的函数参数进行了修改,用一个结构指针解决问题.(谢谢csdn上面的朋友的指点)
/*统计c中代码行和注释行的数量*/
#include<stdio.h>
struct fun{
int ncomment;
int ncode;
int flagcomment;
int flagcode;
}a;
struct fun *p=&a;
void recomment(int c,struct fun *p);
void in_comment(struct fun *p);
void echo_quote(int c);
main()
{
int c;
while( (c=getchar())!=EOF )
recomment(c,p);
printf("%d,%d\n",p->ncomment,p->ncode);
getch();
return 0;
} /*主函数完成*/
void recomment(int c,struct fun *p)
{
int d;
if (c == '/'){
if ( (d=getchar()) =='*' )
in_comment(p);/* 进入注释处理函数*/
else if ( d == '/' )
recomment(d,p); /*递归*/
}
else if ( c == '\'' || c == '"' )
echo_quote(c); /* 在引号内的注释不算*/
else if ( c == '\n'){ /* 对回车的处理(考虑了各种情况)*/
if(p->flagcomment == 1 ) /*此行有注释*/
++ (p->ncomment);
if ( p->flagcode==1 )
++ (p->ncode);
p->flagcode=p->flagcomment=0;
}else if ( p->flagcode == 0 && c !=' ' )
p->flagcode=1;
} /*完成*/
void in_comment(struct fun *p)
{
int c,d;
c=getchar();
d=getchar();
while ( c != '*' || d != '/' ){
if ( c == '\n' ){
++ (p->ncomment);
if ( p->flagcode == 1 )
++ (p->ncode);
}
c=d;
d=getchar();
}
p->flagcomment=1;
} /* 完成*/
void echo_quote(int c)
{
int d;
while ( (d=getchar()) !=c )
if ( d=='\\')
getchar(); /*忽略转义字符*/
} /*完成*/
3.0版本 不再由键盘输入程序,输入程序的路径即可.(但反斜杠问题没有解决0
/*统计c中代码行和注释行的数量*/
#include<stdio.h>
#include<stdlib.h>
struct fun{
int ncomment;
int ncode;
int flagcomment;
int flagcode;
FILE *pf;
}a = {0,0,0,0,NULL};
struct fun *p=&a;
void recomment(int c,struct fun *p);
void in_comment(struct fun *p);
void echo_quote(int c,struct fun *p);
main()
{
int c;
char s[50];
printf("input the path of the file(注意;当输入反斜杠时,请连续输入两个)这个问题将在下一版中解决\n");
scanf("%s",s);
p->pf = fopen(s,"r");
if( p->pf == NULL ){
printf("open fail!\n");
exit(0);
}
while( ( c=fgetc(p->pf) ) != EOF )
recomment(c,p);
printf("%d,%d\n",p->ncomment,p->ncode);
fclose(p->pf);
return 0;
} /*主函数完成*/
void recomment(int c,struct fun *p)
{
int d;
if (c == '/'){
if ( (d=fgetc(p->pf)) =='*' )
in_comment(p);/* 进入注释处理函数*/
else if ( d == '/' )
recomment(d,p); /*递归*/
}
else if ( c == '\'' || c == '"' )
echo_quote(c,p); /* 在引号内的注释不算*/
else if ( c == '\n'){ /* 对回车的处理(考虑了各种情况)*/
if(p->flagcomment == 1 ) /*此行有注释*/
++ (p->ncomment);
if ( p->flagcode==1 )
++ (p->ncode);
p->flagcode=p->flagcomment=0;
}else if ( p->flagcode == 0 && c !=' ' )
p->flagcode=1;
} /*完成*/
void in_comment(struct fun *p)
{
int c,d;
c=fgetc(p->pf);
d=fgetc(p->pf);
while ( c != '*' || d != '/' ){
if ( c == '\n' ){
++ (p->ncomment);
if ( p->flagcode == 1 )
++ (p->ncode);
}
c=d;
d=fgetc(p->pf);
}
p->flagcomment=1;
} /* 完成*/
void echo_quote(int c,struct fun *p)
{
int d;
while ( (d=fgetc(p->pf)) !=c )
if ( d=='\\')
fgetc(p->pf); /*忽略转义字符*/
} /*完成*/
4.0版本 (最终版本) 可以直接输入程序的路径
/*统计c中代码行(不包括空白行)和注释行的数量*/
#include<stdio.h>
#include<stdlib.h>
struct fun{
int ncomment;
int ncode;
int flagcomment;
int flagcode;
FILE *pf;
}a = {0,0,0,0,NULL};
struct fun *p=&a;
void recomment(int c,struct fun *p);
void in_comment(struct fun *p);
void echo_quote(int c,struct fun *p);
char * change(char *ps,char *pt); /*处理路径中的反斜杠问题。因为在字符串中要用\\表示\ */
main()
{
int c;
char s[50];
char t[100];
char *ps = s;
char *pt = t;
printf("input the path of the file\n");
scanf("%s",s);
p->pf = fopen( change(ps,pt),"r" ); /*打开文件*/
if( p->pf == NULL ){ /*输入的文件路径不对或文件不存在*/
printf("open fail!\n");
exit(0);
}
while( ( c = fgetc(p->pf) ) != EOF )
recomment(c,p);
printf("the commend lines are %d\n,the all code lines(not include black lines) are %d\n",p->ncomment,p->ncode);
fclose(p->pf); /*关闭文件*/
return 0;
} /*主函数完成*/
void recomment(int c,struct fun *p)
{
int d;
if (c == '/'){
if ( (d = fgetc(p->pf)) =='*' )
in_comment(p);/* 进入注释处理函数*/
else if ( d == '/' )
recomment(d,p); /*递归*/
}
else if ( c == '\'' || c == '"' )
echo_quote(c,p); /* 在引号内的注释不算*/
else if ( c == '\n'){ /* 对回车的处理(考虑了各种情况)*/
if(p->flagcomment == 1 ) /*如果此行有注释*/
++ (p->ncomment);
if ( p->flagcode == 1 ) /*如果此行有代码*/
++ (p->ncode);
p->flagcode = p->flagcomment = 0; /*把标志复位*/
}else if ( p->flagcode == 0 && c != ' ' )
p->flagcode = 1;
} /*完成*/
void in_comment(struct fun *p) /*寻找注释结束的地方*/
{
int c,d;
c = fgetc(p->pf);
d = fgetc(p->pf);
while ( c != '*' || d != '/' ){
if ( c == '\n' ){
++ (p->ncomment);
if ( p->flagcode == 1 )
++ (p->ncode);
}
c = d;
d = fgetc(p->pf);
}
p->flagcomment = 1;
} /* 完成*/
void echo_quote(int c,struct fun *p)
{
int d;
while ( (d = fgetc(p->pf)) !=c )
if ( d == '\\')
fgetc(p->pf); /*忽略转义字符*/
} /*完成*/
char * change(char *ps,char *pt) /*处理反斜杠的问题*/
{
char *p = pt;
char c;
while( (c = *pt++ = *ps++) != '\0' )
if( c == '\\' )
*pt = '\\';
return p;
}