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

C程序注释移除异常:单行注释仅删除一个'/'的修复求助

我来帮你解决单行注释残留/的问题!咱们先拆解代码里的几个关键问题,再给出修复后的完整代码。

问题根源分析
  1. 局部变量屏蔽全局变量:你的single_comment函数里重新声明了char c,d;,这会把全局的c和d给覆盖掉。函数里读取的字符根本不会更新全局变量,所以处理完单行注释后,全局的d还是之前的/,后续代码就会错误地把这个残留的/输出出去。
  2. check_comment逻辑漏洞:在else分支里,不管当前字符是什么,你都同时输出c和d,这不仅会导致字符重复输出,而且处理完单行注释后,没有跳过这个错误的输出逻辑。
  3. 多行注释处理逻辑错误:incomment里的循环条件while(c == '*' || c == '/')完全不对,它没法正确识别多行注释的结束标记*/,很可能提前退出或者漏掉部分注释。
  4. 全局变量初始化缺失:全局的d没有初始值,容易引发未知的奇怪行为。
针对性解决方案

针对这些问题,我们一步步调整代码:

  • 删掉single_comment里的局部变量,直接用全局变量来跟踪字符状态;
  • 重构check_comment的输出逻辑,只在确定不是注释的情况下输出字符,避免重复或错误输出;
  • 修复incomment的循环,正确识别*/来结束多行注释;
  • 增加参数检查和更严谨的错误处理,避免资源泄漏。
修复后的完整代码
/*Program to remove all the comments from a c program */
#include<stdio.h>
#include<stdlib.h>

void check_comment();
void incomment();
void single_comment();

char c; // 只保留全局的当前字符变量,简化状态管理
FILE *fp, *fp1;

int main(int argc, char** argv) {
    // 先检查命令行参数是否正确
    if (argc != 3) {
        printf("Usage: %s <input-file> <output-file>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    // 输入文件只读打开
    fp = fopen(argv[1], "r");
    if (fp == NULL) {
        perror("Error opening input file");
        exit(EXIT_FAILURE);
    }

    // 输出文件写打开
    fp1 = fopen(argv[2], "w");
    if (fp1 == NULL) {
        perror("Error opening output file");
        fclose(fp); // 打开失败时记得关闭已打开的输入文件
        exit(EXIT_FAILURE);
    }

    // 逐字符处理输入文件
    while ((c = fgetc(fp)) != EOF) {
        check_comment();
    }

    // 关闭文件资源
    fclose(fp);
    fclose(fp1);
    return 0;
}

void check_comment() {
    if (c == '/') {
        char next_char = fgetc(fp); // 临时读取下一个字符,不覆盖全局c
        if (next_char == '*') {
            // 进入多行注释处理
            incomment();
        } else if (next_char == '/') {
            // 进入单行注释处理
            single_comment();
        } else {
            // 不是注释,输出当前字符,把读取的下一个字符放回输入流
            fputc(c, fp1);
            if (next_char != EOF) {
                ungetc(next_char, fp);
            }
        }
    } else {
        // 正常字符直接输出
        fputc(c, fp1);
    }
}

/* 处理多行注释:直到找到 */ 结束标记 */
void incomment() {
    char prev_char = '*'; // 初始为*,因为已经读取了 /*
    while ((c = fgetc(fp)) != EOF) {
        if (prev_char == '*' && c == '/') {
            break; // 找到注释结束符,退出循环
        }
        prev_char = c;
    }
}

/* 处理单行注释:跳过直到换行,保留换行符 */
void single_comment() {
    while ((c = fgetc(fp)) != EOF) {
        if (c == '\n') {
            // 保留换行符,保证输出代码格式正确
            fputc(c, fp1);
            break; // 回到主循环处理下一行
        }
        // 跳过单行注释中的所有字符
    }
}
关键修改说明
  • 简化全局变量:只保留全局的c来跟踪当前读取的字符,减少全局变量带来的状态混乱;
  • 修复单行注释:移除single_comment里的局部变量,直接使用全局c,并且保留换行符(让输出的代码格式更自然);
  • 正确处理多行注释:用prev_char记录前一个字符,准确识别*/结束标记,确保完整移除多行注释;
  • 严谨的错误处理:增加命令行参数检查,打开文件失败时关闭已打开的资源,避免内存泄漏;
  • 避免重复输出:使用ungetc把误读的非注释字符放回输入流,保证后续字符处理的连贯性。

这样修改后,单行注释会被完整移除,不会残留/,多行注释也能正确处理,输出的代码格式也和原文件保持一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:06:22