(一)项目背景
有些平台不能识别C++的注释,而有些程序员又钟情于C++注释,为此我们需要写程序达到自动化的转换。
(二)整体思路。
核心思想其实就是状态机。而这个状态机实际上就是一个含有枚举类型的结构体。
(三)代码实现。
1.设置状态机
typedef enum
{
nostate,
cstate, //定义一个枚举类型,列举所用到的所有的状态类型
cppstate,
endstate
}STATEENUM;
typedef struct state_machine//定义状态机变量
{
FILE *inputfile;
FILE *outputfile;
STATEENUM state;
}STATE_MACHINE;
定义了一个枚举类型,列举无状态类型,C语言注释状态,C++注释状态,结束状态。状态机包含这个枚举类型,和文件输入输出指针。
2.定义几个状态处理函数。
void eventpro(char ch);//状态分配函数。
void eventproatno(char ch);//即非以下两种状态。
void eventproatc(char ch);//处理C状态的函数。
void eventproatcpp(char ch);//处理C++状态的函数。
int covert(FILE *fin, FILE *fout);//主函数中的入口函数,初始化作用。
3.这样整体结构和思路就有了,具体每个函数的功能在代码注释中说明。
(四)代码实现
注意:这里将注释中出现的*或/用空格代替。
# include <stdio.h>
# include<stdlib.h>
# include<string.h>
typedef enum
{
nostate,
cstate, //定义一个枚举类型,列举所用到的所有类型
cppstate,
endstate
}STATEENUM;
typedef struct state_machine//定义状态机变量
{
FILE *inputfile;
FILE *outputfile;
STATEENUM state;
}STATE_MACHINE;
STATE_MACHINE go_state = { 0 };
void eventpro(char ch);//状态处理函数
void eventproatno(char ch);//全局函数申明
void eventproatc(char ch);
void eventproatcpp(char ch);
int covert(FILE *fin, FILE *fout);
int main()
{
FILE *fin, *fout;
char p[50];
printf("请输入要转换的文件:\n");
scanf("%s", &p);
if ((fin = fopen(p, "r")) == NULL)
{
printf("无法打开此文件:\n");
exit(0);
}
if ((fout = fopen("output.txt", "w")) == NULL)
{
printf("无法打开此文件:\n");
exit(0);
}
covert(fin, fout); //在主函数中调用状态转换函数
fclose(fin);
fclose(fout);
return(0);
}
int covert(FILE *fin, FILE *fout)
{
if (fin == NULL || fout == NULL)
{
printf("Error: Argument Invalid!\n");//状态转换函数
return -1;
}
char ch;
go_state.inputfile = fin;
go_state.outputfile = fout;
go_state.state = nostate;
while (go_state.state != endstate)//判断状态机是否暂停的关键是在这里
{
ch = fgetc(go_state.inputfile);
eventpro(ch);
}
}
void eventpro(char ch)//状态处理函数
{
switch (go_state.state)
{
case nostate:
eventproatno(ch);
break;
case cstate:
eventproatc(ch);
break;
case cppstate:
eventproatcpp(ch);
break;
case endstate:
printf("运行结束");
break;
default:
break;
}
}
void eventproatno(char ch)//无状态函数
{
char nextch;
switch (ch)
{
case '/':
nextch = fgetc(go_state.inputfile);
if (nextch == '/')
{
fputc(ch, go_state.outputfile);
fputc('*', go_state.outputfile);
go_state.state = cppstate;
break;
}
else if (nextch == '*')
{
fputc(ch, go_state.outputfile);
fputc(nextch, go_state.outputfile);
go_state.state = cstate;
}
else
{
fputc(ch, go_state.outputfile);
fputc(nextch, go_state.outputfile);
}
break;
case EOF:
go_state.state = endstate;
break;
default:
fputc(ch, go_state.outputfile);
break;
}
}
void eventproatcpp(char ch)//Cpp状态函数
{
char nextch;
switch (ch)
{
case'*':
nextch = fgetc(go_state.inputfile);
if (nextch == '/')
{
fputc(' ', go_state.outputfile);
fputc(' ', go_state.outputfile);
}
else
{
fputc(ch, go_state.outputfile);
fputc(nextch, go_state.outputfile);
}
break;
case'/':
nextch = fgetc(go_state.inputfile);
if (nextch == '/' || nextch == '*')
{
fputc(' ', go_state.outputfile);
fputc(' ', go_state.outputfile);
}
else
{
fputc(ch, go_state.outputfile);
fputc(nextch, go_state.outputfile);
}
break;
case'\n':
{
fputc('*', go_state.outputfile);
fputc('/', go_state.outputfile);
fputc('\n', go_state.outputfile);
go_state.state = nostate;
}
break;
case EOF:
{
fputc('*', go_state.outputfile);
fputc('/', go_state.outputfile);
go_state.state = endstate;
}
break;
default:
fputc(ch, go_state.outputfile);
break;
}
}
void eventproatc(char ch)//C状态函数
{
char nextch;
switch (ch)
{
case '*':
nextch = fgetc(go_state.inputfile);
if (nextch == '/')
{
fputc('*', go_state.outputfile);
fputc('/', go_state.outputfile);
go_state.state = nostate;
}
else
{
fputc(ch, go_state.outputfile);
fputc(nextch, go_state.outputfile);
}
break;
case EOF:
go_state.state = endstate;
break;
case'/':
nextch = fgetc(go_state.inputfile);
if (nextch == '/')
{
fputc(' ', go_state.outputfile);
fputc(' ', go_state.outputfile);
}
else if (nextch == '*')
{
fputc(' ', go_state.outputfile);
fputc(' ', go_state.outputfile);
}
else
{
fputc(ch, go_state.outputfile);
fputc(nextch, go_state.outputfile);
}
break;
default:
fputc(ch, go_state.outputfile);
break;
}
}