程序最美(寻路)

你还在坚持练习你的技术吗?运动员天天训练,音乐家也会演练更难的曲章。你呢?

去注释程序

去注释程序

         C/C++中注释有两种形式:

         1./* … */

         2.// …

         我们要实现的功能就是讲程序中的注释过滤掉。

         我们首先采用一种直接的方法进行过滤,就是顺序扫描整个源代码,检测 /*、*/、// 这些标示,以获取程序的注释。

// 程序1:顺序扫描
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;

void read_prog(const string& file, string& prog)
{
    ifstream fin(file.c_str());
    if (!fin)
    {
        cerr << file << " error!" << endl;
        exit(2);
    }
    prog.clear();
    string line;
    while (getline(fin, line))
    {
        prog += line + '\n';
    }
}

void filter(const string& prog, string& prog_filtered, vector<string>& comments)
{
    prog_filtered.clear();
    comments.clear();

    char ch = 0;

    for (string::size_type i = 0; i < prog.size(); )
    {
        string tmp;
        ch = prog[i];
        if (ch == '/')
        {
            tmp += ch;
            ++i;
            if (i >= prog.size())
            {
                prog_filtered += tmp;
                return;
            }
            ch = prog[i];
            if (ch == '*')
            {
                tmp += ch;
                ++i;
                string::size_type pos = prog.find("*/", i);
                if (pos < prog.size())
                {
                    tmp += prog.substr(i, pos - i + 2);
                    i = pos + 2;
                    comments.push_back(tmp);
                }
                else
                {
                    tmp += prog.substr(i);
                    i = prog.size();
                    prog_filtered += tmp;
                }
            }
            else if (ch == '/')
            {
                tmp += ch;
                ++i;
                string::size_type pos = prog.find('\n', i);
                tmp += prog.substr(i, pos - i);
                i = pos;
                comments.push_back(tmp);
            }
            else
            {
                tmp += ch;
                ++i;
                prog_filtered += tmp;
                tmp.clear();
            }
        }
        else
        {
            tmp += ch;
            ++i;
            prog_filtered += tmp;
            tmp.clear();
        }
    }
}

int main()
{
    string prog, prog_filtered;
    vector<string> comments;

    read_prog("prog.txt", prog);
    cout << prog << endl;
    filter(prog, prog_filtered, comments);

    cout << prog_filtered << endl;
    for (vector<string>::size_type i = 0; i != comments.size(); ++i)
    {
        cout << i + 1 << ':' << comments[i] << endl;
    }
    return 0;
}

测试样例:

#include <iostream>
using namespace std;

/// test1
//* test2*/
// main函数
int main()
{
    /* 主函数 */
    /*
     *注释
         */
}
// 阿萨德发生的发生地方
/* asdfasdf *

 

         做法2:利用状态转换图

 

// 程序2:利用状态转换图进行注释的过滤
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;

void read_prog(const string& file, string& prog)
{
    ifstream fin(file.c_str());
    if (!fin)
    {
        cerr << file << " error!" << endl;
        exit(2);
    }
    prog.clear();
    string line;
    while (getline(fin, line))
    {
        prog += line + '\n';
    }
}

void StateTransitionDiagram(const string& prog, string& prog_filtered, vector<string>& comments)
{
    int state = 1;
    string tmp;
    for (string::size_type i = 0; i < prog.size(); ++i)
    {
        char ch = prog[i];
        switch (state)
        {
        case 1:
            if (ch == '/')
            {
                tmp += ch;
                state = 2;
            }
            else
            {
                prog_filtered += ch;
            }
            break;

        case 2:
            if (ch == '*')
            {
                tmp += ch;
                state = 3;
            }
            else if (ch == '/')
            {
                tmp += ch;
                state = 5;
            }
            else
            {
                tmp += ch;
                prog_filtered += tmp;
                tmp.clear();
                state = 1;
            }
            break;

        case 3:
            if (ch == '*')
            {
                tmp += ch;
                state = 4;
            }
            else
            {
                tmp += ch;
            }
            break;

        case 4:
            if (ch == '/')
            {
                tmp += ch;
                comments.push_back(tmp);
                tmp.clear();
                state = 1;
            }
            else
            {
                tmp += ch;
                state = 3;
            }
            break;

        case 5:
            if (ch == '\n')
            {
                comments.push_back(tmp);
                tmp.clear();
                state = 1;
                --i;
            }
            else
            {
                tmp += ch;
            }
            break;

        default:
            cerr << "Error!" << endl;
            break;
        }
    }
}

int main()
{
    string prog, prog_filtered;
    vector<string> comments;

    read_prog("prog.txt", prog);
    cout << prog << endl;
    StateTransitionDiagram(prog, prog_filtered, comments);

    cout << prog_filtered << endl;
    for (vector<string>::size_type i = 0; i != comments.size(); ++i)
    {
        cout << i + 1 << ':' << comments[i] << endl;
    }
    return 0;
}

测试样例:

#include <iostream>
using namespace std;

/// test1
//* test2*/
// main函数
int main()
{
    /* 主函数 */
    /*
     *注释
         */
}
// 阿萨德发生的发生地方
/* asdfasdf *

 

         总结

         上文利用两种方法进行两种注释的过滤,第一种方式是顺序扫描程序,当检测到/、*等字符时进行检测判断,对符合条件的注释进行提取。

         第二种方法是借助了状态转换图,设置扫描程序中根据不同字符设置当前状态值state,根据当前状态state以及当前字符进行判断,对符合条件的注释进行提取过滤。

         第一种方法是仅仅利用了当前字符的特性,在当前字符条件下进行后续的处理。第二种方法除了利用当前字符的特性外,还结合了检测的状态,这样记录的信息更多,使得程序处理逻辑更为简单清晰,更有利于逻辑的划分和程序的书写,同时也提高了代码的可读性。

         第一种方法是if的嵌套,多层if。第二种方法利用了switch-case语句(也可以是if语句)使得处理逻辑得以平铺,整个处理流程更为清晰易懂。这可能就是状态转换图的优点之所在。

         数据结构决定算法,增加信息表示方法和途径,使得信息处理更为简单易行。预处理的思想也就在于增加信息表达方式,使得后续处理更为快捷和方便。

posted on 2013-08-13 14:05  unixfy  阅读(710)  评论(0编辑  收藏  举报

导航