c语言中的注释方法为 /* ………*/
c++中的注释方法为 //
要将 input.txt里面的c语言注释全部转化为c++的注释,要考虑到各个不同的坑。例如:
// 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*/
要将上述所有的c语言注释全部转化为c++注释,上述中,每一种都是一个不同的情况,要是全部都用判断一下,没有总结是很难的。这时,我们就可以运用一种思想:状态机。就是将问题分成几种不同的状态,然后再几个状态之间来回转换。
例如上题中:一共可以分为四种状态:开始状态(无注释状态)、c语言注释状态、c++注释状态、结束状态。
这时候我们就要分析这几种状态之间对应的关系:如下图:
代码:
头文件
#ifndef __COMMENT_CONVERT_H__
#define __COMMENT_CONVERT_H__
#include <stdio.h>
#include <stdlib.h>
typedef enum State //定义一个枚举,里面是四种状态
{
NUL_STATE, //无注释状态
C_STATE, //C语言注释状态
CPP_STATE, //C++注释状态
END_STATE //结束状态
}State;
void DoNulState(FILE *pfRead, FILE *pfWrite, State *ps); //无注释状态操作
void DoCState(FILE *pfRead, FILE *pfWrite, State *ps); //C语言注释状态操作
void DoCppState(FILE *pfRead, FILE *pfWrite, State *ps); //C++注释状态操作
void CommentConvert(FILE *pfRead, FILE *pfWrite); //状态转换
#endif
源文件
#include "CommentConvert.h"
void CommentConvert(FILE *pfRead, FILE *pfWrite)
{
enum State state = NUL_STATE; //开始为无注释状态
while (state != END_STATE) //如果不是结束状态,持续循环
{
switch (state)
{
case NUL_STATE: //无注释状态
DoNulState(pfRead, pfWrite, &state);
break;
case C_STATE: //C语言注释状态
DoCState(pfRead, pfWrite, &state);
break;
case CPP_STATE: //C++注释状态
DoCppState(pfRead, pfWrite, &state);
break;
default:
break;
}
}
}
void DoNulState(FILE *pfRead, FILE *pfWrite, State *ps)
{
int first = fgetc(pfRead); //记录第一个字符
switch(first)
{
case '/': //表示进入注释状态
{
int second = fgetc(pfRead); //记录第二个字符
switch (second)
{
case '*': //代码为/* 即将进入C语言代码注释
{
fputc('/', pfWrite);
fputc('/', pfWrite); //将其转换为C++注释,并打印到output.txt中
*ps = C_STATE; //进入C语言代码注释状态
}
break;
case '/': //代码为// 即将进入C++代码注释状态
{
fputc('/', pfWrite);
fputc('/', pfWrite); // 将C++注释打印到output.txt中
*ps = CPP_STATE; //进入C++注释状态
}
break;
default: //不是C语言的注释,第一个字符只是一个字符'/'
{
fputc('/', pfWrite); //先将'/'打印
fputc(second, pfWrite); //再将第二个字符打印
}
break;
}
}
break;
case EOF: //表示已经结束
{
fputc(first, pfWrite);
*ps = END_STATE; //进入结束状态
}
break;
default:
{
fputc(first, pfWrite); //表示第一个就是字符,将其打印
}
break;
}
}
void DoCState(FILE *pfRead, FILE *pfWrite, State *ps)
{
int first = fgetc(pfRead); //读取字符进行判断
switch (first)
{
case '*': //表示C语言注释可能会结束
{
int second = fgetc(pfRead); //读取第二个字符
switch (second)
{
case '/': //遇见*/ 表示C语言注释结束
{
int third = fgetc(pfRead); // 读取第三个字符,判断是否换行(上述中的第二种情况)
if (third != '\n') //不是换行符
{
fputc('\n', pfWrite); //要将其换行
ungetc(third, pfRead); //因为我们已经把该字符取出来了,接下来就不容易判断,所以还要讲该字符退回流中
}
else
{
fputc(third, pfWrite); //如果是换行符,直接但因就可以
}
*ps = NUL_STATE; //状态转换为无注释状态
}
break;
default:
{
fputc(first, pfWrite); //第二个字符不是'/',表示第一个 * 只是一个字符'*'
ungetc(second, pfRead); //同上面一样,为了不影响下面的判断,要将该字符退回流中
}
break;
}
}
break;
case '\n': //如果是换行符,就将其打印,但要加上两个/,因为C语言的注释是在每一行的开始
{
fputc(first, pfWrite);
fputc('/', pfWrite);
fputc('/', pfWrite);
}
break;
default :
{
fputc(first, pfWrite); //不是*,表示只是一个字符,将其打印
}
break;
}
}
void DoCppState(FILE *pfRead, FILE *pfWrite, State *ps)
{
int first = fgetc(pfRead); //读取第一个字符
switch (first)
{
case '\n': //如果是'\n',将其打印即可,并回到无注释状态
{
fputc(first, pfWrite);
*ps = NUL_STATE;
}
break;
case EOF: // 表示结束,直接到结束状态
{
fputc(first, pfWrite);
*ps = END_STATE;
}
break;
default:
{
fputc(first, pfWrite); //表示只是一个字符,将其打印
}
break;
}
}
注:ungetc()表示把一个(或多个)字符退回到steam代表的文件流中
主函数(测试代码)
#define _CRT_SECURE_NO_WARNINGS 1
#include "CommentConvert.h"
void test()
{
FILE *pfRead = NULL;
FILE *pfWrite = NULL;
pfRead = fopen("input.txt", "r");
if (pfRead == NULL)
{
perror("open file for read");
system("pause");
exit(EXIT_FAILURE);
}
pfWrite = fopen("output.txt", "w");
if (pfWrite == NULL)
{
perror("open file for write");
system("pause");
exit(EXIT_FAILURE);
}
CommentConvert(pfRead, pfWrite);
fclose(pfRead);
pfRead = NULL;
fclose(pfWrite);
pfWrite = NULL;
}
int main()
{
test();
system("pause");
return 0;
}