注释转换
即将代码中的注释转换为同一类型
C语言中,编译器默认的注释风格是:
/*
要注释的内容*/
C++中,编译器默认的注释风格是://
要注释的内容
注意:
- C注释可以注释多行,但不能嵌套使用
- C++注释是单行注释,但可以嵌套使用
这次要写的代码就是用来将C注释转换为C++注释的,来理一下思路,如下图
首先创建一个input.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*/
根据这几种情况可以分析出不同注释间的转换关系,如下图所示
1、放声明的头文件
CommentConvert.h
#ifndef __COMMENT_CONVERT_H__
#define __COMMENT_CONVERT_H__
#include <stdio.h>
#include <stdlib.h>
typedef enum State
{
NUL_STATE,
C_STATE,
CPP_STATE,
END_STATE
}State;
void CommentConvert(FILE* pfRead, FILE* pfWrite);
void DoNulState(FILE* pfRead, FILE* pfWrite, State* ps);
void DoCState(FILE* pfRead, FILE* pfWrite, State* ps);
void DoCppState(FILE* pfRead, FILE* pfWrite, State* ps);
#endif //__COMMENT_CONVERT_H__
2、实现声明的.c文件
CommentConvert.c
#define _CRT_SECURE_NO_WARNINGS 0
#include "CommentConvert.h"
//无状态转换
void DoNulState(FILE* pfRead, FILE* pfWrite, State* ps)
{
int first = fgetc(pfRead);//从文件中读取一个字符来判断
switch (first)
{
case '/'://表示进入注释状态
{
int second = fgetc(pfRead);//再从文件中读取一个字符来判断
switch (second)
{
case '/'://表示代码为//,进入C++注释状态
{
//将注释输出到文件
fputc(first, pfWrite);
fputc(second, pfWrite);
*ps = CPP_STATE;//状态转换为C++注释状态
}
break;
case '*'://表示代码是/*,进入C注释状态
{
//将它变为C++注释,输出到文件
fputc('/', pfWrite);
fputc('/', pfWrite);
*ps = C_STATE;//状态转换为C注释状态
}
break;
default://表示读取的/是一个字符
{
//将读取的字符输出到文件
fputc(first, pfWrite);
fputc(second, pfWrite);
}
break;
}
}
break;
case EOF://表示代码结束
{
fputc(first, pfWrite);
*ps = END_STATE;
}
break;
default://表示遇到的不是注释,状态不变
fputc(first, pfWrite);
break;
}
}
//C注释转换
void DoCState(FILE* pfRead, FILE* pfWrite, State* ps)
{
int first = fgetc(pfRead);
switch(first)
{
case '*'://表示C注释状态有可能结束
{
int second = fgetc(pfRead);
switch (second)
{
case '/'://C注释状态结束,但还要判断后一位字符是否为'\n',因为C注释以'\n'结束
{
int third = 0;
*ps = NUL_STATE;//状态转换为无注释状态
third = fgetc(pfRead);
if(third != '\n')
{
fputc('\n', pfWrite);//如果不是,帮助换行
ungetc(third, pfRead);//将用来判断的字符从读取流中撤销,防止下次判断时少判断一个字符
}
else
{
fputc(third, pfWrite);
}
}
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;
}
}
//C++状态转换
void DoCppState(FILE* pfRead, FILE* pfWrite, State* ps)
{
int first = fgetc(pfRead);
switch (first)
{
case '\n'://表示C++一行注释结束
{
fputc(first, pfWrite);
*ps = NUL_STATE;//状态转换为无状态
}
break;
case EOF:
*ps = END_STATE;
break;
default:
fputc(first, pfWrite);
break;
}
}
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:
DoCState(pfRead, pfWrite, &state);
break;
case CPP_STATE:
DoCppState(pfRead, pfWrite, &state);
break;
}
}
}
3、主函数合理调用,测试函数功能
test.c
#define _CRT_SECURE_NO_WARNINGS 0
#include "CommentConvert.h"
void test()
{
FILE* pfRead = NULL;
FILE* pfWrite = NULL;
//读文件
pfRead = fopen("input.c", "r");
if (pfRead == NULL)
{
perror("open file for read");
exit(EXIT_FAILURE);
}
//写文件
pfWrite = fopen("output.c", "w");
if (pfWrite == NULL)
{
perror("open file for write");
exit(EXIT_FAILURE);
}
//注释转换
CommentConvert(pfRead, pfWrite);
fclose(pfRead);
pfRead = NULL;
fclose(pfWrite);
pfWrite = NULL;
}
int main()
{
test();
return 0;
}
4、执行函数得到的output.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*/