数据结构课程设计作业--程序分析

程序分析
【问题描述】
读入一个C程序,统计程序中代码、注释和空行的行数以及函数的个数和平
均行数,并利用统计信息分析评价该程序的风格。
【基本要求】
(1) 把 C 程序文件按字符顺序读入源程序;
(2) 边读入程序,边识别统计代码行、注释行和空行,同时还要识别函数的
开始和结束,以便统计其个数和平均行数。
(3) 程序的风格评价分为代码、注释和空行三个方面。每个方面分为 A,B,C
和 D 四个等级 , 等级的划分标准是 :
【测试数据】
先对较小的程序进行分析。当你的程序能正确运行时,对你的程序本身进行
分析。
【实现提示】
为了实现的方便,可作以下约定:
(1) 头两个字符是 FFF 的行称为注释行(该行不含语句)。除了空行和注释
行外,其余均为代码行(包括类型定义、变量定义和函数头)。
(2) 每个函数代码行数(除去空行和注释行)称为该函数的长度。
(3) 每行最多只有一个"{" 、"}"、"switch" 和"struet"(便于识别函数的
结束行)。
【选作内容】
(1) 报告函数的平均长度。
(2) 找出最长函数及其在程序中的位置。
(3) 允许函数的嵌套定义,报告最大的函数嵌套深度。

需求分析:

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值