day4.Express

  1. 初识express

    Express是基于node.js平台,快速、开放、极简的Web开发框架

    通俗理解:Express的作用相当于node.js的内置模块http,是专门用来创建web服务器的。

    Express本质:就是一个npm上的第三方包,提供了快速创建Web服务器的方法

    中文官网地址:https://www.expressjs.com.cn/

    http内置模块用起来比较复杂,开发效率低。而Express是基于内置的http模块进一步封装出来的,能够极大地提高开发效率

    1.Express能做什么?
    • Web网站服务器:专门对外提供Web网页资源的服务器
    • API接口服务器:专门对外提供API接口的服务器

    使用Expresse可以方便的创建Web网站服务器或者接口服务器

    2.Express使用
    1. 安装
      npm install express@4.17.1
      
    2. 创建基本的Web服务器
      // 引入第三方模块
      const express = require('express');
      
      // 创建服务器
      const app = express();
      
      // 启动服务器
      
      app.listen(80,()=>{
          console.log("Express server is running !")
      })
      
    3. 监听GET/POST请求

      可以通过app.get()方法,监听客户端的GET请求,

      可以通过app.post()方法,监听客户端的POST请求

      通过res.send()方法,把处理好的内容,发送给客户端

      app.get('/user', (req, res) => {
          // 调用express提供的res.send()方法,向客户端响应内容,可以是json对象,也可以是文本字符串
          res.send({ name: 'get', id: 20 })
      })
      app.post('/user', (req, res) => {
          res.send('post请求成功')
      })
      
    4. 获取URL中携带的查询参数

      通过req.querry对象,可以访问到客户端通过查询字符串的形式发送到服务器的参数

      app.get( ' / ', (req,res) => {
          // req.query 默认是一个空对象
          //客户端使用?name=zs&age=20这种查询字符串形式,发送到服务器的参数,
          //可以通过req.query对象访问到,例如:
          //req.query.name req.query.age
          console.log(req.query)
      })
      
    5. 获取URL中的动态参数

      通过req.params对象,可以访问到URL中,通过:匹配到动态参数

      // URL地址中,可以通过:参数名的形式,匹配动态参数值
      // 注意:这里的“/:id”是一个动态参数
      app.get('/user/:idd/:name',(req,res)=>{
          // req.params是动态匹配到的URL参数,默认空对象
          res.send(req.params);
          console.log(req.params)
      })
      
      
    6. 托管静态资源
      1. express.static()

        express提供了一个非常好用的函数,叫做express.static(),通过它,可以非常方便的创建一个静态资源服务器。例如,通过如下代码就可以将public目录下的图片、CSS文件、JavaScript文件对外开放访问:

        app.use(express.static('public'))
        

        注意:

        Express在指定的静态目录中查找文件,并对外提供资源的访问路径。因此,存放静态文件的目录名不会出现在URL中

      2.托管多个静态资源

      • 如果要托管多个静态资源目录,可以多次调用express.static()函数

      • 访问静态资源文件是,express.static()函数会根据目录的添加顺序查找所需的文件。

        // 调用express.static()提供对外访问的静态资源,参数为对外提供静态资源所在的文件夹
        app.use(express.static(path.join(__dirname,'./files')));
        app.use(express.static(path.join(__dirname,'./clock')));
        

      3.挂载路径前缀

      如果希望在托管的静态资源访问路径之前,挂载路径前缀,则可以使用如下的方式:

      app.use( ' /public', express.static( ' public '))
      

      现在,就可以通过带有“/public”前缀地址来访问了,例如:http://127.0.0.1/public/index.html

      app.use('/person',express.static(path.join(__dirname,'./files')));
      app.use('/public',express.static(path.join(__dirname,'./clock')));
      
    7. Nodemon

      在编写调试Node.js项目的时候,如果修改了项目的代码,需要频繁的手动关掉,然后重新启动,非常麻烦。

      现在我们可以使用nodemon(https://nodemon.io/)这个工具,它能够监听项目文件的变动,当代被修改后,nodemon会自动帮我们重启项目,极大方便了开发和调式。

      安装:在cmd中

      npm install -g nodemon
      
      1. 使用nodemon

        当基于Node.js编写了一个网站应用的时候,传统的方式,是运行node app.js命令,来启动项目。这样做的坏处是:代码一旦被修改了,就要关掉重启

        因此,将node命令替换为nodemon命令,使用nodemon app.js来启动项目。这样做的好处:源代码一旦被修改,会被nodemon监听到,从而自动重启

  2. express路由

    1. 概念

      在Express中,路由指的是客户端的请求服务器处理函数之间的映射关系

      Express中的路由分3部分组成,分别是请求类型、请求的URL地址、处理函数,格式如下:

      app.post/get(path,handle)//handle处理函数,path请求的url地址
      
    2. 路由匹配过程

      每当一个请求到达服务器之后,需要先经过路由的匹配,只有匹配成功之后,才会调用对应的处理函数。

      在匹配时,会按照路由的顺序进行匹配,如果请求的类型和请求的URL同时匹配成功,则Express会将这次请求,转交给对应的function函数进行处理。

在这里插入图片描述

  `路由匹配注意点`:

  1. 按照定义的先后顺序进行匹配
  2. 请求类型和请求的URL同时匹配成功,才会调用对应的处理函数
  1. 路由的使用
    // 1.引入第三方模块express
    const express = require('express')
    // 2.创建服务器实例
    const app = express()
    // 3.挂载路由
    app.get('/public',(req,res)=>{
        console.log('监听到get请求!')
        res.end('get 请求')
    })
    app.post('/person',(req,res)=>{
        console.log('监听到post请求')
        res.end('post请求')
    })
    // 4.运行服务器
    app.listen(80,()=>{
        console.log('服务器运行在http://127.0.0.1')
    })
    

    使用此方法,挂载多个路由会使代码十分冗余,因此诞生了模块化路由

  2. 模块化路由

    为了方便对路由进行模块化的管理,Express官方不建议将路由直接挂载到app上,而是推荐将路由抽离为单独的模块

    具体步骤如下:

    1. 创建路由模块对应的.js文件

    2. 调用express.Router()函数创建路由对象

    3. 向路由对象上挂载具体的路由

    4. 使用module.exports向外共享路由对象

      // 路由模块
      // 1.导入express模块
      const express = require('express');
      // 2.创建路由对象
      const Router = express.Router();
      // 3.挂在具体的路由
      Router.get('/public',(req,res)=>{
          let str = "Router对象映射到对应的处理函数,get"
          console.log(str)
          res.end(str);
      })
      Router.post('/person',(req,res)=>{
          let str = "Router对象映射到对应的处理函数,post"
          console.log(str)
          res.end(str);
      })
      // 4.向外暴露路由对象
      module.exports = Router;
      
    5. 使用app.use()函数注册路由模块

      // 3.1导入路由模块
      const router =  require('./03.router');
      // 3.2注册路由模块
      app.use(router);
      

      注:app.use()函数就是用来注册全局中间件

    6. 为路由模块添加前缀

      类似于托管静态资源时,为静态资源统一挂载访问前缀一样,路由模块添加统一添加前缀的方式如下:

      // 3.1导入路由模块
      const router =  require('./03.router');
      // 3.2注册路由模块
      //'/API'为所有的路由模块挂载统一的路由前缀
      app.use('/API',router);
      
  3. 常见的express 中间件

    1. 中间件的概念

      概念:中间件(middleware),特指业务流程的中间处理环节

    2. 中间件的调用流程

      当一个请求叨叨Express的服务器之后,可以连续调用多个中间件,从而对这次请求预处理

在这里插入图片描述

  1. Express中间件的格式

    Express的中间件,本质就是一个function处理函数,Express中间件的格式如下:
    在这里插入图片描述

    注:中间件函数的形参列表中,必须包含next参数。而路由器的处理函数中只包含req和res。即如果

  2. next函数的作用

    next()函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件路由

在这里插入图片描述

  1. 如何定义中间函数
    //常量mw所指向的,就是一个中间件函数
    const mw = function (req, res,next) {
    	console.log( '这是一个最简单的中间件函数')
    	//注意:在当前中间件的业务处理完毕后,必须调用next()函数
    	//表示把流转关系转交给下一个中间件或路由
    	next()
    }
    
  2. 全局生效的中间件

    客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效的中间件

    通过调动app.use(中间件函数),即可定义一个全局生效的中间件,具体如下:

    // 定义最简单的中间件函数
    const middleware = function(req,res,next){
        console.log('这是最简单的中间件函数')
        // 把流转关系转交给下一个中间件或路由
        next();
    }
    // 把middleware注册为全局生效的中间件
    app.use(middleware);
    

    全局中间件的简化形式:

    app.use((req,res,next)=>{
        console.log('这是定义全局中间件的简化形式')
        next()
    })
    

    中间件的作用:

    多个中间件之间**,共享同一份req和res。基于这样的特性,我们可以在上游的中间件中,统一为req或res对象添加自定义的属性或方法**,供下游的中间件或路由进行使用。

    定义多个连续的中间件

    可以使用app.use()

  3. 局部生效的中间件

    不使用app.use()定义的中间件,叫做局部生效的中间件,示列代码如下:

    //定义中间件函数 mw1
    const mw1 = function(req,res,next) {
        console.log( '这是中间件函数")
    	next()
    }
    // mN1这个中间件只在"当前路由中生效",这种用法属于"局部生效的中间件"
    app.get( ' /',mw1,function(req,res){
    	res.send( ' Home page. ')
    })
    //mw1这个中间件不会影响下面这个路由↓↓↓
    app.get( ' l/user 'function(req,res) { res.send( 'User page. ') )
    
    

    定义多个局部中间件:

    可以在路由中,通过如下的两种等价的方式,使用多个局部中间件:

    //以下两种写法是"完全等价"的,可根据自己的喜好,选择任意一种方式进行使用
    app.get( ' / ',mw1,mw2,(req,res) => { res.send( ' Home page. '))
    app.get( ' / ',[mw1,mw2],(req,res) => { res.send( ' Home page. ') )
    
    
  4. 中间件的使用的注意事项
    1. 一定要在路由之前去注册中间件
    2. 客户端发送过来的请求,可以连续调用多个中间件进行处理
    3. 执行完中间件的业务代码之后,不要忘记调用next(),转交流转关系
    4. 为了防止代码的逻辑混乱,调用next()函数后不要再写额外的代码。
    5. 连续调用多个中间件时,多个中间件之间,共享req和res对象
  5. 中间件的分类

    为了方便大家项目理解和记忆中间件的使用,Express官方把常见的中间件用法,分成了5大类,分别:

    注:除了错误级别的中间件,其他的中间件,必须在路由之前注册

    1. 应用级别的中间件

      通过app.use()app.get()app.post()绑定到app实例上的中间件,叫做应用级别的中间件,代码示例如下:

      //应用级别中间件(全局中间件)
      app.use((req,res,next)=>{
          console.log("调用全局中间件")
          next()
      })
      //应用级别中间件(局部中间件)
      app.get('/user',mw1,mw2,(req,res)=>{
          res.send('同时多个局部中间件')
      })
      
    2. 路由级别的中间件

      绑定到express.Router()实例上的中间件,叫做路由级别的中间件。它的用法和应用级别中间件没有任何区别。只不过,应用级别中间件是绑定到app实例上,路由级别的中间件是绑定到router实例上。示列代码如下:

      var app = express()
      var router = express.Routero
      //路由级别的中间件
      router.use(function (req, res, next) {
      console.log( "Time: " , Date.now())
      next()
      app.use( ' / ', router)
      
      
    3. 错误级别的中间件

      错误级别的中间件:专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题。

      格式:错误级别的中间的中间件的处理函数中,必须有4个参数,形参顺序从前到后,必须依次是(**err,**req,res,next)

      app.get('/',(req,res)=>{
          // 1.1人为制造错误
          throw new Error("服务内部发生了错误")
          res.send(" home page")
      })
      // 2.定义错误级别的中间件,捕获整个项目的异常错误,防止整个项目的崩溃
      app.use((err,req,res,next)=>{
          console.log("发生了错误:"+err.message)
          res.send('Error:'+err.message)
      })
      

      :错误级别的中间件,必须注册在所有的理由之后

    4. Express内置的中间件

      自Express4.16.0版本开始,Express内置了3个常用的中间件,极大的提高了Express项目的开发效率和体验:

      1. express.static快速托管静态资源的内置中间件,例如:HTML文件、图片、CSS样式等(不需要兼容,4.16.0之前也可以使用)

      2. express.json解析JSON格式的请求体数据(需要兼容,仅在4.16.0版本以上才行)

      3. express.urlencoded解析URL-encoded格式的请求体数据(需要兼容,仅在4.16.0版本以上可以使用)

        //配置解析application/json格式数据的内置中间件
        app.use(express.json())
        //配置解析 application/x-ww-form-urlencoded格式数据的内置中间件
        app.use(express.urlencoded({ extended: false }))
        
    5. 第三方的中间件

      非Express官方内置的,而是由第三方开发出来的中间件,叫做第三方中间件。在项目中,大家可以按需下载并配置第三方中间件,从而提高开发效率

      例如:在express@4.16.0之前的版本中,经常使用body-parser这个第三方中间件,来解析请求体的数据。使用步骤如下:

      1. 运行npm install body-parser安装中间件

      2. 使用require导入中间件

      3. app.use()注册并使用中间件

        // 1、导入解析表单数据的中间件body-parser
        const parser = require('body-parser')
        
        // 2.使用app.use()注册
        app.use(parser.urlencoded({extended:false}))
        app.post('/user', (req, res) => {
            // 如果没有配置任何解析表单数据中的中间件,则req.body默认等于undefind
            console.log(req.body)
            res.send('OK')
        })
        

      注:Express内置的express.urlencodeed中间件,就是基于body-parser这个第三方中间件进一步封装出来的。

    6. 自定义中间件

      eg:模拟类似于express.urlencoded这样的中间件,来解析Post请求体的数据,具体实现步骤:

      1. 定义中间件

      2. 监听req的data 事件监听req的end事件

        • 在中间件中,需要调用req对象的data事件,来获取客户端发送到服务器的数据。如果数据流比较大,无法一次性发送完毕,则**客户端会被数据切割偶,分批发送到服务器。**所以data 事件可能触发多次,因此需要手动对接收到的数据进行拼接。
      3. 使用querystring模块解析请求体数据

        当请求体数据接收完毕之后,会自动触发req的end事件。

        Nodejs 内置了一个querystring模块专门用来处理查询字符串。通过这个模块提供的parse()函数,可以轻松把查询字符串,解析成对象的格式。示例代码如下:

        //导入处理querystring的Node.js内置模块
        const qs = require( ' querystring ')
        //调用qs.parse()方法,把查询字符串解析为对象
        const body = qs.parse(str)
        
        
      4. 将解析出来的数据对象挂载为req.body

        // 3.监听req的end事件
            req.on('end',()=>{
                // 在str中已经存放的是完整的数据了
                const body = qs.parse(str);
                // console.log(body);
                req.body = body;
                next();
                // 3.1把字符串格式的请求体数据,解析成对象格式
            })
        
      5. 将自定义中间件封装为模块

        为了优化代码的结构,我们可以把自定义的中间件函数,封装为独立的模块,示例代码如下:

        // custom-body-parser.js横块中的代码
        const qs = require( ' querystring')
        function bodyParser(req,res,next){ /*省略其它代码*/ }
        module.exports = bodyParser//向外导出解析请求体数据的中间件函数
        ----------------------------------------------------------------
        // 1.导入自定义的中间件模块
        const myBodyParser = require( ' custom-body-parser ' )
        // 2.注册自定义的中间件模块
        app.use(myBodyParser)
        
        
  6. express创建API接口

    1. 创建基本的服务器
      // 导入express
      const express = require('express');
      // 创建一个服务器实例对象‘
      const app = express();
      // 导入路由模块
      const router = require('./14.RouterAPI.js');
      // 注册路由模块
      app.use('/api',router);
      // 启动服务器
      app.listen(80,()=>{
          console.log("server is running at http://127.0.0.1")
      })
      
    2. 创建路由模块
      //14.RouterAPI.js中
      const express = require('express');
      const router = express.Router();
      // 这里挂载对应的路由
      module.exports = router;
      
    3. 编写get接口
      router.get('/get',(req,res)=>{
          // 通过req.query获取客户端通过查询字符串,发送到服务器的数据
          const query = req.query;
          // 调用res.send()方法,向客户端响应处理的结果
          res.send({
              status:0,//0表示处理成功,1表示处理失败
              msg:'get请求成功',//状态的描述
              data:query//需要响应给客户端的数据
          })
      })
      
    4. 编写post接口

      注意:如果要获取URL-encoded格式的请求体数据,必须配置中间件 app.use(express.urlencoded({extended: false })

      // 定义post接口
      router.post('/post',(req,res)=>{
          // 通过req.body获取请求体包含url-encoded格式的数据
          const body = req.body;
          // 调用res.send()方法下个客户端响应结果
          res.send({
              status:0,
              msg:"post请求",
              data:body
      
          });
      })
      
  7. express中启用cors跨域资源共享

    1. 接口的跨域问题(不同协议file、http之间的数据联通)

      以上4中编写的post和get接口,存在一个严重的问题:不支持跨域请求

      解决接口跨域问题的方案主要有两种:

      1. CORS(主流的解决方案,推荐使用)
      2. JSONP(有缺陷的方案:只支持GET请求)
    2. 使用CORS中间件解决跨域问题

      cors是Express的第三方中间件。通过安装和配置cors中间件,可以很方便地解决跨域问题。

      使用步骤如下:

      1. 安装中间件:npm install cors

      2. 使用下面命令,导入中间件

         const cors = requie('cors');
        
      3. 在路由之前调用app.usr(cors())配置中间件

    3. CORS的含义

      CORS (Cross-Origin Resource Sharing,跨域资源共享)由一系列HTTP响应头组成,这些HTTP响应头决定浏览器是否阻止前端JS代码跨域获取资源
      浏览器的同源安全策略默认会阻止网页“跨域”获取资源。但如果接口服务器配置了CORS相关的HTTP响应头,就可以解除浏览器daunt的跨域访问限制。

在这里插入图片描述

  `注:`

  1. CORS主要在服务端进行配置,客户端无须做任何的额外配置,即可请求看起了CORS的接口。
  2. CORS在浏览器中有兼容性。只有支持XMLHttpRequest Level2的浏览器,才能正常访问开启了CORS的服务器端口(如:IE10+,Chrome 4+,FireFox 3.5+)
  1. CORS的响应头部
    • Access-Control-Allow-Origin

      响应头部中可以携带一个Access-Control-Allow-Origin字段,其语法如下:

      Access-Control-Allow-origin: <origin> |*
      

      其中,origin参数的值指定了允许访问的该资源的外域URL。

      例如,下面的字段值将只允许来自http://itcast.cn的请求:

      res.setHeader( ' Access-Control-Allow-origin', 'http:/litcast.cn' )
      

      如果指定了Access-Control-Allow-Origin字段的值为通配符*,表示允许来自任何域的请求,示列代码如下:

      res.setHeader('Access-Control-Allow-Origin','*')
      
    • Access-Control-Allow-Header

      默认情况下,CORS支持客户端向服务器发送如下的9个请求头

      Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width ,Content-Type(值仅限于text/plain、multipart/form-data、application/x-www-form-urlencoded三者之一)

      如果客户端向服务器发送了额外的请求头信息,则需要在服务端,通过Access-Control-Allow-Header对额外的请求头进行声明,否则这次请求会失败!

      //允许客户端额外向服务器发送Content-Type请求头和X-Custom-Header请求头
      //注意:多个请求头之间使用英文的逗号进行分割
      res.setHeader ( ' Access-Control-Allow-Headers ''Content-Type,X-Custom-Header ')
      
      
    • Access-Control-Allow-Methods

      默认情况下,CORS仅支持客户端发起GET、POST、HEAD请求

      如果客户端希望通过PUT****、DELEFT等方式请求服务器的资源,则需要在服务器端,通过Access-Control-Alow-Methods来指明实际请求所允许使用的HTTP方法。

      //只允许POST、GET、DELETE、HEAD请求方法
      res.setHeader( ' Access-Control-Allow-Methods ','POST,GET,DELETE,HEAD')
      //允许所有的 HTTP请求方法
      res.setHeader( 'Access-Control-Allow-Methods ','*')
      
  2. CORS请求的分类

    客户端在请求CORS接口时,根据请求方式请求头的不同,可以将CORSDE请求分为两大类,分别是:

    • 简单请求
    • 预检请求
    1. 简单请求

      同时满足以下两大条件的请求,就属于简单请求:

      • 请求方式:GET、POST、HEAD三者之一
      • HTTP头部信息不超过以下几种字段:无自定义头部字段、Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type(只有三个值application/x-www-form-urlencoded、multipart/form-data、text/plain)
    2. 预检请求

      只要符合以下任何一个条件的请求,都需要进行预检请求:

      • 请求方式为GET、POST、HEAD之外的请求Method类型
      • 请求头中包含自定义头部字段
      • 向服务器发送了application/json格式的数据

      在浏览器与服务器正式通信之前,浏览器会先发送OPTION请求进行预检,以获悉服务器是否允许该实际请求,所以这一次的OPTION请求成为“预检请求”。服务器成功响应

      预检请求后,才会发送真正的请求,并且携带真实数据。

    3. 简单请求和预检请求的区别

      简单请求的特点:客户端与服务器之间只会发生一次请求

      预检请求的特点:客户端与服务器之间会发生两次请求,OPTION预检请求成功之后,才会发起真正的请求

  3. JSONP接口

    定义:浏览器通过<script>标签的src属性,请求服务器上的数据,同时,服务器返回一个函数的调用,这种请求数据的方式叫做JSONP。

    特点:

    1. JSONP不属于真正的Ajax请求,因为它没有使用XMLHttpRequest这个对象。
    2. JSONP仅支持GET请求,不支持POST、PUT、DELETE等请求

    如果项目已经配置了CORS跨域资源共享,为了防止冲突,必须在配置CORS中间件之前声明JSONP的接口。否则JSONP接口会被处理成开启了CORS的接口。示列代码如下:

    //优先创建JSONP接口【这个接口不会被处理成CORS接口】
    app.get( ' lapi/jsonp ', (req, res)=>{ })
    //再配置 CORS 中间件【后续的所有接口,都会被处理成CORS 接口】
    app.use( cors())
    //这是一个开启了CORS 的接口
    app.get( ' lapi/get ' , (req,res)=>{ )
    

实现JSONP接口的步骤

  1. 获取客户端发送过来的回调函数的名字

  2. 得到要通过JSONP形式发送给客户端的数据

  3. 根据前两步得到的数据,拼接出一个函数调用的字符串

  4. 把上一步拼接得到的字符串,响应给客户端<script>标签进行解析执行

    // 必须在配置CORS之前配置JSONP的接口
    app.get('/api/json',(req,res)=>{
        // TODO:定义JSONP接口实现的具体过程
        // 1.得到函数的名称
        const functionName = req.query.callback;
        // 2.定义要发送到客户端的数据对象
        const data = {name:'zs',age:22}
        // 3.拼接出一个函数的调用
        const scriptStr = `${functionName}(${JSON.stringify(data)})`
        // 4.把拼接的字符串响应给客户端
        res.send(scriptStr);
    })
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++ defines a class DateV3 with the following: private member variables: int year, month, day; Has three constructors and one destructor as follows: The first constructor takes three parameters, int y, int m, int n; The second is the copy constructor that takes a DateV3 object as the parameter; The third is the default constructor that takes no parameter; The destructor takes no parameter. (3) Has overloaded operators: int operator-(DateV3 & oneDate); // return difference in days between the calling object and oneDate DateV3 operator+(int inc); // return a Date object that is inc days later than the calling object DateV3 operator-(int dec); // return a Date object that is dec days earlier than the calling object DateV3 operator++(); // overload the prefix ++ operator DateV3 operator++(int); // overload the postfix ++ operator friend ostream& operator<< (ostream& outputStream, DateV3& theDate); // overload the << operator Test class DateV3 in the main function as follows: Declare and initialize an object to represent today, which should be the date that you work on this assignment.Declare and initialize an object to represent your OWN birthday.Express John’s birthday given John is 5 days older than yours. Create Tom’s birthday by using the copy constructor, assuming Tom has the same birthday as you. Display how many days have passed since your birth, John’s birth, and Tom’s birth, respectively. Create an DateV3 object, someday, by cloning Tom’s birthday. Increment someday by the prefix operator ++ once, and by postfix operator ++ once.Display someday, today, your birthday, John’s birthday, and Tom’s birthday. Declare a DateV3 object to represent 28 February 2024, display it, apply the prefix ++ operator on it, display it again, and apply the postfix ++ operator on it and display it again.
06-12

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值