小项目:简单注释转换(C风格转到C++风格)

来源:互联网 发布:当当网和淘宝网哪个好 编辑:程序博客网 时间:2024/06/05 11:38


C的注释是以字符 /* 开始,以字符 */ 结束,注释被包含的内容。C++的注释是以字符 // 开始,碰到换行符 \n 时结束,注释一行。所以,从C注释转到C++,就是在碰到 /* 时将换成 // ,碰到 */ 时 将其删除。当然,这里会有许多种需要细心情况,我们下面再谈。


完成这个项目,我们需要把代码划分4个状态,NULL(无状态),C状态,CPP状态,END状态。没有接触过这个项目的同学对这四个状态可能不太懂,请耐心往下看。

请阅读下面的状态转换图,首先,我们默认代码开始时是NULL 状态。





①当在NULL状态下碰到 /* 时 进入 C状态(同时将 /* 改为 //);

②在C状态下碰到*/,说明C注释已经结束,此时转回到NULL状态(将*/ 删除),进行下一轮新的判断;

③在NULL状态下碰到 // 时,说明c++注释开始,转到CPP状态;

④当在CPP状态下读到 \n 时,说明C++注释结束,此时转回NULL状态,进行下一轮判断;

⑤⑥⑦:当代码读到EOF时,说明代码已经结束,这时转到END状态,结束程序;


上面状态转换图以及序号讲解只说明了状态之间的转换关系,下面我们列举一下将会碰到哪些情况:


// 1.一般情况
/* int i = 0; */


// 2.换行问题
/* int i = 0; */int j = 0;
/* int i = 0; */
int j = 0;


我们需要将 int j = 0; 换到下一行,保证有效内容不被注释。
 
// 3.匹配问题
/*int i = 0;/*xxxxx*/


/* 该与那个*/匹配?


// 4.多行注释问题
/*
int i=0;
int j = 0;
int k = 0;
*/int k = 0;


如何将每行都转换成C++注释?



// 5.连续注释问题
/**//**/


连续的C注释怎么处理?


// 6.连续的**/问题
/****/


连续的***/又该怎么处理?


// 7.C++注释问题
// /*xxxxxxxxxxxx*/


C++注释中遇到C注释该怎么办?


这个小项目中我只处理了这几种问题,当然还有许多情况需要同学们去发掘。例如:当一个双引号中包含 /**/ 或者 // 又改怎么解决?




既然我们这个项目是对代码进行操作,那么我们的输入输出必须是函数啦。在相同的目录下建立一个 input.c 作为输入。函数执行完毕后,自动生成输出.c文件。






在这里,我声明一下,下面的代码中用到了fputc函数,fgetc函数,流等C语言知识点。不懂得同学自行查阅资料。

接下来我们来看代码。我用的编译软件是VS2010,写这个项目的时候将其分成了三部分。如图:




 Commentconvert.h 是头文件,里面包含了所需的一些宏,枚举类型和操作函数的接口。

#ifndef __COMMENT_CONVERT_H__ //防止头文件重定义错误出现#define __COMMENT_CONVERT_H__#include<stdio.h>#include<stdlib.h>#define INPUTFILENAME "input.c"//将文件名定义成宏,方便以后的修改#define OUTPUTFILENAME "output.c"enum STATE//枚举类型{ NUL_STATE, C_STATE, CPP_STATE, END_STATE};void Commentconvert(FILE *pread,FILE *pwrite);//总操作函数void DO_NUL_state(FILE *pread,FILE *pwrite);//NULL状态操作函数void DO_C_state(FILE *pread,FILE *pwrite);//C状态操作函数void DO_CPP_state(FILE *pread,FILE *pwrite);//CPP状态操作函数#endif // __COMMENT_CONVERT_H__


Commentconvert.c中放的是操作函数的代码,与主函数分开是为了便于调试。

