【QT5】<总览五> QT多线程、TCP/UDP

news2024/12/24 3:13:17

文章目录

前言

一、QThread多线程

二、QT中的TCP编程

1. TCP简介

2. 服务端程序编写

3. 客户端程序编写

4. 服务端与客户端测试

三、QT中的UDP编程

1. UDP简介

2. UDP单播与广播程序


前言

承接【QT5】<总览四> QT常见绘图、图表及动画。若存在版权问题,请联系作者删除!


一、QThread多线程

1. 作用:创建多线程,防止应用程序界面卡顿。

2. 主要操作:

  • ①创建的类需要继承QThread类。
  • ②重写run函数,新建的线程会执行run函数。
  • ③线程开启:对象调用start方法,使线程执行run函数。
  • ④线程终止:对象调用terminate方法,使线程不再执行run函数。
  • ⑤线程销毁:动态申请new需要调用deleteLater方法销毁线程对象。(该函数可以放置于run函数内,当run函数执行完毕后就会销毁该线程对象,防止内存泄漏)注意:尽量少用静态申请栈空间的方式创建线程对象,因为很可能该对象销毁时线程仍在执行,就会报错。

3. 实例演示:创建两个按钮,一个按钮点击时创建新线程,另一个按钮点击时终止新线程。

【1】widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QThread>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE


//自定义的线程类
class MyThread : public QThread
{
    Q_OBJECT

public:
    MyThread(QWidget *parent = nullptr){
        Q_UNUSED(parent)//防止编译器警告
    }

    ~MyThread(){
        qDebug("线程销毁");
    }

    void run() override{
        qDebug("线程开始");
        sleep(5);//QThread里才有该方法
        qDebug("线程停止");
        deleteLater();//销毁线程
    }
};


//Widget类
class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

private:
    Ui::Widget *ui;
    MyThread *mythread;
};
#endif // WIDGET_H

【2】widget.cpp:

#include "widget.h"
#include "ui_widget.h"

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

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

//“线程开始”按钮的槽函数
void Widget::on_pushButton_clicked()
{
    mythread = new MyThread;
    mythread->start();
}

//“线程终止”按钮的槽函数
void Widget::on_pushButton_2_clicked()
{
    //若线程没有完成,则终止
    if (!mythread->isFinished())
        mythread->terminate();
}

【3】运行效果:

  • ①当我们点击“线程开始”按钮后,控制台打印“线程开始”,五秒后控制台打印“线程停止”和“线程销毁”。
  • ②当我们点击“线程开始”按钮后,控制台打印“线程开始”,当我们在五秒内点击“线程结束”按钮,控制台什么都没有打印。

二、QT中的TCP编程

1. TCP简介

  • TCP是面向连接的可靠的基于字节流的传输层通信协议。
  • TCP的服务端和客户端通信首先必须建立连接
  • 建立连接方式:服务端监听某个端口,当有客户端通过ip和port连接时,就会创建一个socket连接,之后就可以互发数据了。
  • QT中将socket视为输入输出流,数据的收发是通过read()write()来进行,而不是常见的send和recv。

----------------------------接下来,我们以一个实例来解析服务端和用户端程序编写-------------------------

2. 服务端程序编写

2.1 编写步骤:

【1】配置:①pro文件中添加network;②添加头文件<QTcpServer>和<QTcpSocket>。

【2】创建服务端对象:QTcpServer *tcpServer;(具体分配空间在构造函数中)

【3】服务端-客户端的信号槽连接:connect(tcpServer, SIGNAL(newConnection()), this, SLOT(mNewConnection()));

【4】编写【3】中的槽函数mNewConnection():

  • ①获取客户端对象:QTcpSocket *tmpTcpSocket = tcpServer->nextPendingConnection();
  • ②获取客户端信息:
    • 获取客户端ip:tmpTcpSocket->peerAddress().toString();
    • 获取客户端port:tmpTcpSocket->peerPort();
  • ③创建信号槽来处理客户端的连接状态:connect(tmpTcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(mStateChanged(QAbstractSocket::SocketState)));
  • ④创建信号槽来接收客户端发送的信息:connect(tmpTcpSocket, SIGNAL(readyRead()), this, SLOT(receiveMessage()));

【5】编写【4】中的槽函数mStateChanged(...):用switch-case结构来处理连接状态,当状态为断开连接时,删除当前调用的客户端对象。

