注释转换——C语言注释转换为C++注释状态

在进行注释转换之前,我们首先要对两种注释方法进行简单的对比:

  • C语言注释风格为 / * 注释内容 * /,从 / * 开始,到 * / 结束,中间全是它的注释内容,也就是说,C注释状态可以进行多行注释;
  • C++注释风格为 // 注释内容,不同的是,C++只能进行单行注释。
那么要如何进行转换呢?我们画图来分析。

这里写图片描述

在读取一个.c文件时,可能会遇到四种状态:无注释状态,即正常代码,C语言注释状态,C++注释状态和结束状态。

这四种状态之间的关系我们也画图来进行分析:

这里写图片描述

  • 读文件时,正常代码直接写入,当遇到EOF直接到文件结束状态。遇到 / 时有两种情况,/ * 进入C注释状态,/ / 进入C++注释状态。在C注释状态下,遇到 * / 返回正常代码,在C++注释状态下,遇到 \n 返回正常代码,遇到EOF直接到文件结束状态。需要注意的是,由于C注释是多行注释,所以它不可能直接到文件结束状态。

下面我们写一个示例代码:

input.c

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

// 2.换行问题
/* int i = 0; */int j = 0;
/* int i = 0; */
int j = 0;

// 3.匹配问题
/*int i = 0;/*xxxxx*/

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

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

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

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

接下来,我们采用多文件编译的方式,写函数来实现它。
看代码:

test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "CommentConvert.h"

void test()
{
    FILE *pfRead = NULL;
    FILE *pfWrite = NULL;
    pfRead = fopen("input.c", "r");
    if(pfRead == NULL)
    {
        perror("open file for read");
        exit(EXIT_FAILURE);
    }
    pfWrite = fopen("output.c", "w");
    if(pfWrite == NULL)
    {
        perror("open file for write");
        exit(EXIT_FAILURE);
    }
    CommentConvert(pfRead, pfWrite);
    fclose(pfRead);
    pfRead = NULL;
    fclose(pfWrite);
    pfWrite = NULL;
}

int main()
{
    test();
    return 0;
}

CommentConvert.h

#ifndef __COMMENT_CONVERT_H__
#define __COMMENT_CONVERT_H__

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

typedef enum State  //定义一个枚举,里面是四种状态
{
    NUL_STATE,  //无注释状态(正常代码)
    C_STATE,    //c注释状态
    CPP_STATE,  //c++注释状态
    END_STATE,  //结束状态
}State;

void CommentConvert(FILE *pfRead, FILE *pfWrite);

void DO_NULSTATE(FILE *pfRead, FILE *pfWrite, State *ps);
void DO_CSTATE(FILE *pfRead, FILE *pfWrite, State *ps);
void DO_CPPSTATE(FILE *pfRead, FILE *pfWrite, State *ps);

#endif

CommentConvert.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "CommentConvert.h"

void CommentConvert(FILE *pfRead, FILE *pfWrite)
{
    //注释转换
    State state = NUL_STATE;    //定义初始状态为无注释状态
    while(state != END_STATE)
    {
        switch(state)
        {
        case NUL_STATE:
            DO_NULSTATE(pfRead, pfWrite, &state);
            break;
        case C_STATE:
            DO_CSTATE(pfRead, pfWrite, &state);
            break;
        case CPP_STATE:
            DO_CPPSTATE(pfRead, pfWrite, &state);
            break;
        default:
            break;
        }
    }
}

void DO_NULSTATE(FILE *pfRead, FILE *pfWrite, State *ps)
{
    int first = fgetc(pfRead);
    switch(first)
    {
    case '/':
        {
            int second = fgetc(pfRead);
            switch(second)
            {
            case '*':                       //C注释状态(/*)
                {
                    fputc('/', pfWrite);
                    fputc('/', pfWrite);
                    *ps = C_STATE;
                }
                break;
            case '/':                       //C++注释状态(//)
                {
                    fputc(first, pfWrite);
                    fputc(second, pfWrite);
                    *ps = CPP_STATE;
                }
                break;
            default:
                {
                    fputc(first, pfWrite);
                    fputc(second, pfWrite);
                }
                break;
            }
        }
        break;
    case EOF:                               //文件结束的标志
        fputc(first, pfWrite);
        *ps = END_STATE;
        break;
    default:                                //正常代码
        fputc(first, pfWrite);
        break;
    }
}

void DO_CSTATE(FILE *pfRead, FILE *pfWrite, State *ps)
{
    int first = fgetc(pfRead);
    switch(first)
    {
    case '*':
        {
            int second = fgetc(pfRead);
            switch(second)
            {
            case '/':                       
                {
                    int third = fgetc(pfRead);      
                    if(third == '\n')               //当*/后面没有内容时,将\n写入文件    
                    {
                        fputc(third, pfWrite);
                    }
                    else                            //当*/后面还有内容时,比如/*  */ /*  */或/* */ int a = 1;必须先写入\n,再把读到的内容还回去,防止它被丢掉。
                    {
                        fputc('\n', pfWrite);
                        ungetc(third, pfRead);
                    }
                    *ps = NUL_STATE;
                }
                break;
            case '*':                               //处理**/  ****/这种情况
                {
                    fputc(first, pfWrite);
                    ungetc(second, pfRead);
                }
                break;
            default:                                //正常代码
                {
                    fputc(first, pfWrite);
                    ungetc(second, pfRead);
                }
                break;
            }
        }
        break;
    case '\n':                                      //c注释是多行注释,在转换成c++注释时应先写入\n,再写入//
        {
            fputc(first, pfWrite);
            fputc('/', pfWrite);
            fputc('/', pfWrite);
        }
        break;
    default:                                        //正常代码
        fputc(first, pfWrite);
        break;
    }
}

void DO_CPPSTATE(FILE *pfRead, FILE *pfWrite, State *ps)
{
    int first = fgetc(pfRead);
    switch(first)
    {
    case '\n':                                      //C++注释一行,遇\n注释结束
        {
            fputc(first, pfWrite);
            *ps = NUL_STATE;
        }
        break;
    case EOF:                                       //文件结束
        *ps = END_STATE;
        break;
    default:                                        //正常代码
        fputc(first, pfWrite);
        break;
    }
}

测试结果:

这里写图片描述

猜你喜欢

转载自blog.csdn.net/Nan_Feng726/article/details/81486781