注释转换(c++风格转c风格)

介绍

c语言风格的注释为块注释,c++风格为行注释。

/*块注释*/
//行注释

在项目中人们喜欢用不同风格的注释,或者两种风格的注释混用,这并不影响代码的功能,但是在一些工具当中要求代码的注释风格统一为c或者c++风格。
所以写了一个处理文件注释的代码。

分析

我们使用了状态机的概念,即在对文件中各个字符检测的时候遇到特定的字符对全局变量赋不同的状态值,来代表代码所处的状态,下面为不同状态间相互转换的示意图。
这里写图片描述
例如

//Xi/*You*/Linux//Group

首先检测到了”//”这两个字符,进入c++状态,我们将”//”替换为”/* “然后将后面的”/ “,” /”,”//”换成两个空格代替,然后在最后加上”*/”.转换后如下

/*Xi  You  Linux  Group*/

c语言状态下同理。
需要注意的是还有一种状态是引号的状态,在图中并未列出,在” “中的两种注释风格的注释都是无效的,它们被当作字符串处理,所以在” “中的注释的字符原样输出并不进行处理

代码

convertcomment.h

#ifndef _CONVERTCOMMENT_H
#define _CONVERTCOMMENT_H

int convertcomment(FILE *inputfile, FILE *outputfile);
void eventpro(char ch);
void eventpro_no(char ch);
void eventpro_cpp(char ch);
void eventpro_c(char ch);
void eventpro_quo(char ch);

#endif // _CONVERTCOMMENT_H

convert.c

#include <stdio.h>
#include "convertcomment.h"

int main(int argc, char *argv[])
{
    FILE *fpin = fopen("./src_file/input.c", "r");
    if(NULL == fpin)
    {
        printf("open input.c fail.\n");
        return -1;
    }
    FILE *fpout = fopen("./dest_file/output.c", "w");
    if(NULL == fpout)
    {
        printf("open output.c fail.\n");
        return -1;
    }

    convertcomment(fpin, fpout);

    fclose(fpin);
    fclose(fpout);

    printf("Commnet Convert Completion.......\n");
    return 0;
}

convertcomment.c

#include<stdio.h>
#include "convertcomment.h"

//定义状态
typedef enum
{
    no_comment_state,
    c_comment_state,
    cpp_comment_state,
    quo_state,
    end_state
}enum_state;

//定义状态机
typedef struct
{
    FILE *input;
    FILE *output;
    enum_state ulstate;
}state_machine;

//定义全局状态机
state_machine g_state;

int convertcomment(FILE *inputfile, FILE *outputfile)
{
    if(inputfile==NULL || outputfile==NULL)
    {
        printf("invalid arugment inputfile or outputfile.\n");
        return -1;
    }

    /////////////////////////////////////////////////////////
    //初始化状态机
    g_state.input = inputfile;
    g_state.output = outputfile;
    g_state.ulstate = no_comment_state;

    char ch;
    while(g_state.ulstate != end_state)
    {
        ch = fgetc(g_state.input);
        eventpro(ch);
    }

    return 0;
}

void eventpro(char ch)
{
    switch(g_state.ulstate)
    {
    case no_comment_state:
        eventpro_no(ch);
        break;
    case c_comment_state:
        eventpro_c(ch);
        break;
    case cpp_comment_state:
        eventpro_cpp(ch);
        break;
    case quo_state:
        eventpro_quo(ch);
        break;
    }
}