【6】编写【4】中的槽函数receiveMessage():调用tmpTcpSocket->readAll()来获取客户端发送的信息。

【7】创建函数来给客户端发送数据:内部调用"客户端对象.write("写入的内容")"。

【8】开始监听:调用tcpServer->listen(QHostAddress("192.168.124.151"), 9999); 监听ip为192.168.124.151,port为9999。

2.2 编写代码:

【1】widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void mNewConnection();
    void receiveMessage();
    void mStateChanged(QAbstractSocket::SocketState socketState);
    void on_pushButton_3_clicked();
    void on_pushButton_clicked();
    void on_pushButton_2_clicked();

private:
    Ui::Widget *ui;
    QTcpServer *tcpServer;
};
#endif // WIDGET_H

【2】widget.cpp:

#include "widget.h"
#include "ui_widget.h"


/***********************************************************
  * @函数名:Widget
  * @功  能:构造函数---创建服务端对象,与客户端连接
  * @参  数:parent---父对象
  * @返回值:无
  *********************************************************/
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("服务端");
    //创建对象,与客户端连接
    tcpServer = new QTcpServer(this);
    connect(tcpServer, SIGNAL(newConnection()), this, SLOT(mNewConnection()));
}


/***********************************************************
  * @函数名:~Widget
  * @功  能:析构函数
  * @参  数:无
  * @返回值:无
  *********************************************************/
Widget::~Widget()
{
    delete ui;
}


/***********************************************************
  * @函数名:mNewConnection
  * @功  能:槽函数---若客户端发起连接,服务端连接客户端
  * @参  数:无
  * @返回值:无
  *********************************************************/
void Widget::mNewConnection()
{
    //获取客户端
    QTcpSocket *tmpTcpSocket = tcpServer->nextPendingConnection();
    //打印客户端的ip和port
    QString ipAddr = tmpTcpSocket->peerAddress().toString();
    quint16 port = tmpTcpSocket->peerPort();
    ui->textBrowser->append("客户端的ip地址:" + ipAddr);
    ui->textBrowser->append("客户端的端口:" + QString::number(port));
    //处理客户端连接状态,接收客户端发送的数据
    connect(tmpTcpSocket, SIGNAL(readyRead()), this, SLOT(receiveMessage()));
    connect(tmpTcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
            this, SLOT(mStateChanged(QAbstractSocket::SocketState)));
}


/***********************************************************
  * @函数名:receiveMessage
  * @功  能:槽函数---服务端接收客户端发送的数据
  * @参  数:无
  * @返回值:无
  *********************************************************/
void Widget::receiveMessage()
{
    QTcpSocket *tmpTcpSocket = (QTcpSocket*)sender();
    ui->textBrowser->append("客户端:" + tmpTcpSocket->readAll());
}


/***********************************************************
  * @函数名:mStateChanged
  * @功  能:槽函数---服务端处理客户端的连接状态
  * @参  数:socketState---客户端连接状态
  * @返回值:无
  *********************************************************/
void Widget::mStateChanged(QAbstractSocket::SocketState socketState)
{
    QTcpSocket *tmpTcpSocket = (QTcpSocket*)sender();
    //处理状态,删除断开的QTcpSocket对象
    switch (socketState) {
    case QAbstractSocket::UnconnectedState://断开连接,删除对象
        ui->textBrowser->append("客户端断开连接");
        tmpTcpSocket->deleteLater();
        break;
    case QAbstractSocket::ConnectedState://已连接
        ui->textBrowser->append("客户端已连接");
        break;
    default:
        break;
    }
}


/***********************************************************
  * @函数名:on_pushButton_3_clicked
  * @功  能:按钮"发送消息"的槽函数,将文本信息发送给所有客户端
  * @参  数:无
  * @返回值:无
  *********************************************************/
void Widget::on_pushButton_3_clicked()
{
    QList <QTcpSocket*> clients = tcpServer->findChildren<QTcpSocket*>();
    for (int i = 0; i < clients.length(); ++i) {
        clients[i]->write(ui->lineEdit->text().toUtf8());
    }
}


/***********************************************************
  * @函数名:on_pushButton_clicked
  * @功  能:按钮"开始监听"的槽函数,监听指定的ip和port
  * @参  数:无
  * @返回值:无
  *********************************************************/
