程序新思路:
注释转换一开始去想的时候,会觉得很复杂。因为在一个源文件里出现注释的情况虽然不会太多,但是可能会出现各种各样,形形色色的注释,在转换程度上去想的时候会觉得很复杂,不同的问题都要有不同的解决方法的。
在这里简单的罗列注释转换可能出现的几种情况:
// 1.一般情况
int num = 0;
/* 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*/
在注释转换的时候肯定不仅仅只有这些问题,可能有些也没有想到位。所以我们会发现要处理的情况会很多,如果一个一个问题挨个解决的话,代码就会有复杂性。我们可以这样去给一个思路:
图中:注释转换过程使用了有限状态机,可以给我们提供一个新的思路。把注释转换切换到4中状态中,根据有限的条件进入相应的状态下去处理,并在根据条件进入下一个状态,依次循环,直到遇到eof结束。
有限状态机(finite state machine)是一个数学概念,如果把它运用于程序中,可以发挥很大的作用。它是一种协议,用于有限数量的子程序(“状态”)的发展变化。每个子程序进行一些处理并选择下一种状态(通常取决于下一段输入)。有限状态机(FSM)可以用作程序的控制结构。
程序代码:
头文件AnnotationConversion.h
#ifndef __ANNOTATIONCONVERSION_H__
#include<stdio.h>
#include<windows.h>
#define CHMOD "input.c"
#define FINAL "output.c"
typedef enum STATE //枚举定义四种状态
{
NULL_STATE,
C_STATE,
CPP_STATE,
EOF_STATE,
}STATE;
void Execute(FILE* pfin, FILE* pfout);//转换函数
void DoNULLConvert(FILE* pfin, FILE* pfout,STATE *state);//普通状态
void DoCConvert(FILE* pfin, FILE* pfout, STATE *state);//C状态函数
void DoCPPConvert(FILE* pfin, FILE* pfout, STATE *state);//C++状态函数
#endif//__ANNOTATIONCONVERSION_H__
实现部分AnnotationConversion.c
#include "AnnotationConversion.h"
void Execute(FILE* pfin, FILE* pfout)//转换函数
{
STATE state = NULL_STATE; //定义初始状态为普通状态
while (state != EOF_STATE)
{
switch (state)
{
case NULL_STATE:
DoNULLConvert(pfin, pfout, &state);
break;
case C_STATE:
DoCConvert(pfin, pfout, &state);
break;
case CPP_STATE:
DoCPPConvert(pfin, pfout, &state);
break;
default:
break;
}
}
}
void DoNULLConvert(FILE* pfin, FILE* pfout, STATE *state)//普通状态操作函数
{
int first = fgetc(pfin);
switch (first)
{
case '/':
//普通状态遇到/后,紧接着判断下一个字符。
{
int second = fgetc(pfin);
switch (second)
{
case '/':
//遇到//依然输出//并进入c++注释状态
{
fputc(first, pfout);
fputc(second, pfout);
*state = CPP_STATE;
}
break;
case '*':
//遇到/*依然输出//并进入c注释状态
{
fputc(first, pfout);
fputc('/', pfout);
*state = C_STATE;
}
break;
default://正常语句:(例如/hehe/),直接写进文件。
{
fputc(first, pfout);
fputc(second, pfout);
}
break;
}
}
break;
case EOF:
//结束标志
{
*state = EOF_STATE;
}
break;
default:
//正常语句
{
fputc(first, pfout);
}
break;
}
}
void DoCConvert(FILE* pfin, FILE* pfout, STATE *state)//c注释状态操作函数
{
int first = fgetc(pfin);
switch (first)
{
case '*':
//遇到*,同样紧接着判断下一下个字符
{
int second = fgetc(pfin);
switch (second)
{
case '/':
//如果是/,表示注释结束,直接回到空状态
{
*state = NULL_STATE;
int third = fgetc(pfin);
//获取第三个字符是因为可能出现(/*hehe*/int i = 0;)这种情况
if ('\n' == third)
{
fputc(third, pfout);
}
else
{
fputc('\n', pfout);
ungetc(third, pfin);
}
}
break;
default:
//针对/***/情况
fputc(first, pfout);
ungetc(second, pfin);
break;
}
}
break;
case '\n':
//针对多行C语言注释问题
{
fputc(first, pfout);
fputc('/', pfout);
fputc('/', pfout);
}
break;
default:
fputc(first, pfout);
break;
}
}
void DoCPPConvert(FILE* pfin, FILE* pfout, STATE *state)//C++注释转换操作函数
{
int first = fgetc(pfin);
switch (first)
{
case '\n':
{
fputc(first,pfout);
*state = NULL_STATE;
}
break;
case EOF:
*state = EOF_STATE;
break;
default:
fputc(first, pfout);
break;
}
}
测试部分test.c
针对fopen、fread、fwrite三个函数在我之前写的文件流通讯录中有详细解释http://blog.csdn.net/quinn0918/article/details/72526886
#include "AnnotationConversion.h"
#pragma warning (disable:4996)
int main()
{
FILE* pfread = fopen(CHMOD, "r");
if (pfread == NULL)
{
perror("out of for read");
exit(1);
}
FILE* pfwrite = fopen(FINAL, "w");
if (pfwrite == NULL)
{
fclose(pfread);
perror("out of for write");
exit(1);
}
Execute(pfread, pfwrite);
printf("转换成功\n");
fclose(pfread);
fclose(pfwrite);
system("pause");
return 0;
}
针对前面一开始提出的问题,程序运行注释转换后结果为: