[C.C++] C++去除cpp文件的注释

419 0
Honkers 2026-4-8 01:41:21 | 显示全部楼层 |阅读模式

问题:读取一个cpp文件,去除其中所有的单行注释(//)和多行注释(/**/),将去除注释后的内容写入一个新文件。

注意:

  • 不能去除字符串中的任何字符,如 "asdf//gh/**/k" 需要原样输出
  • 能够识别转义的双引号(\")和非转义的双引号("),如:
    • '\"'(单引号中的转义双引号字符)
    • "asdf\"" (字符串中的转义双引号不能表示字符串结束)
    • \"aaa"bcdef" (同理,转义双引号不能表示字符串开始)

命令行参数为:

  • 参数1:原文件名
  • 参数2:新文件名

 

目录

一、文件流

二、具体逻辑

1.如何循环读入字符

2.处理单行和多行注释

3.注意字符串

4.注意转义双引号

防止转义双引号作为字符串开头">1>防止转义双引号作为字符串开头

防止转义双引号作为字符串结尾">2>防止转义双引号作为字符串结尾

 5.增加简单的查错功能

三、正则实现(Java)


一、文件流

引入头文件,新建ifstream和ofstream对象,如果不能打开文件,则结束整个函数。 

  1. #include <iostream>
  2. #include <fstream>
  3. using namespace std;
  4. bool stripComment(string infile,string outfile){
  5. ifstream ifs;
  6. ifs.open(infile,ios::in);
  7. if(!ifs.is_open()){
  8. cout<<"fail to read!"<<endl;
  9. return true;
  10. }
  11. ofstream ofs;
  12. ofs.open(outfile,ios::out|ios::trunc);//写文件,如果已经存在同名的文件,则删除它创建新文件
  13. if(!ofs.is_open()){
  14. cout<<"fail to write!"<<endl;
  15. return true;
  16. }
  17. ifs.close();
  18. ofs.close();
  19. }
  20. int main(int argc,char** argv){
  21. return 0;
  22. }
复制代码

二、具体逻辑

1.如何循环读入字符

这是最关键的一步。我们利用ifstream对象的get()方法无条件地读取文件流中的一个字符。什么叫无条件?这是与>>运算符相区分的,>>会自动跳过所有空白字符,也就是说,它读不到空格、\t、\n,这不符合我们的需求。 

同时,ifstream对象有一个putback()方法,它就是将一个字符重新放回文件流的末尾,下一次get(),我们还会读到它:这有时候很有用。

get(char c) 会把文件流的末尾一个字符取出,放到char型变量c中。这个函数的返回值可以被转换成一个布尔值,表示流的状态:如果流状态正常,则返回true;如果流状态不正常(bad,fail,读到文件尾符号),返回false。

  1. char temp1{};
  2. while(ifs.get(temp1)){
  3. ofs<<temp1;
  4. }
复制代码

最简单的情况是,利用get()循环读入字符并存入temp1变量中,再把temp1写入新文件中。最终我们会得到与原文件一样的副本。

2.处理单行和多行注释

这两种东西有同一个特点:都是以 / 开头的。所以我们读取到 / 这个字符时,就要小心一点:它是不是意味着我读到了一个注释?

我们可以在此基础上再读一个字符,存入另一个字符变量temp2中,看看它是什么情况:

  • / :一定读到了一个单行注释
  • * :一定读到了一个多行注释
  • 其他字符:刚刚读到的 / 只是一个普通的正斜杠

对于第三种情况, 我们这样善后:

  1. 立刻输出temp1(/)
  2. 把temp2放回文件流中等待下一次读取,因为它可能有用(比如,是个双引号)
  3. 跳转到一开始的while循环

 对于第一种情况:

  1. 一直向后读字符,直到读到一个换行符\n
  2. 将这个换行符放回文件流
  3. 跳转到一开始的while循环

第二种情况最麻烦,我们必须找一个办法确定什么时候多行注释才能结束。C++的语法规定, /* 与最近的 */ 之间是多行注释,那么我们只需找最近的 */ 即可。

  1. while循环一直向后读字符,直到找到一个 *
  2. 再读一个字符,放入字符变量temp3中。
    1. temp3是一个 / ,恭喜!我们已经找到多行注释的完整范围,只要简单地break掉当前的while循环,再跳转到开始的while循环就可以。不用输出任何东西。
    2. 不好,temp3不是 / ,这意味着我们没有找到多行注释的终止处。此时应该将temp3放回文件流,返回步骤1:这是很必要的,如果temp3正好是一个* ,它之后恰好是一个 / 呢?我们不能丢弃任何“可能有用”的字符!
  1. while(ifs.get(temp1)){
  2. //处理 "//" 或 "/**/"
  3. if(temp1=='/'){
  4. checkStatus=true;
  5. ifs.get(temp2);//再读一个字符
  6. if(temp2=='/'){//处理"//"
  7. checkStatus=false;
  8. while(ifs.get(temp2)){//一直向后读字符,直到读到一个换行符\n
  9. if(temp2=='\n') break;
  10. }
  11. ifs.putback('\n');//将换行符放回文件流
  12. continue;//跳转到一开始的while循环
  13. }else if(temp2=='*'){//处理 "/**/"
  14. checkStatus=true;
  15. while(ifs.get(temp3)){
  16. if(temp3=='*'){//找到一个*
  17. ifs.get(temp4);
  18. if(temp4=='/'){//找到一个/
  19. checkStatus=false;
  20. break;
  21. }else{//没找到/
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2026 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行