Qt+QtWebApp开发笔记(二):http服务器日志系统介绍、添加日志系统至Demo测试

前言

  上一篇使用QtWebApp的基于Qt的轻量级http服务器实现了一个静态网页返回的Demo,网页服务器很重要的就是日志,因为在服务器类上并没有直接返回,所以,本篇先把日志加上。

 

Demo

  在这里插入图片描述

下载地址

  链接:http://pan.baidu.com/s/1BPVRLS07qk-WPi-txERKbg?pwd=1234

 

日志系统

生产环境需要查看旧的日志消息,例如两天前的日志消息。

  可以简单地将输出重定向到一个文件(MyFirstWebApp>logfile.txt),但这有两个问题:

  • 在许多系统上,输出重定向有些慢。
  • 日志文件将变得无限大,如果不短时间停止web服务器,就无法防止这种情况发生。

  因此,最好让web服务器自己将所有消息写入文件。这就是记录器模块的作用。
  要将日志模块的源代码包括到项目中,请在项目文件中添加一行:

include(../QtWebApp/QtWebApp/logging/logging.pri)

  这个而模块也是QtWebApp的logging模块,如下:
  在这里插入图片描述
  然后在程序的*.ini文件中添加另一个部分:

[logging]
minLevel=WARNING
bufferSize=100
fileName=../logs/webapp1.log
maxSize=1000000
maxBackups=2
timestampFormat=dd.MM.yyyy hh:mm:ss.zzz
msgFormat={timestamp} {typeNr} {type} {thread} {msg}

  日志级别有:DEBUG(别名ALL)、INFO、WARN或WARNING、CRITICAL(别名ERROR)、FATAL。信息级别由Qt 5.5引入。
  上面的示例配置启用线程本地缓冲区,**这些缓冲区将不太重要的消息保留在内存中,直到出现警告或严重错误。**然后,错误消息与收集到的低级消息一起写入日志文件。只要一切正常,使用缓冲区可以大大减少日志文件的大小。像这样的系统操作员。
  但是,缓冲区的内存和性能成本都很高。收益通常大于成本。要禁用缓冲区,请将bufferSize设置为0。在这种情况下,只有配置了minLevel及以上级别的消息才会写入日志文件。
  如果没有指定文件名,则记录器会写入控制台。日志文件的路径可以是绝对路径,也可以是相对于配置文件的文件夹的路径。maxSize参数限制日志文件的大小(以字节为单位)。当超过此限制时,记录器将启动一个新文件。设置maxBackups指定磁盘上应保留多少旧日志文件。
  时间戳格式设置的作用。QDateTime::toString()的文档以获得对字符的解释,还有更多可用的内容。msgFormat设置指定每条消息的格式。以下字段可用:

  • {timestamp}:创建日期和时间
  • {typeNr}:数字格式的消息类型或级别(0=DEBUG, 4=INFO, 1=WARNING, 2=CRITICAL, 3=FATAL)
  • {type}:字符串格式的消息类型或级别(DEBUG, INFO, WARNING, CRITICAL, FATAL)
  • {thread}:线程的ID号
  • {msg}:消息文本
  • {xxx}:可以自己定义的任何记录器变量QT 5.0及更新版本在调试模式下有一些附加变量:
{file}:Filename of source code where the message was generated
{function}:Function where the message was generated
{line}:Line number where the message was generated

  Qt开发人员将这三个字段添加到他们的框架中。也可以使用\n在消息格式中插入换行符和插入  制表符。上述所有变量也可以在日志消息中使用,例如:

qCritical("An error occured in {file}: out of disk space");

  需要一个指向FileLogger实例的全局指针,以便整个程序都可以访问它。首先添加到global.h:

#include "httpessionstore.h"
#include "staticfilecontroller.h"
#include "templatecache.h"
#include "filelogger.h"

using namespace stefanfrings;

/** Storage for session cookies */
extern HttpSessionStore* sessionStore;

/** Controller for static files */
extern StaticFileController* staticFileController;

/** Cache for template files */
extern TemplateCache* templateCache;

/** Redirects log messages to a file */
extern FileLogger* logger;

#endif // GLOBAL_H

  global.cpp:

#include "global.h"

