C/C++ 注释项目转换

什么是注释转换?
注释转换就是将C语言里面的注释转换成C++风格注释,我们将用有限状态机模型来处理该项目。

什么是有限状态机?
有限状态机FSM是软件上常⽤的⼀种处理⽅法,它把复杂的控制逻辑分解成有限个稳定状态,在每个状态上进⾏处理。 有限状态机是闭环系统,可以⽤有限的状态,处理⽆穷的事务。

通常我们使⽤多路分之语句来处理状态机

switch (state)
{
    case 1:
        break;
    case 2:
        break;
    case 3:
        break;
        ...
    case n:
        break;
    default:
        break;
}

了解了处理方法之后,我们来看一下c/c++注释转换的模型:
这里写图片描述
其中,左边的图表示,将c语言注释的代码放在input.c文件中,然后将注释转换后的c++风格的代码放在output.c中。
我们先将input.c给出来:

// 1.一般情况
/* int i = 0; */

// 2.换行问题
/* int i = 0; */int j = 0;
/* int i = 0; */
int m = 0;
// 3.匹配问题
/*int i = 0;/*xxxxx*/

// 4.多行注释问题
/*
int i=0;
int j = 0;
int k = 0;
*/int k = 0;

// 5.连续注释问题
/**//**/

// 6.连续的**/问题
/***/

// 7.C++注释问题
// /*xxxxxxxxxxxx*/

右边的图就是一个有限状态机模型,在这个模型中共有四种状态:C语言状态,NULL状态,CPP状态,END状态。

假设刚一开始处于NULL状态,然后从input.c中读字符,进行处理时有以下几种情况:
(1)当遇到“/*”时,就进入C状态;
(2)遇到“//”时进入CPP状态;
(3)遇到文件结束标志EOF时,进入END状态;
(4)其余情况直接写入output.c即可。

分析清楚之后,我们给出NULL状态时的转换函数:

void NULL_convert_(FILE *pread, FILE *pwrite)
{
    first = fgetc(pread);//先读取第一个字符
    switch (first)
    {
    case'/'://如果第一个字符是‘/’,则需要判断第二个字符
    {
               second = fgetc(pread);//读取第二个字符
               if ('*' == second)//如果第二个字符是‘*’,则将‘//’写入,并转换为C状态
               {
                   fputc(first, pwrite);
                   fputc('/', pwrite);
                   state = C_convert;
               }
               else if ('/' == second)//如果第二个字符是‘/’,则将读取到的两个字符写入,并转换为CPP状态
               {
                   fputc(first, pwrite);
                   fputc(second, pwrite);
                   state = CPP_convert;
               }
               else//如果是其他情况,则直接写入即可
               {
                   fputc(first, pwrite);
                   fputc(second, pwrite);
               }
    }
        break;
    case EOF://遇到文件结束标志,直接进入结束状态
        state = END_convert;
        break;
    default:
        fputc(first, pwrite);
        break;
    }
}

进入C状态时,从input.c中读到字符之后有以下几种状况:
(1)读到文件结束标志EOF时,直接进入END状态;
(2)当读到“\n”时,将“\n”写入,同时将“//”写入output.c中;
(3)当读到“*/”时,需要再向后读一个字符并分三种情况处理:
a、“*/”后面无其他字符,则不需要处理直接进入NULL状态;
b、“*/”后面又读到一个“/”,则需要向input.c中写入一个“/”,并进入NULL状态即可;
c、“*/”后面读到一个”\n”,则将“\n”写入即可。
(4)当读到“*”时,则将第一个“”写入,再判断第三个字符,如果第三个字符是“/”,则将进入NULL状态即可;
(5)其他情况直接将读到的字符写入output.c即可。

下面给出C语言状态时的转换:

void C_convert_(FILE *pread, FILE *pwrite)
{
    first = fgetc(pread);
    switch (first)
    {
    case '*':
        second = fgetc(pread);
        switch (second)
        {
        case '*':
            third = fgetc(pread);
            fputc(first, pwrite);
            if ('/'== third)
            {
                state = NULL_convert;
            }
            break;
        case '/':
            third = fgetc(pread);
           if (third != '\n')     //   /* int i = 0; */int j = 0;  
             {
                  fputc('\n', pwrite);
             }
           if (third == '/')       //5.连续的注释问题/**//**/  
            {
                  ungetc('/', pread);
                  state = NULL_convert;
                  break;
           }
            fputc(third, pwrite);   //   /* int i = 0; */ \n int j = 0;  
            state = NULL_convert;
            break;
        default:
            fputc(first, pwrite);
            fputc(second, pwrite);
            break;
        }
        break;
    case '\n':
            fputc('\n', pwrite);
            fputc('/', pwrite);
            fputc('/', pwrite);
            break;
    case EOF:
            state = END_convert;
            break;
    default:
            fputc(first, pwrite);
            break; 
    }
}

进入CPP状态时,读到字符后有三种情况需要处理:
(1)读到文件结束标志EOF时,直接进入END状态;
(2)读到字符“\n”时,将“\n”写入output.c中,然后进入NULL状态;
(3)读到其他字符直接写入output.c中即可。

下面是CPP状态时的转换:

void CPP_convert_(FILE *pread, FILE *pwrite)
{
    first = fgetc(pread);
    switch (first)
    {
    case'\n'://如果是'\n'写入,再转换为无状态
    {
                fputc(first, pwrite);
                state = NULL_convert;
    }
        break;
    case EOF://如果遇到EOF,则直接进去结束状态
        state = END_convert;
        break;
    default:
        fputc(first, pwrite);
        break;
    }
}

