log4cplus开源库使用

log4cplus 的github地址:https://github.com/log4cplus/log4cplus

下载链接:log4cplus - Browse /log4cplus-stable/2.0.7 at SourceForge.net

官方文档:log4cplus / Wiki / Home

1.log4cplus配置

(1)打开解决方案

打开Visual Studio,进入 log4cplus-2.x\msvc14目录下,运行log4cplus.sln解决方案。

(2)进行相应设置

编译log4cplus需要注意三点:

①解决方案的平台与目标程序一致,这里选择的是x64;

②版本也要与目标程序一致,这里选择的是release版本;

③属性里面的字符集和目标程序一致;

选择log4cplus项目,右键——>属性——>配置属性——>常规——>字符集,选择Unicode字符集,如下图所示。(log4cplus默认使用多字节字符集,而VS新建项目默认使用Unicode字符集,如果不修改此处,则后面新建项目使用生成的dll时需要手动修改新建的项目为多字节字符集,否则会报错,总之两边统一用一种即可)

编译完成后,会在log4cplus-2.x\msvc14\x64\bin.Release文件夹下生成我们需要的log4cplus.lib和log4cplus.dll两个文件(我编译的是release版),如下图所示。

(3)目标程序的配置

将log4cplus-2.0.x目录下的include文件夹拷贝到我们的目标程序文件夹中,这里面是我们需要的头文件;在目标程序的属性里面设置头文件的包含目录。

设置lib文件的库目录以及将lib文件填入附加依赖项,如下图所示。

将dll文件放到程序的根目录:如果运行的是VS放置到和*.vcxproj一个文件夹下,如果运行的是*.exe,则和*.exe放置到一个文件夹下。

右键——>属性——>链接器——>输入——>附加依赖项——>加入log4cplus.lib,如下图所示。

如果不添加上述附加依赖项,则需要在代码开头中添加如下代码:

#pragma comment(lib, "log4cplus.lib")

2.头文件

主要类说明:

类名

说明

Filter

过滤器,过滤输出消息

Layout

布局器,控制输出消息的格式

Appender

挂接器,与布局器和过滤器紧密配合,将特定格式的消息过滤后输出到所挂接的设备终端如屏幕,文件等

Logger

记录器,保存并跟踪对象日志信息变更的实体,当你需要对一个对象进行记录时,就需要生成一个logger。

Hierarchy

分类器,层次化的树型结构,用于对被记录信息的分类,层次中每一个节点维护一个logger的所有信息

LogLevel

优先权,包括TRACE, DEBUG, INFO, WARNING, ERROR, FATAL。

主要头文件如下:

#include <log4cplus/logger.h> //获取表示记录句柄
#include <log4cplus/loggingmacros.h>//这个头文件声明日志记录宏。除此之外,它还声明了若干个标准日志级别:FATAL, ERROR, WARN, INFO, DEBUG, TRACE
#include <log4cplus/configurator.h>//此头文件声明类 BasicConfigurator。
#include <log4cplus/initializer.h>//这个头文件声明类 Initializer。

在log4cplus2中,上述类都已经包含在头文件log4cplus.h中了,因此只需要包含该头文件即可:

#include <log4cplus/log4cplus.h>
3.初始化Initializer

实例化该类会初始化log4cplus Initializer:

log4cplus::Initializer initializer;

该类还维护一个引用计数。该类可以被实例化多次。当此引用计数达到零时,在的最后一个实例被销毁后,它会关闭log4cplus内部。在log4cplus解除初始化后,无法重新初始化。

log4cplus尝试使用其他一些方法关闭其内部。但是,这意味着在main()退出后不能使用它。

4.基本配置BasicConfigurator
log4cplus::BasicConfigurator config;
config.configure();

这两行使用简单的布局配置根记录器。ConsoleAppender

log4cplus::Logger logger = log4cplus::Logger::getInstance(
LOG4CPLUS_TEXT("main"));

这里我们获得名为main的记录器的记录器句柄。上面使用的宏与Windows上的或宏具有相同的功能:如果定义了预处理器符号,它会在作为参数传递的字符串文字前面加上前缀,使其成为宽字符串文字。

LOG4CPLUS_WARN(logger, LOG4CPLUS_TEXT(“Hello, World!”));

这里我们调用宏来记录Hello,World!将消息输入主记录器。记录的消息将从主记录器传播到根记录器,根记录器连接了一个用于在控制台上打印的日志。在内部,这个宏使用C++字符串流来格式化hello, World!消息这样做的结果是,您可以使用所有标准的C++流操作器。

5.取消初始化

log4cplus试图取消初始化(deinitialize),并在退出后释放所有分配的资源。然而,同样,根据编译器、平台和运行时库的不同,这可能是不可能的。这就是为什么适当的去初始化是必要的。

在2.0及更高版本中,它由类的最后一个实例及其析构函数完成。在以前的版本中,调用是正确的关闭方法Logger::shutdown()

6.日志记录宏

宏在hood下使用C++字符串流。

7.日志级别

此示例显示了如何在运行时通过调整实例上的日志级别阈值来过滤日志消息。log4cplus的优先级由低到高:

  • NOT_SET_LOG_LEVEL:接受缺省的LogLevel,如果有父logger则继承它的LogLevel;
  • ALL_LOG_LEVEL:开放所有log信息输出
  • TRACE_LOG_LEVEL:开放trace信息输出(即ALL_LOG_LEVEL)
  • DEBUG_LOG_LEVEL:开放debug信息输出
  • INFO_LOG_LEVEL:开放info信息输出
  • WARN_LOG_LEVEL:开放warning信息输出
  • ERROR_LOG_LEVEL:开放error信息输出
  • FATAL_LOG_LEVEL:开放fatal信息输出
  • OFF_LOG_LEVEL:关闭所有log信息输出

各个logger可以通过setLogLevel设置自己的优先级,当某个logger的LogLevel设置成NOT_SET_LOG_LEVEL时,该logger会继承父logger的优先级,另外,如果定义了重名的多个logger, 对其中任何一个的修改都会同时改变其它logger。

代码示例:

#include <log4cplus/logger.h>
#include <log4cplus/loglevel.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/configurator.h>
#include <log4cplus/initializer.h>
#include <iomanip>
#include <iostream>void printMessages(log4cplus::Logger const & logger)
{//使用所有常用日志级别打印信息LOG4CPLUS_TRACE(logger, "printMessages()");LOG4CPLUS_DEBUG(logger, "This is a DEBUG message");LOG4CPLUS_INFO(logger, "This is a INFO message");LOG4CPLUS_WARN(logger, "This is a WARN message");LOG4CPLUS_ERROR(logger, "This is a ERROR message");LOG4CPLUS_FATAL(logger, "This is a FATAL message");
}void thresholdTest(log4cplus::LogLevel ll)
{log4cplus::Logger logger= log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("main"));//设置日志级别阈值logger.setLogLevel(ll);//打印信息//log4cplus::tcout << log4cplus::getLogLevelManager().toString(ll) << std::endl;printMessages(logger);std::cout << std::endl;
}int main()
{//初始化log4cplus::Initializer initializer;//基本配置log4cplus::BasicConfigurator config;config.configure();thresholdTest(log4cplus::TRACE_LOG_LEVEL);//开放trace信息输出thresholdTest(log4cplus::DEBUG_LOG_LEVEL);//开放debug信息输出thresholdTest(log4cplus::INFO_LOG_LEVEL);//开放info信息输出thresholdTest(log4cplus::WARN_LOG_LEVEL);//开放warning信息输出thresholdTest(log4cplus::ERROR_LOG_LEVEL);//开放error信息输出thresholdTest(log4cplus::FATAL_LOG_LEVEL);//开放fatal信息输出return 0;
}
8.Appender输出位置

log4cplus默认将输出到控制台,提供ConsoleAppender用于操作。log4cplus还提供了三个类用于文件操作,它们是FileAppender类、RollingFileAppender类、DailyRollingFileAppender类。

