QT的绘图系统QPainterDevice与文件系统QIODevice

news2024/11/15 21:35:38

QT的绘图系统(QPainterDevice)与文件系统(QIODevice)

文章目录

  • 1、Qt 的绘图系统
    • 1、QPainter的使用
    • 2、QPen(画笔)及QBursh(画刷)
    • 3、手动更新窗口
    • 4、绘图设备
        • 1、四种绘图设备的 区别
        • 2、 QBitmap
        • 3、QPixmap
        • 4、 QImage
        • 5、QPicture
        • 6、QImage与QPixmap的转换
  • 2、不规则窗口
  • 3、文件系统
    • 1、QFile文件的读写
    • 2、QT的QString与QByteArray以及char *的相互转换
    • 3、文件信息QFileInfo类
    • 4、二进制文件读写 QDataStream类(打开是看不懂)
    • 5、文本文件读写QTextStream类
    • 6、内存读写QBuffer类
  • 4、总结


1、Qt 的绘图系统

Qt 的绘图系统允许使用相同的 API 在屏幕和其它打印设备上进行绘制。整个绘图系统基于QPainterQPainterDeviceQPaintEngine三个类。
在这里插入图片描述
下图给出了这三个类之间的层次结构:
在这里插入图片描述
上面的示意图告诉我们,Qt 的绘图系统实际上是,使用QPainter在QPainterDevice上进行绘制,它们之间使用QPaintEngine进行通讯(也就是翻译QPainter的指令)。

1、QPainter的使用

对窗口绘图首先要重写**void paintEvent(QPaintEvent *)**虚函数。

  1. 重写绘图事件,虚函数
  2. 如果在窗口绘图,必须放在绘图事件里实现
  3. 绘图事件内部自动调用,窗口需要重绘的时候(状态改变)
void MyWidget::paintEvent(QPaintEvent *)
{
    QPainter p(this);//指定当前窗口为绘图设备
    p.drawPixmap(rect(), QPixmap("../Image/bk.jpg"));     //画背景图
    //画直线
    p.drawLine(50, 50, 150, 50); /* 在坐标50,50的位置画长150,宽50的线 */
    p.drawLine(50, 50, 50, 150);
    //画矩形;l;d
    p.drawRect(150, 150, 100, 50);
    //画圆形
    p.drawEllipse(QPoint(150, 150), 50, 25);
}

注意:在上层目录要有背景图的存在。要先画背景图在画直线,矩形,圆形。
指定QQidget对象为绘图对象。即窗口是绘图设备。QQidget继承与QPaintDevice.
在这里插入图片描述

2、QPen(画笔)及QBursh(画刷)

QPainter有很多以 draw 开头的函数,用于各种图形的绘制,比如drawLine(),drawRect()以及drawEllipse()等。
如果需要设置画家的颜色,风格,线条的粗细。从而引入画笔。如果需要填充图形的颜色需要画刷

void MyWidget::paintEvent(QPaintEvent *)
{
    QPainter p(this);//指定当前窗口为绘图设备
    //画背景图
    p.drawPixmap(rect(), QPixmap("../Image/bk.jpg"));

    //定义画笔
    QPen pen;
    pen.setWidth(5); //设置线宽
    pen.setColor( QColor(14, 9, 234) );//rgb设置颜色
    pen.setStyle(Qt::DashLine); //设置风格
    p.setPen(pen); //把画笔交给画家

    QBrush brush; //创建画刷对象
    brush.setColor(Qt::red); //设置颜色
    brush.setStyle(Qt::Dense1Pattern);//设置样式
    p.setBrush(brush);//把画刷交给画家

    //画直线
    p.drawLine(50, 50, 150, 50); /* 在坐标50,50的位置画长150,宽50的线 */
    p.drawLine(50, 50, 50, 150);
    //画矩形;l;d
    p.drawRect(200, 200, 100, 50);
    //画圆形
    p.drawEllipse(QPoint(150, 150), 50, 25);
}

3、手动更新窗口

当我们在窗口绘制的图不断变化时。需要不断地刷新窗口才会有变化。否则不会有。
mywidget.h

class MyWidget : public QWidget
{
    Q_OBJECT
public:
    MyWidget(QWidget *parent = nullptr);
    ~MyWidget();
    void paintEvent(QPaintEvent *);
private:
    int x;
    QPushButton *button;
private slots:
    void FunSlot(void);
private:
    Ui::MyWidget *ui;
};

mywidget.cpp

#include "mywidget.h"
#include "ui_mywidget.h"
#include <QPainter>

MyWidget::MyWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MyWidget)
{
    ui->setupUi(this);
    x = 0;
    QPushButton *button = new QPushButton(this);
    button->setText("向右移动");
    connect(button, &QPushButton::pressed, this, &MyWidget::FunSlot);
}

MyWidget::~MyWidget()
{
    delete ui;
}

void MyWidget::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    //画笑脸
    p.drawPixmap(x, 180, 80, 80, QPixmap("../Image/face.png"));

}
void MyWidget::FunSlot(void)
{
    x += 20;
    if(x > width()- 80)
    {
        x = 0;
    }
    //刷新窗口,让窗口重绘,整个窗口都刷新
    update(); //间接调用paintEvent()
}

点击按钮绘图不断向右移动变化。到窗口终点又回到起点。

4、绘图设备

1、四种绘图设备的 区别

绘图设备是指继承QPainterDevice的子类。Qt一共提供了四个这样的类,分别是QPixmap、QBitmap、QImage和 QPicture。
在这里插入图片描述
**QBitmap:**是QPixmap的一个子类,它的色深限定为1,可以使用 QPixmap的isQBitmap()函数来确定这个QPixmap是不是一个QBitmap。
总结:它们操作都方法都是差不多一样的。

2、 QBitmap

QBitmap只有黑白两种颜色。

void MyWidget::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    //QPixmap 图片背景透明
    p.drawPixmap(0, 0, QPixmap("../Image/face.png"));
    //QBitmap 图片背景透明
    p.drawPixmap(200, 0, QBitmap("../Image/face.png"));

    //QPixmap 图片背景白色
    QPixmap pixmap;
    pixmap.load("../Image/image.jpg");
    p.drawPixmap(0, 200, pixmap);

    //QBitmap 图片背景白色
    QBitmap bitmap;
    bitmap.load("../Image/image.jpg");
    p.drawPixmap(400, 200, bitmap);
}

在这里插入图片描述
右边为QBitmap 左边为QPixmap。上面的QBitmap为黑色背景。下面为QBitmap的白色背景。

3、QPixmap

如下在QPixmap绘图而不是在窗口。不用重写绘图事件。在构造函数里实现即可。

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MyWidget)
{
    ui->setupUi(this);
    //绘图设备, 400*300
    QPixmap pixmap(400, 300);

    QPainter p(&pixmap);
    //画笔填充白色背景色
    //p.fillRect(0, 0, 400, 300, QBrush(Qt::white));

    //画家填充白色背景色
    pixmap.fill(Qt::white);

    p.drawPixmap(0, 0, 80, 80, QPixmap("../Image/face.png"));

    //上层路径保存图片
    pixmap.save("../pixmap.jpg");
}

在上层目录生成pixmap.jpg文件。
在这里插入图片描述

4、 QImage

QImage可以对像素点进行操作。

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    //创建一个绘图设备,QImage::Format_ARGB32背景是透明
    QImage image(400, 300, QImage::Format_ARGB32);
    QPainter p;
    p.begin(&image);
    //绘图
    p.drawImage(0, 0, QImage("../Image/image.jpg"));
    //对绘图设备前50个像素点进行操作
    for(int i = 0; i < 50; i++)
    {
        for(int j = 0; j < 50; j++)
        {
            image.setPixel(QPoint(i, j), qRgb(0, 255, 0)); /* 设置像素点 */
            //image.pixel(QPoint(i, j)); /* 获取像素点 */
        }
    }
    p.end();
    image.save("../image.png"); // 保存图片
}

在上层目录生成image.png文件。绿色部分为对像素点的操作。
在这里插入图片描述

5、QPicture
MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MyWidget)
{
    ui->setupUi(this);
    QPicture picture;
    QPainter p;
    p.begin(&picture);

    p.drawPixmap(0, 0, 80, 80, QPixmap("../Image/face.png"));
    p.drawLine(50, 50, 150, 50);

    p.end();

    //保存的是二进制文件
    picture.save("../picture.png");
}

在这里插入图片描述
在上层路径生成picture.png的二进制文件。
二进制打开也看不出效果。我们在窗口里加载出来。重写绘图事件。

void MyWidget::paintEvent(QPaintEvent *)
{
    QPicture pic;
    pic.load("../picture.png"); //加载二进制picture.png文件
    QPainter p(this);
    p.drawPicture(0, 0, pic);
}

运行结果如下:
在这里插入图片描述

6、QImage与QPixmap的转换

在对屏幕进行优化可能需要用到QPixmap。在传输可能需要用到QImage。

void MyWidget::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    QPixmap pixmap;
    pixmap.load("../Image/face.png");
    //QPixmap -> QImage
    QImage tempImage = pixmap.toImage();
    p.drawImage(0, 0, tempImage);
    QImage image;
    image.load("../Image/face.png");
    //QImage -> QPixmap
    QPixmap tempPixmap = QPixmap::fromImage(image);
    p.drawPixmap(200, 0, tempPixmap);
}

运行结果:
在这里插入图片描述
第一张是通过QPixmap转QImage画的。第二张是通过QImage转QPixmap画的。

2、不规则窗口

常见的窗体是各种方形的对话框,但有时候也需要非方形的窗体,如圆形,椭圆甚至是不规则形状的对话框。
widget.h

class Widget : public QWidget
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

protected:
    void paintEvent(QPaintEvent *);
    void mouseMoveEvent(QMouseEvent *e);
    void mousePressEvent(QMouseEvent *e);
private:
    QPoint p;
private:
    Ui::Widget *ui;
};

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QMouseEvent>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    //去窗口表框Qt::FramelessWindowHint   windowFlags()其它属性不变
    setWindowFlags(Qt::FramelessWindowHint | windowFlags());

    //把窗口背景设置为透明
    setAttribute(Qt::WA_TranslucentBackground);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    p.drawPixmap(0, 0, QPixmap("../Image/sunny.png"));
}

void Widget::mousePressEvent(QMouseEvent *e)
{
    if(e->button() == Qt::RightButton)
    {
        //如果是右键
        close();
    }
    else if(e->button() == Qt::LeftButton)
    {
        //求坐标差值
        //当前点击坐标(屏幕)-窗口左上角坐标
        p = e->globalPos() - this->frameGeometry().topLeft();
    }
}

void Widget::mouseMoveEvent(QMouseEvent *e)
{
    /* 移动加鼠标左键按下 */
    if(e->buttons() & Qt::LeftButton)
    {
       move(e->globalPos() - p); // 当前点击坐标(屏幕) -  求坐标差值
    }
}

当鼠标左键按下移动无规则窗口跟着移动。鼠标右键按下则无规则窗口关闭。
如下图片关于上面代码的坐标计算的示意图
在这里插入图片描述

3、文件系统

文件操作是应用程序必不可少的部分。Qt 作为一个通用开发库,提供了跨平台的文件操作能力。Qt 通过QIODevice提供了对 I/O 设备的抽象,这些设备具有读写字节块的能力。下面是 I/O 设备的类图(Qt5):
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1、QFile文件的读写

QFile提供了从文件中读取和写入数据的能力。
我们通常会将文件路径作为参数传给QFile的构造函数。不过也可以在创建好对象最后,使用setFileName()来修改。
ui界面如下:
在这里插入图片描述
功能:把读取到文件显示在文本框里。把文本框里的内容保存成文件。

#include "mywidget.h"
#include "ui_mywidget.h"
#include<QFile>
#include<QFileDialog>
#include<QDebug>

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MyWidget)
{
    ui->setupUi(this);
    connect(ui->pushButtonRead, &QPushButton::pressed, this, &MyWidget::ReadSlot);
    connect(ui->pushButtonWrite, &QPushButton::pressed, this, &MyWidget::WriteSlot);
}

