版权声明:Oce2ns的大板 https://blog.csdn.net/weixin_39392653/article/details/81490640
C语言注释对比C++注释,功能要明显差一些,因此,当程序中需要将C语言的注释转化时,就需要一个注释的转化软件。毕竟对于大量的代码,我们不可能一个一个的去更改。
在编程初期,我们应该想到,对于C注释开始的识别,但会牵扯的/是除号。或者别的用途,包括结束时,*号的识别。做一个简单的情况分析后,总结出,将其各种情况,用一个状态机去解决。这样可以将无限种的可能,转化为有限种的情况。文本状态,C语言注释的状态,C++注释的状态,和结束文本的标志(EOF)。
文本状态
遇到了‘/*’就开始进入了C语言的注释状态
遇到了‘//’就开始的C++的注释状态
遇到了‘EOF’代表我的文本已经读取结束
C语言注释状态
遇到‘*/’结束,进入文本状态
C语言不支持嵌套注释,所以里面也不会进入C++注释状态
C语言注释在文本结束前一定会‘*/’结束,不会再结束注释前就EOF退出
C++注释状态
当着一行注释结束时,C语言注释就结束,也就是遇到‘/n’结束
当注释中找到EOF文件结束标志,证明这行就是最后一行,直接结束
同理,在C++注释中也不会跳到C语言的注释
结束标志EOF
结束都结束了,也就不谈转入别的状态了好吧
解决完这个就是开始码代码。同样使用多个.c文件,将代码拆开写。这样问题比较容易找出。先是测试的test.c文件。
test.c
#include"Annotation.h"//印一下.h的头文件
void test()
{
FILE * pread = NULL;
FILE * pwrite = NULL;
pread = fopen("HeadsomeYZX.txt","r");//从流中读取文本内容,这里的。txt文件名是乱起的,就是输入文件,就是已经有的文本
if(pread == NULL)
{
printf("Error opening read");//解决读取失败。
exit(EXIT_FAILURE);
}
pwrite = fopen("SomelyMYT.txt","w");//从流中写一个文件
if(pwrite == NULL)
{
printf("Error opening write");
exit(EXIT_FAILURE);
}
AnnCtoCPP(pread,pwrite);//核心的转换功能,将他写到核心.c文件中
fclose(pread);//结束流
pread = NULL;//指针指向空
fclose(pwrite);
pwrite = NULL;
}
int main()
{
test();
return 0;
}
Annotation.c
核心文件
#include"Annotation.h"
void AnnCtoCPP(FILE *pread,FILE *pwrite)
{
State state = text_state;//初始化状态,初始化为文本状态
while(state != end_state)//只有读取到文字并非结束状态时进入状态选择
{
switch(state)
{
case c_state:
Annotationc_cPP(pread,pwrite,&state);//进入c注释转化为c++注释状态
break;
case text_state:
Annotationtext_cPP(pread,pwrite,&state);//进入文本状态
break;
case cPP_state:
NOTAnnotation(pread,pwrite,&state);//进入C++注释状态
break;
}
}
}
void Annotationc_cPP(FILE *pread,FILE *pwrite,State *p)
{
int first = fgetc(pread);//先读一个字符
switch(first)
{
case '*'://读到*,开始敏感,因为可能是遇到了C注释的结束
{
int second = fgetc(pread);
switch(second)
{
case '/'://cPP注释结束。
{
int third = fgetc(pread);//判断后面还有没有内容
if(third == '\n')//后面无内容
{
fputc(third,pwrite);
}
else
{
fputc('\n',pwrite);//注释结束了,但是后面有内容,将其换行打印
ungetc(third,pread);
}
*p = text_state;
}
break;
case '*'://这是一个特殊状态,即/***/读到*,后下一个不是/,继续读,可能错过*/的结束标志
{
fputc(first,pwrite);
ungetc(second,pread);//将其返回文本中,下一次继续从这里读
}
break;
default :
{
fputc(first,pwrite);
ungetc(second,pread);
}
break;
}
}
break;
case '\n'://在C语言的注释中如果遇到\n就换行,在输出两个/
{
fputc(first,pwrite);
fputc('/',pwrite);
fputc('/',pwrite);
}
break;
default ://后面什么都不是就代表,这个*不是注释的结束
{
fputc(first,pwrite);
}
break;
}
}
void Annotationtext_cPP(FILE *pread,FILE *pwrite,State *p)
{
int first = fgetc(pread);
switch(first)
{
case '/'://文本状态读取到/开始敏感,可能进入注释状态
{
int second = fgetc(pread);
switch(second)
{
case '*'://遇到*进入C语言注释状态,把他转化成//的C++注释状态
{
fputc('/',pwrite);
fputc('/',pwrite);
*p = c_state;//进入C语言注释状态,去寻找注释结束标志
}
break;
case '/'://遇到/进入C++注释状态
{
fputc('/',pwrite);
fputc('/',pwrite);
*p = cPP_state;
}
break;
default ://后面不是代表/只是别的功能
{
fputc(first,pwrite);
fputc(second,pwrite);
}
break;
}
}
break;
case EOF://文本遇到EOF,结束文本
{
fputc(first,pwrite);
*p = end_state;
}
break;
default ://正常打印文本
fputc(first,pwrite);
break;
}
}
void NOTAnnotation(FILE *pread,FILE *pwrite,State *p)
{
int first = fgetc(pread);
switch(first)
{
case '\n'://C++注释换行就意味着结束注释
{
fputc(first,pwrite);
*p = text_state;
}
break;
case EOF://遇到EOF结束文件
*p = end_state;
break;
default :
fputc(first,pwrite);
break;
}
}
Annotation.h
头文件
#ifndef __AnnotationCtoCPP_H__
#define __AnnotationCtoCPP_H__
#include <stdio.h>
#include <stdlib.h>
typedef enum //使用枚举,状态机
{
text_state,
c_state,
cPP_state,
end_state
}State;//重命名,这样后面写代码,可以少写一些
void AnnCtoCPP(FILE *pread,FILE *pwrite);
void Annotationc_cPP(FILE *pread,FILE *pwrite,State *pstate);
void Annotationtext_cPP(FILE *pread,FILE *pwrite,State *pstate);
void NOTAnnotation(FILE *pread,FILE *pwrite,State *pstate);
#endif
测试一下功能
例子貌似不够刁钻啊。那来个刁钻测试用例