在编写代码中,经常会注释掉某段代码,C语言一般有两种方式:一种是/*xxxxxx*/,另一种是://xxxxx.第一种注释方式不能嵌套使用,在/与*的匹配上可能会造成理解错误,第二种注释可以注释掉一行,两种风格各有优缺点,今天讲一下怎样将第一种风格转换成第二种风格。
虽然转换本身不难,但要考虑到匹配时会出现多种情况,在这里,我们用到了状态机编程的思想。
定义四种状态:NUL_STATE(无状态),C_STATE(C状态),CPP_STATE(C++状态),END_STATE(结束状态);四种状态转化如下图所示:
在input.c文件里输入需要转换的代码:
// 1.一般情况
int i = 0;
/* int j = 0; */
// 2.换行问题
/* int k = 0; */int m = 0;
/* int tmp = 0; */
int n = 0;
// 3.匹配问题
/*int k = 0;/*hehehe*/
// 4.多行注释问题
/*
int i=0;
int j = 0;
int k = 0;
*/int m = 0;
// 5.连续注释问题
/*abc*//*def*/
// 6.连续的**/问题
/****/
// 7.C++注释问题
// /*abcdef*/
转换后的结果在output文件中
CommentConvert.h
#ifndef __COMMEENT_CONVERT_H__
#define __COMMEENT_CONVERT_H__
#include <stdio.h>
#include <stdlib.h>
enum STATE
{
NUL_STATE,
C_STATE,
CPP_STATE,
END_STATE
};
void DoNulState(FILE* pfIn, FILE* pfOut, enum STATE* state);
void DoCState(FILE* pfIn, FILE* pfOut, enum STATE* state);
void DoCppState(FILE* pfIn, FILE* pfOut, enum STATE* state);
#endif//__COMMEENT_CONVERT_H__
CommentConvert.c
#define _CRT_SECURE_NO_WARNINGS
#include "CommentConvert.h"
void DoNulState(FILE* pfIn, FILE* pfOut, enum STATE* s)
{
int first = fgetc(pfIn);
switch (first)
{
case '/':
{
int second = fgetc(pfIn);
switch (second)
{
case '/':
*s = CPP_STATE;//遇到//转换至C++状态
fputc(first, pfOut);
fputc(second, pfOut);
break;
case '*'://将/*转换成//,转换至C状态
*s = C_STATE;
fputc('/', pfOut);
fputc('/', pfOut);
break;
default:
fputc(second, pfOut);
}
}
break;
case EOF:
*s = END_STATE;//文件结束,转换至结束状态
break;
default:
fputc(first, pfOut);
break;
}
}
void DoCState(FILE* pfIn, FILE* pfOut, enum STATE* s)
{
int first = fgetc(pfIn);
switch (first)
{
case '*':
{
int second = fgetc(pfIn);
switch (second)
{
case '/'://遇到*/转换至无状态,将*/去除或换行
{
*s = NUL_STATE;
int third = fgetc(pfIn);
if (third != '\n')
{
fputc('\n', pfOut);
ungetc(third, pfIn);
}
else
{
fputc(third, pfOut);
}
}
break;
case '*':
fputc(first, pfOut);
ungetc(second, pfIn);
break;
default:
fputc(first, pfOut);
fputc(second, pfOut);
break;
}
}
break;
case '\n'://多行注释的处理
fputc(first, pfOut);
fputc('/', pfOut);
fputc('/', pfOut);
break;
case EOF://文件结束,转换至无状态
*s = END_STATE;
break;
default:
fputc(first, pfOut);
break;
}
}
void DoCppState(FILE* pfIn, FILE* pfOut, enum STATE* s)
{
int first = fgetc(pfIn);
switch (first)
{
case '\n':
*s = NUL_STATE;//C++状态注释一行结束,转换至无状态
fputc(first, pfOut);
break;
case EOF:
*s = END_STATE;
break;
default:
fputc(first, pfOut);
break;
}
}
test.c
#define _CRT_SECURE_NO_WARNINGS
#include "CommentConvert.h"
void CommentConvert(FILE* pfIn, FILE* pfOut)
{
enum STATE state = NUL_STATE;
while (state != END_STATE)
{
switch (state)
{
case NUL_STATE:
DoNulState(pfIn, pfOut, &state);
break;
case C_STATE:
DoCState(pfIn, pfOut, &state);
break;
case CPP_STATE:
DoCppState(pfIn, pfOut, &state);
break;
}
}
}
void test()
{
FILE* pfIn = 0;
FILE* pfOut = 0;
pfIn = fopen("input.c", "r");
if (pfIn == NULL)
{
perror("open for read");
exit(EXIT_FAILURE);
}
pfOut = fopen("output.c", "w");
if (pfOut == NULL)
{
perror("open for write");
fclose(pfIn);
exit(EXIT_FAILURE);
}
CommentConvert(pfIn, pfOut);
fclose(pfIn);
fclose(pfOut);
}
int main()
{
test();
return 0;
}
运行结果如下图: