注释转换(c注释->c++注释)

前言:本篇文章介绍了一个基于各类文件操作函数的一个小项目“注释转换”,功能是将C风格的注释装换成C++风格的注释,当然对于C++风格的注释装换C风格的注释原理是一样的。本篇博文里所用到的一些文件操作函数在我的上一篇博文(输入/输出函数总结)里有详细介绍。

项目介绍

本项目基于一个状态机的思想,每次处理完成之后通过状态的装换继续处理后边的内容。另外,利用各类的文件操作函数,实现将将C风格的注释装换成C++风格的注释的一个简单功能。大概如下图:
这里写图片描述

什么是状态机?

一个极度确切的描述是它是一个有向图形,由一组节点和一组相应的转移函数组成。状态机通过响应一系列事件而“运行”。每个事件都在属于“当前” 节点的转移函数的控制范围内,其中函数的范围是节点的一个子集。函数返回“下一个”(也许是同一个)节点。这些节点中至少有一个必须是终态。当到达终态, 状态机停止。(百度摘抄)

在本项目中,会用到四种状态,既空状态(正常代码区)、c注释状态(c风格注释区)、c++注释状态(c++风格注释区)、文件结束状态(EOF),下面是四种状态的装换图:
这里写图片描述

因为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*/

参考代码

CommentCovert.h

    #ifndef __COMMENTCOVERT_H__
    #define __COMMENTCOVERT_H__

    enum status
    {
        END_STATUS,
        NUL_STATUS,
        C_STATUS,
        CPP_STAUS
    };
    #include<stdio.h>
    #include<stdlib.h>
    #pragma warning(disable:4996)

    void CommentCovert(FILE *pfIn, FILE *pfOut);
    void DoNulStaus(FILE *pfIn, FILE *pfOut, enum status *ps);
    void DoCStaus(FILE *pfIn, FILE *pfOut, enum status *ps);
    void DoCppStaus(FILE *pfIn, FILE *pfOut, enum status *ps);


    #endif //__COMMENTCOVERT_H__
CommentCovert.c

    //为了方便理解,下面的代码存在向原状态装换的过程,这是不必要的,已经注释掉。
    #include"CommentCovert.h"

    //正常代码处理
    void DoNulStaus(FILE *pfIn, FILE *pfOut, enum status *ps)
    {
        int first = fgetc(pfIn);
        switch (first)
        {
        case '/':
        {
                    int second = fgetc(pfIn);
                    switch (second)
                    {
                    case'*':
                    {
                               fputc('/', pfOut);
                               fputc('/', pfOut);
                               *ps = C_STATUS;
                    }
                        break;
                    case'/':
                    {
                               fputc(first, pfOut);
                               fputc(second, pfOut);
                               *ps = CPP_STAUS;
                    }
                        break;
                    default:
                    {
                               fputc(first, pfOut);
                               fputc(second, pfOut);
                               /**ps = NUL_STATUS;*/
                    }
                        break;
                    }
        }
            break;
        case EOF:
        {
                    fputc(first, pfIn);
                    *ps = END_STATUS;
        }
            break;
        default:
        {
                   fputc(first, pfOut);
                   /**ps = NUL_STATUS;*/
        }
            break;
        }
    }
    //c风格代码注释区处理
    void DoCStaus(FILE *pfIn, FILE *pfOut, enum status *ps)
    {
        int first = fgetc(pfIn);
        switch (first)
        {
        case'*':
        {
                   int second = fgetc(pfIn);
                   switch (second)
                   {
                   case'/':
                   {
                              int third = fgetc(pfIn);
                              if (third != '\n')
                              {
                                  fseek(pfIn, -1, SEEK_CUR);
                                  //如果third不是'\n',那个字符已经被读走,应该把那个字符还回去在放一个'\n'
                                  fputc('\n', pfOut);
                              }
                              else
                              {
                                  fputc(third, pfOut);
                              }
                              *ps = NUL_STATUS;
                   }
                       break;
                   case'*':
                   {
                              fputc(first, pfOut);
                              fseek(pfIn, -1, SEEK_CUR);
                              /**ps = C_STATUS;*/
                              //把fp指针移动到离文件当前位置-1字节处,回退1个字符
                              //因为第二个字符如果是*要和/一起判断是否是C语言注释风格结束
                   }
                       break;
                   default:
                   {
                              fputc(first, pfOut);
                              fputc(second, pfOut);
                              /**ps = C_STATUS;*/
                   }
                       break;
                   }
        }
            break;
        case'\n':
        {
                    fputc(first, pfOut);
                    fputc('/', pfOut);
                    fputc('/', pfOut);
                    /**ps = C_STATUS;*/
        }
            break;
        default:
        {
                   fputc(first, pfOut);
                   /**ps = C_STATUS;*/
        }
            break;
        }
    }
    //c++风格代码注释区处理
    void DoCppStaus(FILE *pfIn, FILE *pfOut, enum status *ps)
    {
        int first = fgetc(pfIn);
        switch (first)
        {
        case'\n':
        {
                    fputc(first, pfOut);
                    *ps = NUL_STATUS;
        }
            break;
        case EOF:
            fputc(first, pfOut);
            *ps = END_STATUS;
            break;
        default:
            fputc(first,pfOut);
            /**ps = CPP_STAUS;*/
            break;
        }
    }
fseek的简单理解

    SEEK_SET: 文件开头
    SEEK_CUR: 当前位置
    SEEK_END: 文件结尾
    其中SEEK_SET,SEEK_CUR和SEEK_END依次为012
    例如:
    fseek(fp,100L,0);把stream指针移动到离文件开头100字节处;
    fseek(fp,100L,1);把stream指针移动到离文件当前位置100字节处;
    fseek(fp,-100L,2);把stream指针退回到离文件结尾100字节处。
test.c

        #include"CommentCovert.h"

    void CommentCovert(FILE *pfIn, FILE *pfOut)
    {
        enum status status = NUL_STATUS;
        while (status != END_STATUS)
        {
            switch (status)
            {
            case NUL_STATUS:
                DoNulStaus(pfIn, pfOut, &status);
                break;
            case C_STATUS:
                DoCStaus(pfIn, pfOut, &status);
                break;
            case CPP_STAUS:
                DoCppStaus(pfIn, pfOut, &status);
                break;
            default:
                break;
            }
        }
    }
    int main()
    {
        FILE *pfIn = NULL;
        FILE *pfOut = NULL;
        pfIn = fopen("input.c", "r");
        if (pfIn == NULL)
        {
            perror("use file to read");
            exit(EXIT_FAILURE);
        }
        pfOut = fopen("output.c", "w");
        if (pfOut == NULL)
        {
            perror("use file to write");
            fclose(pfIn);
            pfIn = NULL;
            exit(EXIT_FAILURE);
        }
        //注释转换
        CommentCovert(pfIn, pfOut);

        fclose(pfIn);
        pfIn = NULL;
        fclose(pfOut);
        pfOut = NULL;

        return 0;
    }

源代码:CommentCovert

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include "mylogin.h" mylogin::mylogin(QWidget *parent) : QDialog(parent) { this->init_ui(); connect(this->bnt_login, &QPushButton::clicked, this, &mylogin::do_login); connect(this->bnt_register, &QPushButton::clicked , this ,&mylogin::do_enroll); } mylogin::~mylogin() { } void mylogin::init_ui() { this->setFixedSize(QSize(600,350)); this->setWindowTitle(tr("岑超升")); this->setWindowIcon(QIcon(":/src/1.png")); this->lb1 = new QLabel(); this->lb2 = new QLabel(); this->lb3 = new QLabel(); this->lb1->setFixedSize(QSize(560,200)); QPixmap pic; pic.load(":/src/2.png"); //this->lb1->setPixmap(pic.scaled(this->lb1->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); this->lb1->setPixmap(QPixmap(":/src/2.png")); this->lb2->setText(tr("用户名:")); this->lb3->setText(tr("密 码:")); this->usr_name_le = new QLineEdit(); //这两个参数后面传入信号中去,然后emit发射出去 this->usr_pass_le = new QLineEdit(); this->usr_pass_le->setEchoMode(QLineEdit::Password); this->bnt_login = new QPushButton(tr("登 陆")); this->bnt_register = new QPushButton(tr("注 册")); this->hb1 = new QHBoxLayout(); this->hb2 = new QHBoxLayout(); this->hb3 = new QHBoxLayout(); this->hb1->addWidget(this->lb2); this->hb1->addWidget(this->usr_name_le); this->hb2->addWidget(this->lb3); this->hb2->addWidget(this->usr_pass_le); this->hb3->addWidget(this->bnt_login); this->hb3->addWidget(this->bnt_register); this->vb1 = new QVBoxLayout(); this->vb1->addWidget(this->lb1); this->vb1->addLayout(this->hb1); this->vb1->addLayout(this->hb2); this->vb1->addLayout(this->hb3); this->setLayout(this->vb1); } void mylogin::do_login() { emit sig_login(usr_name_le->text(), usr_pass_le->text()); //需要把这里输入的账号密码信息发送到myapp那去,用到的函数是emit //需要自定义一个信号,sig_login //这个槽函数能够发出信号 } void mylogin::do_enroll() { emit sig_enroll(); }用C++语言解释并注释每行代码,并说明他们的功能和作用
06-09

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值