有穷状态机思想——注释转换
画状态转换图
所谓自动机思想就是假设有一台机器,上面有状态指示灯,作用是通过传送带前后改变通过的物体。
当状态灯保持时,货物按一定规则输出,当状态灯突变时,货物根据另一种规则输出。
利用这种思想,可以将所有有穷的状态列出来,大大清晰了思路,只需要往每一个状态里填对应的处理函数。
例如注释转换问题,把形如/**/的c风格注释转换为c++风格//注释。
如图,开始状态默认为不是注释,线上代表现状态进入下一状态需要读入的字符。
枚举状态
c语言通过enum列举所有的状态。
先写出状态转换框架
利用switch case语句和while循环配合,完成状态之间跳转。
添加动作函数
在每一个case里写函数需要做的任务
扫描二维码关注公众号,回复: 1434462 查看本文章
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
typedef enum State {
Normal, //普通
MayToAnn, //可能成为注释
CAnn, //c注释
CppAnn, //c++注释
MayToNor //可能回到普通
}State;
void StateMachine()
{
FILE *in = fopen("input.c", "r");
FILE *out = fopen("test.c", "w");
int ch;
State state = Normal;
while ((ch = fgetc(in)) != EOF)
{
switch (state)
{
case Normal:
if (ch == '/') {
state = MayToAnn;
}
else {
state = Normal;
}
fputc(ch, out);
printf("读入%c 状态变为:%d \n", ch, state);
break;
case MayToAnn:
if (ch == '/') {
state = CppAnn;
fputc(ch, out);
}
else if (ch == '*') {
state = CAnn;
fputc('/', out);
}
else {
state = Normal;
fputc(ch, out);
}
printf("读入%c 状态变为:%d \n", ch, state);
break;
case CAnn:
if (ch == '*') {
state = MayToNor;
//欠
int tmp;
tmp = fgetc(in);
if (tmp == '/') {
}
else {
fputc(ch, out);
}
ungetc(tmp, in);
}
else {
if (ch == '\n') {
fputc(ch, out);
fputc('/', out);
fputc('/', out);
}
else {
fputc(ch, out);
}
state = CAnn;
}
printf("读入%c 状态变为:%d \n", ch, state);
break;
case CppAnn:
if (ch == '\n') {
state = Normal;
}
else
state = CppAnn;
fputc(ch, out);
printf("读入%c 状态变为:%d \n", ch, state);
break;
case MayToNor:
if (ch == '*') {
state = MayToNor;
fputc(ch, out);
}
else if (ch == '/') {
state = Normal;
int tmp;
tmp = fgetc(in);
if (tmp == '\n') {
}
else {
fputc('\n', out);
}
ungetc(tmp, in);
}
else {
state = CAnn;
fputc(ch, out);
}
printf("读入%c 状态变为:%d \n", ch, state);
break;
default:
break;
}
}
fclose(in);
fclose(out);
}
测试样例:
// 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*/
输出:
// 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*/