今天我们来做一个经典练习题,注释转换。首先我们得先知道各种状态之间的关系:
代码如下:
#define _CRT_SECURE_NO_WARNINGS_ #include<stdio.h> #include<stdlib.h> #include<Windows.h> typedef enum State{ NOT_COMMENT, //不是注释。 MAYBE_IN, //可能进注释。 C_COMMENT, //C风格注释。 CPP_COMMENT, //C++风格注释。 MAYBE_OUT, //可能出注释。 }State; int main() { FILE *pIn; //建立两个文件。 FILE *pOut; int ch,nextch; State state=NOT_COMMENT; //假设初始为不是注释状态。 const char *statestr[]={"不是注释", "可能进注释", "C风格注释", "Cpp风格注释", "可能出注释"}; //用数组记录所有状态可能性。 pIn=fopen("input.c","r"); //打开文件只能取读。 if(pIn==NULL) { perror(""); //如果是空文件,就输出错误原因。 system("pause"); return 1; } pOut=fopen("output.c","w"); //如上所述。 if(pOut==NULL) { perror(""); system("pause"); fclose(pIn); //关闭文件。 return 1; } while(1) { ch=fgetc(pIn); //从文件中读取一个一个的字符。 if(ch==EOF) { break; } switch(state) //用switch来分别说明各个状态的情况。 { case NOT_COMMENT: //当是不是注释状态时。 if(ch=='/') { state=MAYBE_IN; //如果ch为'/',状态为可能进入,按原数继续输出。 fputc(ch,pOut); } else{ state=NOT_COMMENT; //否则还是不是注释状态。 fputc(ch,pOut); } break; case MAYBE_IN: //当为可能进入状态时。 if(ch=='/') //如果为'/',状态为c++注释。 { state=CPP_COMMENT; fputc(ch,pOut); } else if(ch=='*') //当为*时为C风格注释。 { state=C_COMMENT; fputc('/',pOut); } else { //否则还是为不是注释状态。 state=NOT_COMMENT; fputc(ch,pOut); } break; case CPP_COMMENT: //当C++风格注释状态时。 if(ch=='\n') { state=NOT_COMMENT; //如果为换行,则变成不是注释状态。 fputc(ch,pOut); } else{ //否则变为C++风格注释状态。 state=CPP_COMMENT; fputc(ch,pOut); } break; case C_COMMENT: //为C风格注释时。 if(ch=='*') { state=MAYBE_OUT; //如果为*则变成可能出注释状态。 } else{ state=C_COMMENT; //否则为C风格注释。 fputc(ch,pOut); if(ch=='\n') //但是当为换行时,要将原数转为//。 { fprintf(pOut,"//"); } } break; case MAYBE_OUT: //当为可能出注释时。 if(ch=='/') { state=NOT_COMMENT; //如果为'/',为不是注释状态。 nextch = fgetc(pIn); if (nextch != '\n') { //并且它下一个字符为换行时,输出换行。 fputc('\n', pOut); } ungetc(nextch, pIn); } else if (ch == '*') { //当为*时,为可能输出状态,输出*。 state = MAYBE_OUT; fputc('*', pOut); } else { //否则为C风格注释状态。 state = C_COMMENT; fputc('*', pOut); fputc(ch, pOut); } break; } printf("%c:当前状态是 : %s\n", ch, statestr[state]); //输出最后的状态。 } fclose(pIn); //关闭两个文件。 fclose(pOut); system("pause"); return 0; }