MyWidget::~MyWidget()
{
    delete ui;
}

void MyWidget::ReadSlot(void)
{
    QString path = QFileDialog::getOpenFileName(this,"open", "../", "TXT(*.txt)");
    if(path.isEmpty() == false)
    {
        //文件对象
        QFile file(path);

        //打开文件,只读方式
        bool isOk = file.open(QIODevice::ReadOnly);
        if(isOk == true)
        {
// 一次读取全部
#if 0 \
    //读文件,默认只识别utf8编码 在文件流才可以改变编码格式
            QByteArray array = file.readAll();
            //显示到编辑区
            //ui->textEdit->setText(QString(array));
            //ui->textEdit->setText(array);
#endif

            // 一次读取一行
            QByteArray array;
            while( file.atEnd() == false)
            {
                //读一行
                array += file.readLine();
            }
            ui->textEdit->setText(array);

        }

        //关闭文件
        file.close();
    }
}

void MyWidget::WriteSlot(void)
{
    QString path = QFileDialog::getSaveFileName(this, "save", "../", "TXT(*.txt)");
    if(path.isEmpty() == false)
    {
        QFile file; //创建文件对象
        //关联文件名字
        file.setFileName(path);
        //打开文件,只写方式
        bool isOk = file.open(QIODevice::WriteOnly); /* 有就打开否则创建 */
        if(isOk == true)
        {
            //获取编辑区内容
            QString str = ui->textEdit->toPlainText();
            //写文件
            file.write(str.toUtf8());
        }
        file.close();
    }
}

2、QT的QString与QByteArray以及char *的相互转换

            // QString -> QByteArray
            file.write(str.toUtf8());

            //QString -> c++ string -> char *
            file.write(str.toStdString().data());

            //转换为本地平台编码
            file.write(str.toLocal8Bit());


            //QString -> QByteArray
            QString buf = "123";
            QByteArray a = buf.toUtf8(); //中文
            a = buf.toLocal8Bit(); //本地编码

            //QByteArray -> char *
            char *b = a.data();

            //char * -> QString
            char *p = "abc";
            QString c = QString(p);

3、文件信息QFileInfo类

在这里插入图片描述

#include <QFileDialog>
#include <QFileInfo>
#include <QDebug>
#include <QDateTime>
    QString path = QFileDialog::getOpenFileName(this, "open", "../");
    if(path.isEmpty() == false)
    {
    //获取文件信息
        QFileInfo info(path);
        qDebug() << "文件名字:" << info.fileName().toUtf8().data();
        qDebug() << "文件后缀:" << info.suffix();
        qDebug() << "文件大小:" << info.size();
        qDebug() << "文件创建时间:" <<info.birthTime().toString("yyyy-MM-dd hh:mm:ss"); //2024-01-04 15:13:00
    }

4、二进制文件读写 QDataStream类(打开是看不懂)

在这里插入图片描述
mywidget.h

#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class MyWidget; }
QT_END_NAMESPACE

class MyWidget : public QWidget
{
    Q_OBJECT

public:
    MyWidget(QWidget *parent = nullptr);
    ~MyWidget();
    void writeData();
    void readData();
private:
    Ui::MyWidget *ui;
};

mywidget.cpp

#include "mywidget.h"
#include "ui_mywidget.h"
#include <QDataStream>
#include <QFile>
#include <QDebug>
#define cout qDebug() << "[" << __FILE__ <<":" << __LINE__ << "]"

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MyWidget)
{
    ui->setupUi(this);
    writeData();
    readData();
}

MyWidget::~MyWidget()
{
    delete ui;
}

void MyWidget::writeData()
{
    //创建文件对象
    QFile file("../hello.txt");

    //打开文件, 只写方式打开
    bool isOk = file.open(QIODevice::WriteOnly);
    if(true == isOk)
    {
        //创建数据流,和file文件关联
        //往数据流中写数据,相当于往文件里写数据
        QDataStream stream(&file);

        stream << QString("你好") << 777;

        file.close();

    }

}

void MyWidget::readData()
{
    //创建文件对象
    QFile file("../hello.txt");

    //打开文件, 只读方式打开
    bool isOk = file.open(QIODevice::ReadOnly);
    if(true == isOk)
    {
        //创建数据流,和file文件关联
        //往数据流中读数据,相当于往文件里读数据
        QDataStream stream(&file);
        //读的时候,按写的顺序取数据
        QString str;
        int a;
        stream >> str >> a;
        //qDebug() << str.toUtf8().data() << a;
        cout << str.toUtf8().data() << a;

        file.close();
    }
}

先写入数据流(二进制形式),然后以写的顺序读出来。
需要注意的是,你必须按照写入的顺序,将数据读取出来。顺序颠倒的话,程序行为是不确定的,严重时会直接造成程序崩溃。
那么,既然QIODevice提供了read()、readLine()之类的函数,为什么还要有QDataStream呢?QDataStream同QIODevice有什么区别?区别在于,QDataStream提供流的形式,性能上一般比直接调用原始 API 更好一些。

5、文本文件读写QTextStream类

在这里插入图片描述
ui界面:
在这里插入图片描述

widget.h

#include <QWidget>

namespace Ui {
class Widget;
}
class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
    void writeData();
private slots:
    void on_pushButton_clicked();
private:
    Ui::Widget *ui;
};

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QTextStream>
#include <QFile>
#include <QDebug>
#include <QFileDialog>
#define cout qDebug() << "[" << __FILE__ <<":" << __LINE__ << "]"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    writeData();

}

Widget::~Widget()
{
    delete ui;
}

void Widget::writeData()
{
    QFile file;
    file.setFileName("../TextStream.txt");

    bool isOk = file.open(QIODevice::WriteOnly);
    if(true == isOk)
    {
        QTextStream stream(&file);
        //指定编码
        stream.setEncoding(QStringConverter::Utf8);

        stream << QString("你好") << 777;

        file.close();
    }
}

void Widget::on_pushButton_clicked()
{
    QString path = QFileDialog::getOpenFileName(this,
             "open", "../"  );
    if(false == path.isEmpty())
    {
        QFile file;
        file.setFileName(path);

        bool isOk = file.open(QIODevice::ReadOnly);
        if(true == isOk)
        {
            QTextStream stream(&file);
            //指定编码
            stream.setEncoding(QStringConverter::Utf8);
            QString str = stream.readAll();
            ui->textEdit->setText(str);
            file.close();
        }

    }
}

当使用QDataStream写入的时候,实际上会在要写入的内容前面,额外添加一个这段内容的长度值。而以文本形式写入数据,是没有数据之间的分隔的。因此,使用文本文件时,很少会将其分割开来读取,而是使用诸如使用:
QTextStream::readLine() 读取一行
QTextStream::readAll()读取所有文本。

6、内存读写QBuffer类

    QByteArray array;
    QBuffer memFile(&array); //创建内存文件 还指定QByteArray对象
    memFile.open(QIODevice::WriteOnly);
    memFile.write("5455454");
    memFile.write("6564565");
    memFile.close();
    qDebug() << memFile.buffer();
    qDebug() << "array:" << array;

写进了内存也保存在了指定的QByteArray对象里。

QBuffer与QDataStream一起操作dome。

    QBuffer memFile1;
    memFile1.open(QIODevice::WriteOnly); /* 只写 */
    QDataStream stream(&memFile1); /* QBuffer与QDataStream关联 */
    stream << QString("测试") << 999;
    memFile1.close();/* 关闭文件 */
    qDebug() <<  memFile1.buffer();
    
    memFile1.open(QIODevice::ReadOnly); /* 只读 */
    QDataStream in;
    in.setDevice(&memFile1);
    QString str;
    int a;
    in >> str >> a;
    memFile1.close(); /* 关闭文件 */
    qDebug() << str.toUtf8().data() << a;
    qDebug() <<  memFile1.buffer();

运行结果:
在这里插入图片描述

4、总结

例如:以上就是今天要讲的内容,本文仅仅简单介绍了QT的绘图系统与文件系统。

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

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

