【PTA】6-1 删除C程序中的注释 (31 分)

该博客介绍了一个C语言源代码处理函数,用于删除所有的注释并保留源码结构。函数Pack通过状态机实现,能处理单行和多行注释,同时考虑了字符串和字符常量中的特殊情况。程序提供了一种方法来整理C程序,删除注释并用空格替换,以保持代码的可读性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

请你编写一个函数,将C语言源程序中的注释全部删去。

函数原型
// 删除注释
void Pack(FILE *src, FILE *dst);

说明:参数 srcdst 均为文件指针,其中:src 指示原始程序文件,dst 指示整理后得到的文件。

C语言规定:注释以 /* 开始,以 / 结束。注释可以跨行,不允许嵌套。字符串中的 / 和 */ 不是注释。

此外C语言还规定:注释相当于一个空白字符。因此,注释被删除后应补入一个空格。

裁判程序
#include <stdio.h>
#include <ctype.h>
#include <string.h>

// 删除注释
void Pack(FILE *src, FILE *dst);

int main()
{
    char sname[1024], dname[1024];
    FILE *sfile, *dfile;

    gets(sname);
    gets(dname);

    sfile = fopen(sname, "rb");
    if (!sfile)
    {
        printf("%s 无法打开!\n", sfile);
    }
    dfile = fopen(dname, "wb");
    if (!dfile)
    {
        printf("%s 无法打开!\n", dfile);
    }

    if (sfile && dfile)
    {
        printf("正在整理...");
        Pack(sfile, dfile);
        puts("整理完成!");
    }

    if (sfile)
    {
        fclose(sfile);
    }
    if (dfile)
    {
        fclose(dfile);
    }
    return 0;
}

/* 你提交的代码将被嵌在这里 */
思路

在没到文本末尾持续读取

每次开头判断是否读取到EOF,读到则退出

默认初始状态是普通状态

如果是普通状态

  • 判断第一个是/,读取下一个,如果是*,改变状态为多行注释,如果是/,改变状态为单行注释,如果是其他,输出这两个字符。
  • 判断第一个是单引号,输出单引号,改变状态为字符
  • 判断第一个是是双引号,输出双引号,改变状态为字符串
  • 判断第一个是其他照常输出

如果是单行注释状态

  • 其他字符不输出
  • 如果读到换行符,先输出一个空格,再输出换行,然后将状态换为普通状态

如果是多行注释状态

  • 其他字符不输出
  • 如果读到*号,读取下一个字符,如果是/,输出一个空格,将状态换为普通状态。

如果是字符状态

  • 所有字符照常输出
  • 如果读到 ’ 号,将状态换为普通状态

如果是字符串状态

  • 所有字符照常输出
  • 如果读入的是双引号,输出后把状态换为普通状态
  • 如果读取到\,则为转义字符,再读取下一个字符一起输出
代码
void Pack(FILE *src, FILE *dst)
{
	#define IN_COMMON 1
	#define IN_SINGLE 2
	#define IN_MULTILINE 3
	#define IN_CHARACTER 4
	#define IN_STRING 5
	int state = IN_COMMON;
	int ch1;
	int ch2;
	while(!feof(src))
	{
		ch1 = fgetc(src);
		if(ch1 == EOF)
			break;
		if(state == IN_COMMON)//在普通状态 
		{
			if(ch1 == '/')
			{
				ch2 = fgetc(src);
				if(ch2 == '/')//是单行注释 
					state = IN_SINGLE;
				else if(ch2 == '*')//是多行注释 
					state = IN_MULTILINE;
				else
				{
					fputc(ch1,dst);
					fputc(ch2,dst);
				}
			}
			else if(ch1 == '\'')
			{
				fputc(ch1,dst);
				state = IN_CHARACTER;
			}
			else if(ch1 == '\"')
			{
				fputc(ch1,dst);
				state = IN_STRING;
			}
			else
				fputc(ch1,dst);
		}
		else if(state == IN_SINGLE)//单行注释状态 
		{
			if(ch1 == '\n')
			{
				fputc(' ',dst);
				fputc(ch1,dst);
				state = IN_COMMON;
			}
		}
		else if(state == IN_MULTILINE)//多行注释状态 
		{
			if(ch1 == '*')
			{
				ch2 = fgetc(src);
				if(ch2 == '/')
				{
					fputc(' ',dst);
					state = IN_COMMON;
				}
			}
		}
		else if(state == IN_CHARACTER)//字符状态 
		{
			if(ch1 == '\'')
			{
				fputc(ch1,dst);
				state = IN_COMMON;
			}
			else
				fputc(ch1,dst);
		}
		else if(state == IN_STRING)//字符串状态 
		{
			if(ch1 == '\"')
			{
				fputc(ch1,dst);
				state = IN_COMMON;
			}
			else if(ch1 == '\\')
			{
				ch2 = fgetc(src);
				fputc(ch1,dst);
				fputc(ch2,dst);
			}
			else
				fputc(ch1,dst);
		}
	}	
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值