Appender会注册到Logger中,Logger在写日志时,通过继承机制遍历所有注册到它本身和其父节点的Appender(在additivity为true的情况下),调用doAppend()方法,实现日志的写入。在doAppend方法中,若当前Appender注册了Filter,则doAppend还会判断当前日志时候通过了Filter的过滤,通过了Filter的过滤后,如果当前Appender继承自SkeletonAppender,还会检查当前日志级别时候要比当前Appender本身的日志级别阀门要打,所有这些都通过后,才会将LoggingEvent实例传递给Layout实例以格式化成一行日志信息,最后写入相应的目的地,在这些操作中,任何出现的错误都由ErrorHandler字段来处理。

(1)控制台输出ConsoleAppender

参考上文,输出在控制台中。

(2)文件输出FileAppender

FileAppender::FileAppender( const tstring& filename_,std::ios_base::openmode mode_, bool immediateFlush_,bool createDirs_)
  • filename:文件名;
  • mode:文件类型,可选择的文件类型包括app、ate、binary、in、out、trunc,因为实际上只是对stl的一个简单包装,这里就不多讲了。缺省是trunc,表示将先前文件删除;
  • immediateFlush:缓冲刷新标志,如果为true表示每向文件写一条记录就刷新一次缓存,否则直到FileAppender被关闭或文件缓存已满才更新文件,一般是要设置true的,比如你往文件写的过程中出现了错误(如程序非正常退出),即使文件没有正常关闭也可以保证程序终止时刻之前的所有记录都会被正常保存;
  • createDirs:是否创建目录;

输出在文件中,参考代码:

#include <log4cplus/log4cplus.h>int main()
{//用Initializer类进行初始化log4cplus::Initializer initializer;//第1步:建立ConsoleAppenderlog4cplus::SharedAppenderPtr appender(new log4cplus::FileAppender(LOG4CPLUS_TEXT("E:\\test.log")));//第2步:设置Appender的名称和输出格式(SimpleLayout)appender->setName(LOG4CPLUS_TEXT("console"));log4cplus::tstring pattern = LOG4CPLUS_TEXT("%D{%m/%d/%y %H:%M:%S,%Q} [%t] %-5p %c - %m [%l]%n");appender->setLayout(std::unique_ptr<log4cplus::Layout>(new log4cplus::PatternLayout(pattern)));//第3步:得到一个Logger实例,并设置其日志输出等级阈值log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("test"));logger.setLogLevel(log4cplus::INFO_LOG_LEVEL);//第4步:为Logger实例添加ConsoleAppenderlogger.addAppender(appender);//第5步:使用宏将日志输出LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("Hello world"));return 0;
}

同时输出到控制台和文件,代码示例:

#include <log4cplus/log4cplus.h>int main()
{//用Initializer类进行初始化log4cplus::Initializer initializer;//第1步:建立ConsoleAppenderlog4cplus::SharedAppenderPtr consoleAppender(new log4cplus::ConsoleAppender);log4cplus::SharedAppenderPtr fileAppender(new log4cplus::FileAppender(LOG4CPLUS_TEXT("E:\\test.log")));//第2步:设置Appender的名称和输出格式(SimpleLayout)consoleAppender->setName(LOG4CPLUS_TEXT("console"));consoleAppender->setLayout(std::unique_ptr<log4cplus::Layout>(new log4cplus::SimpleLayout()));fileAppender->setName(LOG4CPLUS_TEXT("console"));log4cplus::tstring pattern = LOG4CPLUS_TEXT("%D{%m/%d/%y %H:%M:%S,%Q} [%t] %-5p %c - %m [%l]%n");fileAppender->setLayout(std::unique_ptr<log4cplus::Layout>(new log4cplus::PatternLayout(pattern)));//第3步:得到一个Logger实例,并设置其日志输出等级阈值log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("test"));logger.setLogLevel(log4cplus::INFO_LOG_LEVEL);//第4步:为Logger实例添加ConsoleAppenderlogger.addAppender(consoleAppender);logger.addAppender(fileAppender);//第5步:使用宏将日志输出LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("Hello world"));return 0;
}

(4)RollingFileAppender

RollingFileAppender可以实现滚动转储的文件操作功能:

RollingFileAppender类可以根据你预先设定的大小来决定是否转储,当超过该大小,后续log信息会另存到新文件中,除了定义每个记录文件的大小之外,你还要确定在RollingFileAppender类对象构造时最多需要多少个这样的记录文件(maxBackupIndex+1),当存储的文件数目超过maxBackupIndex+1时,会删除最早生成的文件,保证整个文件数目等于maxBackupIndex+1。然后继续记录。

RollingFileAppender(
const log4cplus::tstring& filename,
long maxFileSize = 10*1024*1024, // 10 MB
int maxBackupIndex = 1,
bool immediateFlush = true,
bool createDirs = false);
  • filename:文件名;
  • maxFileSize:文件的最大尺寸;
  • maxBackupIndex:最大记录文件数;
  • immediateFlush:缓冲刷新标志;
  • createDirs:创建目录;

(4)DailyRollingFileAppender

DailyRollingFileAppender实现根据频度来决定是否转储的文件转储功能:

DailyRollingFileAppender类可以根据你预先设定的频度来决定是否转储,当超过该频度,后续log信息会另存到新文件中,这里的频度包括:MONTHLY(每月)、WEEKLY(每周)、DAILY(每日)、TWICE_DAILY(每两天)、HOURLY(每时)、MINUTELY(每分)。

需要指出的是这里的"频度"并不是你写入文件的速度,其实是否转储的标准并不依赖你写入文件的速度,而是依赖于写入的那一时刻是否满足了频度条件,即是否超过了以分钟、小时、周、月为单位的时间刻度,如果超过了就另存。

DailyRollingFileAppender(
const log4cplus::tstring& filename,
DailyRollingFileSchedule schedule = DAILY,
bool immediateFlush = true,
int maxBackupIndex = 10,
bool createDirs = false);
  • filename:文件名;
  • schedule:存储频度;
  • immediateFlush:缓冲刷新标志;
  • maxBackupIndex:最大记录文件数;
  • createDirs:创建目录

其中schedule为一个枚举类型,如下

enum DailyRollingFileSchedule { 
MONTHLY, 
WEEKLY, 
DAILY,
TWICE_DAILY, 
HOURLY, 
MINUTELY
};

(5)SocketAppender

log4cplus提供了SocketAppender,实现了C/S方式的日志记录,用于支持重定向到远程服务器。

①客户端程序需要做的工作

定义一个SocketAppender类型的挂接器

SharedAppenderPtr _append(new SocketAppender(host, 8888, "ServerName"));

把该挂接器加入到logger中

Logger::getRoot().addAppender(_append);

SocketAppender类型不需要Layout, 直接调用宏就可以将信息发往loggerServer了

LOG4CPLUS_INFO(Logger::getRoot(), "This is a test: ")

②服务器端程序需要做的工作

定义一个ServerSocket

ServerSocket serverSocket(port);

调用accept函数创建一个新的socket与客户端连接

Socket sock = serverSocket.accept();

此后即可用该sock进行数据read/write了:

     SocketBuffer msgSizeBuffer(sizeof(unsigned int));if(!clientsock.read(msgSizeBuffer)){return;}unsigned int msgSize = msgSizeBuffer.readInt();SocketBuffer buffer(msgSize);if(!clientsock.read(buffer)){return;}

为了将读到的数据正常显示出来,需要将SocketBuffer存放的内容转换成InternalLoggingEvent格式:

log4cplus::spi::InternalLoggingEvent event = readFromBuffer(buffer);

然后输出:

Logger logger = Logger::getInstance(event.getLoggerName()); logger.callAppenders(event);

注意:read/write是按照阻塞方式实现的,意味着对其调用直到满足了所接收或发送的个数才返回。

9.布局设置

log4cplus通过布局器(Layouts)来控制输出的格式,log4cplus提供了三种类型的Layouts,分别是SimpleLayout、PatternLayout、和TTCCLayout。

(1)SimpleLayout

一种简单格式的布局器,在输出的原始信息之前加上LogLevel和一个"-",如果初始化时没有将布局器附加到挂接器,则默认使用SimpleLayout。