#include"Commentconvert.h"enum STATE state=NUL_STATE;void DO_NUL_state(FILE *pread,FILE *pwrite){  int first = 0;  char second = 0;  first = fgetc(pread);  switch(first)  {  case '/':<span></span>  second = fgetc(pread);<span></span>  if(second=='*')         //NULL状态下 读到 /* 转换到 C状态<span></span>  {<span></span>    fputc('/',pwrite);   // 放入//<span></span>fputc('/',pwrite);<span></span>state = C_STATE;    <span></span>  }<span></span>  else if(second=='/')   //NULL状态下 读到 /* 转换到 C++状态<span></span>  {<span></span>   fputc(first,pwrite);<span></span>   fputc(second,pwrite);<span></span>   state = CPP_STATE;<span></span>  }<span></span>  else<span></span>  {<span></span>   fputc(first,pwrite);<span></span>   fputc(second,pwrite);<span></span>  }<span></span> break;  case EOF:       //NULL状态下 读到 EOF 转换到 END状态<span></span>  fputc(first,pwrite);<span></span>  state = END_STATE;<span></span>  break;  default:<span></span>  fputc(first,pwrite);<span></span>  break;    }}void DO_C_state(FILE *pread,FILE *pwrite){  char first = 0;  char second = 0;  first = fgetc(pread);  switch(first)  {  case '*':<span></span>  second = fgetc(pread);<span></span>  if(second == '/')         //换行问题 当读到 */ 时,我们还得判断它的下一个字符是不是\n ,                                  <span></span>  { <span></span>  int third = 0;<span></span>  third = fgetc(pread);<span></span>  if(third == '\n')        //如果是则将\n读到pwrite中,<span></span>  {<span></span> fputc(third,pwrite);<span></span> state = NUL_STATE;<span></span>  }<span></span>  else                         //如果不是,我们则添加一个换行符<span></span>  {<span></span>fputc('\n',pwrite);   <span></span>ungetc(third,pread);<span></span>state = NUL_STATE;<span></span>  }        <span></span> <span></span>  }<span></span>  else  //   多个**/问题  如果 * 的下一个字符不是 / ,则将这个字符返还给pread<span></span>  {<span></span>     fputc(first,pwrite);<span></span>     ungetc(second,pread);<span></span> <span></span>  }<span></span>  break;  case '\n':                  //多行注释问题    C状态下读到\n  放回\n  读到下一行开头 并放入 //<span></span>   fputc(first,pwrite);<span></span>   fputc('/',pwrite);<span></span>   fputc('/',pwrite);<span></span>  break;  case EOF:               // C状态下读到EOF   换到END 状态<span></span>   fputc(first,pwrite);<span></span>   state = END_STATE;<span></span>   break;  default:<span></span> fputc(first,pwrite);<span></span> break;  }}void DO_CPP_state(FILE *pread,FILE *pwrite){ char first = 0; char second = 0; first = fgetc(pread); switch(first) { case '/':<span></span> second = fgetc(pread);  <span></span>  if(second == '*')      //C++状态下遇到 /* 不做操作 并放回<span></span> {<span></span>    fputc(first,pwrite);<span></span>   fputc(second,pwrite);<span></span> }<span></span> else<span></span> {<span></span>   fputc(first,pwrite);<span></span>   fputc(second,pwrite);<span></span> }<span></span> break; case EOF:     //c++状态下遇到 EOF  转换到END<span></span> fputc(first,pwrite);<span></span> state = END_STATE;<span></span> break; case '\n':           //c++状态下遇到 \n ,转换到NULL状态<span></span> state = NUL_STATE; default:<span></span>  fputc(first,pwrite);<span></span>  break; }}void Commentconvert(FILE *pread,FILE *pwrite){   while(state!=END_STATE)  {    switch(state)<span></span>{<span></span>case NUL_STATE:<span></span>DO_NUL_state(pread,pwrite);<span></span>break;<span></span>case C_STATE:<span></span>DO_C_state(pread,pwrite);<span></span>break;<span></span>case CPP_STATE:<span></span>DO_CPP_state(pread,pwrite);<span></span>break;<span></span>case END_STATE:<span></span>break;<span></span>}  }}

test.c中放的是调试代码,包括主函数。

#include"Commentconvert.h" int main() {    FILE *pread=NULL; FILE *pwrite=NULL; printf("转换开始"); pread=fopen(INPUTFILENAME,"r");  if(NULL==pread)  {   printf(" open file for read");   exit(EXIT_FAILURE);  } pwrite=fopen(OUTPUTFILENAME,"w"); if(NULL==pwrite) {   fclose(pread);   printf(" open file for write");   exit(EXIT_FAILURE); } Commentconvert(pread,pwrite); printf("转换结束"); fclose(pread); //用完之后,要关闭它。(良好编程习惯) fclose(pwrite);     return 0; }


如果你的代码成功的话,将上面列举的问题输入 input.c,执行代码,你会看到下面的结果。




套用我学长的一句话,为什么选择当程序员,“工资高,自由度大,前景好,有车有房有未来”。 哈哈, 同志们加油!



1 0