void Widget::on_pushButton_clicked()
{
    tcpServer->listen(QHostAddress("192.168.124.151"), 9999);
}


/***********************************************************
  * @函数名:on_pushButton_2_clicked
  * @功  能:按钮"停止监听"的槽函数
  * @参  数:无
  * @返回值:无
  *********************************************************/
void Widget::on_pushButton_2_clicked()
{
    tcpServer->close();
}

3. 客户端程序编写

3.1 编写步骤:

【1】配置:①pro文件中添加network;②添加头文件<QTcpSocket>和<QHostAddress>。

【2】创建客户端对象:QTcpSocket *tcpSocket;(具体分配空间在构造函数中)

【3】创建信号槽来处理客户端的连接状态:connect(tcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(mStateChanged(QAbstractSocket::SocketState)));

【4】创建信号槽来接收客户端发送的信息:connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(receiveMessage()));

【5】编写【3】中的槽函数mStateChanged(...):switch-case处理。

【6】编写【4】中的槽函数receiveMessage(): 调用tcpSocket->readAll().

【7】创建函数来给服务端发送数据:内部调用"客户端对象.write("写入的内容")"。

【8】启动连接服务端:调用tcpSocket->connectToHost(QHostAddress("192.168.124.151"), 9999);

【9】断开连接服务端:调用tcpSocket->disconnectFromHost();

3.2 编写代码:

【1】widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpSocket>
#include <QHostAddress>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void receiveMessage();
    void mStateChanged(QAbstractSocket::SocketState socketstate);
    void on_pushButton_3_clicked();
    void on_pushButton_clicked();
    void on_pushButton_2_clicked();

private:
    Ui::Widget *ui;
    QTcpSocket *tcpSocket;
};
#endif // WIDGET_H

【2】widget.cpp:

#include "widget.h"
#include "ui_widget.h"


/***********************************************************
  * @函数名:Widget
  * @功  能:构造函数---创建客户端对象,与服务端连接
  * @参  数:parent---父对象
  * @返回值:无
  *********************************************************/
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    //ui部分
    ui->setupUi(this);
    this->setWindowTitle("客户端");
    ui->pushButton->setEnabled(true);
    ui->pushButton_2->setEnabled(false);
    //tcp部分
    tcpSocket = new QTcpSocket(this);
    connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(receiveMessage()));
    connect(tcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
            this, SLOT(mStateChanged(QAbstractSocket::SocketState)));
}


/***********************************************************
  * @函数名:~Widget
  * @功  能:析构函数
  * @参  数:无
  * @返回值:无
  *********************************************************/
Widget::~Widget()
{
    delete ui;
}


/***********************************************************
  * @函数名:receiveMessage
  * @功  能:槽函数---客户端接收服务端发送的数据
  * @参  数:无
  * @返回值:无
  *********************************************************/
void Widget::receiveMessage()
{
    ui->textBrowser->append("服务端:" + tcpSocket->readAll());
}


/***********************************************************
  * @函数名:mStateChanged
  * @功  能:槽函数---客户端连接状态改变的处理
  * @参  数:socketstate---当前连接状态
  * @返回值:无
  *********************************************************/
void Widget::mStateChanged(QAbstractSocket::SocketState socketstate)
{
    switch (socketstate) {
    case QAbstractSocket::UnconnectedState:
        ui->textBrowser->append("与服务端断开连接");
        ui->pushButton->setEnabled(true);
        ui->pushButton_2->setEnabled(false);
        break;
    case QAbstractSocket::ConnectedState:
        ui->textBrowser->append("与服务端成功连接");
        ui->pushButton->setEnabled(false);
        ui->pushButton_2->setEnabled(true);
        break;
    default:
        break;
    }
}


/***********************************************************
  * @函数名:on_pushButton_3_clicked
  * @功  能:"发送消息"按钮的槽函数,必须连接了服务端才发送
  * @参  数:无
  * @返回值:无
  *********************************************************/
void Widget::on_pushButton_3_clicked()
{
    if (tcpSocket->state() == QAbstractSocket::ConnectedState){
        tcpSocket->write(ui->lineEdit->text().toUtf8());
    }
    else {
        ui->textBrowser->append("请先连接服务端!");
    }
}


/***********************************************************
  * @函数名:on_pushButton_clicked
  * @功  能:"连接服务端"按钮的槽函数
  * @参  数:无
  * @返回值:无
  *********************************************************/