(2)PatternLayout

一种有词法分析功能的模式布局器,类似于C语言的printf()函数,能够对预定义的转换标识符(conversion specifiers)进行解析,转换成特定格式输出。

以下代码片段演示了如何使用PatternLayout。

#include <log4cplus/log4cplus.h>int main()
{//用Initializer类进行初始化log4cplus::Initializer initializer;//第1步:建立ConsoleAppenderlog4cplus::SharedAppenderPtr appender(new log4cplus::ConsoleAppender());//第2步:设置Appender的名称和输出格式(SimpleLayout)appender->setName(LOG4CPLUS_TEXT("console"));log4cplus::tstring pattern = LOG4CPLUS_TEXT("%D{%m/%d/%y %H:%M:%S,%Q} [%t] %-5p %c - %m [%l]%n");appender->setLayout(std::unique_ptr<log4cplus::Layout>(new log4cplus::PatternLayout(pattern)));//第3步:得到一个Logger实例,并设置其日志输出等级阈值log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("test"));logger.setLogLevel(log4cplus::INFO_LOG_LEVEL);//第4步:为Logger实例添加ConsoleAppenderlogger.addAppender(appender);//第5步:使用宏将日志输出LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("Hello world"));return 0;
}

PatterLayout支持的转换标识符主要包括:

  • "%%",转义为%, 即,std::string pattern = “%%” 时输出"%"。
  • "%c",输出logger名称,比如std::string pattern ="%c" 时输出: “test_logger.subtest”, 也可以控制logger名称的显示层次,比如"%c{1}“时输出"test_logger”,其中数字表示层次。
  • "%D",显示本地时间,当std::string pattern ="%D" 时输出:“2004-10-16 18:55:45”,%d显示标准时间,所以当std::string pattern ="%d" 时输出 “2004-10-16 10:55:45” (因为北京时间位于东8区,差8个小时)。
  • 可以通过%d{…}定义更详细的显示格式,比如%d{%H:%M:%s}表示要显示小时:分钟:秒。大括号中可显示的预定义标识符如下:
  • %a – 表示礼拜几,英文缩写形式,比如"Fri"
  • %A – 表示礼拜几,比如"Friday"
  • %b – 表示几月份,英文缩写形式,比如"Oct"
  • %B – 表示几月份,“October”
  • %c – 标准的日期+时间格式,如 “Sat Oct 16 18:56:19 2004”
  • %d – 表示今天是这个月的几号(1-31)“16”
  • %H – 表示当前时刻是几时(0-23),如 “18”
  • %I – 表示当前时刻是几时(1-12),如 “6”
  • %j – 表示今天是哪一天(1-366),如 “290”
  • %m – 表示本月是哪一月(1-12),如 “10”
  • %M – 表示当前时刻是哪一分钟(0-59),如 “59”
  • %p – 表示现在是上午还是下午, AM or PM
  • %q – 表示当前时刻中毫秒部分(0-999),如 “237”
  • %Q – 表示当前时刻中带小数的毫秒部分(0-999.999),如 “430.732”
  • %S – 表示当前时刻的多少秒(0-59),如 “32”
  • %U – 表示本周是今年的第几个礼拜,以周日为第一天开始计算(0-53),如 “41”
  • %w – 表示礼拜几,(0-6, 礼拜天为0),如 “6”
  • %W – 表示本周是今年的第几个礼拜,以周一为第一天开始计算(0-53),如 “41”
  • %x – 标准的日期格式,如 “10/16/04”
  • %X – 标准的时间格式,如 “19:02:34”
  • %y – 两位数的年份(0-99),如 “04”
  • %Y – 四位数的年份,如 “2004”
  • %Z – 时区名,比如 “GMT”
  • "%F",输出当前记录器所在的文件名称,比如std::string pattern ="%F" 时输出: “main.cpp”。
  • "%L",输出当前记录器所在的文件行号,比如std::string pattern ="%L" 时输出: “51”
  • "%l",输出当前记录器所在的文件名称和行号,比如std::string pattern ="%L" 时输出"main.cpp:51"。
  • "%m",输出原始信息,比如std::string pattern ="%m" 时输出: “teststr”,即上述代码中LOG4CPLUS_DEBUG的第二个参数,这种实现机制可以确保原始信息被嵌入到带格式的信息中。
  • "%n",换行符,没什么好解释的。
  • "%p",输出LogLevel,比如std::string pattern ="%p" 时输出: “DEBUG”。
  • "%t",输出记录器所在的线程ID,比如std::string pattern ="%t" 时输出: “1075298944”。
  • "%x",嵌套诊断上下文NDC (nested diagnostic context) 输出,从堆栈中弹出上下文信息,NDC可以用对不同源的log信息(同时地)交叉输出进行区分,关于NDC方面的详细介绍会在下文中提到。
  • 格式对齐,比如std::string pattern ="%-10m"时表示左对齐,宽度是10,此时会输出"teststr “,当然其它的控制字符也可以相同的方式来使用,比如”%-12d","%-5p"等等。

(3)TTCCLayout

TTCCLayout是在PatternLayout基础上发展的一种缺省的带格式输出的布局器, 其格式由时间,线程ID,Logger和NDC 组成(consists of time, thread, Logger and nested diagnostic context information, hence the name),因而得名。

10.基本步骤

使用log4cplus有六个基本步骤:

  1. 实例化一个封装了输出介质的appender对象;
  2. 实例化一个封装了输出格式的layout对象;
  3. 将layout对象绑定(attach)到appender对象;如省略此步骤,简单布局器SimpleLayout(参见5.1小节)对象会绑定到logger。
  4. 实例化一个封装了日志输出logger对象,并调用其静态函数getInstance()获得实例,log4cplus::Logger::getInstance(“logger_name”);
  5. 将appender对象绑定(attach)到logger对象;
  6. 设置logger的优先级,如省略此步骤,各种有限级的日志都将被输出。

代码示例:

#include <log4cplus/log4cplus.h>int main()
{//用Initializer类进行初始化log4cplus::Initializer initializer;//第1步:创建ConsoleAppender(实例化一个appender对象)log4cplus::SharedAppenderPtr appender(new log4cplus::ConsoleAppender());//第2步:设置Appender的名称和输出格式(SimpleLayout)appender->setName(LOG4CPLUS_TEXT("console"));//第3步:实例化一个layout对象,将layout对象绑定到appender对象appender->setLayout(std::unique_ptr<log4cplus::Layout>(new log4cplus::SimpleLayout));//第4步:实例化一个封装了日志输出的Logger对象,并设置其日志输出等级阈值log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("test"));//第5步:将appender对象绑定到logger对象logger.addAppender(appender);//第6步:设置日志log的优先级logger.setLogLevel(log4cplus::INFO_LOG_LEVEL);//使用宏将日志输出LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("Hello world"));return 0;
}
11.注意事项

(1)如果使用ConsoleAppender()默认参数,那么控制台消息不会实时输出,需要等到缓冲区达到一定大小才会输出。当时这个可调试了好一会。因为我当时需要的效果就是实时输出到控制台与文件。代码如下:

log4cplus::SharedAppenderPtr append_console(new log4cplus::ConsoleAppender(false,true));

(2)输出数字、字符、字符串的方法如下:

    //第5步:使用宏将日志输出//数字输出for(int i=0; i<10; ++i){LOG4CPLUS_INFO(logger, "Entering loop #" << i);}//字符输出char x='i';LOG4CPLUS_INFO(logger, "Entering loop #" << x);//字符串输出std::string y="xyz";LOG4CPLUS_INFO(logger, "Entering loop #" << LOG4CPLUS_C_STR_TO_TSTRING(y));

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/434424.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

利用柯西积分公式证明最大模定理

一、利用柯西积分公式证明最大模定理 一、利用柯西积分公式证明最大模定理 设复变函数f(z)在封闭区域上的解析&#xff0c;则该复变函数的模|f(z)|的最大值只能出现在该区域的边界上&#xff0c;除非是个常数

字符串相关函数【超详细】(strcpy,strstr等string.h中的函数)

