我们想要将一个代码文件中的所有C风格注释全部转换成C++风格注释,那么就首先要了解C与C++注释的区别。
C++风格注释:
C语言风格的注释格式为://xxxxxxxxx 。它一次只能注释一行内容。
C风格注释:
C++风格的注释格式为:/*xxxxxxxxxx*/。从"/*"到"*/"都是它的注释范围。
C和C++两种风格注释的区别:
最大的区别为C++风格的注释一次只能注释一行内容,而C风格的注释则没有这个限制。然而就是这一个区别却会在注释转换时产生很多可能会被我们忽略的情况。
如:
1,换行问题
C风格:
/*int i = 3;*/int k = 4;
/*int i = 3;*/
int k = 4;
直接转换后结果:
C++风格:
//int i = 3;int k = 4;
//int i = 3;
int k = 4;
我们可以看到,这种情况下直接转换就会将本来没有注释的代码也注释掉了。所以对于这种情况我们需要特别处理。
2,匹配问题
C风格:
/*int i = 3;/*int j = 4;*/
直接转换后结果:
C++风格:
//int i = 3;//int j = 3;
这种情况下又会直接改变注释的内容,也需要特殊处理。
3,多行注释问题
//3,多行注释问题
C风格:
/*
int i = 3;
int j = 4;
*/
直接装换后结果:
C++风格:
//
int i = 3;
int j = 4;
这样会使的原本要注释的内容没有被注释,也需要特殊处理。
。。。
还有一些类似这样的情况就不一一介绍了。
有这么多种特殊的情况,那我们到底该怎样进行注释的转换呢?每种情况都进行一次特殊处理的话需要的代码将会是一个极其庞大数目,并且也会十分杂乱,不适于进行读取和调试。我们需要一种新的思考方式。
思考:
在这个代码文件中其实所有的内容可以分为4个部分:
1,普通的代码;
2,C风格注释以及被C风格注释的代码;
3,C++风格注释以及被C++风格注释的代码;
4,文件j结束。
我们把文件的内容分为这4个部分后,我们再来考虑我们的目的。我们要将C风格注释转换为C++风格注释其实就是把第二部分的内容进行转换,我们只要对第二部分的内容进行操作就可以了。
那么,我们就可以想一下如何区分出第二部分的内容对其进行操作,并且,不改变其他部分的内容。我们假设有一个文件指针。由这个文件指针来读取文件内容。我们来仔细看看这个文件指针和四部分内容的关系(接下来这几部分内容我们直接用数字进行代替):
- 首先我们来这个指针没有在C或C++注释中,我们就叫它1类型指针,简称1。1的后面加上“//”就变为了2类型指针,简称2;1的后面加上“/*”就变成了3类型指针,简称3;1走到了文件结束就是4类型指针简称4;
- 接着看2,2后面出现“*/”才能变成其它内容,而只要出现了“*/”它就没有在C或C++注释中,此时它就是1,也可能是1。
- 接着看3,3后面出现“\n”就会变成其它内容,而只要出了C++注释它就没在C或C++注释中,此时它就是1。也有可能它并没有出现“\n”,而是文件直接结束,此时它变为4;
- 最后是4类型指针,这个指针指向文件结束,文件直接结束,它不会再变化。
以上的思维解释可能有些抽象,那么让我们来用图表达一下上面的思想:
以这样的思路就可以轻松写出可读性与可调式性极高的代码,之后我们在对一些难以处理的情况进行转换时的讨论。
下面就是我的注释转换代码:
//头文件
#ifndef __ZHUSHI_H__
#define __ZHUSHI_H__
#include <stdio.h>
#include <stdlib.h>
typedef enum zhuangtai //表示在文件中会出现的所有状态
{
NUL_STATE, //无状态或正常文本
C_STATE, //C语言注释及文本
CPP_STATE, //C++语言注释及文本
END_STATE = EOF, //结束——EOF
}zhuangtai;
void test(FILE *fread,FILE *fwrite);
void NUL_STATE_CHULI(FILE *fread,FILE *fwrite,zhuangtai *pc);
void C_STATE_CHULI(FILE *fread,FILE *fwrite,zhuangtai *pc);
void CPP_STATE_CHULI(FILE *fread,FILE *fwrite,zhuangtai *pc);
#endif //__ZHUSHI_H__
//函数部分
#include "zhushi.h"
void NUL_STATE_CHULI(FILE *fread, FILE *fwrite,zhuangtai *pc) //文件指针为无状态时的函数
{
int first = fgetc(fread);
switch (first) //文件指针指向的可能情况 :'/','EOF',其它。
{
case '/':
{
int second = fgetc(fread);
switch (second) //文件指针首先指向为‘/’的下一次可能情况:'/','*','EOF',其它。
{
case '/':
{
fputc(first, fwrite);
fputc(second, fwrite);
*pc = CPP_STATE;
}
break;
case '*':
{
fputc(first, fwrite);
fputc('/', fwrite);
*pc = C_STATE;
}
break;
case END_STATE:
*pc = END_STATE;
break;
default:
{
fputc(first,fwrite);
fputc(second, fwrite);
}
break;
}
}
break;
case END_STATE:
*pc = END_STATE;
break;
default:
{
fputc(first, fwrite);
}
break;
}
}
void C_STATE_CHULI(FILE *fread, FILE *fwrite, zhuangtai *pc)//文件指针为C状态注释
{
int first = fgetc(fread);
switch (first) //文件指针指向内容的可能情况:'*','\n','其它'
{
case '*':
{
int sconed = fgetc(fread);
switch (sconed) //文件指针指向'*'的下一次指向内容可能情况:'*','/','其它'
{
case '*':
{
fputc(first, fwrite);
ungetc(sconed, fread);
//int third = fgetc(fread);
//switch (third) //文件指针指向第二个'*'的下一次指向内容可能情况:'/','其它'
//{
//case '/':
//{
// *pc = NUL_STATE;
//}
// break;
//default:
//{
// fputc(sconed, fwrite);
// fputc(third, fwrite);
//}
// break;
//}
}
break;
case '/':
{
int third = fgetc(fread);
if ('\n' != third)
{
fputc('\n', fwrite);
}
ungetc(third, fread);
*pc = NUL_STATE;
}
break;
default:
{
fputc(first, fwrite);
fputc(sconed, fwrite);
}
break;
}
}
break;
case '\n':
{
fputc('\n', fwrite);
fputc('/', fwrite);
fputc('/', fwrite);
}
break;
default:
{
fputc(first, fwrite);
}
break;
}
}
void CPP_STATE_CHULI(FILE *fread, FILE *fwrite, zhuangtai *pc)
{
int first = fgetc(fread);
switch (first) //文件指针指向的内容情况可能:'\n','EOF','其它'
{
case '\n':
{
fputc(first, fwrite);
*pc = NUL_STATE;
}
break;
case END_STATE:
*pc = END_STATE;
break;
default:
{
fputc(first, fwrite);
}
break;
}
}
//主函数
#include "zhushi.h"
void test(FILE *fread, FILE *fwrite)
{
zhuangtai state;
zhuangtai *pc = &state;
state = NUL_STATE;
while (state != END_STATE)
{
switch (state)
{
case NUL_STATE: //文件指针状态为无状态
{
NUL_STATE_CHULI(fread, fwrite,pc);
}
break;
case C_STATE: //文件指针为C注释状态
{
C_STATE_CHULI(fread, fwrite, pc);
}
break;
case CPP_STATE: //文件指针为C++注释状态
{
CPP_STATE_CHULI(fread, fwrite, pc);
}
break;
}
}
//文件指针为结束状态
}
int main()
{
FILE *fread = fopen("input.c", "r");
if (fread == NULL)
{
perror("open file for read");
exit(EXIT_FAILURE);
}
FILE *fwrite = fopen("out.c", "w");
if (fwrite == NULL)
{
perror("open file for write");
exit(EXIT_FAILURE);
}
test(fread,fwrite);
fclose(fread);
fread = NULL;
fclose(fwrite);
fwrite = NULL;
return 0;
}
还有代码运行后的结果:
以上就是我进行这次注释转换的实现思路和代码,欢迎大家来这里多多交流。