void eventpro_no(char ch)
{
    char nextch;
    switch(ch)
    {
    case '/':
        nextch = fgetc(g_state.input);
        if(nextch == '/')   //C++
        {
            fputc('/', g_state.output);
            fputc('*', g_state.output);
            g_state.ulstate = cpp_comment_state;
        }
        else if(nextch=='*')
        {
            fputc('/', g_state.output);
            fputc('*', g_state.output);
            g_state.ulstate = c_comment_state;
        }
        else
        {
            fputc(ch, g_state.output);
            fputc(nextch, g_state.output);
        }
        break;
     case '"':
        fputc('"', g_state.output);
        g_state.ulstate = quo_state;
        break;
     case EOF:
        g_state.ulstate = end_state;
        break;
     default:
        fputc(ch, g_state.output);
        break;
    }
}
void eventpro_c(char ch)
{
    char nextch;
    switch(ch)
    {
    case '/':
        nextch = fgetc(g_state.input);
        if(nextch=='/')
        {
            fputc(' ', g_state.output);
            fputc(' ', g_state.output);
        }
        else
        {
            fputc(ch, g_state.output);
            fputc(nextch, g_state.output);
        }
        break;
    case '*':
        nextch = fgetc(g_state.input);
        if(nextch=='/')
        {
            fputc(ch, g_state.output);
            fputc(nextch, g_state.output);
            g_state.ulstate = no_comment_state;
        }
        else if(nextch=='*')
        {
            fseek(g_state.input,-1L,SEEK_CUR);         //防止/*  ***/这种情况
        }
        else
        {
            fputc(ch, g_state.output);
            fputc(nextch, g_state.output);
        }
        break;
    case EOF:
        g_state.ulstate = end_state;
        break;
    default:
        fputc(ch, g_state.output);
        break;
    }
}
void eventpro_cpp(char ch)
{
    char nextch;
    switch(ch)
    {
    case EOF:
        fputc('*', g_state.output);
        fputc('/', g_state.output);
        g_state.ulstate = end_state;
        break;
    case '/':
        nextch=fgetc(g_state.input);
        if(nextch=='/'||nextch=='*')
        {
            fputc(' ', g_state.output);
            fputc(' ', g_state.output);
        }
        else if(nextch=='\n')
        {
            fputc(ch, g_state.output);
            fputc('*', g_state.output);
            fputc('/', g_state.output);
            fputc('\n', g_state.output);
            g_state.ulstate = no_comment_state;
        }
        else
        {
            fputc(ch, g_state.output);
            fputc(nextch, g_state.output);
        }
        break;
    case '*':
        nextch=fgetc(g_state.input);
        if(nextch=='/')
        {
            fputc(' ', g_state.output);
            fputc(' ', g_state.output);
        }
        else
        {
            fputc(ch, g_state.output);
            fputc(nextch, g_state.output);
        }
        break;
    case '\n':
        fputc('*', g_state.output);
        fputc('/', g_state.output);
        fputc('\n', g_state.output);
        g_state.ulstate = no_comment_state;
        break;
    default:
        fputc(ch, g_state.output);
        break;
    }
}

void eventpro_quo(char ch)
{
    char nextch;
    switch(ch)
    {
    case '\n':
    case '"':
        fputc(ch, g_state.output);
        g_state.ulstate = no_comment_state;
        break;
    case EOF:
        g_state.ulstate = end_state;
        break;
    default:
        fputc(ch, g_state.output);
        break;
    }
}

makefile

cct:convert.o convertcomment.o
    gcc -o cct convert.o convertcomment.o
convert.o:convert.c
    gcc -o convert.o -c convert.c
convertcomment.o:convertcomment.c
    gcc -o convertcomment.o -c convertcomment.c
clean:
    rm *.o cct

./src_file/input.c

//每个区由若干个内存块组成

//每个区由若干个内存块组成,//每个块是4096个字节

//int i = 0;*/

//*//*int i = 0;

// /**/int i = 0;

/* int i = 0;
 *//*
  */

  /* int i = 0;
  //*/int j = 0;

  /*
  //每个区由若干个内存块组成,每个块是4096个字节
  //每个块的第0个整数指向下个区
  //所以是单链表结构
  //所以每个区只有4092个字节存放真正的数据
  */

  /* int i = 0;*//*int j = 0;
   */
     printf("/*Hello Linux! */");

   /*
    *//*
     */int i =0;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////     5

//"abcdefghijklmn~~~~!!!!!!!!"

char *str = "hello // world.";

/*abc**/

//char *str = "hello /*123*/ xyz";

./src_file/output.c

/*每个区由若干个内存块组成*/

/*每个区由若干个内存块组成,  每个块是4096个字节*/

/*int i = 0;  */

/*    int i = 0;*/

/*     int i = 0;*/

/* int i = 0;
 *//*
  */

  /* int i = 0;
    */int j = 0;

  /*
    每个区由若干个内存块组成,每个块是4096个字节
    每个块的第0个整数指向下个区
    所以是单链表结构
    所以每个区只有4092个字节存放真正的数据
  */

  /* int i = 0;*//*int j = 0;
   */
     printf("/*Hello Linux! */");

   /*
    *//*
     */int i =0;

