小项目之C注释转换为C++注释状态

首先来看如下C注释状态的测试用例:

// 1.一般情况
/* 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*/

转换为C++注释状态后:

// 1.一般情况
// 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*/

现在来分析如何转换,先设定C注释的文件夹名为input,装换为C++注释的文件夹名为output,并且设置三个全局变量first,second,third用来记录读取到的连续的三个字符,一个全局变量state记录当前的注释状态,初值为空状态。
0 .对于本身就是C++注释状态,判断是C++注释状态的条件为读取到的两个连续字符都为‘/’,此时向output文件中输入两个字符‘/’,并且,将state赋值为C++的状态。继续从input文件中读取字符,若读到换行符‘\n’,则将换行符输入到output文本中,将state赋值为空状态,代表此时已经完成一行注释,接着开始新的注释装换;若为文件尾,则state赋值为文件尾标志,否则代表读取到的都为注释状态,应跟在开始输入的“//”后面。代码如下:

void DoCPP_State(FILE *pfread, FILE *pfwrite)
{
    first = fgetc(pfread);
    switch (first)
    {
    case '\n':
        fputc('\n', pfwrite);
        state = NUL_State;
        break;
    case EOF:
        state = END_State;
        break;
    default:
        fputc(first, pfwrite);
        break;
    }
}

1.对于第一种最一般的情况,一行只有一个C的注释状态,判断条件为first==‘/’,second==‘* ’,此时向文件中输入两个‘/’字符,并将state赋值为C的注释状态,接下来进行C的注释状态结束判断。结束条件为first==‘*’,second==‘/’,此时将state赋值为空状态,代表此时已经完成一行注释,接着开始新的注释装换。
2.对于第二种换行问题,当读取到C的注释状态结束时,应该继续读取下一个字符,赋值给third,此时third的值应该是非注释内容,应该换行并且将内容输入到output文件中。
3.对于第三种匹配问题,当确认为C的注释转态后,只有当first==‘* ’,second==‘/’时才认为注释结束,需要排除注释内容有字符‘*’和‘/’的情况。
4.后面的情况为前几种情况的综合。
处理代码如下:

void DoC_State(FILE *pfread, FILE *pfwrite)
{
    assert(pfread);
    assert(pfwrite);

    first = fgetc(pfread);
    switch (first)
    {
    case '*':
        second = fgetc(pfread);
        switch (second)
        {
        case '/':
            third = fgetc(pfread);
            if (third == '/')  //连续注释的状态,如:/*xxx*//*xxx*/
            {
                fputc('\n', pfwrite);
                ungetc(third, pfread);
                state = NUL_State;  
                break;
            }
            state = NUL_State;

            if (third != '\n')
            {
                fputc('\n', pfwrite);
            }
            fputc(third, pfwrite);
            break;
        case '*':    //注释中有“*”,如/***/
            third = fgetc(pfread);
            fputc(first, pfwrite);//把“*”输入到转换后的文件流中
            if (third == '/')  //C注释后面紧跟非注释内容,如/***/ int=a;
                fputc('\n', pfwrite);
                state = NUL_State;
            break;
        default:     //不是注释的字符  
            fputc(first, pfwrite);
            fputc(second, pfwrite);
            break;
        }
        break;

    case '\n':   //C注释中的多行注释  
        fputc('\n', pfwrite);
        fputc('/', pfwrite);
        fputc('/', pfwrite);
        break;
    case EOF:   //文件结束标志  
        state = END_State;
        break;
    default:   //不是注释的字符
        fputc(first, pfwrite);
        break;
    }
}

完整代码如下:


CommentConvert.h


#ifndef __COMMENTCONVERT_H__
#define __COMMENTCONVERT_H__
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdlib.h>
#include<assert.h>
#include<stdio.h>
#define INPUT "input.c"
#define OUTPUT "output.c"

enum STATE
{
    NUL_State,
    C_State,
    CPP_State,
    END_State
};

void DoCommentConvert(FILE *pfread, FILE *pfwrite);
void DoNUL_State(FILE *pfread, FILE *pfwrite);
void DoC_State(FILE *pfread, FILE *pfwrite);
void DoCPP_State(FILE *pfread, FILE *pfwrite);

