C++语言实现代码注释的自动删除

注释种类:

1) /* hello world */

2) // hello world
3) #if 0
   hello world
   #endif

在转载的那篇C语言实现代码注释的自动删除文章,提供了一个很好的思想,那就是有限状态机的思想。

在原来文件只是实现了c语言注释的第一种情况,今天利用空闲时间研究了一下这算法,借鉴这算法思想和部分基础代码并把第二种c++中常用的注释删除算法完成了。

其中关键部分就是要设置好状态机的状态转换图,剩下的工作就容易多了。


今天算法开始考虑过程中,对 折行这个情况没有考虑好,没有当做一个状态来考虑,一直不好处理,设置一个状态后续处理非常方便。 

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

static FILE* fpin;
static FILE* fpout;

/*
 * 删除注释状态机的状态
 */

#define STATUS_NORMAL   0 //正常状态;
#define STATUS_QUOTE    1 //引号内”;
#define STATUS_STIN1    2 //碰到第一个"/" 等待第二个"/";
#define STATUS_STIN2    3 //碰到第二个"/" 并进入到注释内部;
#define STATUS_STINN    4 //进入到注释内部,碰到折行"\";
#define STATUS_STACT    5 //虚拟状态,表示状态机打印。

/*
 * 状态机的动作
 */

#define STFLAG_NOACT    0 //没有任何动作,忽略字符;
#define STFLAG_FPUTC    1 //打印输出;
#define STFLAG_UNPUTC   2 //回退上一个字符;

/*
 * 128主要是考虑ascii码基本字符128个。这个状态表第一维表示状态机状态,第二维表示遇到的下一个字符,整个码表表示遇到下一个字符需要设置的状态。
 */
static int status_table[6][128];
static int status = STATUS_NORMAL;

#define st(i,j) status_table[(i)][(j)]

/*
 * 初始化状态码表,这里描述整体状态机的转换图。
 */

void set_status_table(int i,int j,int s)
{
    if (-1 != j){
        st(i,j) = s;
    }else{
        for (j = 0; j<128; ++j) {
            st(i,j) = s;
        }
    }
}

void init_status()
{
    set_status_table(STATUS_NORMAL,-1,STATUS_NORMAL);
    set_status_table(STATUS_NORMAL,'"',STATUS_QUOTE);
    set_status_table(STATUS_NORMAL,'/',STATUS_STIN1);
    
    set_status_table(STATUS_QUOTE,-1,STATUS_QUOTE);
    set_status_table(STATUS_QUOTE,'"',STATUS_NORMAL);
    
    set_status_table(STATUS_STIN1,-1,STATUS_NORMAL);
    set_status_table(STATUS_STIN1,'/',STATUS_STIN2);
    
    set_status_table(STATUS_STIN2,-1,STATUS_STIN2);
    set_status_table(STATUS_STIN2,'\\',STATUS_STINN);
    set_status_table(STATUS_STIN2,'\n',STATUS_NORMAL);
    
    set_status_table(STATUS_STINN,-1,STATUS_STINN);
    set_status_table(STATUS_STINN,'\n',STATUS_STIN2);
    
    set_status_table(STATUS_STACT, STATUS_NORMAL, STFLAG_FPUTC);
    set_status_table(STATUS_STACT, STATUS_QUOTE, STFLAG_FPUTC);
    set_status_table(STATUS_STACT, STATUS_STIN1, STFLAG_UNPUTC);
    set_status_table(STATUS_STACT, STATUS_STIN2, STFLAG_NOACT);
    set_status_table(STATUS_STACT, STATUS_STINN, STFLAG_NOACT);
    
}


#define file_noact ((status_handler_t)NULL)
typedef void (*status_handler_t)(char);

static void file_putc(char c);
static void file_unputc(char c);

static void status_handler(char c)
{
    const status_handler_t handler_a[] = {
        file_noact, file_putc, file_unputc
    };
    int actidx = st(STATUS_STACT, status);
    status_handler_t handler = handler_a[actidx];
    if (handler != NULL) handler(c);
}

static void show_status(char c);
static void show_status_end();

/*
 * 删除注释函数调用。
 */

