计导作业 (c语言文件管理)

计导作业 (c语言文件管理)

实验12_4_过滤注释

先上题目:

题目描述

C语言的注释分为两种,第一种:在一行源代码中“//”后的内容为注释内容。第二种:“/”与“/”之间的内容为注释内容。第三种:程序中只出现了“/”,没有“/”与之对应,那么将“/”后的全部内容都要过滤掉。注意,只要是注释内容,那么注释内容中的字符应该全部忽略,即不起任何的作用。例如“/”与“/”之间如果再有“//”,那么“//”不应起作用;如果“//”再有“/”,那么“/”也不应起作用。
你的任务是先打开一个名字为dict.dic的文本文件,该文件中前5行每行为1个整数,从第6行开始为5段C语言的源代码。那5个数字代表这5段源代码结束的行数,比如如果第一行的整数为20,第二行的整数为60,则表示从第6行到第20为第一段代码,从第21行到第60为第二段代码。然后根据输入要求将源代码中所有注释过滤掉。
在本过滤注释系统中,你可以忽略源文件中双引号导致“//”、“/
”、“/”失去作用的情况,即只要“//”、“/”、“*/”不是注释内容,在任何情况下都起作用。

输入
只可能是1,2,3,4,5之一

输出
输入为1则输出第一段代码过滤后的结果,输入为2则输出第二段代码过滤后的结果,依此类推。

样例输入
1

样例输出
如果第一段代码是这样:

/*
	@Author: BUPT
	@Date: 2010 8 26
*/

#include<stdio.h>

int main()
{
	int a = 10 , b = 2 , c ;
	c = a / b ; //I just want to test '/'
	printf("I love programming C.\n") ; //"printf" is a useful function /*
	printf("I hope you love it too!\n") ;
	/*
	//C is not always hard , if you love it , it will not treat you rough.
	*/
	return 0 ;
}

则输出是这样:



#include<stdio.h>

int main()
{
        int a = 10 , b = 2 , c ;
        c = a / b ;
        printf("I love programming C.\n") ;
        printf("I hope you love it too!\n") ;

        return 0 ;
}

下面开始解题
yysy,这种题目对于我这样刚入门的还是蛮有难度的
一开始一直觉得思路很乱,看到群里的大佬提到自动机以后去查了一下,才算开始思路了
但好不容易把代码写出来了,却发现提交是80分
怎么都找不到原因,就去直接私大佬
在这里插入图片描述
没想到短短几个字就让我“悟了”
其实这是蛮常见的错误了,就是匹配完字符串以后,直接从当前位置继续往后了,是不对的
比如想要匹配abcabcd
被匹配对象是abcabcabcd
如果匹配到第七个发现’a’ != 'd’以后,直接从第八个继续往后匹配,就错了
应该读到第七个发现不对以后,再返回到第二个重新开始匹配

下面是代码:
不过代码写的好像不大规范,以后慢慢改(嘻嘻)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int n[6];

int filter(FILE *fp, int x);

int main()
{
    FILE *fp;
    int x;
    n[0] = 5;  // 开头前五行
    fp = fopen("dict.dic","r");
    fscanf(fp,"%d\n%d\n%d\n%d\n%d",&n[1],&n[2],&n[3],&n[4],&n[5]);  //  五段结束行数

    char cn;
    cn = fgetc(fp);  //单独读一个换行

    scanf("%d",&x);
    filter(fp,x);

    fclose(fp);  // 结束
}

int filter(FILE *fp, int x)
{
    char ch,ch1;
    for(int i=1;i<x;i++)  // 跳过前面几段
    {
        for(int j=0;j<(n[i]-n[i-1]);j++)
        {
            ch = fgetc(fp);
            while(ch != '\n')
            {
                ch = fgetc(fp);
            }
        }
    }

    int ty=0; //  0:非注释状态 1://注释状态 2:/*注释状态
    int l=n[x-1];   // 让计数器等于上一段最后一行
    while(l<n[x])   // 只要计数器小于该段最后一行就执行
    {
        ch1 = fgetc(fp);  // 读取
        switch (ty)
        {
        case 0:{
            if(ch1 == '/') // 读到/ 
            {
                ch1 = fgetc(fp);  // 再读取一个进行判断
                if(ch1 == '/')    // 若为/,状态变为1
                {
                    ty = 1;
                }else if(ch1 == '*'){  // 若为*,状态变为2
                    ty = 2;
                }else{  // 其他,状态不变
                    if(ch1 == '\n' || ch1 == EOF)  // 读到换行或结尾,计数器++
                    {
                        l++;
                    }
                    printf("/%c",ch1); // 输出/ + 当前字符
                }
            }else{
                if(ch1 == '\n' || ch1 == EOF)  // 读到换行或结尾,计数器++
                {
                    l++;
                }
                printf("%c",ch1);  // 一般输出
            }

            break;
        }

        case 1:{  // 状态1:单行注释
            while(ch1 != '\n' && ch1 != EOF)ch1 = fgetc(fp); // 读到换行或结束符就结束
            l++;  // 计数器++
            ty = 0;  // 回到状态0
            if(ch1 == '\n')printf("\n"); // 换行

            break;
        }

        case 2:{
            if(ch1 == '*')  //读到*执行
            {
                ch1 = fgetc(fp); //再读一个进行判断
                if(ch1 == '/')  // 若为/,则注释结束,回到状态0
                {
                    ty = 0;
                }else{  // 若不是/,就往回退一个位置
                    fseek(fp, -1, 1);
                    break;
                }
            }else{  // 没有读到*
                if(ch1 == '\n' || ch1 == EOF) // 读到换行或结尾,计数器++
                {
                    l++;
                }
            }

            break;
        }
        } // switch结束
    }  // 循环结束
    return 0;
}
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值