HttpSessionStore* sessionStore;
StaticFileController* staticFileController;
TemplateCache* templateCache;
FileLogger* logger;

  在main.cpp中,配置FileLogger的实例:

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    QString configFileName=searchConfigFile();

    // Configure logging
    QSettings* logSettings=new QSettings(configFileName,QSettings::IniFormat,&app);
    logSettings->beginGroup("logging");
    logger=new FileLogger(logSettings,10000,&app);
    logger->installMsgHandler();

    // Log the library version
    qDebug("QtWebApp has version %s",getQtWebAppLibVersion());

    // Session store
    QSettings* sessionSettings=new QSettings(configFileName,QSettings::IniFormat,&app);
    sessionSettings->beginGroup("sessions");
    sessionStore=new HttpSessionStore(sessionSettings,&app);

    // Static file controller
    QSettings* fileSettings=new QSettings(configFileName,QSettings::IniFormat,&app);
    fileSettings->beginGroup("files");
    staticFileController=new StaticFileController(fileSettings,&app);

    // Configure template cache
    QSettings* templateSettings=new QSettings(configFileName,QSettings::IniFormat,&app);
    templateSettings->beginGroup("templates");
    templateCache=new TemplateCache(templateSettings,&app);

    // HTTP server
    QSettings* listenerSettings=new QSettings(configFileName,QSettings::IniFormat,&app);
    listenerSettings->beginGroup("listener");
    new HttpListener(listenerSettings,new RequestMapper(&app),&app);

    return app.exec();
}

  数字10000是以毫秒为单位的刷新间隔,记录器使用它来重新加载配置文件。因此,可以在程序运行时编辑任何记录器设置,并且更改在几秒钟后生效,而无需重新启动服务器。如果不希望自动重新加载,请使用值0。
  给了一个示例代码,用于查询和记录库的版本号。一些人要求添加该功能。
不要忘记创建一个空文件夹MyFirstWebApp/logs。记录器本身不会创建文件夹。
  现在可以启动应用程序并查看会发生什么。因为程序没有错误,所以日志文件保持为空。但  可以看到控制台窗口中的输出已降至最低:
  在这里插入图片描述

  让在logincontroller.cpp中插入一条qCritical()消息,然后可以看到日志缓冲区工作:
  然后打开URLhttp://localhost:8080/login?username=test&password=wrong.
  再次查看日志文件,它就在那里:
  在这里插入图片描述

  现在通过将min Level降低到DEBUG来进行另一个测试。保存ini文件,等待10秒,然后打开URLhttp://localhost:8080/hello.再次检查日志文件。可以看到,尽管没有发生错误,但现在所有的调试消息都已写入。因此,在不重新启动程序的情况下更改日志级别可以很好地工作。
  在这里插入图片描述

  其实这个很容易看出来,是直接对qt的几个日志等级进行了(PS:这个日志库还不错,installMsgHandler可以截断qDebug等相关的错误信息,可以直接无缝使用到每一个qt项目中,有这个兴趣可以试一试)。
  在这里插入图片描述

 

记录器变量

  写到记录器支持用户定义的变量。这些变量是线程本地的,在清除它们之前一直保留在内存中。对于web应用程序,在每条消息中记录当前用户的名称可能很有用。向requestmapper.cpp添加代码以设置记录器变量:

void RequestMapper::service(HttpRequest& request, HttpResponse& response) {
    QByteArray path=request.getPath();
    qDebug("RequestMapper: path=%s",path.data());
    HttpSession session=sessionStore->getSession(request,response,false);
    QString username=session.get("username").toString();
    logger->set("currentUser",username);
    ...
}

  通过这种方式,请求映射器在将请求传递给控制器类之前,为所有传入的HTTP请求查询调用用户的名称。
  现在可以修改ini文件以使用该变量:

msgFormat={timestamp} {typeNr} {type} {thread} User:{currentUser} {msg}

  运行程序并打开URLhttp://localhost:8080/login?username=test&password=hello两次。然后再次检查日志文件:
  在这里插入图片描述

  在用户登录之前,可以看到变量{currentUser}为空。然后,所有以下请求都会以该用户的名称记录。
  注意:在RequestMapper类中放置了许多静态资源(logger、sessionStore、staticFileController、templateCache)。在实际应用程序中,建议创建一个单独的类,例如名称为“Globals”的类,这样每个人都知道在哪里可以找到这样的资源。或者按照在Demo1项目中的例子,将它们放在任何类之外的cpp源文件中。

日志缓冲区和线程池

  由于线程被重新用于后续的HTTP请求,记录器可能会输出更多的细节。例如,假设第一个成功的HTTP请求会产生一些隐藏的调试消息,然后由同一线程处理的第二个请求会产生错误。然后,日志文件将包含错误消息以及所有缓冲的调试消息。但其中一些来自以前的HTTP请求,并不需要它。
  要清除两个HTTP请求之间的缓冲区,请添加到requestmapper.cpp:

void RequestMapper::service(HttpRequest& request, HttpResponse& response) {
    ...
    else {
        response.setStatus(404,"Not found");
        response.write("The URL is wrong, no such document.");
    }

    qDebug("RequestMapper: finished request");
    logger->clear(true,true);
}

  因此,每当HTTP请求的处理完成时,都要清理记录器的内存。当同一个线程处理下一个请求时,它将以空缓冲区开始。(碰到错误则会输出到文件,所以一个http请求完成了,就是其前面的日志都是无错误,所以可以清空了)。

双文件记录器

  该项目还包含一个DualFileLogger类,可用于并行生成两个日志文件。这可能对以下设置组合有用:

  • 主记录日志文件
minLevel=INFO
bufferSize=0
  • 第二日志文件
minLevel=ERROR (or WARNING)
bufferSize=100

  这样,主日志文件就不包含调试消息。但是,当发生错误时,辅助日志文件会包含该错误以及多达100条相关的调试消息。如果错误消息本身无法识别问题原因,则此文件特别有用。

总结

  这个日志logging模块起到的最大作用,是因为在QtWebApp三方源码中的qDebug,qWarn,QFatal等相关系统直接输出到控制台的,使用该日志则截断才可以获取httpervice模块以及其他模块中的打印调试信息,而这些信息是在函数返回值中没有体现的。
  为了能查看到三方模块日志,则必须要使用logging模块,或者自己写一个模块去截断,或者直接修改三方源码中的调试信息的代码。
  使用httpervice肯定是最好使用logging模块了。

 

Demo增量:添加logging日志模块

步骤一:准备代码模板

  准备之前的demo模板:
  在这里插入图片描述

步骤二:拷贝logging模块

  将QtWebApp中的logging,符合模块化设计准则,如下图:
  在这里插入图片描述

  拷贝到的Demo
  在这里插入图片描述

  添加模块进入工程:

# logging模块,QtWebApp自带的三方模块
include ($$PWD/modules/logging/logging.pri)

  在这里插入图片描述
  第三方的模块。

步骤三:添加配置logging的配置文件

  先把上一篇的Demo配置文件加了listener之后就读不出的问题解决了,其实区别关键在下面:
  在这里插入图片描述

  beginGroup就是进入了这一组,这一组拿到key就可以不带前缀。
  在这里插入图片描述

  然后开始添加日志配置,也在httpServerManager,因为配置文件beginGroup之后就是操作单独一组了,这里从第三方源码中也可以看出来:
  在这里插入图片描述

  本次加入logging,也要进行配置文件分组的区分,原来的_pSettings改成_pHttpListenerSettings,然后新增_pLoggingListenerSettings用于配置logging模块的配置实例:

步骤四:新增logging日志代码

  在这里插入图片描述

  在这里插入图片描述

  在这里插入图片描述

步骤五:运行结果

   在这里插入图片描述
  至此,日志加入成功

步骤六:日志配置调整

  在这里插入图片描述

  修改下日志时间:
  在这里插入图片描述

  记录日志则是:
  在这里插入图片描述

 

Demo源码

HttpServerManager.h

#ifndef HTTPSERVERMANAGER_H
#define HTTPSERVERMANAGER_H

#include <QObject>
#include <QMutex>

#include "httplistener.h"
#include "filelogger.h"

#include "HelloWorldRequestHandler.h"

class HttpServerManager : public QObject
{
    Q_OBJECT
private:
    explicit HttpServerManager(QObject *parent = 0);

public:
    static HttpServerManager *getInstance();

public slots:
    void slot_start();                              // 开启线程
    void slot_stop();                               // 停止线程

private:
    static HttpServerManager *_pInstance;
    static QMutex _mutex;

private:
    bool _running;                                  // 运行状态

private:
    HttpListener *_pHttpListener;                   // http服务监听器
    QSettings *_pHttpListenerSettings;              // http服务器配置文件

    FileLogger *_pFileLogger;                       // 日志记录
    QSettings *_pFileLoggerSettings;                // 日志配置文件

private:
    QString _ip;                // 服务器监听ip(若为空,则表示监听所有ip)
    quint16 _port;              // 服务器监听端口
    int _minThreads;            // 空闲最小线程数
    int _maxThreads;            // 负载最大线程数
    int _cleanupInterval;       // 空线程清空间隔(单位:毫秒)
    int _readTimeout;           // 保持连接空载超时时间(单位:毫秒)
    int _maxRequestSize;        // 最大请求数
    int _maxMultiPartSize;      // 上载文件最大数(单位:字节)
};


#endif // HTTPSERVERMANAGER_H

HttpServerManager.cpp

#include "HttpServerManager.h"
#include <QApplication>

#include <QDir>

#include <QDebug>
#include <QDateTime>
//#define LOG qDebug()<<__FILE__<<__LINE__
//#define LOG qDebug()<<__FILE__<<__LINE__<<__FUNCTION__
//#define LOG qDebug()<<__FILE__<<__LINE__<<QThread()::currentThread()
//#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd")
#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")

HttpServerManager *HttpServerManager::_pInstance = 0;
QMutex HttpServerManager::_mutex;

HttpServerManager::HttpServerManager(QObject *parent)
    : QObject(parent),
      _pHttpListener(0),
      _pHttpListenerSettings(0),
      _pFileLogger(0),
      _pFileLoggerSettings(0),
      _running(false),
      _port(8088),
      _minThreads(2),
      _maxThreads(10),
      _cleanupInterval(60000),
      _readTimeout(60000),
      _maxRequestSize(100),
      _maxMultiPartSize(1024*1024*1024)
{

}

HttpServerManager *HttpServerManager::getInstance()
{
    if(!_pInstance)
    {
        QMutexLocker lock(&_mutex);
        if(!_pInstance)
        {
            _pInstance = new HttpServerManager();
        }
    }
    return _pInstance;
}

void HttpServerManager::slot_start()
{
    if(_running)
    {
        LOG << "It's running!!!";
        return;
    }
    _running = true;
    LOG << "Succeed to run";

    QString httpServerPath = QString("%1/etc/httpServer.ini").arg(qApp->applicationDirPath());
    LOG << httpServerPath << "exit:" << QFile::exists(httpServerPath);

    // 启动日志几里路
    {
        if(!_pFileLoggerSettings)
        {
            _pFileLoggerSettings = new QSettings(httpServerPath, QSettings::IniFormat);
        }
        _pFileLoggerSettings->beginGroup("logging");

        // 日志不会主动创建文件夹,这里需要补全
        {
            QFileInfo fileInfo(httpServerPath);
            QString dirPath = fileInfo.dir().absolutePath();
            dirPath = QString("%1/%2")
                    .arg(dirPath)
                    .arg(_pFileLoggerSettings->value("fileName").toString());
            dirPath = dirPath.mid(0, dirPath.lastIndexOf("/"));
            QDir dir;
            dir.mkpath(dirPath);
        }
        _pFileLogger = new FileLogger(_pFileLoggerSettings);
        _pFileLogger->installMsgHandler();
    }

    // 启动http的监听
    {
        if(!_pHttpListenerSettings)
        {
            _pHttpListenerSettings = new QSettings(httpServerPath, QSettings::IniFormat);
        }
        _pHttpListenerSettings->beginGroup("listener");
        _pHttpListener = new HttpListener(_pHttpListenerSettings, new HelloWorldRequestHandler);
    }
    LOG;
}

void HttpServerManager::slot_stop()
{
    if(!_running)
    {
        LOG <<"It's not running!!!";
        return;
    }
    _running = false;
    LOG << "Succeed to stop";
}
 

工程模板v1.1.0

  在这里插入图片描述

 

入坑

入坑一:日志一直不出来

问题

  日志一直不出来

原因

  在这里插入图片描述

  日志log文件的路径是基于ini配置文件的相对路径

解决

  在这里插入图片描述

本文转载于网络 如有侵权请联系删除