#endif //__COMMENTCONVERT_H__

main.c


#include"CommentConvert.h"

int main()
{
    FILE *pfread = fopen(INPUT, "r");
    if (NULL == pfread)
    {
        perror("open file for read");
        exit(EXIT_FAILURE);
    }
    FILE *pfwrite = fopen(OUTPUT, "w");
    if (NULL == pfwrite)
    {
        fclose(pfread);
        perror("open file for write");
        exit(EXIT_FAILURE);
    }
    DoCommentConvert(pfread, pfwrite);
    fclose(pfread);
    fclose(pfwrite);

    return 0;
}

CommentConvert.c


#include"CommentConvert.h"

enum STATE state = NUL_State;  //设最开始是空状态
char first = 0;
char second = 0;
char third = 0;

void DoCommentConvert(FILE *pfread, FILE *pfwrite)
{
    while (state != END_State)
    {
        switch (state)
        {
        case NUL_State:
            DoNUL_State(pfread, pfwrite);
            break;
        case C_State:
            DoC_State(pfread, pfwrite);
            break;
        case CPP_State:
            DoCPP_State(pfread, pfwrite);
            break;
        case END_State:
            break;
        default:
            break;
        }
    }
}

void DoNUL_State(FILE *pfread, FILE *pfwrite)
{
    assert(pfread);
    assert(pfwrite);

    first = fgetc(pfread); //从文件中读取一个字符

    switch (first)
    {
    case '/':
            second = fgetc(pfread); 
            if (second == '*')
            {
                fputc('/', pfwrite);
                fputc('/', pfwrite);
                state = C_State;  //代表此时为C状态
            }
            else if (second == '/') //说明此时本来就是C++注释的状态
            {
                fputc(first, pfwrite);
                fputc(second, pfwrite);
                state = CPP_State;
            }
            else
            {
                fputc(first, pfwrite); //说明此时非注释状态
                fputc(second, pfwrite);
            }
            break;
    case '\n':
        fputc('\n', pfwrite);
        break;
    case EOF:
        state = END_State;
        break;
    default:
        fputc(first, pfwrite);
        break;
    }
}

void DoC_State(FILE *pfread, FILE *pfwrite)
{
    assert(pfread);
    assert(pfwrite);

    first = fgetc(pfread);
    switch (first)
    {
    case '*':
        second = fgetc(pfread);
        switch (second)
        {
        case '/':
            third = fgetc(pfread);
            if (third == '/')  //连续注释的状态,如:/*xxx*//*xxx*/
            {
                fputc('\n', pfwrite);
                ungetc(third, pfread);
                state = NUL_State;  
                break;
            }
            state = NUL_State;

            if (third != '\n')
            {
                fputc('\n', pfwrite);
            }
            fputc(third, pfwrite);
            break;
        case '*':    //注释中有“*”,如/***/
            third = fgetc(pfread);
            fputc(first, pfwrite);//把“*”输入到转换后的文件流中
            if (third == '/')  //C注释后面紧跟非注释内容,如/***/ int=a;
                fputc('\n', pfwrite);
                state = NUL_State;
            break;
        default:     //不是注释的字符  
            fputc(first, pfwrite);
            fputc(second, pfwrite);
            break;
        }
        break;

    case '\n':   //C注释中的多行注释  
        fputc('\n', pfwrite);
        fputc('/', pfwrite);
        fputc('/', pfwrite);
        break;
    case EOF:   //文件结束标志  
        state = END_State;
        break;
    default:   //不是注释的字符
        fputc(first, pfwrite);
        break;
    }
}
void DoCPP_State(FILE *pfread, FILE *pfwrite)
{
    first = fgetc(pfread);
    switch (first)
    {
    case '\n':
        fputc('\n', pfwrite);
        state = NUL_State;
        break;
    case EOF:
        state = END_State;
        break;
    default:
        fputc(first, pfwrite);
        break;
    }
}

猜你喜欢

转载自blog.csdn.net/it_10/article/details/54098526
今日推荐