相关文章

革新区块链:代理合约与智能合约升级的未来

作者 张群&#xff08;赛联区块链教育首席讲师&#xff0c;工信部赛迪特聘资深专家&#xff0c;CSDN认证业界专家&#xff0c;微软认证专家&#xff0c;多家企业区块链产品顾问&#xff09;关注张群&#xff0c;为您提供一站式区块链技术和方案咨询。 代理合约&#xff08;Prox…

使用Go语言编写HTTP代理服务器

在Go语言中&#xff0c;编写一个HTTP代理服务器相对简单且直观。代理服务器的主要职责是接收客户端的请求&#xff0c;然后将请求转发到目标服务器&#xff0c;再将目标服务器的响应返回给客户端。下面是一个简单的示例&#xff0c;展示如何使用Go语言编写一个基本的HTTP代理服…

地方债务余额数据,Shp、excel格式,2008-2020年,含公共财政收入、支出、负债率等多个字段

基本信息&#xff1a; 数据名称: 地方债务余额数据 数据格式: Shp、excel 数据时间: 2008-2020年 数据几何类型: 面 数据坐标系: WGS84 数据来源&#xff1a;网络公开数据 数据字段&#xff1a; 序号字段名称字段说明1zfzqsl地方政府债-债券数量(只)2zfzqye地方政府…

美团收银餐饮版培训教程

硬件连接方式及介绍: 双屏收银机 收银一体机 双屏收银机连接图 收银一体机连接图 前台打印机 后厨打印机 标签打印机 前台打印机连接图 后厨打印机连接图 其它收银机配件 软件前期设置 1、机器联网 点开桌面的设置&#xff0c;点击更多&#xff0c;点击以太网&#xff0c;最上…

杭电网课笔记

技巧 1.判断得数为整数还是小数&#xff0c;可以%1&#xff0c;得数为0是整数 或者用instanceof Integer number 9; // 自动装箱 System.out.println(number instanceof Integer); // 输出&#xff1a;true 2.a * b 最大公约数 * 最小公倍数 LCM 最小公倍数 GCD 最大公…

聊聊Java虚拟机(一)—— 类加载子系统

1. 前言 ​ 虚拟机就是一款用来执行虚拟计算机指令的计算机软件。它相当于一台虚拟计算机。大体上&#xff0c;虚拟机分为系统虚拟机和程序虚拟机。系统虚拟机就相当于一台物理电脑&#xff0c;里面可以安装操作系统&#xff1b;程序虚拟机是为了执行单个计算机程序而设计出来…

FPGA之分布式RAM(2)

1) 128 X1 Single Port Distributed RAM 下图中可以看出来,通过2个LUT的组合使用可以串联实现更大深度的分布式RAM.下图中出现了F7BMUX的加入, F7BMUX可以用于LUT输出的选通. 原语调用&#xff1a; RAM128XIS#(INIT(128h00000000000000000000000000000000) // Initial conten…

动态规划——炮兵回城【集训笔记】

题目描述 游戏盘面是一个m行n列的方格矩阵&#xff0c;将每个方格用坐标表示&#xff0c;行坐标从下到上依次递增&#xff0c;列坐标从左至右依次递增&#xff0c;左下角方格的坐标为(1,1)&#xff0c;则右上角方格的坐标为(m,n)。 游戏结束盘上只剩下一枚炮兵没有回到城池中&a…

ERP系统哪个好用?用友,金蝶,ORACLE,SAP综合测评

ERP系统哪个好用&#xff1f;用友&#xff0c;金蝶&#xff0c;ORACLE&#xff0c;SAP综合测评 ERP领域SAP、ORACLE相对于国内厂商如用友、金蝶优势在哪&#xff1f; SAP&#xff0c;ORACLE操作习惯一般国人用不惯&#xff1b;相对于国产软件&#xff0c;界面也很难看&#x…

深入理解C语言(2):字符、字符串与内存函数