/*                                                                                                                                                                                                                               5*/

/*"abcdefghijklmn~~~~!!!!!!!!"*/

char *str = "hello // world.";

/*abc**/

/*char *str = "hello   123   xyz";*/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
相当经典的教程,这次的上传一共5集,5分,相当于每1集要1分下载. 本课程是C++ Primer初级教程,课程内容是学习C++语言基础知识,对应着教材的第1章到第8章。 第1章 速入门 1.1 编写简单的C++程序 1.2 初窥输入/输出 1.2.1 标准输入与输出对象 1.2.2 一个使用IO库的程序 1.3 关于注释 1.4 控制结构 1.4.1 while语句 1.4.2 for语句 1.4.3 if语句 1.4.4 读入未知数目的输入 1.5 类的简介 1.5.1 Sales_item类 1.5.2 初窥成员函数 1.6 C++程序 第2章 变量和基本类型 2.1 基本内置类型 2.1.1 整型 2.1.2 浮点型 2.2 字面值常量 2.3 变量 2.3.1 什么是变量 2.3.2 变量名 2.3.3 定义对象 2.3.4 变量初始化规则 2.3.5 声明和定义 2.3.6 名字的作用域 2.3.7 在变量使用处定义变量 2.4 const限定符 2.5 引用 2.6 typedef名字 2.7 枚举 2.8 类类型 2.9 编写自己的头文件 2.9.1 设计自己的头文件 2.9.2 预处理器的简单介绍 第3章 标准库类型 3.1 命名空间的using声明 3.2 标准库string类型 3.2.1 string对象的定义和初始化 3.2.2 String对象的读写 3.2.3 string对象的操作 3.2.4 string对象中字符的处理 3.3 标准库vector类型 3.3.1 vector对象的定义和初始化 3.3.2 vector对象的操作 3.4 迭代器简介 3.5 标准库bitset类型 3.5.1 bitset对象的定义和初始化 3.5.2 bitset对象上的操作 第4章 数组和指针 4.1 数组 4.1.1 数组的定义和初始化 4.1.2 数组操作 4.2 指针的引入 4.2.1 什么是指针 4.2.2 指针的定义和初始化 4.2.3 指针操作 4.2.4 使用指针访问数组元素 4.2.5 指针和const限定符 4.3 C风格字符串 4.3.1 创建动态数组 4.3.2 新旧代码的兼容 4.4 多维数组 第5章 表达式 5.1 算术操作符 5.2 关系操作符和逻辑操作符 5.3 位操作符 5.3.1 bitset对象或整型值的使用 5.3.2 将移位操作符用于IO 5.4 赋值操作符 5.4.1 赋值操作的右结合性 5.4.2 赋值操作具有低优先级 5.4.3 复合赋值操作符 5.5 自增和自减操作符 5.6 箭头操作符 5.7 条件操作符 5.8 sizeof操作符 5.9 逗号操作符 5.10 复合表达式的求值 5.10.1 优先级 5.10.2 结合性 5.10.3 求值顺序 5.11 new和delete表达式 5.12 类型转换 5.12.1 何时发生隐式类型转换 5.12.2 算术转换 5.12.3 其他隐式转换 5.12.4 显式转换 5.12.5 何时需要强制类型转换 5.12.6 命名的强制类型转换 5.12.7 旧式强制类型转换 第6章 语句 6.1 简单语句 6.2 声明语句 6.3 复合语句(块) 6.4 语句作用域 6.5 if语句 6.6 switch语句 6.6.1 使用switch 6.6.2 switch中的控制流 6.6.3 default标号 6.6.4 switch表达式与case标号 6.6.5 switch内部的变量定义 6.7 while语句 6.8 for循环语句 6.8.1 省略for语句头的某些部分 6.8.2 for语句头中的多个定义 6.9 do while语句 6.10 break语句 6.11 continue语句 6.12 goto语句 6.13 try块和异常处理 6.13.1 throw表达式 6.13.2 try块 6.13.3 标准异常 6.14 使用预处理器进行调试 第7章 函数 7.1 函数的定义 7.1.1 函数返回类型 7.1.2 函数形参表 7.2 参数传递 7.2.1 非引用形参 7.2.2 引用形参 7.2.3 vector和其他容器类型的形参 7.2.4 数组形参 7.2.5 传递给函数的数组的处理 7.2.6 main:处理命令行选项 7.2.7 含有可变形参的函数 7.3 return语句 7.3.1 没有返回值的函数 7.3.2 具有返回值的函数 7.3.3 递归 7.4 函数声明 7.5 局部对象 7.5.1 自动对象 7.5.2 静态局部对象 7.6 内联函数 7.7 类的成员函数 7.7.1 定义成员函数的函数体 7.7.2 在类外定义成员函数 7.7.3 编写Sales_item类的构造函数 7.7.4 类代码文件的组织 7.8 重载函数 7.8.1 重载与作用域 7.8.2 函数匹配与实参转换 7.8.3 重载确定的三个步骤 7.8.4 实参类型转换 7.9 指向函数的指针 第8章 标准IO库 8.1 面向对象的标准库 8.2 条件状态 8.3 输出缓冲区的管理 8.4 文件的输入和输出 8.4.1 文件流对象的使用 8.4.2 文件模式 8.4.3 一个打开并检查输入文件的程序 8.5 字符串流
Effective C++(编程的50个细节) Effective C++(编程的50个细节)着重讲解了编写C++程序应该注意的50个细节问题,书中的每一条准则描述了一个编写出更好的C++的方式,每一个条款的背后都有具体范例支持,书中讲的都是C++的编程技巧和注意事项,很多都是自己平时不太注意但又很重要的内容,绝对经典,作者Scott Meyers是全世界最知名的C++软件开发专家之一。 电子书PDF格式下载:http://www.yanyulin.info/pages/2013/11/effective.html 1、从CC++ 条款1:尽量用CONST和INLINE而不用#DEFINE 条款2:尽量用而不用 条款3:尽量用NEW和DELETE而不用MALLOC和FREE 条款4:尽量使用C++风格注释 2、内存管理 条款5:对应的NEW和DELETE要采用相同的形式 条款6:析构函数里对指针成员调用DELETE 条款7:预先准备好内存不够的情况 条款8:写OPERATOR NEW与OPERATOR DELETE要遵循常规 条款9:避免隐藏标准形式的NEW 条款10:如果写了OPERATOR NEW就要同时写OPERATOR DELETE 条款11:为需要动态分配内存的类声明一个拷贝构造函数和一个赋值函数 条款12:尽量使用初始化而不要在构造函数里赋值 条款13:初始化列表中成员列出顺序和它们在类中的声明顺序相同 条款14:确定基类有虚析构函数 条款15:让OPERATOR=返回*THIS的引用 条款16:在OPERATOR=中对所有数据成员赋值 条款17:在OPERATOR=中检查给自已赋值的情况 3、类和函数:设计与声明 条款18:争取使类的接口完整并且最小 条款19:分清成员函数,非成员函数和友元函数 条款20:避免PUBLIC接口出现数据成员 条款21:尽可能使用CONST 条款22:尽量用传引用而不用传值 条款23:必须返回一个对象时不要试图返回一个引用 条款24:在函数重载与设定参数默认值间慎重选择 条款25:避免对指针与数字类型的重载 条款26:当心潜在的二义性 条款27:如果不想使用隐式生成的函数要显示的禁止它 条款28:划分全局名字空间 4、类和函数:实现 条款29:避免返回内部数据的句柄 条款30:避免这样的成员函数,其返回值是指向成员的非CONST指针或引用 条款31:千万不要返回局部对象的引用,也不要返回函数内部用NEW初始化的指针 条款32:尽可能推迟变量的定义 条款33:明智的使用INLINE 条款34:将文件间的编译依赖性阡至最低 5、继承与面向对象设计 条款35:使公有继承体现是一个的函义 条款36:区分接口继承与实现继承 条款37:绝不要重新定义继承而来的非虚函数 条款38:绝不要重新定义继承而来的缺省参数值 条款39:避免向下转换继承层次 条款40:通过分层来体现有一个和用...来实现 条款41:区分继承和模板 条款42:明智的使用私有继承 条款43:明智的使用多继承 条款44:说你想说的,理解你说的 6、杂项 条款45:弄清C++在幕后为你所写、所调用的函数 条款46:宁可编译与链接时出错,也不要运行时出错 条款47:确保非局部静态对象在使用前被初始化 条款48:重视编译器警告 条款49:熟悉标准库 条款50:提高对C++的认识

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值