void Widget::on_pushButton_clicked()
{
    tcpSocket->connectToHost(QHostAddress("192.168.124.151"), 9999);
}


/***********************************************************
  * @函数名:on_pushButton_2_clicked
  * @功  能:"断开服务端"按钮的槽函数
  * @参  数:无
  * @返回值:无
  *********************************************************/
void Widget::on_pushButton_2_clicked()
{
    tcpSocket->disconnectFromHost();
}

4. 服务端与客户端测试

4.1 注意事项:

  • 服务端中的"开始监听"和"停止监听"应该设置成互斥的。方法一:在ui设计器里将它们添加到一个按钮组,然后选中"exclusive",将它们的"checkable"勾选上,再将"停止监听"按钮的"checked"勾选。方法二:使用代码ui->pushButton->setEnable(对/错);实现它们逻辑的互斥。
  • 客户端中的"连接服务端"和"断开服务端"应该用上述的方法二实现互斥。
  • 在服务端中,当客户端断开连接时,直接调用delete可能会出错(其他地方可能还在用这个变量)。因此,应当使用tmpTcpSocket.deleteLater(); 来删除客户端对象。

4.2 运行效果:


三、QT中的UDP编程

1. UDP简介

  • 是一个轻量级的,不可靠的,面向数据报的无连接协议。
  • 通常音频、视频和普通数据在传送时使用 UDP 较多。
  • UDP 消息传送有三种模式:单播、广播和组播三种模式。

2. UDP单播与广播程序

2.1 编写步骤:

【1】配置:①pro文件中添加network;②添加头文件<QUdpSocket>。

【2】创建UDP对象:QUdpSocket *udpSocket;(具体分配空间在构造函数中)

【3】编写函数绑定端口:调用udpSocket->bind(端口号);

【4】编写函数解除绑定:调用udpSocket->abort();

【5】“发送-接收”的信号槽连接:connect(udpSocket, SIGNAL(readyRead()), this, SLOT(receiveMessage()));

【6】编写【5】中的receiveMessage来获取接收的数据:内部调用udpSocket->readDatagram(mesg.data(), mesg.size(), &receiveAddress, &port);

【7】编写函数来单播发送数据:调用udpSocket->writeDatagram(ui->lineEdit->text().toUtf8(), QHostAddress("127.0.0.1"), 9999);

【8】编写函数来广播发送数据:与【7】类似,只是将倒数第二个参数换成QHostAddress::Broadcast。要广播几个ip和端口,就调用几次writeDatagram。

【8】要想获取当前连接的状态,操作和TCP中的一样。

2.2 实例代码:

【1】widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QUdpSocket>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void receiveMessage();

    void on_pushButton_3_clicked();

    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

    void on_pushButton_4_clicked();

private:
    Ui::Widget *ui;
    QUdpSocket *udpSocket;
};
#endif // WIDGET_H

【2】widget.cpp:

#include "widget.h"
#include "ui_widget.h"

/* 构造函数 */
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->pushButton->setEnabled(true);
    ui->pushButton_2->setEnabled(false);
    //创建udp对象
    udpSocket = new QUdpSocket(this);
    connect(udpSocket, SIGNAL(readyRead()), this, SLOT(receiveMessage()));
}


/* 析构函数 */
Widget::~Widget()
{
    delete ui;
}


/* 接收信息的槽函数*/
void Widget::receiveMessage()
{
    QByteArray mesg;
    mesg.resize(udpSocket->pendingDatagramSize());
    QHostAddress receiveAddress;
    quint16 port;

    while (udpSocket->hasPendingDatagrams()) {
        udpSocket->readDatagram(mesg.data(), mesg.size(), &receiveAddress, &port);//保存接收的数据
        ui->textBrowser->append("接收来自:" + receiveAddress.toString() + ", 端口:" + QString::number(port));
        ui->textBrowser->append("接收信息:" + mesg);
    }
}


/* 发送信息按钮的槽函数 */
void Widget::on_pushButton_3_clicked()
{
    udpSocket->writeDatagram(ui->lineEdit->text().toUtf8(), QHostAddress("127.0.0.1"), 9999);
    ui->textBrowser->append("发送信息:" + ui->lineEdit->text().toUtf8());
}


