C语言代码行数分类统计小程序(源代码)

1 需求分析
 1) 问题描述: 读入一个(最多9个)C程序代码文件,统计程序中代码、注释和空行数以及函数的个数,显示函数名并生成相应的记录日志。
 2) 基本要求如下: 
(1)、把程序文件(如.c或者.txt等)按字符顺序读入源程序; 
(2)、输入正确性检查;
(3)、边读入程序,边识别统计代码行、注释行和空行,同时还要识别函数,统计代码个数;
(4)、最多允许一次分析9个文件


2 显示结果
备注:本文的代码试验IDE为VS2013。本代码对比较常规的编程习惯下编写的C代码可以比较好的识别,但是对一些特殊情况不能识别。

1)输入正确的文件个数和路径


2)输入正确时生成的日志文件



3 程序结构

1)整体结构


2)分析模块结构


4 源代码

整个工程共有三个文件构成:statist.h;source.c;main.c


1) statist.h

#define SIZE_N 100
#define SIZE_L 200
#define NUM_F 9
#define title "------------------------Life is a Fight-----------------------------------"

extern bool com_flag;

void getline(FILE* pfile, char* pt);
char* clearblank(char*pt);
char* mystrstr(char* s1, char* s2);
bool Isblank(char* pt);
int Iscom(char* pt);
bool Isfunc(char* pt);
bool Qtycheck(int* pt);



2) source.c

#include<stdio.h>
#include<string.h>
#include<stdbool.h>
#include"statist.h"

void getline(FILE* pfile,char* pt)
{
	while (!feof(pfile))
	{
		*pt = fgetc(pfile);
		if (*pt=='\n')	//成功读取完一行,直到换行符
		{
			*pt = '\0';
			return;
		}
		pt++;	
	}
	*pt = '\0';	//如果还没有检测到换行符,文件已经结束,则在末尾添加终止符
}

 char* clearblank(char* pt)
{
	while ((*pt == ' ') || (*pt == '   '))
	{
		pt++;
	}
	return pt;
}

char* mystrstr(char* s1, char* s2)
{
	char*s, *sp1, *temp1, *temp2;
	int q_flag = 0;

	if (strstr(s1, "\"") == NULL)	//如果没有发现引号
	{
		s = strstr(s1, s2);
		return s;
	}
	else	//如果发现引号
	{
		sp1 = s1;
		while (*sp1)
		{
			temp1 = strstr(sp1, "\"");
			temp2 = strstr(sp1, s2);
			if ((temp1 != NULL) && (temp1 == sp1))
			{
				if (q_flag == 0)
					q_flag = 1;
				else
					q_flag = 0;
			}
			if ((temp2 != NULL) && (q_flag == 0) && (temp2 == sp1))
				return sp1;
			sp1++;
		}
		return NULL;
	}
}

bool Isblank(char* pt)
{
	clearblank(pt);
	if (*pt == '\0')
		return 1;
	return 0;
}

int Iscom(char* pt)
{
	char* pt1,*pt2,*pt3;

	clearblank(pt);
	pt1 = mystrstr(pt, "//");
	pt2 = mystrstr(pt, "/*");
	pt3 = mystrstr(pt, "*/");
	if (com_flag == 0)
	{
		if ((pt2!=NULL) && (pt3 == NULL))	//如果只有/*表明注释开始
			com_flag = 1;
		if (pt1 == pt)	//双斜杠开头的注释
			return 1;
		else if (pt1 - pt > 0 || pt2 - pt > 0)	//有注释符号,但是不是顶头开始
			return 2;
		else if ((pt2 == pt) && ((pt3 != NULL && (*(pt3 + 2) == '\0')) || (pt3 == NULL)))	//以/*开头以*/结尾,或者以/*开头,没有检测到*/
			return 1;
		else if ((pt2 == pt) && (pt3 != NULL) && (*(pt3 + 2) != '\0'))	//以/*开头但是没有以*/结尾
			return 2;
		else if (pt1 == NULL || pt2 == NULL)	//没有检测到注释符号
			return 0;
	}
	else if (com_flag == 1)
	{
		if (pt3!=NULL)
		{
			com_flag = 0;
			return 1;
		}
		printf("\nYYYY\n");
		return 1;	//如果com_flag==1,且没有检测到*/则是一句注释
	}
}

