You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言注释移除程序Bug排查:单行注释首斜杠无法删除

问题分析与修复

你的程序在处理单行注释时第一个'/'无法删除,核心原因是两处逻辑缺陷:

1. 错误的输出过滤条件

代码中最后一个输出判断:

if (c != '/' && mlcomment == OFF && slcomment == OFF && d_quotes == OFF)
    fputc(c, ft);

这里的c != '/'完全不合理——它会过滤掉所有非注释场景下的正常'/'(比如除法运算符/),同时在单行注释流程中,导致第一个'/'的处理逻辑混乱,最终被错误保留。

2. 单行注释的收尾处理漏洞

当检测到//时,程序仅设置slcomment = ON,但未处理第二个'/'作为c_prev的后续逻辑。在后续循环中,当c_prev是第二个'/'、当前字符是注释内其他内容时,会进入if (c_prev == '/')的else分支,将第二个'/'错误输出,而第一个'/'因为输出条件限制被遗漏处理,最终表现为第一个'/'被保留。


修复后的代码

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

#define ON 1
#define OFF 0

int main()
{
    FILE* fs, * ft;
    int c = 1, c_prev = 1, slcomment = OFF, mlcomment = OFF, d_quotes = OFF;

    fs = fopen("source.c", "rb");
    ft = fopen("target.c", "wb");

    // 增加文件打开失败的错误处理
    if (fs == NULL || ft == NULL) {
        printf("Failed to open file!\n");
        getch();
        return 1;
    }

    c_prev = fgetc(fs);
    // 处理空文件情况
    if (c_prev == EOF) {
        fclose(fs);
        fclose(ft);
        printf("Source file is empty.\n");
        getch();
        return 0;
    }

    while ((c = fgetc(fs)) != EOF)
    {
        // 优化引号处理:增加转义引号判断(仍有局限,但比原逻辑准确)
        if (c == '"' && d_quotes == OFF && c_prev != '\\')
            d_quotes = ON;
        else if (c == '"' && d_quotes == ON && c_prev != '\\')
            d_quotes = OFF;

        if (mlcomment == OFF && d_quotes == OFF) {
            // 检测单行注释,直接跳过两个'/'
            if (c_prev == '/' && c == '/') {
                slcomment = ON;
                c_prev = c;
                continue;
            }
            // 检测多行注释,直接跳过两个字符
            else if (c_prev == '/' && c == '*') {
                mlcomment = ON;
                c_prev = c;
                continue;
            }
        }

        // 单行注释结束,输出换行符并关闭注释标记
        if (c == '\n' && slcomment == ON) {
            slcomment = OFF;
            fputc(c, ft);
            c_prev = c;
            continue;
        }

        // 多行注释结束,跳过结束标记的'/'
        if (mlcomment == ON && c_prev == '*' && c == '/') {
            mlcomment = OFF;
            c = fgetc(fs);
            c_prev = c;
            continue;
        }

        // 仅在非注释、非引号状态下输出字符
        if (mlcomment == OFF && slcomment == OFF && d_quotes == OFF) {
            fputc(c_prev, ft);
        }

        c_prev = c;
    }

    // 处理文件最后一个字符
    if (mlcomment == OFF && slcomment == OFF && d_quotes == OFF) {
        fputc(c_prev, ft);
    }

    fclose(fs);
    fclose(ft);
    printf("Program, after removal of comments, has been copied in target.c...\n");

    getch();
    return 0;
}

关键修复说明

  1. 移除了输出条件中的c != '/',确保正常的'/'(如除法运算)能被正确输出。
  2. 检测到//时直接跳过两个'/',避免任何一个被错误保留。
  3. 单行注释结束时主动输出换行符,保证代码格式完整。
  4. 增加了文件打开失败、空文件的错误处理,提升程序健壮性。
  5. 优化引号判断逻辑,避免转义引号被误判为引号结束。
  6. 循环结束后处理最后一个字符,避免遗漏文件末尾的有效内容。

内容的提问来源于stack exchange,提问作者Vinayak Deshmukh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 04:08:11