编译原理学习一,去除代码中的注释

栏目: 服务器 · 编程工具 · 发布时间: 6年前

内容简介:开始学习编译原理了耶~ 关于编译原理的所有练习,按照老规矩,还是用我最喜欢的C#语言来实现,运行在.NetCore平台上~ 关于这个系列的所有代码已经上传到github了,项目主页:对C或C++等高级程序设计语言编写的源程序中的//注释和/

开始学习编译原理了耶~ 关于编译原理的所有练习,按照老规矩,还是用我最喜欢的C#语言来实现,运行在.NetCore平台上~ 关于这个系列的所有代码已经上传到github了,项目主页:

github.com/Deali-Axy/C…

本次题目

对C或C++等高级程序设计语言编写的源程序中的//注释和/ /注释进行删除,保留删除后的源程序。要求以文件形式进行保存。

思路分析

程序主要功能就是消除已经编写好的源程序中的注释。在源程序中注释有两种形式,一种是单行注释,用“//”表示,另一种是多行注释,用“/ /”表示。针对这两种形式,程序中用了if..else..语句加以判断,并做出相应的处理。在这里还有可能出现另一种情况,上述两种注释符号可能出现在引号中,出现在引号中的注释符号并没有注释功能,因此在引号中出现的注释符号不应该被消除。所以,这次编写的程序将要分三种情况分析。

第一种情况,单行注释:

if (ch != temp)
{
    // 这里就是单行注释
    ofile.put(ch);
    ch = ifile.get();
}
复制代码

或者

if (ch != temp)
{
    /* 这里就是单行注释 */
    ofile.put(ch);
    ch = ifile.get();
}
复制代码

第二种情况,块注释:

if (ifile.fail() || ofile.fail())
{
    cerr << "open file fail\n";
    return EXIT_FAILURE;
    /*返回值EXIT_FAILURE(在cstdlib库中定义),用于向操作系统报*
    告打开文件失败*/
}
复制代码

第三种情况,行后注释:

ifile.close(); // 关闭文件
ofile.close();
cout << "/////*////ret/rtr////";
system("pause");
return 0;
复制代码

还有一个关键的注意点

可以看到这一行

cout << "/////*////ret/rtr////";
复制代码

这个字符串用双引号包起来的代码中有很多斜杠,所以要避免将这些斜杠识别为注释。 这里我用的方法是在处理注释前先把包含注释符号的字符串替换掉,等注释删除之后,再添加回去。

实现代码

注释写得很详细啦,配合上面的思路分析,我就不再继续分析代码了~

var sReader = new StreamReader(filePath);
var newSource = "";
var inBlock = false;
var replaceFlag = false;
var tempLine = ""; // 用于保存被替换的特殊行代码
while (!sReader.EndOfStream)
{
    var line = sReader.ReadLine();
    if (line.Length == 0) continue; // 去除空行

    var quotationPattern = "^(.*?)\".*//.*\"";
    var quotationResult = Regex.Match(line, quotationPattern);
    if (quotationResult.Success)
    {
        System.Console.WriteLine("替换特殊代码,双引号中包裹注释斜杠");
        tempLine = quotationResult.Groups[0].Value;
        replaceFlag = true;
        line = Regex.Replace(line, quotationPattern, REPLACEMENT);
    }

    // 单行注释
    if (line.Trim().StartsWith(@"//"))
        continue;
    if (line.Trim().StartsWith(@"/*") && line.EndsWith(@"*/"))
        continue;

    // 注释块
    if (Regex.Match(line.Trim(), @"^/\*").Success)
        inBlock = true;
    if (Regex.Match(line.Trim(), @"\*/$").Success)
    {
        inBlock = false;
        continue;
    }

    // 行后注释
    // 使用非贪婪模式(.+?)匹配第一个//
    var pattern = @"^(.*?)//(.*)";
    // var pattern = @"[^(.*?)//(.*)]|[^(.*?)/\*(.*)\*/]";
    var result = Regex.Match(line, pattern);
    if (result.Success)
    {
        System.Console.WriteLine("发现行后注释:{0}", result.Groups[2]);
        line = result.Groups[1].Value;
    }

    // 还原被替换的代码
    if (replaceFlag)
    {
        System.Console.WriteLine("还原特殊代码");
        line = line.Replace(REPLACEMENT, tempLine);
        replaceFlag = false;
    }

    if (inBlock) continue;
    newSource += line + Environment.NewLine;
}

var outputPath = "output/exp1.src";
System.Console.WriteLine("去除注释完成,创建新文件。");
using (var sWriter = new StreamWriter(outputPath))
{
    sWriter.Write(newSource);
}
System.Console.WriteLine("操作完成!文件路径:{0}", outputPath);
复制代码

