本次这个小项目的目的是把.c文件中的C风格的注释转换成为C++风格的注释。
C注释风格:/**/
C++注释风格://
首先我们分析一下会出现的几种状态,以及各种状态之间的转换关系:
首先我们在这里对一些状态进行了标注,我们这里已知的有4种状态,
第一种是END_STATE
第二种是C_STATE
第三种是CPP_STATE
第四种是我们平时的NULL_state。
在这里,注释转换操作的是文件,所以接下来我么采用文件操作。
首先我们要打开input.c文件,对这个文件内部的文件进行读取,然后处理,否则直接提示用户有错误。
接下来,我们还要打开output.c文件,对处理以后的代码进行写入。
接下来,我们就要分析各种可能会遇到的情况:
input.c
// 1.一般情况
/* 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*/
在这里我们对这个小项目编写的方法和我们前面对通讯录的方式是一样的,采用三个文件封装,一个test.c文件封装测试文件,一个comment_covert.c文件封装实现函数,一个comment_covert.h文件封装头文件。
在这里对待每一个状态,我们就可以采取枚举常量。
static enum STATE
{
NULL_STATE,
C_STATE,
CPP_STATE,
END_STATE
};
然后你要清楚,现在我们所要处理的默认状态是从NULL_STATE,所以接下来我们实现NULL_STATE函数,然后我们借助上面我所绘制的各种状态之间的转换关系,我们可以知道,在这里我们最需要判断的是所检察的第一个字符是什么,在这里有三种情况:‘/’,普通字符,EOF,所以我们先要接收第一个字符,然后利用我们的有限状态机,当为’/’时,我们进行下一个字符的判断,判断是否为‘*’,如果是,那么我们接下来让state为C_STATE,如果是‘/’那么进入CPP_state,接下来,其他字符,按照限定自行做出编辑即可。
comment_covert.h
#ifndef __COMMENT_CONVERT_H
#define __COMMENT_CONVERT_H
#include<stdio.h>
#include<stdlib.h>
#define READFILENAME "input.c"
#define WRITEFILENAME "output.c"
static enum STATE
{
NULL_STATE,
C_STATE,
CPP_STATE,
END_STATE
};
void CommentConvert(FILE *fRead, FILE *fWrite);
void Do_C_State(FILE *fRead, FILE *fWrite);
void Do_CPP_State(FILE *fRead, FILE *fWrite);
void Do_Null_state(FILE *fRead, FILE *fWrite);
#endif //!__COMMENT_CONVERT_H
comment_covert.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"comment_covert.h"
enum STATE state = NULL_STATE;
void Do_C_State(FILE *fRead, FILE *fWrite)
{
char first = 0;
char second = 0;
char third = 0;
first = fgetc(fRead);
switch (first)
{
case‘*‘:
second = fgetc(fRead);
switch (second)
{
case‘/‘:
third = fgetc(fRead);
if (third != ‘\n‘)
fputc(‘\n‘, fWrite);
if (third == ‘/‘)
{
ungetc(third, fRead);
state = NULL_STATE;
break;
}
fputc(third, fWrite);
state = NULL_STATE;
break;
case‘*‘:
third = fgetc(fRead);
fputc(first, fWrite);
if (third == ‘/‘)
{
state=NULL_STATE;
}
break;
default:
fputc(first, fWrite);
fputc(second, fWrite);
break;
}
break;
case‘\n‘:
fputc(first, fWrite);
fputc(‘/‘, fWrite);
fputc(‘/‘, fWrite);
break;
case EOF:
state = END_STATE;
break;
default:
fputc(first, fWrite);
break;
}
}
void Do_CPP_State(FILE *fRead, FILE *fWrite)
{
char first = 0;
first = fgetc(fRead);
switch (first)
{
case ‘\n‘:
fputc(first, fWrite);
state = NULL_STATE;
break;
case EOF:
state = END_STATE;
break;
default:
fputc(first, fWrite);
break;
}
}
void Do_Null_state(FILE *fRead, FILE *fWrite)
{
char first = 0;
char second = 0;
first = fgetc(fRead);
switch (first)
{
case‘/‘:
second = fgetc(fRead);
if (second == ‘*‘)
{
fputc(‘/‘, fWrite);
fputc(‘/‘, fWrite);
state = C_STATE;
}
else if (second == ‘/‘)
{
fputc(first, fWrite);
fputc(second, fWrite);
state = CPP_STATE;
}
else
{
fputc(first, fWrite);
fputc(second, fWrite);
}
break;
case EOF:
state = END_STATE;
break;
default:
fputc(first, fWrite);
break;
}
}
void CommentConvert(FILE *fRead, FILE *fWrite)
{
while (state!=END_STATE)
{
switch (state)
{
case NULL_STATE:
Do_Null_state(fRead, fWrite);
break;
case C_STATE:
Do_C_State(fRead, fWrite);
break;
case CPP_STATE:
Do_CPP_State(fRead, fWrite);
break;
default:
break;
}
}
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"comment_covert.h"
int main()
{
FILE *fRead = NULL;
FILE *fWrite = NULL;
printf("*****注释转换开始******\n");
fRead = fopen(READFILENAME, "r");
if (NULL == fRead)
{
perror("read of file");
exit(EXIT_FAILURE);
}
fWrite = fopen(WRITEFILENAME, "w");
if (NULL == fRead)
{
fclose(fRead);
perror("write of file");
exit(EXIT_FAILURE);
}
CommentConvert(fRead, fWrite);
printf("*****注释转换结束******\n");
fclose(fRead);
fclose(fWrite);
system("pause");
return 0;
}
最终就可以完成这个小项目了,代码的分析需要一步一步来,想要解决问题,也不能急,一步一步分析,哪怕最费劲的进行单步调试。