文章主题&#xff1a;字符、字符串与内存函数&#x1f30f;所属专栏&#xff1a;深入理解C语言&#x1f4d4;作者简介&#xff1a;更新有关深入理解C语言知识的博主一枚&#xff0c;记录分享自己对C语言的深入解读。&#x1f606;个人主页&#xff1a;[₽]的个人主页&#x1f3…

buctoj——2024寒假集训 进阶训练赛 (五)

问题 A: 约瑟夫问题 题目描述 N个人围成一圈&#xff0c;从第一个人开始报数&#xff0c;数到M的人出圈&#xff1b;再由下一个人开始报数&#xff0c;数到M的人出圈&#xff1b;……输出依次出圈的人的编号。N&#xff0c;M由键盘输入。 输入 一行&#xff0c;包含两个正整数…

C++中命名空间、缺省参数、函数重载

目录 1.命名空间 2.缺省参数 3.函数重载 1.命名空间 在C中定义命名空间我们需要用到namespace关键字&#xff0c;后面跟上命名空间的名字&#xff0c;结构框架有点类似结构体&#xff08;如图所示&#xff09; 上面的代码我一一进行讲解&#xff1a; 1.我们先来说第三行和main函…

shopee智利选品:如何在Shopee智利站点上进行有效的选品

在Shopee智利站点进行选品时&#xff0c;卖家需要采取一系列策略来提高产品的市场接受度和销售潜力。以下是一些建议&#xff0c;可以帮助卖家在Shopee智利站点上进行有效的选品。 先给大家推荐一款shopee知虾数据运营工具知虾免费体验地址&#xff08;复制浏览器打开&#xf…

多场景建模:阿里多场景多任务元学习方法M2M

multi-scenario multi-task meta learning approach (M2M) 背景 广告领域大部分是针对用户建模的&#xff0c;像点击率预估&#xff0c;很少有针对广告主需求建模&#xff08;广告消耗预估、活跃率/流失率预估、广告曝光量预估&#xff09;&#xff0c;广告的类型较多&#x…

GPU与SSD间的P2P DMA访问机制

基于PCIe&#xff08;Peripheral Component Interconnect Express&#xff09;总线连接CPU、独立GPU和NVMe SSD的系统架构。 在该架构中&#xff0c;PCIe Swicth支持GPU与SSD之间快速的点对点直接内存访问&#xff08;peer-to-peer, p2p DMA&#xff09;。通常情况下&#xff0…

Verilog基础:强度建模与net型信号的多驱动问题(三)

相关阅读 Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm1001.2014.3001.5482 四、一般情况下的net型信号的线与组合&#xff08;线网多驱动&#xff09; 在Verilog基础&#xff1a;强度建模与net型信号的多驱动问题&#xff08;二&#xff0…

【Redis】更改redis中的value值

今天继续进步一点点~~ 背景&#xff1a;今天有个前端的同事问我&#xff0c;能不能在Redis中他本人登录公众号的 sessionID 加上一列openID 于是我上网查了一堆在Redis里面的命令&#xff0c;以及不同的客户端怎么输入命令&#xff0c;但是后来问了下同事&#xff0c;他就给我…

压缩字符串

#include <iostream> using namespace std; int main() {// 请在此输入您的代码string a;int f 1, count;cin >> a;for (int i 0; a[i]; i) {if (a[i] a[i 1]) {f 0; count 1;for (i; a[i] a[i 1]; i)count 1;cout << a[i] << count;}if (cou…

vivado JTAG链、连接、IP关联规则

JTAG链 这列出了定义板上可用的不同JTAG链。每个链都列在下面<jtag_chain>以及链的名称&#xff0c;以及定义名称和链中组件的位置&#xff1a; <jtag_chains> <jtag_chain name"chain1"> <position name"0" component"part0…

RK3568笔记十:Zlmediakit交叉编译

若该文为原创文章&#xff0c;转载请注明原文出处。 编译Zlmediakit的主要目的是想实现在RK3568拉取多路RTPS流&#xff0c;并通过MPP硬解码&#xff0c;DRM显示出来。为了实现拉取多路流选择了Zlmediakit,使用FFMEPG也可以&#xff0c;在RV1126上已经验证了可行性。 一、环境…