问题的引入:为什么需要注释?
问题的解答:1.使用一些注释符来增加我们程序的可读性,2.屏蔽掉一些不需要程序。
注释符一般分为两种:一种是以“/*”开头,在中间加上注释内容,并以“*/”结尾的段落注释符。在“/*”和“*/”之间的即为注释。
另一种是以“//”开头,后面加注释内容的单行注释符。在“//”之后的即为注释。
其中:`1.C语言的注释符是以“/*”开头并以“*/”结尾的串。在“/*”和“*/”之间的即为注释。 2.在C++语言源程序中可以用“/*....*/”做注释符,也可以用“//”做注释符。其中,“/*....*/”为多行注释符,“//”为单行注释符。
示例:请将以下input.c文件中的注释,全部转换为c++的注释风格
// 1.一般情况
int num = 0;
/* 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*/
通过文件我们分析到主要牵扯到四种问题:c语言和无状态的互相转换,c++和无状态的转换,无状态和结束状态的转换,c++和结束状态的转换。
编程思路:建立一个主函数——主函数放用于实现注释转换功能的调用函数——然后这个调用函数存放用于实现这四种状态的函数——然后分别实现这四种状态函数
以下为图解
下面就是函数代码
头文件
#define _CRT_SECURE_NO_WARNINGS 1
#ifndef __COMMENT_CONVERT_H__
#define __COMMENT_CONVERT_H__
#include<stdio.h>
#include<stdlib.h>
typedef enum State
{
NUL_STATE,
C_STATE,
CPP_STATE,
END_STATE,
}State;
void donostate(FILE*pFread, FILE*pFwrite, State *ps);
void docstate(FILE*pFread, FILE*pFwrite, State *ps);
void docppstste(FILE *pFread, FILE* pFwrite, State *ps);
void commentconvert(FILE*pFread, FILE*pFwrite);
#endif //__COMMENT_CONVERT_H__
源函数
#define _CRT_SECURE_NO_WARNINGS 1
#include"comment_convert.h"
void donostate(FILE*pFread, FILE*pFwrite, State *ps)//无状态函数
{
int first = fgetc(pFread);//记录第一个字符
{
switch (first)
{
case '/': //第一个字符如果是‘/'(三种情况,/* // 单纯的字符/
{
int second = fgetc(pFread);//记录第二个字符
switch (second)
{
case '*': //第一种情况,代码为c语言注释
{
fputc('/', pFwrite);
fputc('/', pFwrite);//转换到c++注释,并写到output.txt
*ps = C_STATE;//进入c语言代码注释状态
}
break;
case'/': //第二种情况
{
fputc('/', pFwrite);
fputc('/', pFwrite);//转换到c++注释,并写到output.txt
*ps = CPP_STATE;//进入c++代码注释状态
}
break;
default:
{
fputc('/', pFwrite);//第三种状态
fputc(second, pFwrite);//直接将字符打印出来
}
break;
}
}
break;
case EOF: //表示结束
{
fputc(first, pFwrite);
*ps = END_STATE; //进入结束状态
}
break;
default:
{
fputc(first, pFwrite); //既不是/也不是EOF,表示第一个就是字符,将其打印
}
break;
}
}
}
void docstate(FILE*pFread, FILE*pFwrite, State *ps)//c语言状态
{
int first = fgetc(pFread);//记录第一个字符
{
switch (first) //c语言状态种/*已经确定
{
case '*': //两种情况 (*/ 和 *)
{
int second = fgetc(pFread);
switch (second)
{
case '/': //第一种状况,c语言注释完毕
{
int third = fgetc(pFread);//判断一下第三个字符是不是'\n'
if (third != '\n')
{
fputc('\n', pFwrite);//若不是,我们就要添加\n
ungetc(third, pFread);//将拿到的字符退回到原来的位置,保持程序的完整性
}
else
{
fputc(third, pFwrite);//若是,打印出来就行
}
*ps = NUL_STATE; //状态转换为无注释状态
}
break;
default:
{
fputc(first, pFwrite);//第二个字符不是'/',表示第一个 * 只是一个字符'*'
ungetc(second, pFread);//将我们拿到的第二个字符还回去,保证完整性
}
break;
}
}
break;
case '\n': //是\n
{
fputc(first, pFwrite);
fputc('/', pFwrite);
fputc('/', pFwrite);//将其打印,并加上//
}
break;
default:
{
fputc(first, pFwrite);//第二种情况
}
break;
}
}
}
void docppstste(FILE *pFread, FILE* pFwrite, State *ps)//c++状态
{
int first = fgetc(pFread);
switch (first)
{
case'\n':
{
fputc(first, pFwrite);
*ps = NUL_STATE;
}
break;
case EOF:
{
fputc(first, pFwrite);
*ps = END_STATE;
}
break;
default:
{
fputc(first, pFwrite); //表示第一个就是字符,将其打印
}
break;
}
}
void commentconvert(FILE*pFread, FILE*pFwrite)
{
enum State state = NUL_STATE;
while (state != END_STATE)
{
switch (state)
{
case NUL_STATE:
donostate(pFread, pFwrite,&state);
break;
case C_STATE:
docstate(pFread, pFwrite, &state);
break;
case CPP_STATE:
docppstste(pFread, pFwrite, &state);
break;
default:
break;
}
}
}
主函数
#define _CRT_SECURE_NO_WARNINGS 1
#include"comment_convert.h"
int main()
{
FILE * pFread=NULL ;
FILE * pFwrite=NULL ;
pFread = fopen("input.c", "r");
if (pFread == NULL)
{
perror("open file for read");
system("pause");
exit(EXIT_FAILURE);
}
pFwrite = fopen("output.txt", "w");
if (pFwrite == NULL)
{
perror("open file for write");
system("pause");
exit(EXIT_FAILURE);
}
commentconvert(pFread, pFwrite);
fclose(pFread);
pFread = NULL;
fclose(pFwrite);
pFwrite = NULL;
system("pause");
return 0;
}
最后函数实现如图