void del_comment(char *inpath, char *outpath)
{
    char c;
    init_status();
    fpin = fopen(inpath, "r");
    fpout = fopen(outpath, "w");
    assert(fpin && fpout != NULL);
    while ((c = fgetc(fpin)) != EOF) {
        show_status(c);             //输入下一个字符前状态
        if (c == '\r') continue;
        status = st(status, (int)c);
        show_status_end();          //输入下一个字符后状态
        status_handler(c);
    }
}


/*
 *基础字符处理函数。
 */

static char *c_str(char c, char *buf, int size)
{
    if (c == ' ') return "_";
    else if (c == '\t') return "\\t";
    else if (c == '\n') return "\\n";
    else if (c == '\r') return "\\r";
    else if (c == '\0') return "\\0";
    snprintf(buf, size, "%c", c);
    return buf;
}

#define RET_STATUS_STRING(s)    \
if (status == (s)) return #s

static char *status_str(void)
{
    RET_STATUS_STRING(STATUS_NORMAL);
    RET_STATUS_STRING(STATUS_QUOTE);
    RET_STATUS_STRING(STATUS_STIN1);
    RET_STATUS_STRING(STATUS_STIN2);
    RET_STATUS_STRING(STATUS_STINN);
    return "invalid status";
}

static void show_status(char c)
{
    char t[4];
    fprintf(stdout, "[%s] -->(%s)-->",
            status_str(), c_str(c, t, sizeof t));
}

static void show_status_end()
{
    fprintf(stdout, "[%s]\n",status_str());
}

#define MAXLINE 256
static char linebuf[MAXLINE];
static char *lineptr = linebuf;

static void init_line_buf(void)
{
    memset(linebuf, 0, sizeof linebuf);
    lineptr = linebuf;
}

#define isblank(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')

/* 
 * is writable (非空行 + 不多于1个的空行,可以输出。)
 */
static int is_wrt(void)
{
    char c, *ptr = linebuf;
    for ( ; (c = *ptr); ptr++) {
        if (!isblank(c))
        {
            //非空行
            return 1;
        }
    }
    return 0;
}

static void file_puts(void)
{
    static int lines; /* empty lines */
    
    if (is_wrt())//不是空行,设置lines = 0;
        lines = 0;
    else
        lines++;//统计有多少空行,如果多于1个空行就不把空行输出。
    if (lines > 1)
    {
        return;
    }
    
    unsigned long len = strlen(linebuf);
    fwrite(linebuf, len, 1, fpout);
}

static void file_putc(char c)
{
    *lineptr++ = c;
    /*
     *如果碰到换行符,输出获得的一行。
     */
    if (c == '\n') {
        file_puts();
        init_line_buf();
    }
}

static void file_unputc(char c)
{
    *--lineptr = 0;
}



测试样式:


#include <stdio.h>

int main()
{
    //###\\\\\\\\\ \
    ###" // \\ "123

    //123
    printf("this is a \ //456
            \n %s[]", //789
            "sss");//<666
    return 0;
}


删除注释输出:


#include <stdio.h>

int main()
{

    printf("this is a \ //456
            \n %s[]",
            "sss")
    return 0;
}


状态转换图:

[STATUS_NORMAL] -->(#)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(i)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(n)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(c)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(l)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(u)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(d)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(e)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(_)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(<)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(s)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(t)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(d)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(i)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(o)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(.)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(h)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(>)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(\n)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(\n)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(i)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(n)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(t)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(_)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(m)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(a)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(i)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(n)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(()-->[STATUS_NORMAL]
[STATUS_NORMAL] -->())-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(\n)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->({)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(\n)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(\t)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(/)-->[STATUS_STIN1]
[STATUS_STIN1] -->(/)-->[STATUS_STIN2]
[STATUS_STIN2] -->(#)-->[STATUS_STIN2]
[STATUS_STIN2] -->(#)-->[STATUS_STIN2]
[STATUS_STIN2] -->(#)-->[STATUS_STIN2]
[STATUS_STIN2] -->(\)-->[STATUS_STINN]
[STATUS_STINN] -->(\)-->[STATUS_STINN]
[STATUS_STINN] -->(\)-->[STATUS_STINN]
[STATUS_STINN] -->(\)-->[STATUS_STINN]
[STATUS_STINN] -->(\)-->[STATUS_STINN]
[STATUS_STINN] -->(\)-->[STATUS_STINN]
[STATUS_STINN] -->(\)-->[STATUS_STINN]
[STATUS_STINN] -->(\)-->[STATUS_STINN]
[STATUS_STINN] -->(\)-->[STATUS_STINN]
[STATUS_STINN] -->(_)-->[STATUS_STINN]
[STATUS_STINN] -->(\)-->[STATUS_STINN]
[STATUS_STINN] -->(\n)-->[STATUS_STIN2]
[STATUS_STIN2] -->(\t)-->[STATUS_STIN2]
[STATUS_STIN2] -->(#)-->[STATUS_STIN2]
[STATUS_STIN2] -->(#)-->[STATUS_STIN2]
[STATUS_STIN2] -->(#)-->[STATUS_STIN2]
[STATUS_STIN2] -->(")-->[STATUS_STIN2]
[STATUS_STIN2] -->(_)-->[STATUS_STIN2]
[STATUS_STIN2] -->(/)-->[STATUS_STIN2]
[STATUS_STIN2] -->(/)-->[STATUS_STIN2]
[STATUS_STIN2] -->(_)-->[STATUS_STIN2]
[STATUS_STIN2] -->(\)-->[STATUS_STINN]
[STATUS_STINN] -->(\)-->[STATUS_STINN]
[STATUS_STINN] -->(_)-->[STATUS_STINN]
[STATUS_STINN] -->(")-->[STATUS_STINN]
[STATUS_STINN] -->(1)-->[STATUS_STINN]
[STATUS_STINN] -->(2)-->[STATUS_STINN]
[STATUS_STINN] -->(3)-->[STATUS_STINN]
[STATUS_STINN] -->(\n)-->[STATUS_STIN2]
[STATUS_STIN2] -->(\n)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(\t)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(/)-->[STATUS_STIN1]
[STATUS_STIN1] -->(/)-->[STATUS_STIN2]
[STATUS_STIN2] -->(1)-->[STATUS_STIN2]
[STATUS_STIN2] -->(2)-->[STATUS_STIN2]
[STATUS_STIN2] -->(3)-->[STATUS_STIN2]
[STATUS_STIN2] -->(\n)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(\t)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(p)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(r)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(i)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(n)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(t)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(f)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(()-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(")-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(t)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(h)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(i)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(s)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(_)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(i)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(s)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(_)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(a)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(_)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(\)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(_)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(/)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(/)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(4)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(5)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(6)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(\n)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(\t)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(\t)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(\t)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(\)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(n)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(_)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(%)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(s)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->([)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(])-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(")-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(,)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(_)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(/)-->[STATUS_STIN1]
[STATUS_STIN1] -->(/)-->[STATUS_STIN2]
[STATUS_STIN2] -->(7)-->[STATUS_STIN2]
[STATUS_STIN2] -->(8)-->[STATUS_STIN2]
[STATUS_STIN2] -->(9)-->[STATUS_STIN2]
[STATUS_STIN2] -->(\n)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(\t)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(\t)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(\t)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(")-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(s)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(s)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(s)-->[STATUS_QUOTE]
[STATUS_QUOTE] -->(")-->[STATUS_NORMAL]
[STATUS_NORMAL] -->())-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(;)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(/)-->[STATUS_STIN1]
[STATUS_STIN1] -->(/)-->[STATUS_STIN2]
[STATUS_STIN2] -->(<)-->[STATUS_STIN2]
[STATUS_STIN2] -->(6)-->[STATUS_STIN2]
[STATUS_STIN2] -->(6)-->[STATUS_STIN2]
[STATUS_STIN2] -->(6)-->[STATUS_STIN2]
[STATUS_STIN2] -->(\n)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(_)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(_)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(_)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(_)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(r)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(e)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(t)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(u)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(r)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(n)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(_)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(0)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(;)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(\n)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(})-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(\n)-->[STATUS_NORMAL]
[STATUS_NORMAL] -->(\n)-->[STATUS_NORMAL]



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值