分析:
在进行从C注释向C++注释转换的过程中,我们应进行一下的分析:
首先,一个C源文件的内容应该包括四个部分:正常代码、C注释状态、C++注释状态、文件结束。其次,我们就可以对这四种状态下的遇到的情况进行进一步分析:
- 正常代码:在程序执行起来时,我们会在文件中遇到正常代码,这些代码不需要做处理,直接写进输出文件中。但在这个过程中,如果遇到 “ / * ” 说明接下来的这部分内容是C注释,状态要切换到C注释状态下,遇到 “ * /” 则说明C注释完毕,应回到正常代码状态下;如果遇到 “ / / ” 则说明接下来的内容是C++注释,状态应切换到C++注释下,在遇到 “ \ n ” 时C++注释结束,切回到正常代码状态下;如果遇到EOF文件结束标志,则文件中的内容结束,状态应为文件结束状态,随后结束程序。
- C注释状态:如果遇到 “ * / ” 时结束C注释状态回到正常代码状态下;如果遇到 “ \ n ” 时,说明一行C注释结束,进行下一行的C注释时要加 “ // ” C++注释符;但在C注释状态下,是不会遇到转到C++注释状态和文件结束状态的情况的。
- C++注释状态:如果遇到 “ // ” 说明符号之后的这行内容为C++注释;遇到 “ \ n ” 时此行的C++注释结束,进入正常代码状态;如果遇到EOF文件结束标志,则文件中的内容结束,状态切换到文件结束状态。同样,C++注释状态也不会切换到C注释状态下的。
- 文件结束状态:当在文件执行过程中遇到EOF文件结束标志时,说明文件中的内容已经执行完毕,结束程序。
过程如下图所示:
在进行代码编写时应考虑到以下几种情况:
整体代码
头文件
CommentConvert.h
#ifndef __COMMENT_CONVERT_H__
#define __COMMENT_CONVERT_H__
#include <stdio.h>
#include <stdlib.h>
typedef enum State //创建一个枚举类型用来存放四种状态
{
NUL_STATE,
C_STATE,
CPP_STATE,
END_STATE
}State;
void CommentCovert(FILE *pfRead,FILE *pfWrite); //注释转换函数
void DoNulState(FILE *pfRead,FILE *pfWrite,State *ps); //正常代码状态下的函数
void DoCState(FILE *pfRead,FILE *pfWrite,State *ps); //C注释状态下的函数
void DoCppState(FILE *pfRead,FILE *pfWrite,State *ps); //C++注释状态下的函数
#endif //__COMMENT_CONVERT_H__
测试代码
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include "CommentConvert.h"
void test()
{
FILE *pfRead = NULL; //创建一个变量用于对input.c文件进行操作
FILE *pfWrite = NULL; //创建一个变量用于对output.c文件进行操作
pfRead = fopen("input.c","r");
if(pfRead == NULL)
{
perror("open file for read");
}
pfWrite = fopen("output.c","w");
if(pfWrite == NULL)
{
perror("open file for write");
}
//注释转换
CommentCovert(pfRead,pfWrite);
fclose(pfRead);
pfRead = NULL;
fclose(pfWrite);
pfWrite = NULL;
return;
}
int main()
{
test();
return 0;
}
注释转换部分
CommentConvert.c
#include <stdio.h>
#include "CommentConvert.h"
void CommentCovert(FILE *pfRead,FILE *pfWrite)
{
State state = NUL_STATE;
while(state != END_STATE) //在有效状态下执行下面程序
{
switch(state)
{
case NUL_STATE:
DoNulState(pfRead,pfWrite,&state);
break;
case C_STATE:
DoCState(pfRead,pfWrite,&state);
break;
case CPP_STATE:
DoCppState(pfRead,pfWrite,&state);
break;
}
}
}
//正常代码状态函数
void DoNulState(FILE *pfRead,FILE *pfWrite,State *ps)
{
int first = fgetc(pfRead);
switch(first)
{
case '/': //第一个字符为'/',判断之后的第二位,看其是否是C注释部分或者C++注释部分
{
int second = fgetc(pfRead);
switch(second)
{
case '*':
{
fputc('/',pfWrite);
fputc('/',pfWrite);
*ps = C_STATE;
}
break;
case '/':
{
fputc(first,pfWrite);
fputc(second,pfWrite);
*ps = CPP_STATE;
}
break;
default:
{
fputc(first,pfWrite);
fputc(second,pfWrite);
}
break;
}
}
break;
case EOF://判断字符是否是文件结束标志
*ps = END_STATE;
break;
default:
fputc(first,pfWrite);
break;
}
}
//C注释状态函数
void DoCState(FILE *pfRead,FILE *pfWrite,State *ps)
{
int first = fgetc(pfRead);
switch(first)
{
case '*':
{
int second = fgetc(pfRead);
switch(second)
{
case '/'://判断是否遇到C注释结束标志
{
int third = fgetc(pfRead);
if((third != '\n'))//判断C注释结束后是否有正常代码
{
if(third == '/')//解决C注释是否为连续注释问题
{
int forth = fgetc(pfRead);
if(forth == '*')
{
ungetc(forth,pfRead);
ungetc(third,pfRead);
}
else
{
fputc('\n',pfWrite);
ungetc(forth,pfRead);
ungetc(third,pfRead);
}
}
else
{
fputc('\n',pfWrite);
ungetc(third,pfRead);
}
}
else
{
fputc(third,pfWrite);
}
*ps = NUL_STATE;
}
break;
case '*'://解决连续的**/问题
{
fputc(first,pfWrite);
ungetc(second,pfRead);
}
//
break;
default:
{
fputc(first,pfWrite);
fputc(second,pfWrite);
}
break;
}
}
break;
case '\n'://解决多行注释问题
{
int second = fgetc(pfRead);
fputc(first,pfWrite);
switch(second)
{
case '/':
{
int third = fgetc(pfRead);
if(third == '/')
{
fputc(second,pfWrite);
fputc(third,pfWrite);
}
else
{
fputc('/',pfWrite);
fputc('/',pfWrite);
fputc(second,pfWrite);
fputc(third,pfWrite);
}
}
break;
case '*':
{
int third = fgetc(pfRead);
if(third == '/')
{
*ps = NUL_STATE;
}
else
{
fputc(second,pfWrite);
fputc(third,pfWrite);
}
}
break;
default:
{
fputc('/',pfWrite);
fputc('/',pfWrite);
fputc(second,pfWrite);
}
break;
}
}
break;
default:
fputc(first,pfWrite);
break;
}
}
//C++注释状态函数
void DoCppState(FILE *pfRead,FILE *pfWrite,State *ps)
{
int first = fgetc(pfRead);
switch(first)
{
case '\n'://判断C++注释是否结束
{
fputc(first,pfWrite);
*ps = NUL_STATE;
}
break;
case EOF:
*ps = END_STATE;
break;
default:
fputc(first,pfWrite);
break;
}
}