bool Isfunc(char* pt)
{
	char* pt1, *pt2, *pt3,*pt4,*pt5,*pt6;

	clearblank(pt);
	pt1 = mystrstr(pt, "(");
	pt2 = mystrstr(pt, ";");
	pt3 = mystrstr(pt, "if");
	pt4 = mystrstr(pt, "while");
	pt5 = mystrstr(pt, "for");
	pt6 = mystrstr(pt, "switch");
	if (pt1 != NULL&&pt2 == NULL&&pt3 == NULL&&pt4 == NULL&&pt5 == NULL&&pt6 == NULL)
		return true;
	return false;
}

bool Qtycheck(int* pt)//只允许输入一个1到9的数字
{
	char temp[3];
	char c;
	fflush(stdin);
	gets(temp);
	if (temp[0]>'0'&&temp[0] <= '9'&&temp[1] == '\0')
		*pt = (int)(temp[0] - 48);
		else
		{
			fflush(stdin);
			printf("Please re-enter the file quantity(0<n<10):");
			return 0;
		}
		return 1;
}




3) main.c

#include<stdio.h>
#include<string.h>
#include<stdbool.h>
#include"statist.h"
#include<stdlib.h>//system()的头文件
#include<malloc.h>

bool com_flag;

int main(void)
{
	FILE* in,*log;
	char con;
	char temp[SIZE_L + 1];
	char name[SIZE_N];
	char* pt;
	char* name_t;
	int* result;

	int n = 0;
	struct FIL{
		int cod;
		int blk;
		int com;
		int fct;
	}fil = { 0, 0, 0, 0 };
	com_flag = 0;
	do{
		printf("%s", title);
		printf("\n\n\nPlease enter the file quantity(0<n<10):");
		while (!Qtycheck(&n));
		name_t = (char*)malloc(n*sizeof(name));
		result = (int*)malloc(n * 4 * sizeof(int));
		log = fopen("log.txt", "w");
		fprintf(log, "%s\n\n\n", title);

		for (int i = 0; i < n; i++)
		{
			printf("please enter file \"%d\" name:", i + 1);
			scanf("%s", name_t + i*SIZE_N);
			in = fopen(name_t + i*SIZE_N, "r");
			while (!in)
			{
				fflush(stdin);
				printf("please re-enter file \"%d\" name:", i + 1);
				scanf("%s", name_t + i*SIZE_N);
				in = fopen(name_t + i*SIZE_N, "r");
			}
			fclose(in);
		}

		for (int i = 0; i < n; i++)
		{
			in = fopen(name_t + i*SIZE_N, "r");
			while (!feof(in))
			{
				getline(in, temp);
				pt = clearblank(temp);
				if (Isblank(pt) == 1 && com_flag == 0)
				{
					fil.blk++;
					continue;
				}
				else if (Iscom(pt) == 1)
				{
					fil.com++;
					continue;
				}
				else if (Iscom(pt) == 2 && Isfunc(pt) == 0)
					fil.com++;
				else if (Iscom(pt) == 2 && Isfunc(pt) == 1)
				{
					fil.com++;
					fil.fct++;
					fil.cod++;
					fprintf(log, "%s	%s\n", name_t + i*SIZE_N, temp);
					continue;
				}
				else if (Isfunc(pt) == 1)
				{
					fil.fct++;
					fprintf(log, "%s	%s\n", name_t + i*SIZE_N, temp);
				}
				fil.cod++;
			}
			*(result + 4 * i) = fil.blk;
			*(result + 4 * i + 1) = fil.cod;
			*(result + 4 * i + 2) = fil.com;
			*(result + 4 * i + 3) = fil.fct;
			fil.blk = 0;
			fil.cod = 0;
			fil.com = 0;
			fil.fct = 0;
			com_flag = 0;
			fclose(in);
			if (fil.fct)
				fprintf(log, "\n\n\n");
		}

		fprintf(log, "%s", "\n\n\n==========================================================");
		printf("==========================================================");
		printf("\nFile No.	Blank	Code	Commen	Function\n");
		fprintf(log, "\n%s\n", "File No.	Blank	Code	Commen	Function");
		for (int i = 0; i < n; i++)
		{
			printf("%d		%d	%d	%d	%d\n", i + 1, *(result + 4 * i), *(result + 4 * i + 1), *(result + 4 * i + 2), *(result + 4 * i + 3));
			fprintf(log, "%d		%d	%d	%d	%d\n", i + 1, *(result + 4 * i), *(result + 4 * i + 1), *(result + 4 * i + 2), *(result + 4 * i + 3));
		}
		fclose(log);
		free(name_t);
		free(result);
		printf("\n\n\nPress 'Y' to continue\n");
		fflush(stdin);
		con = getchar();
		printf("\n\n\n");
	} while (con=='Y'||con=='y');

	system("pause");
	return 0;
}


  • 6
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值