结果测试

源文件

#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
using namespace std;

int main()
{
    cout << '/';
    ifstream ifile; //建立文件流对象
    ofstream ofile;
    ifile.open("f:\\上机实验题\\C++\\ConsoleApplication2\\ConsoleApplication2\\源.cpp"); //打开F盘根目录下的fileIn.txt文件
    ofile.open("f:\\上机实验题\\C++\\ConsoleApplication2\\ConsoleApplication2\\源.obj");
    if (ifile.fail() || ofile.fail())
    { //测试打开操作是否成功
        cerr << "open file fail\n";
        return EXIT_FAILURE;
        /*返回值EXIT_FAILURE(在cstdlib库中定义),用于向操作系统报*
    告打开文件失败*/
    }
    char ch;
    ch = ifile.get(); //进行读写操作
    while (!ifile.eof())
    {
        if (ch == 34)
        {                   //双引号中若出现“//”,双引号中的字符不消除
            char temp = ch; //第一个双引号
            ofile.put(ch);
            ch = ifile.get();
            while (!ifile.eof())
            {
                if (ch != temp)
                { //寻找下一个双引号
                    ofile.put(ch);
                    ch = ifile.get();
                }
                else
                {
                    ofile.put(ch);
                    break;
                }
            }
            ch = ifile.get();
            continue; //双引号情况结束,重新新一轮判断
        }
        if (ch == 47)
        { //出现第一个斜杠
            char temp2 = ch;
            ch = ifile.get();
            if (ch == 47)
            { //单行注释情况
                ch = ifile.get();
                while (!(ch == '\n'))
                    ch = ifile.get();
            }
            else if (ch == '*')
            { //多行注释情况
                while (1)
                {
                    ch = ifile.get();
                    while (!(ch == '*'))
                        ch = ifile.get();
                    ch = ifile.get();
                    if (ch == 47)
                        break;
                }
                ch = ifile.get();
            }
            else
            {
                ofile.put(temp2); //temp2保存第一个斜杠,当上述两种情况都没有时,将此斜杠输出
            }
            //ch = ifile.get();
        }
        //cout << ch << endl;
        ofile.put(ch);    //将字符写入文件流对象中
        ch = ifile.get(); //从输入文件对象流中读取一个字符
    }
    ifile.close(); //关闭文件
    ofile.close();
    cout << "/////*////ret/rtr////";
    system("pause");
    return 0;
}
复制代码

处理后的结果

#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
using namespace std;
int main()
{
    cout << '/';
    ifstream ifile; 
    ofstream ofile;
    ifile.open("f:\\上机实验题\\C++\\ConsoleApplication2\\ConsoleApplication2\\源.cpp"); 
    ofile.open("f:\\上机实验题\\C++\\ConsoleApplication2\\ConsoleApplication2\\源.obj");
    if (ifile.fail() || ofile.fail())
    { 
        cerr << "open file fail\n";
        return EXIT_FAILURE;
    }
    char ch;
    ch = ifile.get(); 
    while (!ifile.eof())
    {
        if (ch == 34)
        {                   
            char temp = ch; 
            ofile.put(ch);
            ch = ifile.get();
            while (!ifile.eof())
            {
                if (ch != temp)
                { 
                    ofile.put(ch);
                    ch = ifile.get();
                }
                else
                {
                    ofile.put(ch);
                    break;
                }
            }
            ch = ifile.get();
            continue; 
        }
        if (ch == 47)
        { 
            char temp2 = ch;
            ch = ifile.get();
            if (ch == 47)
            { 
                ch = ifile.get();
                while (!(ch == '\n'))
                    ch = ifile.get();
            }
            else if (ch == '*')
            { 
                while (1)
                {
                    ch = ifile.get();
                    while (!(ch == '*'))
                        ch = ifile.get();
                    ch = ifile.get();
                    if (ch == 47)
                        break;
                }
                ch = ifile.get();
            }
            else
            {
                ofile.put(temp2); 
            }
        }
        ofile.put(ch);    
        ch = ifile.get(); 
    }
    ifile.close(); 
    ofile.close();
    cout << "/////*////ret/rtr////";
    system("pause");
    return 0;
}
复制代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Numerical Methods and Methods of Approximation in Science and En

Numerical Methods and Methods of Approximation in Science and En

Karan Surana / CRC Press / 2018-10-31

ABOUT THIS BOOK Numerical Methods and Methods of Approximation in Science and Engineering prepares students and other readers for advanced studies involving applied numerical and computational anal......一起来看看 《Numerical Methods and Methods of Approximation in Science and En》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

SHA 加密
SHA 加密

SHA 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具