/* 绑定端口按钮的槽函数 */
void Widget::on_pushButton_clicked()
{
    udpSocket->bind(9999);
    ui->textBrowser->append("当前绑定端口:" + QString::number(9999));
    ui->pushButton->setEnabled(false);
    ui->pushButton_2->setEnabled(true);
}


/* 解除绑定按钮的槽函数 */
void Widget::on_pushButton_2_clicked()
{
    udpSocket->abort();
    ui->textBrowser->append("解除绑定");
    ui->pushButton->setEnabled(true);
    ui->pushButton_2->setEnabled(false);
}


/* 广播信息按钮的槽函数 */
void Widget::on_pushButton_4_clicked()
{
    udpSocket->writeDatagram(ui->lineEdit->text().toUtf8(), QHostAddress::Broadcast, 9999);
    ui->textBrowser->append("发送信息:" + ui->lineEdit->text().toUtf8());
}

【3】ui设计器:

【4】运行效果:双开该程序,每次新运行程序前修改一下绑定的端口号并编译。同时,这两个端口号需要对应才能显示单播的效果。

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

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

相关文章

[Vue-常见错误]浏览器显示Uncaught runtime errors

文章目录 错误描述正确写法具体如下 错误描述 当前端代码发生错误时&#xff0c;浏览器中出现以下错误提示。 正确写法 显然这不是我们所期望的&#xff0c;在vue.config.js中配置如下设置关闭Uncaught runtime errors显示 devServer: {client: {overlay: false}具体如下 …

Java核心: 类加载器

这一节我们来学习Java的类加载器&#xff0c;以及常用的类加载器实现URLClassLoader。 1. Java类加载器 类加载器用于将字节码读取并创建Class对象。我们知道JVM本身是用C写的&#xff0c;一开始执行的时候由C程序来加载并引导字节码的运行&#xff0c;这些由C编写的加载字节…

图神经网络(GNN)的原理及应用

什么是图神经网络 &#xff08;GNN&#xff09;&#xff1f; 图神经网络 &#xff08;GNN&#xff09; 是一种神经网络架构和深度学习方法&#xff0c;可以帮助用户分析图&#xff0c;使他们能够根据图的节点和边描述的数据进行预测。 图形表示数据点&#xff08;也称为节点&…

ENSP校园网设计实验

前言 哈喽&#xff0c;我是ICT大龙。本次更新了使用ENSP仿真软件设计校园网实验。时间比较着急&#xff0c;可能会有错误&#xff0c;欢迎大家指出。 获取本次工程文件方式在文章结束部分。 拓扑设计 拓扑介绍---A校区 如图&#xff0c;XYZ大学校园网设计分为3部分&#xff0…

硬盘坏了数据能恢复吗 硬盘数据恢复一般多少钱

在数字化时代&#xff0c;我们的生活和工作离不开电脑和硬盘。然而&#xff0c;硬盘故障是一个常见的问题&#xff0c;可能会导致我们的数据丢失。当我们的硬盘坏了&#xff0c;还能恢复丢失的数据吗&#xff1f;今天我们就一起来探讨关于硬盘坏了数据能恢复吗&#xff0c;硬盘…

请求 响应

在web的前后端分离开发过程中&#xff0c;前端发送请求给后端&#xff0c;后端接收请求&#xff0c;响应数据给前端 请求 前端发送数据进行请求 简单参数 原始方式 在原始的web程序中&#xff0c;获取请求参数&#xff0c;需要通过HttpServletRequest 对象手动获取。 代码…

如何在本地和远程删除 Git 分支

欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷分享知识&#xff0c;目前是武汉城市开发者社区主理人 擅长.net、C、python开发&#xff0c; 如果遇…

在线按模板批量生成文本工具

具体请前往&#xff1a;在线按模板批量生成文本工具

【手推公式】如何求SDE的解(附录B)

【手推公式】如何求SDE的解&#xff08;附录B&#xff09; 核心思路&#xff1a;不直接求VE和VP的SDE的解xt&#xff0c;而是求xt的期望和方差&#xff0c;从而写出x0到xt的条件分布形式&#xff08;附录B&#xff09; 论文&#xff1a;Score-Based Generative Modeling throug…

2024年人工智能与云计算国际会议(ICAICC 2024)

2024 International Conference on Artificial Intelligence and Cloud Computing 【1】大会信息 大会时间&#xff1a;2024-07-19 大会地点&#xff1a;中国长沙 截稿时间&#xff1a;2024-07-05(以官网为准&#xff09; 审稿通知&#xff1a;投稿后2-3日内通知 会议官网&am…