相关文章

  • 创新or炒作?低代码是真神器还是伪风口?

    受疫情影响,很多企业原有的商业化模式、协作模式、研发模式都受到了一定冲击,特别是对于部分中小企业,是一次不小的考验,在此背景下,支持“可视化拖拉拽+写少量代码”、成本更低的低代码开发模式,开始进入大众的视野。低代码自此成为行业的热点,无论是资本市场还是企业用户都纷纷追捧,有人认为低代码可以达到全民普及,也有人认为低代码只是炒作概念。毕竟在二三十年前,低代码可视化开发这个核心特性就有人实践过,比如Delphi、PowerBuiler等IDE工具。低代码为什么在今年能够大火起来?究其本身,究竟是变革生产力的真神器,还是噱头与假需求并存的伪风口?谁在支持低代码?2021年以来,低代码成为智能产业圈的一大热词,不仅国内众多互联网大厂纷纷布局,而且在今年微软Build大会,你也能看到它花了很大篇幅讲解低代码平台PowerPlatform,证明了低代码风靡全球的魅力。如果一个概念能在科技圈火起来,它往往兼具字面简明和内涵丰富的特征,并具有某种重塑产业格局的潜力。低代码就具有这种魅力。顾名思义,低代码就是指少用代码,甚至不用代码,仅通过拖拽模块的方式实现应用开发,提高工作的效率。在当前数字化趋势下,

  • 计算机网络-概论

    ##1.计算机网络在信息时代的作用###浏览信息发布信息###通讯交流###休闲娱乐###资源共享###电子商务###远程协作###.....##2.因特网概述###网络&互联网&因特网-网络Network(物理网络)-若干节点(Node)和链路(Link)组成-互联网interent(逻辑网络)-通过路由器将网络互联,构成更大范围的网络,即互联网-因特网Interent-世界上最大的互联网###因特网发展-阶段1-从单个网络ARPANET向互联网发展-阶段2-逐步形成三级结构的因特网-主干网-地区网-校园网-阶段3-逐步形成多层次ISP结构的互联网-第一层-因特网主干网:与其他第一层相连-第二层-大公司:区域性或者国家性覆盖规模-第三层-本地ISP:拥有本地范围的网络-当两个同级的IPS相连时,彼此时对等(Peer)的###因特网标准化工作-因特网协会-因特网体系结构委员会-因特网工程部-短期或者中期工程问题,负责协议的开发和标准化-因特网研究部-理论研究-制定标准过程-因特网草案-建议标准-草案标准-因特网标准##3.英特网组成###边缘部分-概念-用户直接使用-原

  • 原生JS实现影集展示特效

    分享一个用原生JS实现的影集展示特效,效果如下:实现的代码如下:<!doctypehtml> <html> <head> <metacharset="utf-8"> <title>原生JS实现影集展示特效</title> <styletype="text/css"> *{ margin:0; padding:0; list-style:none; } li{ width:300px; height:200px; position:absolute; transition:0.8s; transform:perspective(800px); } liimg{ width:100%; height:100%; } li.s0{ left:50%; margin-left:450px; top:50%; margin-top:-100px; transform:perspective(800px)rotateY(-90deg); opacity:0; } l

  • PHP利用curl发送HTTP请求的实例代码

    cURL函数概述PHP支持的由DanielStenberg创建的libcurl库允许你与各种的服务器使用各种类型的协议进行连接和通讯。libcurl目前支持http、https、ftp、gopher、telnet、dict、file和ldap协议。libcurl同时也支持HTTPS认证、HTTPPOST、HTTPPUT、FTP上传(这个也能通过PHP的FTP扩展完成)、HTTP基于表单的上传、代理、cookies和用户名+密码的认证。PHP中使用cURL实现Get和Post请求的方法这些函数在PHP4.0.2中被引入。实例因为需要在php开发中对接其它接口需要用phpcurl去对接其它接口我把他们封装成函数希望能对大家有所帮助。这里面是封装好的会自动把data进行转成json格式,同时解码成php数组输出。<?php functiongeturl($url){ $headerArray=array("Content-type:application/json;","Accept:application/json"); $ch=curl_in

  • 智能合约:solidity语法(一)

    版本声明首先,所有的solidity源码前面必须标明编译器版本pragmasolidity^0.4.18;复制这个就声明了版本是0.4.18到0.5.0的编译器中是可以工作的 合约写一个合约的基本框架是:contractname{}复制变量下面来看一下怎么声明变量,状态变量会永久的保存在合约里uint表示无符号整数,int表示有符号的在solidity里面uint默认表示uint256,其他的还有uint8、uint16、uint32...声明一个变量:uintid=115;复制结构体solidity也可以用结构体:下面声明了一个叫Student的结构体,有两个属性一个是string类型的name,另一个是uint类型的idstructStudent{stringname;uintid;}复制数组solidity支持两种类型的数组,静态数组、动态数组uint类型的固定长度为10的静态数组iduint[10]id;复制uint类型的长度不定的动态数组iduint[]id;复制也可以建立一个结构体类型的数组studentsStudent[]students;复制函数习惯上,函数里面的变量都

  • 039.集群网络-Pod和SVC网络实践

    一 Pod和SVC网络1.1 实践准备及原理Docker实现了不同的网络模式,Kubernetes也以一种不同的方式来解决这些网络模式的挑战。本完整实验深入剖析Kubernetes在网络层是如何实现及工作的。实验节点架构:如上图所示,Kubernetes的网络模型要求每个Node上的容器都可以相互访问。默认的Docker网络模型提供了一个IP地址段是172.17.0.0/16的docker0网桥。每个容器都会在这个子网内获得IP地址,并且将docker0网桥的IP地址(172.17.42.1)作为其默认网关。需要注意的是,Docker宿主机外面的网络不需要知道任何关于这个172.17.0.0/16的信息或者知道如何连接到其内部,因为Docker的宿主机针对容器发出的数据,在物理网卡地址后面都做了IP伪装MASQUERADE(隐含NAT)。也就是说,在网络上看到的任何容器数据流都来源于那台Docker节点的物理IP地址。这里所说的网络都指连接这些主机的物理网络。默认的Docker网络模型简单便捷,但需要依赖端口映射的机制。在Kubernetes的网络模型中,每台主机上的docker0网桥

  • 清华AI研究院里程碑事件:成立「智能人机交互研究中心」,发布四大开放平台

    机器之心报道作者:孙茜茜昨日(5月21日),清华大学「智能人机交互研究中心」成立仪式在清华大学李兆基科技大楼举行。这是继「知识智能研究中心」、「听觉智能研究中心」、「基础理论研究中心」后,清华大学AI研究院第四个研究中心。清华大学副校长、清华大学AI研究院管委会主任尤政院士和清华大学AI研究院院长张钹院士出席成立仪式,共同为中心揭牌。尤政院士在致辞中表示,成立智能交互研究中心是清华大学推进人工智能发展的重要举措,也是清华大学AI研究院的里程碑事件。图说:智能交互中心成立仪式合影「人工智能的重要需求来自人机交互。」张钹院士在致辞中表示,⼈机交互核⼼问题是⾃然⾏为的意图理解,而解决这一核心问题必须要经过跨学科的研究。为了更好汇聚清华大学在智能人机交互方面多学科的优势研究力量,清华大学AI研究院决定成立智能人机交互研究中心(英文:IntelligentHumanComputerInteractionResearchCenter,简称THUII,以下简称「智能交互中心」)。史元春教授(清华大学计算机系「长江学者」特聘教授、清华大学全球创新学院GIX院长)被聘请为智能交互中心主任,高文教授(中国

  • CodeForces D.Powerful array(Div.1)

    D.Powerfularray  大意是是说,问区间[L,R]内的的一个值,这个值是arr[x]出现次数cnt[arr[x]]^2^*arr[x]  这道题Java版的莫队怎么都tle,实在是没办法了,用c过的,就改一下莫队的remove和add函数即可importjava.io.BufferedInputStream; importjava.util.Arrays; importjava.util.Comparator; importjava.util.Scanner; publicclassCF522A{ finalstaticintN=(int)200001; staticlongnowAns=0;//当前答案 staticintn,m,k,block; staticint[]cnt=newint[N];//每个数出现的次数 staticlong[]ans=newlong[N];//记录每个答案 staticint[]arr=newint[N];//数组 staticQuery[]q=newQuery[N];//询问 publicstaticclasscmpimpleme

  • 模拟大脑的2类实践:计算机科学、生物学

    大数据文摘编辑 素材来自: 雷锋网(http://www.leiphone.com/) 生物探索(http://www.biodiscover.com/)导读:不同的科学家用自己的方式探索这个星球最复杂的机器——人类大脑。计算机科学家尝试用芯片、机器学习搭建大脑;生物科学家在用人体的其他细胞(比如皮肤细胞)经过重新编程后,培育出大脑。哪一个才是方向,亦或兼而有之?今天的文章带您感受这两个领域的最新进展。IBM用48块芯片构建啮齿动物大脑作者:老吕IO/雷锋网、wired在美国圣何塞附近的研究室里,IBM用48块TrueNorth试验芯片构建了一个电子的啮齿动物大脑,每一块芯片都可以模拟大脑的一个基本构件。最近连线杂志的记者在项目负责人DharmendraModha的带领下,近距离接触了整个工程。雷锋网得知,它体积就像一个浴室的医药箱,遍体是半透明塑料板,能清晰的看到里面的芯片,电路板和它内部多彩的指示灯。它看起来就像一个七十年代科幻电影里的物体,不过Modha却表示:“你看到的是一个小型啮齿动物。”他是说一个小型啮齿动物的大脑,至少这堆芯片能顶的上那样的大脑。这些芯片充当了大脑的基本构

  • 【博客美化】02.公告栏显示个性化时间

    博客园美化:1.添加公告栏显示个性化时间效果图:<divid="myTime"><objectclassid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0"width="160"height="70"id="honehoneclock"align="center"> <paramname="allowScriptAccess"value="always"/> <paramname="movie"value="http://chabudai.sakura.ne.jp/blogparts/honehonecloc

  • Linux系统中修改文件内容「建议收藏」

    大家好,又见面了,我是你们的朋友全栈君。1、进入文件:vim文件名vimcommon.js复制2、查找待修改内容位置:(1)按住shift输入“:”,使文件变成可查询状态(2)输入“/”+要修改的内容,回车(例如:要修改服务器地址和端口号)3、修改内容定位到要修改的位置后按i键变成可编辑状态,对要修改的内容进行修改4、退出按ESC键,退出修改状态5、保存(不保存)修改:保存修改:(1)按住shift输入“:”,使文件变成可查询状态(2)输入wq!回车不保存修改:(1)按住shift输入“:”,使文件变成可查询状态(2)输入q!发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/164458.html原文链接:https://javaforall.cn

  • [loj2546][JSOI2018]潜入行动(树形DP)

    题目描述 外星人又双叒叕要攻打地球了,外星母舰已经向地球航行!这一次,JYY已经联系好了黄金舰队,打算联合所有JSOIer抵御外星人的进攻。 在黄金舰队就位之前,JYY打算事先了解外星人的进攻计划。现在,携带了监听设备的特工已经秘密潜入了外星人的母舰,准备对外星人的通信实施监听。 外星人的母舰可以看成是一棵n个节点、n-1条边的无向树,树上的节点用1,2,\cdots,n1,2,⋯,n编号。JYY的特工已经装备了隐形模块,可以在外星人母舰中不受限制地活动,可以神不知鬼不觉地在节点上安装监听设备。 如果在节点uu上安装监听设备,则JYY能够监听与uu直接相邻所有的节点的通信。换言之,如果在节点uu安装监听设备,则对于树中每一条边(u,v),节点vv都会被监听。特别注意放置在节点uu的监听设备并不监听uu本身的通信,这是JYY特别为了防止外星人察觉部署的战术。 JYY的特工一共携带了kk个监听设备,现在JYY想知道,有多少种不同的放置监听设备的方法,能够使得母舰上所有节点的通信都被监听?为了避免浪费,每个节点至多只能安装一个监听设备,且监听设备必须被用完。 输入格式 输入第一行包含两个整数

  • stm32使用printf重定向到usart1

    原文出处:https://www.cnblogs.com/shangdawei/p/3970489.html   一、对工程属性进行配置,详细步骤如下   1、首先要在你的main文件中包含“stdio.h”(标准输入输出头文件)。   2、在main文件中重定义<fputc>函数   如下: //发送数据 intfputc(intch,FILE*f) { USART_SendData(USART1,(unsignedchar)ch);//USART1可以换成USART2等 while(!(USART1->SR&USART_FLAG_TXE)); return(ch); } //接收数据 intGetKey(void){ while(!(USART1->SR&USART_FLAG_RXNE)); return((int)(USART1->DR&0x1FF)); }复制 这样在使用printf时就会调用自定义的fputc函数,来发送字符。   3、在工程属性

  • springboot+docker发布项目20220827

    1、springboot打包项目  1)、application-dev.yml      对应配置修改  2)、项目package 生成包       3)、生成包             4)、运行项目包                                2、springboot+dockerfile打包及发布项目  1)、application-prod.yml 发布到外网一般用application-prod      对应配置修改        2)、项目package 生成包

  • 【转】33 个 2017 年必须了解的 iOS 开源库

    1.IGListKit,作者是InstagramEngineering Instagram程序员做的,IGListKit是数据驱动的UICollectionView框架,为了构建快速和可扩展的列表。另外,它有助于你在app结束对于大量视图控制器的使用。看看这篇来自 RayWenderlich 的教程,关于如何在项目中实现这个库,或者读读这篇RodrigoCavalcante 的文章,关于迁移现有的UITableView到IGListCollectionView。 Instagram/IGListKit-为了构建快速和可扩展的列表而生的数据驱动UICollectionView框架 2. Realm,作者是realm.io Realm是一个直接运行在手机、平板和可穿戴设备内部的移动端数据库,不只是iOS。如果你想试一点和CoreData不一样的,就用Realm。许多人说它是一个现代化的、产品已经可以替代苹果原生的解决方案。 realm/realm-cocoa-Realm是一个移动端数据库:CoreData和SQLite的替代品 3.Moya,作者

  • Grafana + Prometheus + Mysqld_exporter 监控 Mysql

      最近研究了对于Mysql的监控,感觉Prometheus还是挺强大的,有各种适配的度量导出工具,Mysqld_exporter也是旗下的一款工具,可以在Prometheus官网下载。 因为本机电脑用的操作系统是Windows,所以下载了win版本的Mysqld_exporter:   https://prometheus.io/download/   1.在mysql中为Mysqld_exporter创建用户: CREATEUSER'exporter'@'localhost'IDENTIFIEDBY'root'WITHMAX_USER_CONNECTIONS3; GRANTPROCESS,REPLICATIONCLIENT,SELECTON*.*TO'exporter'@'localhost';复制   在GitHub上也有详细说明:https://github.com/prometheus/mysqld_exporter   2.将下载的Mysqld_exporter的压缩包解压,创建.my.cnf文件,压缩包中未包含该文件,需要自己手动创建 [client] host=l

  • 网络流

    蜥蜴 思路 题目限制了点的流量,我们可以把每一个点拆开,连一条上限为这个点的上限的边,对于每一个有蜥蜴的点,向超级原点建一条权值为1边,对于每一个可以跳出范围的点,建一个向超级汇点权值为inf的边,然后跑最大流就可以求出可以逃离的最大值了(需要注意的是d不是曼哈顿距离) code #include<bits/stdc++.h> #defineintll #definedbdouble #definelllonglong #definereregister #definegcgetchar() #definegetchwhile(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=gc;} #definegetnuwhile(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=gc;} usingnamespacestd; inlineintread(){ints=0,f=1;charch=gc;getch;getnu;returns*f;} constint

  • 操作关联表方法

    mysql>CREATEDATABASEstudent_tb;QueryOK,1rowaffected mysql>USEstudent_tb;Databasechanged mysql>CREATETABLEdepartment(->didint(4)NOTNULLPRIMARYKEY,->dnamevarchar(36)->);QueryOK,0rowsaffected mysql>CREATETABLEemployee(->idint(4)NOTNULLPRIMARYKEY,->namevarchar(36),->ageint(2),->didint(4)NOTNULL->);QueryOK,0rowsaffected mysql>INSERTINTOdepartment(did,dname)VALUES(1,'网络部');QueryOK,1rowaffected mysql>INSERTINTOdepartment(did,dname)VALUES(2,'媒体部');QueryOK,1rowaf

  • vue封装弹窗组件,供其它页面引用

    写在前面:   最近开始使用vue写前段项目,从零开始一步一步自己摸索,博文作为学习记录,有哪写的不对的请指正。 正文:   页面弹窗内容多,或者弹窗可封装供多个界面使用,就使用以下方法封装组件。 弹窗页面代码: <template> <div> <el-dialogtitle="检测项目":visible.sync="modalShow"width="60%":before-close="modalClose"> 弹窗内容 </el-dialog> </div> </template> <script> exportdefault{ name:"index", data(){ return{ modalShow:false, } }, methods:{ init(){ this.modalShow=true }, modalClose(){ this.modalShow=false; } }, } </script> <stylescoped> </styl

  • Collecting Bugs POJ2096

    题目链接 简单的期望DP,只不过是二维形式,设\(dp_{i,j}\)为两种分别选了\(i,j\)种后还需要的期望数,则\(dp_{i,j}=\frac{i*j}{n*s}*dp_{i,j}+\frac{(n-i)*j}{n*s}*dp_{i+1,j}+\frac{i*(s-j)}{n*s}*dp_{i,j+1}+\frac{(n-i)*(s-j)}{n*s}*dp_{i+1,j+1}+1\),移项整理即可 #include<iostream> #include<vector> #include<algorithm> #include<cstring> #include<cstdio> usingnamespacestd; constintmaxn=1007; doubledp[maxn][maxn]; voidrun_case(){ intn,s; cin>>n>>s; for(inti=n;i>=0;--i) for(intj=s;j>=0;--j){ if(i==n&&a

  • 学习笔记TF018:词向量、维基百科语料库训练词向量模型

    词向量嵌入需要高效率处理大规模文本语料库。word2vec。简单方式,词送入独热编码(one-hotencoding)学习系统,长度为词汇表长度的向量,词语对应位置元素为1,其余元素为0。向量维数很高,无法刻画不同词语的语义关联。共生关系(co-occurrence)表示单词,解决语义关联,遍历大规模文本语料库,统计每个单词一定距离范围内的周围词汇,用附近词汇规范化数量表示每个词语。类似语境中词语语义相似。用PCA或类似方法降维出现向量(occurrencevector),得到更稠密表示。性能好,追踪所有词汇共生矩阵,宽度、高度为词汇表长度。2013年,Mikolov、Tomas等提出上下文计算词表示方法,《Efficientestimationofwordrepresentationsinvectorspace》(arXivpreprintarXiv:1301.3781(2013))。skip-gram模型,从随机表示开始,依据当前词语预测上下文词语简单分类器,误差通过分类器权值和词表示传播,对两者调整减少预测误差。大规模语料库训练模型表示赂量逼近压缩后共生向量。 数据集, 

相关推荐

推荐阅读