昨天无意中看到一道题:“编写一个程序,使一段合理C语言中的注释全部大写“。突然兴趣来了,于是决定自己动手来试试。这道题目看起来很简单,但是实际动起手来,还是有点难度。
C语言注释说明
C语言的注释分为两种,一种是单行注释,一种是多行注释。
- 单行注释:顾名思义就是当遇到换行之后即表示注释已结束,用//表示
- 多行注释:注释以/*开始并且以*/结束,中间的任意字符就是注释
注意问题
该题要注意多个地方:
1. 汉字,由于C语言处理汉字比较麻烦,所以这里就不处理汉字,即假设源文件中没有汉字,全部由字母组成。
2. 注释嵌套,单行字符中除非遇到换行,否则后面的字符一律为注释内容,多行注释不管遇到什么字符,除非注释结束,否则内容都将是注释
3. 多行注释如果有多个注释结束符(*/),则匹配最近的一个。
4. 若字符串中包含有注释符,则该注释符不是注释符,而是字符串。
状态变化图
整个过程的变化可以用一个状态图来说明,如下所示,如有错漏,感谢指正:
状态定义
- SRC_TEXT:文本状态,即输入的是普通文本
- SRC_TEXT_STRING_START:字符串开始状态,表示接下来的字符属于字符串
- SRC_COMMENT_BEGIN:注释开始状态,表示当前字符是”/”,接下来可能是注释开始(输入字符为”/”)
- SRC_SINGLE_START:单行注释开始状态,表示上一个字符是”/”,且当前的字符依然是”/”,即表示单行注释开始
- SRC_MULTI_START:多行注释开始状态,表示上一个字符是”/”,且当前字符是”*”,即表示多行注释开始
- SRC_MULTI_WILL_END:多行注释即将结束状态,表示当前是”*”,接下可能是多行注释结束(输入字符为”/”)
- SRC_MULTI_END:多行注释结束状态,表示上一个字符是”*”,当前字符是”/”,即表示多行注释结束
由此我们可以定义各种状态,如下所示:
状态变迁
- 空白状态时,如果用户输入的不是字符”/”,则表示为普通字符,进入到SRC_TEXT状态,否则进入到SRC_COMMENT_START状态
- SRC_TEXT状态时,输入任意字符,状态依然不变。若此时输入为引号,表示字符串开始,进入到SRC_TEXT_STRING_START,在该状态若再次输入引号,返回到SRC_TEXT。
- 当不在SRC_TEXT_STRING_START状态时,输入字符”/”,即表示可能开始注释,此时若下一个是字母,即返回到SRC_TEXT。如果是”/”,表示单行注释开始,进入到SRC_SINGLE_START状态。如果是”*”,表示多行注释开始,进入SRC_MULTI_START状态。
- 在SRC_SINGLE_START状态,如果输入非换行符,则输入依然是注释,否则表示单行注释结束,返回到SRC_TEXT状态
- 在SRC_MULTI_START状态,如果输入非”*”字符,则输入依然是注释,多行注释与换行无关,如果输入是”*”,则表示接下来可能要结束多行注释,进入到SRC_MULTI_WILL_END状态
- 在SRC_MULTI_WILL_END状态,如果输入不是”/”字符,表示注释继续,返回到SRC_MULTI_START状态,否则表示多行注释结束,进入SRC_MULT_END状态
- 在SRC_MULTI_END状态,输入非”/”字符,表示输入为程序正文,进入到SRC_TEXT状态,否则重新进入到SRC_COMMENT_BEGIN状态。其实SRC_MULTI_END状态就是SRC_TEXT状态,只是为了更清晰,加入SRC_MULTI_END状态。
完整代码
说了这么多废话,不如直接上代码来的实际,如下所示:
其中,第一段注释是我自己乱写的注释,第二段注释是我从stdio.h中copy出来的注释,
处理之后的结果如下所示(_main.cpp):