文章目录 strlen库中函数定义函数作用函数大概“工作”流程函数使用注意&#xff08;要求&#xff09;函数使用例举 strcpy库中函数定义函数作用函数使用注意&#xff08;要求&#xff09;函数大概“工作”流程函数使用例举 strcat库中函数定义函数作用函数使用注意&#xff08…

EventSource 长链接执行

EventSource 说明文档MDN 其他参考文档 一、利用node启服务 import fs from fs import express from express const app express() // eventSource 仅支持 get 方法 // 服务器端发送的数据必须是纯文本格式&#xff0c;不能是二进制数据。 app.get(/api, (req, res) > …

预训练语言模型transformer

预训练语言模型的学习方法有三类&#xff1a;自编码&#xff08;auto-encode, AE)、自回归&#xff08;auto regressive, AR&#xff09;&#xff0c;Encoder-Decoder结构。 决定PTM模型表现的真正原因主要有以下几点&#xff1a; 更高质量、更多数量的预训练数据增加模型容量…

第20届纪念款-牛客周赛 Round 20 B.C简单构造

B 答案要么是0 要么是1 所以你全部填0或者要么填1然后算就好了 #include<bits/stdc.h> using namespace std; using ll long long; const int N 1e510; int n;void solve() {//全0 全1&#xff1f;string str;cin>>str;n str.size();string str1 str;int ans…

基于springboot网上图书商城源码和论文

在Internet高速发展的今天&#xff0c;我们生活的各个领域都涉及到计算机的应用&#xff0c;其中包括网上图书商城的网络应用&#xff0c;在外国网上图书商城已经是很普遍的方式&#xff0c;不过国内的管理网站可能还处于起步阶段。网上图书商城具有网上图书信息管理功能的选择…

Spring 的存储和获取Bean

文章目录 获取 Spring 上下文对象的方式存储 Bean 对象的方式类注解配置扫描路径&#xff08;必须&#xff09;Controller&#xff08;控制器存储&#xff09;Service&#xff08;服务&#xff09;Repository&#xff08;持久层&#xff09;Component&#xff08;工具&#xff…

【Qt无门槛入门】信号以及信号机制及其常用控件(1)

信号与信号槽 信号源&#xff1a;由哪个控件发出的信号。 信号的类型&#xff1a;用户进行不同的操作&#xff0c;就可能出发不同的信号。 信号处理的方式:槽&#xff08;slot&#xff09;某个对象接收到这个信号之后&#xff0c;就会做一些相关的处理动作。但是Qt对象不会无故…

ANN论文总结

本文主要是个人笔记&#xff0c;记录与存储相关的ANN工作&#xff0c;想着写都写了不如发出来与大家分享&#xff0c;大多写得比较简单有些稍微详细一点&#xff0c;内容仅供参考。 CognitiveSSD S. Liang, Y. Wang, Y. Lu, et al. Cognitive SSD: A Deep Learning Engine for…

按配置数据绘制配置型地图marker的icon,自定义marker

一、需求 需要自定义配置数据的marker&#xff0c;其中图片内容要灵活可配置自动生成。此处项目用的百度地图。 效果图&#xff1a; 二、思路 用背景图canvas绘制数字的方式生成icon的图片资源。 再将icon生成对应地图marker。 三、代码 canvasImg.js <!-- * descrip…

“东坡庙会·回家过年”活动正式启动

1月26日下午&#xff0c;“东坡庙会回家过年”启动仪式在黄冈市遗爱湖东坡广场隆重举行。启动仪式以回家过年为故事主线&#xff0c;黄冈历史名人、近现代名人为引&#xff0c;编排了精彩的传统文艺节目&#xff0c;展现武鄂黄黄一家亲、全国人民一家亲、古今名人归故里的黄冈年…

二分算法模版

二分算法模版 实数二分算法模版实数二分模版题 整数二分算法模版向上取整二分模版向下取整二分模版二分模版的注意点二分模版中check函数的实现能够使用二分的条件 二分主要分两类&#xff0c; 一类是对实数进行二分&#xff0c;一类是对整数进行二分 对整数二分又分成2种&…