Pico4 MR Unity零基础开发之开启MR透视

一、新建场景&#xff1a;SeethroughScene 1、新建场景。 二、添加 XR 摄像机进行设置 1、在 Hierarchy 窗口中&#xff0c;右击默认添加的 Main Camera&#xff0c;然后点击 Delete 将其删除。 2、点击 > XR > XR Origin (VR)&#xff0c;将 XR Origin 添加至场景 3、…

股票数据集2-纳斯达克NASDAQ 100 分析

1. 数据清洗 用邻近均值的方法&#xff0c;去掉Non_Padding中的NaN数据 这里没用df.fillna(), 因为其只有前向(ffill )和 后向 (bfill) 插值&#xff0c;不适合大量连续的NaN pd转换为np&#xff0c;写一个函数, 返回np数组的空值&#xff0c;lambda的匿名函数返回y轴空值的索…

CSAPP Lab01——Data Lab完成思路

陪你把想念的酸拥抱成温暖 陪你把彷徨写出情节来 未来多漫长再漫长还有期待 陪伴你 一直到 故事给说完 ——陪你度过漫长岁月 完整代码见&#xff1a;CSAPP/datalab-handout at main SnowLegend-star/CSAPP (github.com) 01 bitXor 这道题是用~和&计算x^y。 异或是两个…

mongodb总概

一、mongodb概述 mongodb是最流行的nosql数据库&#xff0c;由C语言编写。其功能非常丰富&#xff0c;包括: 面向集合文档的存储:适合存储Bson(json的扩展)形式的数据;格式自由&#xff0c;数据格式不固定&#xff0c;生产环境下修改结构都可以不影响程序运行;强大的查询语句…

著名AI人工智能社会学家唐兴通谈数字社会学网络社会学主要矛盾与数字空间社会网络社会的基本议题与全球海外最新热点与关注社会结构社会分工数字财富数字游民数字经济

如果人工智能解决了一切&#xff0c;人类会做什么&#xff1f; 这个问题的背后是人工智能时代的社会主要矛盾会是什么&#xff1f;那么整个社会的大的分工体系就会围绕主要矛盾开展。 《人工智能社会主要矛盾》 在农业社会&#xff0c;主要矛盾是人口增长和土地资源之间的关…

atcoder abc357

A Sanitize Hands 问题&#xff1a; 思路&#xff1a;前缀和&#xff0c;暴力&#xff0c;你想咋做就咋做 代码&#xff1a; #include <iostream>using namespace std;const int N 2e5 10;int n, m; int a[N];int main() {cin >> n >> m;for(int i 1…

【日常记录】【JS】中文转拼音的库 pinyin-pro

文章目录 1、介绍2、pinyin-pro 基本使用3、参考链接 1、介绍 pinyin-pro 是一个专业的 JavaScript 中文转拼音的库&#xff0c;具备多音字识别准确、体积轻量、性能优异、功能丰富等特点。 常用的案例 搜索功能增强&#xff1a;在输入框输入汉字时&#xff0c;可以转化为拼音输…

英特尔:AI落地,未来已来

引言 随着AI技术的发展和大模型的普及&#xff0c;人工智能正在逐渐渗透到我们的日常生活中。2023年5月底&#xff0c;我参加了台北的英特尔技术展&#xff0c;深入了解了英特尔在AI个人电脑领域的最新进展。本文将详细介绍英特尔的新一代移动处理器Lunar Lake&#xff0c;以及…

【C51】C51单片机实现的 抽奖机 设计与编程指南

文章目录 前言&#xff1a;1. 实现效果2. 准备工作3. 编写代码总结&#xff1a; 前言&#xff1a; 在本文中&#xff0c;我们将介绍如何使用C51单片机来实现一个简单的抽奖机。这个项目不仅能够展示C51单片机的基本应用&#xff0c;还能让我们了解如何通过编程来控制硬件&…

卡尔曼滤波器例子

卡尔曼滤波器 卡尔曼滤波器(Kalman Filter)是一种用于线性系统状态估计的递归算法,可以有效地融合传感器数据和系统模型来估计系统的状态。它在机器人学中广泛应用,尤其是位置和速度等状态的估计。通过卡尔曼滤波器,可以有效地估计机器人在二维平面内的真实位置,并减小测…