[C++]——同步异步日志系统(2)

同步异步日志系统

  • 一、 不定参函数
    • 1.1 不定参宏函数的使用
    • 1.2 C 语言中不定参函数的使用
    • 1.3 C++不定参数使用
  • 二、设计模式
    • 2.1 单列模式
    • 2.2 工厂模式
    • 2.3 建造者模式
    • 2.4 代理模式

在我们开发同步异步日志系统之前,需要了解一些相关的技术知识。

一、 不定参函数

在初学C语⾔的时候,我们都⽤过printf函数进⾏打印。其中printf函数就是⼀个不定参函数,在函数内 部可以根据格式化字符串中格式化字符分别获取不同的参数进⾏数据的格式化。

1.1 不定参宏函数的使用

  1. 首先我们看怎么打印数字和字符。
/*
学习不定参宏函数的使用
*/
#include<stdio.h>
int main()
{
//编译器内置的宏:__FILE__当前文件名;__LINE__当前行号。
printf("[%s:%d],%s %d",__FILE__,__LINE__,"你好世界",521);return 0;
}   

在这里插入图片描述
2. 用宏表示不定参数

  1. 不定参的表示用:“…”
  2. 不定参的使用:“ __ VA_REGS __”。(如果 __ VA_REGS __是空的话就在前面加 ## ,这里的作用就是取消前面的逗号。)
#include<stdio.h>
#define LOG(fmt,...) printf("[%s:%d]", __FILE__, __LINE__, __VA_ARGS__);
int main()
{
//编译器内置的宏:__FILE__当前文件名;__LINE__当前行号。LOG("%s %d\n","你好世界",521)return 0;
}   

在这里插入图片描述
3. 如果只有LOG(“你好世界”),就会报错;这时候就要加##号。
在这里插入图片描述

#include<stdio.h>
#define LOG(fmt,...) printf("[%s:%d]", __FILE__, __LINE__,##__VA_ARGS__);
int main()
{
//编译器内置的宏:__FILE__当前文件名;__LINE__当前行号。LOG("你好世界")return 0;
} 

在这里插入图片描述

1.2 C 语言中不定参函数的使用

/*
C语言中不定参函数的使用,不定参数据的访问
*/
#define _GNU_SOURCE//使用vasprintf函数必须带这个宏
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
//参数类型一样
void printNum(int n, ...)
{va_list al;//可变参数va_start(al, n); //  获取指定参数的起始地址,这里就是获取n参数之后的第一个参数的起始地址for (int i = 0; i < n; i++){int num = va_arg(al, int); // 从可变参数中取出⼀个整形参数printf("param[%d]:%d\n", i, num);}va_end(al); // 清空可变参数列表--其实是将al置空
}
//参数类型不一样
void myprintf(const char*fmt,...)
{va_list ap;va_start(ap,fmt);char *res;//对不定参数的基本使用;給一个一级指针的地址进去,根据fmt里面的字符串格式,一个一个的取出参数列表的每个数。int ret=vasprintf(&res,fmt,ap);if(ret!=-1){printf(res);free(res);}va_end(ap);//将ap指针置空
}
int main()
{printNum(3, 11, 22,33);printNum(5, 44, 55, 66, 77, 88);myprintf("%s %d","hello",521);return 0;
}

在这里插入图片描述

1.3 C++不定参数使用

#include <iostream>//特化
void xprintf()
{std::cout<<std::endl;
}template <typename T,typename ...Args>
void xprintf(const T &v,Args &&...args)
{std::cout<<v;//sizeof计算参数包参数的个数if((sizeof ...(args))>0){//完美转发xprintf(std::forward<Args>(args)...);}else{//递归为0的情况 xprintf();}
}int main()
{
xprintf("hello!","world",521);
xprintf("hello!","world");
xprintf("hello!");return 0;
}

在这里插入图片描述

二、设计模式

设计模式是前辈们对代码开发经验的总结,是解决特定问题的⼀系列套路。它不是语法规定,⽽是⼀ 套⽤来提⾼代码可复⽤性、可维护性、可读性、稳健性以及安全性的解决⽅案。

六大原则:

  1. 1. 单一职责原则(SingleResponsibilityPrinciple )
    • 类的职责应该单⼀,⼀个⽅法只做⼀件事。
    • 使⽤建议:两个完全不⼀样的功能不应该放⼀个类中,⼀个类中应该是⼀组相关性很⾼的函数或数据的封装。
    • 例子:⽹络聊天:⽹络通信&聊天,应该分割成为⽹络通信类&聊天类。
    2. 开闭原则(OpenClosedPrinciple )
    • 对扩展开放,对修改封闭。
    • 使⽤建议:对软件实体的改动,最好⽤扩展⽽⾮修改的⽅式。
    • ⽤例:超时卖货:商品价格—不是修改商品的原来价格,⽽是新增促销价格。
    3. 里氏替换原则(LiskovSubstitutionPrinciple )
    • 通俗点讲,就是只要⽗类能出现的地⽅,⼦类就可以出现,⽽且替换为⼦类也不会产⽣任何错误或异常。
    • 在继承类时,务必重写⽗类中所有的⽅法,尤其需要注意⽗类的protected⽅法,⼦类尽量不要暴露⾃⼰的public⽅法供外界调⽤。
    • 使⽤建议:⼦类必须完全实现⽗类的⽅法,孩⼦类可以有⾃⼰的个性。覆盖或实现⽗类的⽅法时,输⼊参数可以被放⼤,输出可以缩⼩。
    • ⽤例:跑步运动员类-会跑步,⼦类⻓跑运动员-会跑步且擅⻓⻓跑,⼦类短跑运动员-会跑步且擅⻓短跑。
    4. 依赖倒置原则(Dependence Inversion Principle)
    • ⾼层模块不应该依赖低层模块,两者都应该依赖其抽象.不可分割的原⼦逻辑就是低层模式,原⼦逻辑组装成的就是⾼层模块。
    • 模块间依赖通过抽象(接⼝)发⽣,具体类之间不直接依赖。
    • 使⽤建议:每个类都尽量有抽象类,任何类都不应该从具体类派⽣。尽量不要重写基类的⽅法。结合⾥⽒替换原则使⽤。
    • ⽤例:奔驰⻋司机类–只能开奔驰;司机类–给什么⻋,就开什么⻋;开⻋的⼈:司机–依赖于抽象。
    5. 迪⽶特法则(LawofDemeter),⼜叫“最少知道法则”
    • 尽量减少对象之间的交互,从⽽减⼩类之间的耦合。⼀个对象应该对其他对象有最少的了解。 对类的低耦合提出了明确要求:1.只和直接的朋友交流,朋友之间也是有距离的。⾃⼰的就是⾃⼰的。(如果⼀个⽅法放在本类中,既不增加类间关系,也对本类不产⽣负⾯影响,那就放置在本类中)
    • ⽤例:⽼师让班⻓点名–⽼师给班⻓⼀个名单,班⻓完成点名勾选,返回结果,⽽不是班⻓点名,⽼师勾选。
    6. 接⼝隔离原则(Interface Segregation Principle );
    • 客⼾端不应该依赖它不需要的接⼝,类间的依赖关系应该建⽴在最⼩的接⼝上。
    • 使⽤建议:接⼝设计尽量精简单⼀,但是不要对外暴露没有实际意义的接⼝。
    • ⽤例:修改密码,不应该提供修改⽤⼾信息接⼝,⽽就是单⼀的最⼩修改密码接⼝,更不要暴露数据库操作。

从整体上来理解六⼤设计原则,可以简要的概括为⼀句话,⽤抽象构建框架,⽤实现扩展细节,具体到每⼀条设计原则 则对应⼀条注意事项:

  1. 单⼀职责原则告诉我们实现类要职责单⼀;
  2. 开闭原则是总纲,告诉我们要对扩展开放,对修改关闭;
  3. ⾥⽒替换原则告诉我们不要破坏继承体系;
  4. 依赖倒置原则告诉我们要⾯向接⼝编程;
  5. 迪⽶特法则告诉我们要降低耦合;
  6. 接⼝隔离原则告诉我们在设计接⼝的时候要精简单⼀。

2.1 单列模式

一个类只创建一个对象。 该设计模式可以保证系统中该类只有⼀个实例化对象,并提供⼀个访问它的全局访问点,该实例被所有程序模块共享。⽐如在某个服务器程序中,该服务器的配置信息存放在⼀个⽂件中,这些配置数据由⼀个单例对象统⼀读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种⽅式简化了在复杂环境下的配置管理。

  1. 饿汉模式

程序启动时就会创建⼀个唯⼀的实例对象。因为单例对象已经确定,所以⽐较适⽤于多线程环境中,多线程获取单例对象不需要加锁,可以有效的避免资源竞争,提⾼性能。

#include <iostream>
// 饿汉模式的单例模式
class Singleton
{
private:static Singleton _eton; // 实例化一个对象,这个是声明,需要在类外面定义Singleton() : _data(99){std::cout << "单例对象构造\n";;}; // 初始化列表Singleton(const Singleton &) = delete; // 禁止拷贝构造~Singleton(){};                        // 析构函数
private:int _data; // 日期
public:// 给类外调用的接口,获得类的信息。static Singleton &getInstance(){return _eton;}int getData(){return _data;}
};
Singleton Singleton::_eton;int main()
{std::cout << Singleton::getInstance().getData(); // 获得实例化后对象的信息;return 0;
}

在这里插入图片描述
2. 懒汉模式

懒加载,延迟加载的思想,一个对象在用的时候在进行实例化。 如果单例对象构造特别耗时或者耗费济 源(加载插件、加载⽹络资源等), 可以选择懒汉模式, 在第⼀次使⽤的时候才创建对象。

  • 这⾥介绍的是《Effective C++》⼀书作者ScottMeyers 提出的⼀种更加优雅简便的单例模式 Meyers’Singleton in C++。
  • C++11 Static local variables特性以确保C++11起,静态变量将能够在满⾜ thread-safe 的前提 下唯⼀地被构造和析构
#include <iostream>
// 懒汉模式的单例模式:定义对象的时候不是直接实例化对象
class Singleton
{
private:Singleton() : _data(99){std::cout << "单例对象构造\n";;}; // 初始化列表Singleton(const Singleton &) = delete; // 禁止拷贝构造~Singleton(){};                        // 析构函数
private:int _data; // 日期
public:// 给类外调用的接口,获得类的信息。static Singleton &getInstance(){static Singleton _eton; // c++11之后才开始这么做,c++11之前都是先定义一个对象指针,如果是空就不实例化对象,不是空就new对象,存在线程安全的问题,要加锁return _eton;}int getData(){return _data;}
};
int main()
{std::cout << Singleton::getInstance().getData(); // 获得实例化后对象的信息;return 0;
}

在这里插入图片描述

2.2 工厂模式

⼯⼚模式是⼀种创建型设计模式,它提供了⼀种创建对象的最佳⽅式。在⼯⼚模式中,我们创建对象时不会对上层暴露创建逻辑,⽽是通过使⽤⼀个共同结构来指向新创建的对象,以此实现创建-使⽤的分离。

⼯⼚模式可以分为:

  1. 简单工厂模式

简单⼯⼚模式实现由⼀个⼯⼚对象通过类型决定创建出来指定产品类的实例。假设有个⼯⼚能⽣产出⽔果,当客⼾需要产品的时候明确告知⼯⼚⽣产哪类⽔果,⼯⼚需要接收⽤⼾提供的类别信息,当新增产品的时候,⼯⼚内部去添加新产品的⽣产⽅式。

//简单⼯⼚模式:通过参数控制可以⽣产任何产品
// 优点:简单粗暴,直观易懂。使⽤⼀个⼯⼚⽣产同⼀等级结构下的任意产品
// 缺点:
// 1. 所有东西⽣产在⼀起,产品太多会导致代码量庞⼤
//2. 开闭原则遵循(开放拓展,关闭修改)的不是太好,要新增产品就必须修改⼯⼚⽅法。
#include <iostream>
#include <memory>
// 简单工厂模式
// 水果类
class Fruits
{
public:Fruits(){}; // 构造函数// 创建生产方式的纯虚函数virtual void show() = 0;
};
// 水果的产品
class Apple : public Fruits
{
public:Apple(){};virtual void show(){std::cout << "我是一个红苹果" << std::endl;};
};
class Banana : public Fruits
{
public:Banana(){};virtual void show(){std::cout << "我是一个黄香蕉" << std::endl;};
};// 给我们使用的水果工厂
class FritisFactory
{
public:// 创建水果的方法static std::shared_ptr<Fruits> create(const std::string &name){if (name == "苹果")return std::make_shared<Apple>();elsereturn std::make_shared<Banana>();}
};int
main()
{std::shared_ptr<Fruits> fruit = FritisFactory::create("苹果"); // 工厂生产苹果fruit->show();                                                 // 显示苹果fruit = FritisFactory::create("香蕉");                         // 工厂生产香蕉fruit->show();                                                 // 显示香蕉return 0;
}

在这里插入图片描述
这个模式的结构和管理产品对象的⽅式⼗分简单, 但是它的扩展性⾮常差,当我们需要新增产品的时 候,就需要去修改⼯⼚类新增⼀个类型的产品创建逻辑,违背了开闭原则。

  1. 工厂方法模式

在简单⼯⼚模式下新增多个⼯⼚,多个产品,每个产品对应⼀个⼯⼚。假设现在有 A、B 两种产品,则开两个⼯⼚,⼯⼚ A 负责⽣产产品 A,⼯⼚ B 负责⽣产产品 B,用户只知道产品 的⼯⼚名,⽽不知道具体的产品信息,⼯⼚不需要再接收客户的产品类别,⽽只负责⽣产产品。

//⼯⼚⽅法:定义⼀个创建对象的接⼝,但是由⼦类来决定创建哪种对象,使⽤多个⼯⼚分别⽣产指定 的固定产品
// 优点: 
// 1. 减轻了⼯⼚类的负担,将某类产品的⽣产交给指定的⼯⼚来进⾏
// 2. 开闭原则遵循较好,添加新产品只需要新增产品的⼯⼚即可,不需要修改原先的⼯⼚类
// 缺点:对于某种可以形成⼀组产品族的情况处理较为复杂,需要创建⼤量的⼯⼚类.
#include <iostream>
#include <memory>
// 工厂方法模式
// 水果类
class Fruits
{
public:Fruits(){}; // 构造函数// 创建生产方式的纯虚函数virtual void show() = 0;
};
// 水果的产品
class Apple : public Fruits
{
public:Apple(){};virtual void show(){std::cout << "我是一个红苹果" << std::endl;};
};
class Banana : public Fruits
{
public:Banana(){};virtual void show(){std::cout << "我是一个黄香蕉" << std::endl;};
};// 给我们使用的水果工厂
class FritisFactory
{
public:// 创建水果的纯虚函数virtual std::shared_ptr<Fruits> create() = 0;
};// 苹果工厂
class AppleFactory
{
public:std::shared_ptr<Fruits> create() override // 用来重写基类的同名虚函数{return std::make_ptr<Apple>();}
};
// 香蕉工厂
class BananFactory
{
public:std::shared_ptr<Fruits> create() override // 用来重写基类的同名虚函数{return std::make_ptr<Banana>();}
};int main()
{std::shared_ptr<FritisFactory> ff(new AppleFactory()); // 创建一个苹果工厂std::shared_ptr<Fruits> fruit = ff->create();          // 生产苹果fruit->show();ff.reset(new BananFactory()); // 重新管理工厂为香蕉工厂fruit = ff->create();         // 创建一个香蕉fruit->show();                // 生产香蕉return 0;
}

在这里插入图片描述
⼯⼚⽅法模式每次增加⼀个产品时,都需要增加⼀个具体产品类和⼯⼚类,这会使得系统中类的个数 成倍增加,在⼀定程度上增加了系统的耦合度。

  1. 抽象工厂模式

⼯⼚⽅法模式通过引⼊⼯⼚等级结构,解决了简单⼯⼚模式中⼯⼚类职责太重的问 题,但由于⼯⼚⽅法模式中的每个⼯⼚只⽣产⼀类产品,可能会导致系统中存在⼤量的⼯⼚类,势必会增加系统的开销。此时,我们可以考虑将⼀些相关的产品组成⼀个产品族(位于不同产品等级 结构中功能相关联的产品组成的家族),由同⼀个⼯⼚来统⼀⽣产,这就是抽象⼯⼚模式的基本思想。

//抽象⼯⼚:围绕⼀个超级⼯⼚创建其他⼯⼚。每个⽣成的⼯⼚按照⼯⼚模式提供对象。
// 思想:将⼯⼚抽象成两层,抽象⼯⼚ & 具体⼯⼚⼦类, 在⼯⼚⼦类种⽣产不同类型的⼦产品
#include <iostream>
#include <memory>
// 抽象工厂模式
// 水果类
class Fruits
{
public:Fruits(){}; // 构造函数// 创建生产方式的纯虚函数virtual void show() = 0;
};
// 水果的产品
class Apple : public Fruits
{
public:Apple(){};virtual void show(){std::cout << "我是一个红苹果" << std::endl;};
};
class Banana : public Fruits
{
public:Banana(){};virtual void show(){std::cout << "我是一个黄香蕉" << std::endl;};
};// 动物类
class Animal
{
public:Animal(){}; // 构造函数// 创建生产方式的纯虚函数virtual void name1() = 0;
};
// 动物的产品
class Lamp : public Animal
{
public:Lamp(){};virtual void name1(){std::cout << "我是一只山羊" << std::endl;};
};
class Dog : public Animal
{
public:Dog(){};virtual void name1(){std::cout << "我是一只狗" << std::endl;};
};// 给我们使用的抽象工厂
class Factory
{
public:// 创建分类的纯虚函数virtual std::shared_ptr<Fruits> getFruits(const std::string &name) = 0;virtual std::shared_ptr<Animal> getAnimal(const std::string &name) = 0;
};// 水果工厂
class FruitFactory : public Factory
{
public:virtual std::shared_ptr<Animal> getAnimal(const std::string &name){return std::shared_ptr<Animal>(); // 返回一个空对象}virtual std::shared_ptr<Fruits> getFruits(const std::string &name){if (name == "苹果")return std::make_shared<Apple>();else if (name == "香蕉")return std::make_shared<Banana>();elsereturn std::shared_ptr<Fruits>(); // 否则为空}
};
// 动物工厂
class AnimalFactory : public Factory
{
public:virtual std::shared_ptr<Fruits> getFruits(const std::string &name){return std::shared_ptr<Fruits>(); // 返回一个空对象}virtual std::shared_ptr<Animal> getAnimal(const std::string &name){if (name == "小羊")return std::make_shared<Lamp>();else if (name == "小狗")return std::make_shared<Dog>();elsereturn std::shared_ptr<Animal>(); // 否则为空}
};// 超级工厂
class FactoryProducer
{
public:static std::shared_ptr<Factory> getFactory(const std::string &name){if (name == "动物"){return std::make_shared<AnimalFactory>();}else{return std::make_shared<FruitFactory>();}}
};int main()
{std::shared_ptr<Factory> fruit_factory = FactoryProducer::getFactory("⽔果");std::shared_ptr<Fruits> fruit = fruit_factory->getFruits("苹果");fruit->show();fruit = fruit_factory->getFruits("香蕉");if (fruit == nullptr){return 0;}fruit->show();std::shared_ptr<Factory> animal_factory = FactoryProducer::getFactory("动物");std::shared_ptr<Animal> animal = animal_factory->getAnimal("小羊");animal->name1();animal = animal_factory->getAnimal("小狗");if (animal == nullptr){return 0;}animal->name1();return 0;
}

在这里插入图片描述
抽象⼯⼚模式适⽤于⽣产多个⼯⼚系列产品衍⽣的设计模式,增加新的产品等级结构复杂,需要对原 有系统进⾏较⼤的修改,甚⾄需要修改抽象层代码,违背了“开闭原则”。

2.3 建造者模式

建造者模式是⼀种创建型设计模式, 使⽤多个简单的对象⼀步⼀步构建成⼀个复杂的对象(可能会按照一定的顺序才能构建成产品),能够将⼀个复杂的对象的构建与它的表⽰分离,提供⼀种创建对象的最佳⽅式。主要⽤于解决对象的构建过于 复杂的问题。

建造者模式主要基于四个核⼼类实现:

  • 抽象产品类:
  • Product(产品角色):⼀个具体的产品对象类
  • Builder(抽象建造者):创建⼀个产品对象所需的各个部件的抽象接⼝
  • ConcreteBuilder(具体建造者):实现抽象接⼝,构建各个部件
  • Director类(指挥者):统⼀组建过程,提供给调⽤者使⽤,通过指挥者来构造产品。
#include <iostream>
#include <memory>
#include <string>
// 建造者模式
// 1.先创建产品的抽象类
class Computer
{
public:// 构建零部件的方法void setBoard(const std::string &board){_board = board;}void setDisply(const std::string &display){_display = display;}virtual void setOs() = 0;std::string toString(){std::string computer = "Computer:{\n";computer += "\tboard=" + _board + ",\n";computer += "\tdisplay=" + _display + ",\n";computer += "\tOs=" + _os + ",\n";computer += "}\n";return computer;}protected: // 如果是私有的零部件,// 这是我们构造电脑所需要的零部件。std::string _board;   // 主板std::string _display; // 显示屏std::string _os;      // 操作系统
};// 2.对产品抽象接口的具体实现
class MacBook : public Computer
{
public:// 构建抽象零部件的方法void setOs() override{_os = "Mac os x12";}
};// 3.完成各个零部件的生产过程
class Builder
{
public:virtual void builBoard(const std::string &board) = 0;virtual void builDisplay(const std::string &display) = 0;virtual void builOs() = 0;virtual std::shared_ptr<Computer> build() = 0;
};// 4.实现抽象接⼝,构建各个部件
class MacBookBuild : public Builder
{
public:MacBookBuild() : _computer(new MacBook()) {}void builBoard(const std::string &board){_computer->setBoard(board);}void builDisplay(const std::string &display){_computer->setDisply(display);}void builOs(){_computer->setOs();}std::shared_ptr<Computer> build(){return _computer;}std::shared_ptr<Computer> _computer;
};// 指挥者
class Director
{
public:Director(Builder *builder) : _builder(builder) {}void construct(const std::string &board, const std::string &display){_builder->builBoard(board);_builder->builDisplay(display);_builder->builOs();}private:std::shared_ptr<Builder> _builder;
};int main()
{Builder *builder = new MacBookBuild();                     // 苹果系统的建造者构造std::unique_ptr<Director> director(new Director(builder)); // 指挥者准备好了director->construct("华硕主板", "三星显示器");             // 组装好了std::shared_ptr<Computer> computer = builder->build();     //std::cout << computer->toString();return 0;
}

在这里插入图片描述

2.4 代理模式

代理模式指代理控制对其他对象的访问, 也就是代理对象控制对原对象的引⽤。在某些情况下,⼀个对象不适合或者不能直接被引⽤访问,⽽代理对象可以在客⼾端和⽬标对象之间起到中介的作⽤。代理模式的结构包括⼀个是真正的你要访问的对象(⽬标类)、⼀个是代理对象。⽬标对象与代理对象实现同⼀个接⼝,先访问代理类再通过代理类访问⽬标对象。

代理模式分为静态代理、动态代理:

  • 静态代理指的是,在编译时就已经确定好了代理类和被代理类的关系。也就是说,在编译时就已经 确定了代理类要代理的是哪个被代理类。
  • 动态代理指的是,在运⾏时才动态⽣成代理类,并将其与被代理类绑定。这意味着,在运⾏时才能 确定代理类要代理的是哪个被代理类。

以租房为例,房东将房⼦租出去,但是要租房⼦出去,需要发布招租启⽰, 带⼈看房,负责维修,这 些⼯作中有些操作并⾮房东能完成,因此房东为了图省事,将房⼦委托给中介进⾏租赁。
代理模式实现:

// 房东要把一个房子通过中介租出去
#include <iostream>
#include <string>
// 代理模式
// 出租房子
class RentHouse
{
public:virtual void rentHouse() = 0;
};
// 房东
class Landlord : public RentHouse
{
public:void rentHouse(){std::cout << "将房子租出去\n";}
};// 中介代理出租
class Intermediary : public RentHouse
{
public:void rentHouse(){std::cout << "发布招租启示\n";std::cout << "带人看房\n";_landlord.rentHouse();std::cout << "负责租后服务\n";}private:Landlord _landlord;
};int main()
{Intermediary intermediary; // 中介对象intermediary.rentHouse();  // 出租房子return 0;
}

在这里插入图片描述

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

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

相关文章

VCL界面组件DevExpress VCL v24.1 - 发布全新的矢量主题

DevExpress VCL是DevExpress公司旗下最老牌的用户界面套包&#xff0c;所包含的控件有&#xff1a;数据录入、图表、数据分析、导航、布局等。该控件能帮助您创建优异的用户体验&#xff0c;提供高影响力的业务解决方案&#xff0c;并利用您现有的VCL技能为未来构建下一代应用程…

Hadoop权威指南-读书笔记-03-Hadoop分布式文件系统

Hadoop权威指南-读书笔记 记录一下读这本书的时候觉得有意思或者重要的点~ 还是老样子~挑重点记录哈&#x1f601;有兴趣的小伙伴可以去看看原著&#x1f60a; 第三章 Hadoop分布式文件系统 当数据集的大小超过一台独立的物理计算机的存储能力时&#xff0c;就有必要对它进行分…

【数据结构】(C语言):二叉搜索树(不使用递归)

二叉搜索树&#xff1a; 非线性的&#xff0c;树是层级结构。基本单位是节点&#xff0c;每个节点最多2个子节点。有序。每个节点&#xff0c;其左子节点都比它小&#xff0c;其右子节点都比它大。每个子树都是一个二叉搜索树。每个节点及其所有子节点形成子树。可以是空树。 …

【堆 优先队列】23. 合并 K 个升序链表

本文涉及知识点 堆 优先队列 LeetCode23. 合并 K 个升序链表 给你一个链表数组&#xff0c;每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中&#xff0c;返回合并后的链表。 示例 1&#xff1a; 输入&#xff1a;lists [[1,4,5],[1,3,4],[2,6]] 输出&#…

【Whisper】WhisperX: Time-Accurate Speech Transcription of Long-Form Audio

Abstract Whisper 的跨语言语音识别取得了很好的结果&#xff0c;但是对应的时间戳往往不准确&#xff0c;而且单词级别的时间戳也不能做到开箱即用(out-of-the-box). 此外&#xff0c;他们在处理长音频时通过缓冲转录

「C++系列」C++ 变量作用域

文章目录 一、C 变量作用域二、局部变量三、全局变量四、类作用域五、相关链接 一、C 变量作用域 在C中&#xff0c;变量的作用域&#xff08;Scope&#xff09;指的是变量在程序中可以被访问的区域。作用域由花括号{}定义&#xff0c;这些花括号可以出现在函数体、控制结构&a…

windows安装jdk21

下载 下载zip解压 设置环境变量 设置JAVA_HOME环境变量 Path环境变量添加如下值%HAVA_HOME%\bin 打开新的cmd&#xff0c;输入java --version查看效果

恒创科技:HTTP错误码403禁止意味着什么,怎么修复它?

HTTP错误码403禁止意味着客户端无权访问特定网页或服务器。403 错误表示客户端存在问题&#xff0c;无论用户使用的是哪种网络浏览器&#xff0c;都可能发生这种情况。幸运的是&#xff0c;阻止服务器允许访问特定页面的问题通常可以修复。以下是一些常见原因和相应的解决方案。…

【ROS2】Ubuntu 24.04 源码编译安装 Jazzy Jalisco

目录 系统要求 系统设置 设置区域启用所需的存储库安装开发工具 构建 ROS 2 获取 ROS 2 代码使用 rosdep 安装依赖项安装额外的 RMW 实现&#xff08;可选&#xff09;在工作区构建代码 设置环境 尝试一些例子 下一步 备用编译器 Clang保持最新状态 故障排除 卸载 系统要求 当前…

滤波算法学习笔记

目录 引言 一、定义 二、分类 三、常见滤波算法 四、应用与优势 五、发展趋势 例程 1. 均值滤波&#xff08;Moving Average Filter&#xff09; 2. 中值滤波&#xff08;Median Filter&#xff09; 3. 高斯滤波&#xff08;Gaussian Filter&#xff09; 4.指数移动…

微信开发者工具报错 Error: module ‘xxx.js‘ is not defined, require args is ‘xxx.js‘

背景 报错如下 检查 代码逻辑和写法都是ok的重新打开项目又是可以的 解决方案 先确保微信开发者工具和uniapp的将js编译成es5都开着&#xff08;这个是默认开的&#xff09; 然后把微信开发者工具关了重开 一般做这一步就会好了&#xff0c;但是只是临时解决 &#xff08…

《Winodws API每日一练》8.2 static控件

在 Windows 编程中&#xff0c;"Static" 控件是一种常见的用户界面元素&#xff0c;用于显示静态文本或图像&#xff0c;而无法进行用户交互。它通常用于显示标签、标题、说明文本或静态图像等信息。Static 控件是一种静态的、只读的显示元素&#xff0c;不接受用户的…

秒懂设计模式--学习笔记(6)【创建篇-建造者模式】

目录 5、建造者模式5.1 介绍5.2 建造步骤的重要性5.3 地产开发商的困惑5.4 建筑施工方5.5 工程总监5.6 项目实施5.7 建造者模式的各角色定义5.8 建造者模式 5、建造者模式 5.1 介绍 建造者模式&#xff08;Builder&#xff09;又称为生成器模式&#xff0c;主要用于对复杂对象…

爬虫-豆瓣电影排行榜

获取数据 requests库 获取数据环节需要用到requests库。安装方式也简单 pip install requests 爬取页面豆瓣读书 Top 250 用requests库来访问 import requests res requests.get(https://book.douban.com/top250/) 解析&#xff1a; 导入requests库调用了requests库中的…

明星代言6个提升企业形象的杀手锏-华媒舍

在当今竞争激烈的商业世界中&#xff0c;企业形象的塑造对于品牌的发展至关重要。而明星代言作为一种常见的营销手段&#xff0c;被广泛使用来提升企业形象和产品销售。本文将介绍明星代言的六个杀手锏&#xff0c;帮助您了解如何通过明星代言来提升企业形象。 1. 拥有广泛的影…

关于虚拟机CentOS 7使用ssh无法连接(详细)

虚拟机CentOS 7使用ssh无法连接 猜测&#xff1a;可能是虚拟机软件的网关和和centos7的网关不同导致的问题。 首先打开CentOS7的终端, 输入ifconfig&#xff0c;查看一下系统的ip 打开虚拟机的虚拟网络编辑器, 查看一下网关, 发现确实不一样. 这里有两种方式, 要么修改虚…

Pytorch实战(二):VGG神经网络

文章目录 一、诞生背景二、VGG网络结构2.1VGG块2.2网络运行流程2.3总结 三、实战3.1搭建模型3.2模型训练3.3训练结果可视化3.4模型参数初始化 一、诞生背景 从网络结构中可看出&#xff0c;所有版本VGG均全部使用33大小、步长为1的小卷积核&#xff0c;33卷积核同时也是最小的能…

Java | Leetcode Java题解之第205题同构字符串

题目&#xff1a; 题解&#xff1a; class Solution {public boolean isIsomorphic(String s, String t) {Map<Character, Character> s2t new HashMap<Character, Character>();Map<Character, Character> t2s new HashMap<Character, Character>(…

Java-数据结构

数据结构概述 常见的数据结构 栈 队列 数组 链表 二叉树 二叉查找树 平衡二叉树 红黑树 示例&#xff1a;

【Go】编译frp,绕过内网安全工具

文章目录 概述常用命令编译环境配置开发环境拉取依赖打包exe输出运行打包好的exe测试 绕过安全产品实践frp使用教程 本文所提供的程序(方法)可能带有攻击性&#xff0c;仅供安全研究与教学之用。文章作者无法鉴别判断读者使用信息及工具的真实用途&#xff0c;若读者将文章中的…