所有的状态之间的转换至此已将全部分析完了,当然还需要一个函数来完成各种状态之间的转换:

void CommentConvert(FILE *pread, FILE *pwrite)
{
    state = NULL_convert;//刚开始处于无状态
    while (state!=END_convert)
    {
        switch (state)
        {
        case NULL_convert:
            NULL_convert_(pread, pwrite);
            break;
        case C_convert:
            C_convert_(pread, pwrite);
            break;
        case CPP_convert:
            CPP_convert_(pread, pwrite);
            break;
        }
    }
}

接下来给出该项目的源码:

头文件部分:

#define _CRT_SECURE_NO_WARNINGS 1
#ifndef __ZHUSHICONVERT_H__
#define __ZHUSHICONVERT_H__

#include <stdio.h>

enum STATE
{
    NULL_convert,
    C_convert,
    CPP_convert,
    END_convert
};

void NULL_convert_(FILE *pread, FILE *pwrite);
void C_convert_(FILE *pread, FILE *pwrite);
void CPP_convert_(FILE *pread, FILE *pwrite);
void CommentConvert(FILE *pread, FILE *pwrite);

#endif // zhushiconvert.h

各个函数的实现:

#include "zhushiconvert.h"

enum STATE state = NULL_convert;
int first = 0;
int second = 0;
int third = 0;

void NULL_convert_(FILE *pread, FILE *pwrite)
{
    first = fgetc(pread);//先读取第一个字符
    switch (first)
    {
    case'/'://如果第一个字符是‘/’,则需要判断第二个字符
    {
               second = fgetc(pread);//读取第二个字符
               if ('*' == second)//如果第二个字符是‘*’,则将‘//’写入,并转换为C状态
               {
                   fputc(first, pwrite);
                   fputc('/', pwrite);
                   state = C_convert;
               }
               else if ('/' == second)//如果第二个字符是‘/’,则将读取到的两个字符写入,并转换为CPP状态
               {
                   fputc(first, pwrite);
                   fputc(second, pwrite);
                   state = CPP_convert;
               }
               else//如果是其他情况,则直接写入即可
               {
                   fputc(first, pwrite);
                   fputc(second, pwrite);
               }
    }
        break;
    case EOF://遇到文件结束标志,直接进入结束状态
        state = END_convert;
        break;
    default:
        fputc(first, pwrite);
        break;
    }
}
void C_convert_(FILE *pread, FILE *pwrite)
{
    first = fgetc(pread);
    switch (first)
    {
    case '*':
        second = fgetc(pread);
        switch (second)
        {
        case '*':
            third = fgetc(pread);
            fputc(first, pwrite);
            if ('/'== third)
            {
                state = NULL_convert;
            }
            break;
        case '/':
            third = fgetc(pread);
           if (third != '\n')     //   /* int i = 0; */int j = 0;  
             {
                  fputc('\n', pwrite);
             }
           if (third == '/')       //5.连续的注释问题/**//**/  
            {
                  ungetc('/', pread);
                  state = NULL_convert;
                  break;
           }
            fputc(third, pwrite);   //   /* int i = 0; */ \n int j = 0;  
            state = NULL_convert;
            break;
        default:
            fputc(first, pwrite);
            fputc(second, pwrite);
            break;
        }
        break;
    case '\n':
            fputc('\n', pwrite);
            fputc('/', pwrite);
            fputc('/', pwrite);
            break;
    case EOF:
            state = END_convert;
            break;
    default:
            fputc(first, pwrite);
            break; 
    }
}



void CPP_convert_(FILE *pread, FILE *pwrite)
{
    first = fgetc(pread);
    switch (first)
    {
    case'\n'://如果是'\n'写入,再转换为无状态
    {
                fputc(first, pwrite);
                state = NULL_convert;
    }
        break;
    case EOF://如果遇到EOF,则直接进去结束状态
        state = END_convert;
        break;
    default:
        fputc(first, pwrite);
        break;
    }
}
void CommentConvert(FILE *pread, FILE *pwrite)
{
    state = NULL_convert;//刚开始处于无状态
    while (state!=END_convert)
    {
        switch (state)
        {
        case NULL_convert:
            NULL_convert_(pread, pwrite);
            break;
        case C_convert:
            C_convert_(pread, pwrite);
            break;
        case CPP_convert:
            CPP_convert_(pread, pwrite);
            break;
        }
    }
}

测试部分:

#include "zhushiconvert.h"
#include <stdlib.h>
int main()
{
    FILE *pread = NULL;
    FILE *pwrite = NULL;
    pread = fopen("input.c", "r");
    if (NULL == pread)
    {
        perror("file to read");
        exit(EXIT_FAILURE);
    }
    pwrite = fopen("output.c","w");
    if (NULL == pwrite)
    {
        fclose(pread);
        perror("file to write");
        exit(EXIT_FAILURE);
    }
    CommentConvert(pread, pwrite);
    fclose(pread);
    fclose(pwrite);
    return 0;
}

最后来看一下output.c文件里面的内容是不是跟我们预想的一样呢?

// 1.一般情况
// int i = 0; 

// 2.换行问题
// int i = 0; 
int j = 0;
// int i = 0; 
int m = 0;
// 3.匹配问题
//int i = 0;/*xxxxx

// 4.多行注释问题
//
//int i=0;
//int j = 0;
//int k = 0;
//
int k = 0;

// 5.连续注释问题
//
//

// 6.连续的**/问题
//*

// 7.C++注释问题
// /*xxxxxxxxxxxx*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值