- c注释-->c++注释,将.c风格的注释转换成.cpp风格
- 采用有限状态机的方式实现
- 设置四种状态,c状态,c++状态,空状态,结束状态,主要关注四种状态转换的条件,状态转换如下:
//test.cpp
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<assert.h>
#include"CommentConvert.h"
using namespace std;
int main()
{
FILE *pRead=fopen("input.cpp","r");
if (pRead == NULL)
{
perror("open file for read");//将上一个函数发生错误的原因输出到标准设备(stderr)。参数 s 所指的字符串会先打印出,后面再加上错误原因字符串
exit(EXIT_FAILURE);//exit()函数先处理完上面你列出的许多后事,最后将它的参数返回给操作系统作为exit status。所以从exit函数本身执行来说并没有什么不同。不同的是操作系统对这个exit status的解释。一般0表示程序寿终正寝,1表示死于非命。
}
FILE *pWrite = fopen("output.cpp", "w");
if (pWrite == NULL)
{
fclose(pRead);//写的不存在,需要把读的关掉。那不相当于关了两次?,应该出现异常执行不到后面的fclose
perror("open file for write");
exit(EXIT_FAILURE);
}
_StartConvert(pRead, pWrite);
fclose(pRead);
fclose(pWrite);
system("pause");
return 0;
}
//CommentConvert.h
# pragma once
#include<iostream>
using namespace std;
void _StartConvert(FILE* fin, FILE* fout);
void OnNullState(FILE* fin, FILE* fout);
void OnCState(FILE* fin, FILE* fout);
void OnCppState(FILE* fin, FILE* fout);
//CommentConvert.cpp
#include<iostream>
#include<assert.h>
#include"CommentConvert.h"
using namespace std;
enum State
{
NULL_STATE,//空状态
C_STATE,//C状态
CPP_STATE,//C++状态
END_STATE,//结束
};
enum State state = NULL_STATE;
void OnNullState(FILE* fin, FILE* fout)
{
char first = fgetc(fin);
if (first == '/')
{
char second = fgetc(fin);
if (second == '/')
{
//fputs("//", fout);
state = CPP_STATE;
}
else if (second == '*')
{
//fputs("//", fout);
state = C_STATE;
}
fputs("//", fout);
}
//else if (state == '\n')
//{
// fputc(first, fout);
// state = NULL_STATE;
//}
else if (state == EOF)
{
fputc(first, fout);
state = END_STATE;
}
else
{
fputc(first, fout);
}
}
void OnCState(FILE* fin, FILE* fout)
{
char first = fgetc(fin);
if (first == '*')
{
char second = fgetc(fin);
if (second == '/')
{
state = NULL_STATE;
char third = fgetc(fin);
if (third != '\n')
{
fputs("\n", fout);//如果/后边的字符不是回车,需要写进去回车,然后再把独到的字符放回。//考虑到连续两个c注释的问题 比如 /* int a = 1; */ /* int b = 1;*/ 将它们放在两行
ungetc(third, fin);
}
else
{
fputc(third, fout);
}
}
else
{
fputc(first, fout);
//如果遇到*,但是后边不是/,把*放进去,*后边的字符放回,比如,/***/,进入c状态以后,
//遇到*,后边的字符也是*,如果把两个*都写进去,后边就只剩下/,就不能找到c状态结束的标志,
//所以,需要把第二个字符原样写回。//接下来执行哪儿,跳不到51呀
ungetc(second, fin);
}
}
else if (state == '\n')//多行注释
{
fputc(first, fout);
//state = NULL_STATE;
fputs("//", fout);//?????????????????
}
/*else if (state == EOF)
{
fputc(first, fout);
state = END_STATE;
}*/
else
{
fputc(first, fout);
}
}
void OnCppState(FILE* fin, FILE* fout)
{
char first = fgetc(fin);
if (state == '\n')
{
fputc(first, fout);
state = NULL_STATE;
}
else if (state == EOF)
{
fputc(first, fout);
state = END_STATE;
}
else
{
fputc(first, fout); //别忘了这个else,不然CPP_STATE中的正常字符都不会输出。考虑特殊情况,也别忘了正常情况。
}
}
void _StartConvert(FILE *fin, FILE *fout)
{
while (1)
{
switch (state)
{
case NULL_STATE:OnNullState(fin, fout); break;
case C_STATE: OnCState(fin, fout); break;
case CPP_STATE: OnCppState(fin, fout); break;
case END_STATE: break;
default:assert(false); break;
}
}
}