需求分析:
1. 输入:
- 输入为一个C程序文件,以字符顺序读入。
- 文件名为 "input.c",在实际使用时可能需要根据实际情况进行更改。
2. 输出:
- 输出为统计信息,包括代码行数、注释行数、空行数、函数个数和平均函数长度。
- 输出评价该程序的代码、注释和空行的风格。
3. 功能性需求:
- 读取C程序文件并按照字符顺序逐字符处理。
- 识别和统计代码行、注释行和空行。
- 识别函数的开始和结束,以便统计函数的个数和平均行数。
- 根据不同等级的划分标准,评价代码、注释和空行的风格。
- 计算并输出统计信息,包括代码行数、注释行数、空行数、函数个数和平均函数长度。
4. 非功能性需求:
- 性能:
- 程序应在合理的时间内完成对较小程序的分析。
- 能够处理一般规模的C程序文件。
- 可维护性:
- 代码应具备清晰的结构,易于理解和维护。
- 可能的调整点(如文件名、评价标准)应易于更改。
- 可扩展性:
- 程序应考虑到未来可能的扩展,如支持更复杂的代码结构。
- 可以通过选作内容实现更多功能。
5. 评价标准:
- 代码行、注释行和空行的评价标准按照等级划分。
- 对于选作内容,评价程序在报告函数的平均长度、找出最长函数和最大函数嵌套深度方面的性能。
6. 约定:
- 使用文件名 "input.c" 作为默认的输入文件名,但程序应具有灵活性,允许用户指定其他文件名。
- 考虑一些简化约定,例如以 "FFF" 开头的行为注释行。
7. 测试:
- 首先,对较小的C程序进行分析,确保程序能够正确运行。
- 然后,使用程序对自身进行分析,验证其功能。
代码实现:
#include <stdio.h>
// 函数用于检查字符是否为空白字符
int isWhitespace(char c) {
return (c == ' ' || c == '\t' || c == '\n' || c == '\r');
}
int main() {
FILE *fp;
char c;
int codeLines = 0, commentLines = 0, blankLines = 0;
int insideComment = 0, insideFunction = 0;
int functionCount = 0, totalFunctionLines = 0;
fp = fopen("input.c", "r");
if (fp == NULL) {
printf("打开文件错误。\n");
return 1;
}
while ((c = fgetc(fp)) != EOF) {
// 检测注释并处理多行注释
if (c == '/' && (c = fgetc(fp)) == '*') {
insideComment = 1;
commentLines++;
continue;
} else if (c == '*' && (c = fgetc(fp)) == '/') {
insideComment = 0;
continue;
}
// 检测单行注释
if (c == '/' && (c = fgetc(fp)) == '/') {
insideComment = 1;
commentLines++;
while ((c = fgetc(fp)) != '\n' && c != EOF) {
// 跳过直到行尾或文件末尾的字符
}
insideComment = 0;
continue;
}
// 检测新行并处理注释和函数内部
if (c == '\n') {
if (insideComment) {
commentLines++;
} else if (insideFunction) {
insideFunction = 0;
functionCount++;
} else {
blankLines++;
}
}
// 检测函数开始
if (!insideComment && c == '{' && !isWhitespace(fgetc(fp))) {
insideFunction = 1;
}
// 检测函数结束
if (!insideComment && c == '}' && !isWhitespace(fgetc(fp))) {
insideFunction = 0;
}
// 检测以FFF开头的行以识别注释行
if (c == 'F' && (c = fgetc(fp)) == 'F' && (c = fgetc(fp)) == 'F' && (c = fgetc(fp)) == ' ' && !insideComment) {
commentLines++;
while ((c = fgetc(fp)) != '\n' && c != EOF) {
// 跳过直到行尾或文件末尾的字符
}
}
// 统计函数内的代码行数
if (!insideComment && !insideFunction && c != '\n') {
codeLines++;
}
// 统计总函数行数
if (insideFunction && !isWhitespace(c)) {
totalFunctionLines++;
}
}
fclose(fp);
// 计算并输出统计信息
double avgFunctionLength = (functionCount == 0) ? 0 : (double)totalFunctionLines / functionCount;
printf("代码行数:%d\n", codeLines);
printf("注释行数:%d\n", commentLines);
printf("空行数:%d\n", blankLines);
printf("函数个数:%d\n", functionCount);
printf("平均函数长度:%.2f\n", avgFunctionLength);
return 0;
}