C++ Qt 学习(六):Qt http 编程

1. http 基础

  • HTTP 基础教程
  • C++ Web 框架
    • drogon
    • oatpp

2. C++ Qt 用户登录、注册功能实现

在这里插入图片描述

  • login_register.h
#pragma once

#include <QtWidgets/QDialog>
#include "ui_login_register.h"
#include <QNetworkReply>

class login_register : public QDialog {
    Q_OBJECT

public:
    login_register(QWidget *parent = Q_NULLPTR);

private:
    void test_http_post();
    void test_timeout_http_post();

private slots:
    void on_btnLogin_clicked();
    void post_requestFinished(QNetworkReply* reply);

private:
    Ui::login_registerClass ui;
};
  • login_register.cpp
#pragma execution_character_set("utf-8")

#include "login_register.h"

#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QJsonValue>
#include <QMessageBox>
#include <QTimer>

login_register::login_register(QWidget *parent) : QDialog(parent) {
    ui.setupUi(this);
}

void login_register::on_btnLogin_clicked() {
    //test_http_post();
    test_timeout_http_post();
}

void login_register::test_http_post() {
    QNetworkAccessManager* pHttpMgr = new QNetworkAccessManager();

    // 设置 url
    QString url = "http://127.0.0.1:8080/login";

    // 设置头信息
    QNetworkRequest requestInfo;
    requestInfo.setUrl(QUrl(url));
    requestInfo.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));

    // setRawData
    QJsonObject rawJson;
    rawJson.insert("username", "zhangsan");
    rawJson.insert("password", "123456");

    QByteArray byte_array = QJsonDocument(rawJson).toJson();
  
    // 发送 post 请求
    QNetworkReply* reply = pHttpMgr->post(requestInfo, byte_array);

    if (reply) {
        // 添加事件循环机制,返回后再运行后面的
        connect(pHttpMgr, &QNetworkAccessManager::finished, 
            this, &login_register::post_requestFinished);
    }
}

void login_register::post_requestFinished(QNetworkReply* reply) {
    // 获取 http 状态码
    QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    if (statusCode.isValid())
        qDebug() << "status code=" << statusCode.toInt();

    QVariant reason = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
    if (reason.isValid())
        qDebug() << "reason=" << reason.toString();

    QNetworkReply::NetworkError err = reply->error();

    if (err != QNetworkReply::NoError) {
        // 请求失败
        QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);

        QMessageBox::information(this, "warn",
            "http post failed, error code = " + statusCode.toString() + " error info: " + reply->errorString());

        return;
    } else {
        // 请求成功
        // 接收请求结果
        QByteArray responseByte = reply->readAll();
        QString strRes = responseByte;

        QMessageBox::information(this, "http post success",
            "post response = " + strRes);
    }
}

void login_register::test_timeout_http_post() {
    QNetworkAccessManager* pHttpMgr = new QNetworkAccessManager();

    // 设置 url
    QString url = "http://127.0.0.1:8080/login";

    // 设置头信息
    QNetworkRequest requestInfo;
    requestInfo.setUrl(QUrl(url));
    requestInfo.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));

    // setRawData
    QJsonObject rawJson;
    rawJson.insert("username", "zhangsan");
    rawJson.insert("password", "123456");

    QByteArray byte_array = QJsonDocument(rawJson).toJson();

    // 发送 post 请求
    QNetworkReply* reply = pHttpMgr->post(requestInfo, byte_array);

    // 添加超时处理,1ms 超时
    QEventLoop eventloop;
    connect(reply, SIGNAL(finished()), &eventloop, SLOT(quit()));

    // 比如设置 1ms 内完成请求,否则就认为是超时
    QTimer::singleShot(1000, &eventloop, &QEventLoop::quit);
    eventloop.exec();

    QByteArray array;
    if (reply->isFinished()) {
        if (reply->error() == QNetworkReply::NoError) {
            // 正常结束,读取响应数据
            QByteArray result = reply->readAll();
            QString strRes = result;

            QMessageBox::information(this, "http post success",
                "post response = " + strRes);
        } else {
            // 异常结束
            // 请求失败
            QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);

            QMessageBox::information(this, "warn",
                "http post failed, error code = " + statusCode.toString() + " error info: " + reply->errorString());

            return;
        }
    } else {
        // 请求超时
        disconnect(reply, &QNetworkReply::finished, &eventloop, &QEventLoop::quit);
        reply->abort();
        
        QMessageBox::information(this, "http post timeout", "http post timeout");
    }

    reply->deleteLater();
}

3. Qt json 解析介绍

  • ch65_qtjson.cpp
#include "ch65_qtjson.h"
#include <string>
#include <QJsonDocument> 
#include <QJsonObject>
#include <QDebug>

using namespace std;

ch65_qtjson::ch65_qtjson(QWidget *parent) : QWidget(parent) {
    ui.setupUi(this);

    /*string json_str = R"(
        {
            "date": "20220701",
            "level": 1,
            "msg": "register account",
            "status": "success",
            "username": "jackli"
        }
    )";*/

    string json_str = R"({})";

    QString qstr = QString::fromStdString(json_str);

    if (qstr.isEmpty()) {
        qDebug() << "qstr is empty";
        return;
    }

    QByteArray jbyte = qstr.toLocal8Bit();
    // 捕获转换过程中出现的错误
    QJsonParseError error;
    QJsonDocument jdoc = QJsonDocument::fromJson(jbyte, &error);

    if (error.error != QJsonParseError::NoError) {
        // 有错误
        qDebug() << "json parse error";
        return;
    }
    qDebug() << "json parse success";

    if (jdoc.isNull() || jdoc.isEmpty()) {
        qDebug() << "json docment is empty";
        return;
    }

    QJsonObject jobj = jdoc.object();
    QString date = jobj["date"].toString();
    qDebug() << "date" << date;

    int level = jobj["level"].toInt();
    qDebug() << "level" << level;
}

ch65_qtjson::~ch65_qtjson() {}

4. C++ nlohmann::json 使用介绍

  • nlohmann::json

  • Qt 有 json 解析相关的类,但不推荐使用,建议使用 nlohmann::json,这个 json 适用于任何 C++ 框架

  • nlohmann::json 只需要一个头文件 json.hpp,不需要编译成 lib,直接放到项目中即可使用

  • main.cpp

#include <iostream>
#include "json.hpp"
#include <string>

using json_t = nlohmann::json;

using namespace std;

int parse_array() {
    string jsonstr = R"(
        {
            "id":"2022",
            "name":{"EnglishName":"JackMa"},
            "title":[
                {
                    "company":"taobao", 
                    "position" : "AAA", 
                    "salary" : "10000"
                },
                { 
                    "company":"zhifubao",
                    "position" : "CCC",
                    "salary" : "890898" 
                },
                { 
                    "company":"pingtouge",
                    "position" : "KKK",
                    "salary" : "76843" 
                }
            ]
        }
    )";

    try {
        json_t jsonObj = json_t::parse(jsonstr);

        // 取出 name
        json_t nameJson = jsonObj["name"];
        string engName = nameJson["EnglishName"];
        cout << "engName = " << engName << endl;

        // 取出 title
        json_t titleJson = jsonObj["title"];
        int size = titleJson.size();
        cout << "size = " << size << endl;

        for (auto jsonItem : titleJson) {
            cout << jsonItem["company"] << endl;
            cout << jsonItem["position"] << endl;
            cout << jsonItem["salary"] << endl;
        }
    } catch (const std::exception&) {
        return -1;
    }

    return 0;
}

int main() {
    /* 序列化,把 json 数据转成 string */
    json_t jRawdata;
    jRawdata["username"] = "jackli";
    jRawdata["pwd"] = "123456";

    // nlohmann::json 中的 dump 方法实现数据转储
    string _rawdata = jRawdata.dump(4);
    cout << _rawdata << endl; 

    /* 反序列化,把 string 数据转成 json */
    string json_str = R"(
        {
            "date": "20220701",
            "level": 1,
            "msg": "register account",
            "status": "success",
            "username": "jackli"
        }
    )";

    try  {
        json_t j2 = json_t::parse(json_str);
        string date = j2["date"];
        cout << date << endl;
    } catch (std::exception& e) {
        cout << "json parse failed" << endl;
        return -1;
    }

    /* 解析复杂 json 数据 */
    cout << "解析 json 数组" << endl;
    if (parse_array() != 0) {
        cout << "parse array failed" << endl;
    }

    return 0;
}

5. libcurl 解析

  • libcurl 是一个跨平台的网络协议库,支持 http、https,ftp,telnet 等应用层协议
  • libcurl 主要功能就是用不同的协议连接和沟通不同的服务器

5.1 libcurl 编译

  • 流程同 CEF 编译
    • 参考链接

5.2 使用 libcurl 进行 http post 请求

#include <iostream>
#include "curl/curl.h"
#include <iostream>
#include <sstream>
#include <string>
#include "json.hpp"

using namespace std;

using json_t = nlohmann::json;

// 数据处理回调函数
size_t write_data(void* ptr, size_t size, size_t nmemb, void* stream) {
    string data((const char*)ptr, (size_t)size * nmemb);
    *((stringstream*)stream) << data << endl;
    return size * nmemb;
}

int main() {
    /* 以下代码为通过 Postman 生成 */
    // Postman 是一款用于发送 HTTP 请求的测试工具
    CURL* curl;
    CURLcode res;
    stringstream jsonRespon;

    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
        curl_easy_setopt(curl, CURLOPT_URL, "127.0.0.1:8080/login");
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        //curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
        struct curl_slist* headers = NULL;
        headers = curl_slist_append(headers, "Content-Type: application/json");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        
        string data = R"(
            {
                "username":"jackhui",
                "password":"1234"
            }
        )";

        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &jsonRespon);

        res = curl_easy_perform(curl);
        if (res != 0) {
            cout << "request failed" << endl;
            return -1;
        }
    }
    curl_easy_cleanup(curl);
    cout << "request success 222" << endl;
    /* 以上代码为通过 Postman 生成 */

    string json = jsonRespon.str();

    try {
        json_t j = json_t::parse(json);
        cout << j.dump(4) << endl;

        string data = j["date"];
    } catch (std::exception& e) {
        cout << "json parse failed" << endl;
        return -2;
    }

    return 0;
}

在这里插入图片描述

6. websocket

6.1 基本概念

  • websocket 是 HTML5 中新增的一个协议,这个协议的出现,让客户端和服务器之前的数据交互变成全双工的

  • websocket 的出现,最主要的变化是允许服务器主动给客户端推送数据。这一大改变,就让 websocket 具有了以往其它协议无法比拟的实时通信能力。要实现 websocket 服务,需要客户端和服务端都得支持 websocket 协议才可以

  • websocket 详解

  • Websocket 能做什么?

    • 聊天、消息推送、多人在线业务
    • 推荐一个开源项目 OpenIM
  • websocket 与 http 的区别

    • 相同点
      • 都是一样基于 TCP 的,都是可靠性传输协议
      • 都是应用层协议
    • 不同点
      • websocket 是持久连接,http 是短连接
      • websocket 的协议是以 ws/wss 开头,http 对应的是 http/https
      • websocket 是有状态的,http 是无状态的
      • websocket 连接之后服务器和客户端可以双向发送数据,http 只能是客户端发起一次请求之后,服务器才能返回数据
      • websocket 连接建立之后,不需要再发送 request 请求,数据直接从 TCP 通道传输
  • websocketpp 是用 c++ 实现的一个 websocket 库,用来支持 websocket 协议

    • websocketpp

6.2 C++ Qt 实现 websocket server

Qt websocket 的实现(需包含 websockets 第三方模块)

  • QWebSocketServer(服务端)
  • QWebSocket(客户端)

在这里插入图片描述

  • WebsocketServer.h
#pragma once

#include <QtWidgets/QWidget>
#include "ui_WebsocketServer.h"
#include <QWebSocketServer>
#include <QWebSocket>
#include <QMap>

class WebsocketServerDemo : public QWidget {
    Q_OBJECT

public:
    WebsocketServerDemo(QWidget *parent = Q_NULLPTR);
    ~WebsocketServerDemo();

private slots:
    void on_btnOpenServer_clicked();
    void on_btnCloseServer_clicked();
    void on_btnSend_clicked();

    void onNewConnection();
    void processTextMessage(QString message);
    void socketDisconnected();

private:
    Ui::WebsocketServerClass ui;

    QWebSocketServer* m_WebSocketServer = nullptr;

    QList<QWebSocket*> m_clients;
    bool m_debug;
    QWebSocket* pSocket;
    QDateTime* current_date_time;
    QMap<QString, QWebSocket*> mapSocket;
};
  • WebsocketServer.cpp
#include "WebsocketServer.h"
#include <QMessageBox>
#include <string>
#include <Windows.h>
#include <iostream>

using namespace std;

WebsocketServerDemo::WebsocketServerDemo(QWidget *parent) : QWidget(parent) {
    ui.setupUi(this);
   
    this->setWindowTitle(u8"Websocket Server");
    this->resize(1000, 600);

    ui.lineEdit_IP->setText("192.168.74.1");
    ui.lineEdit_Port->setText("8000");

    // 创建服务
    m_WebSocketServer = new QWebSocketServer(u8"server", QWebSocketServer::NonSecureMode);
}

WebsocketServerDemo::~WebsocketServerDemo() {
    if (m_WebSocketServer) {
        if(m_WebSocketServer->isListening())
            m_WebSocketServer->close();
    }  
}

// 开启服务
void WebsocketServerDemo::on_btnOpenServer_clicked() {
    QString ip = ui.lineEdit_IP->text();
    QString port = ui.lineEdit_Port->text();

    // 监听 ip 和端口
    if (m_WebSocketServer->listen(QHostAddress(ip), port.toInt())) {
        ui.textEdit_RecvMsg->append(u8"服务开启成功");
        ui.btnOpenServer->setEnabled(false);
        // 服务成功开启则触发 onNewConnection() 槽函数
        connect(m_WebSocketServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
    } else {
        QMessageBox::information(this, u8"提示", u8"监听失败, 是否开启了代理,或者IP错误");
    }
}

// 关闭服务
void WebsocketServerDemo::on_btnCloseServer_clicked() {
    if (m_WebSocketServer) {
        if (m_WebSocketServer->isListening()) {
            m_WebSocketServer->close();
            ui.btnOpenServer->setEnabled(true);
            ui.textEdit_RecvMsg->append(u8"服务关闭");
        }
    }
}

// 处理新的客户端连接
void WebsocketServerDemo::onNewConnection() {
    pSocket = m_WebSocketServer->nextPendingConnection();
    m_clients << pSocket;

    // 处理接到消息的信号
    connect(pSocket, SIGNAL(textMessageReceived(QString)), this, SLOT(processTextMessage(QString)));
    // 处理断线的信号
    connect(pSocket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));

    QString peerName = pSocket->requestUrl().toString();
    cout << "peerName = " << peerName.toStdString() << endl;

    // 将 ip 和 socket 保存到 map
    mapSocket[peerName] = pSocket;

    ui.listWidget_OnlineUser->addItem(peerName);
}

// 处理接收到的消息
void WebsocketServerDemo::processTextMessage(QString message) {
    QString time = current_date_time->currentDateTime().toString("yyyy.MM.dd hh:mm:ss.zzz ddd");
    QString item = pSocket->requestUrl().toString();
    ui.textEdit_RecvMsg->append(time + "" + item + "\n" + message);

    // 处理消息转发
    //...
}

// 客户端连接断开的操作
void WebsocketServerDemo::socketDisconnected() {
    for (auto sk : m_clients) {
        if (!sk->isValid()) {
            QString temp_key;
            ui.textEdit_RecvMsg->append("map size = " + QString(mapSocket.size()) + "\n");
            for (auto it = mapSocket.begin(); it!=mapSocket.end(); it++) {
                if (it.value() == sk) {
                    // 删除项
                    QList<QListWidgetItem*> list;
                    list = ui.listWidget_OnlineUser-> findItems(it.key(), Qt::MatchCaseSensitive);

                    QListWidgetItem* sel = list[0];
                    int r = ui.listWidget_OnlineUser->row(sel);

                    QListWidgetItem* item = ui.listWidget_OnlineUser->takeItem(r);
                    ui.listWidget_OnlineUser->removeItemWidget(item);

                    delete item;
                    m_clients.removeOne(sk);

                    QString time = current_date_time->currentDateTime().toString("yyyy.MM.dd hh:mm:ss.zzz ddd");
                    ui.textEdit_RecvMsg->append(time + "" + it.key() + "下线了\n");

                    temp_key = it.key();
                }
            }

            mapSocket.remove(temp_key);
            ui.textEdit_RecvMsg->append("after remove, map size = " + QString(mapSocket.size()) + "\n");
        }
    }
}

// 群发消息
void WebsocketServerDemo::on_btnSend_clicked() {
    QString msg = ui.textEdit_send->document()->toPlainText();

    for (auto sk : m_clients) {
        sk->sendTextMessage(msg);
    }
}

6.3 C++ Qt 实现 websocket client

在这里插入图片描述

  • WebSocketClientDemo.h
#pragma once

#include <QtWidgets/QWidget>
#include "ui_WebSocketClientDemo.h"
#include <QLineEdit>
#include <QLabel>
#include <QTextEdit>
#include <QListWidget>
#include <QPushButton>
#include <QSpinBox>
#include <QButtonGroup>
#include <QObject>
#include <QWidget>
#include <QUrl>
#include <time.h>
#include <QByteArray>
#include <QWebSocket>

class WebSocketClientDemo : public QWidget {
    Q_OBJECT

public:
    WebSocketClientDemo(QWidget *parent = Q_NULLPTR);
    ~WebSocketClientDemo();

private slots:
    void on_btnConnect_clicked();
    void on_btnDisconnect_clicked();
    void on_btnSend_clicked();

    void onconnected();
    void onTextMessageReceived(const QString& message);
    void closeConnection();    

private:
    Ui::WebSocketClientDemoClass ui;

    QUrl m_url;
    QWebSocket m_websocket;
    bool m_debug;
    QDateTime* current_date_time;
};
  • WebSocketClientDemo.cpp
#include "WebSocketClientDemo.h"
#include <QLabel>
#include <QWidget>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QtCore>
#include <QDebug>
#include <iostream>
#include <string>

using namespace std;

WebSocketClientDemo::WebSocketClientDemo(QWidget *parent) : QWidget(parent) {
    ui.setupUi(this);

    ui.lineEdit_URL->setText("ws://192.168.74.1:8000/topic=10001");
    ui.label_ConnectStatus->clear();

    connect(&m_websocket, SIGNAL(connected()), this, SLOT(onconnected()));
    connect(&m_websocket, SIGNAL(disconnected()), this, SLOT(closeConnection()));
    connect(&m_websocket, SIGNAL(textMessageReceived(QString)), this, SLOT(onTextMessageReceived(QString)));
}

WebSocketClientDemo::~WebSocketClientDemo() {
    m_websocket.errorString();
    m_websocket.close();
}

// 断开连接操作
void WebSocketClientDemo::closeConnection()  {   
    ui.label_ConnectStatus->setText("disconnected");
}

// 连接服务器
void WebSocketClientDemo::on_btnConnect_clicked() {
    QString _text = ui.lineEdit_URL->text();
    QUrl url = QUrl(_text);
    m_websocket.open(url);
}

// 连接上之后
void WebSocketClientDemo::onconnected() {
    ui.label_ConnectStatus->setText(tr("connected"));
    ui.btnConnect->setEnabled(false);
    ui.btnDisconnect->setEnabled(true);
}

// 收到消息
void WebSocketClientDemo::onTextMessageReceived(const QString& message) {
    QString time = current_date_time->currentDateTime().toString("yyyy.MM.dd hh:mm:ss.zzz ddd");
    ui.textEdit_recv->setText(time + "\n" + message);
}

// 断开
void WebSocketClientDemo::on_btnDisconnect_clicked() {
    m_websocket.close();
}

// 发送消息
void WebSocketClientDemo::on_btnSend_clicked() {
    QString msg = ui.textEdit_send->document()->toPlainText();

    string dataMsg = R"(
        "sender":"10002",
        "receiver":"10001",
        "msg":"你好"
    )";
    
    m_websocket.sendTextMessage(msg);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

信息系统项目管理师 教材目录、考试大纲、考情

文章目录 考情考试大纲第1章 信息化发展第2章 信息技术发展第3章 信息系统治理第4章 信息系统管理第5章 信息系统工程第6章 项目管理概论第7章 项目立项管理第8章 项目整合管理第9章 项目范围管理272第10章 项目进度管理297第11章 项目成本管理334第12章 项目质量管理358第13章…

KDE Plasma 6 将不支持较旧的桌面小部件

KDE Plasma 6 进行了一些修改&#xff0c;需要小部件作者进行调整。开发人员&#xff0c;移植时间到了&#xff01; KDE Plasma 6 是备受期待的桌面环境版本升级版本。 最近&#xff0c;其发布时间表公布&#xff0c;第一个 Alpha 版本将于 2023 年 11 月 8 日上线&#xff0…

基于蜻蜓算法优化概率神经网络PNN的分类预测 - 附代码

基于蜻蜓算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于蜻蜓算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于蜻蜓优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络的光滑…

云原生 黑马Kubernetes教程(K8S教程)笔记——第一章 kubernetes介绍——Master集群控制节点、Node工作负载节点、Pod控制单元

参考文章&#xff1a;kubernetes介绍 文章目录 第一章 kubernetes介绍1.1 应用部署方式演变传统部署&#xff1a;互联网早期&#xff0c;会直接将应用程序部署在物理机上虚拟化部署&#xff1a;可以在一台物理机上运行多个虚拟机&#xff0c;每个虚拟机都是独立的一个环境&…

【操作系统】考研真题攻克与重点知识点剖析 - 第 3 篇:内存管理

前言 本文基础知识部分来自于b站&#xff1a;分享笔记的好人儿的思维导图与王道考研课程&#xff0c;感谢大佬的开源精神&#xff0c;习题来自老师划的重点以及考研真题。此前我尝试了完全使用Python或是结合大语言模型对考研真题进行数据清洗与可视化分析&#xff0c;本人技术…

【论文】利用移动性的比例公平蜂窝调度测量和算法

&#xff08;一支笔一包烟&#xff0c;一节论文看一天 &#xff09;&#xff08;一张纸一瓶酒&#xff0c;一道公式推一宿&#xff09; 摘要1. 引言2. 相关工作3. 模型和问题公式4. 预测FPF调度 &#xff08; P F &#xff09; 2 S &#xff08;PF&#xff09;^2S &#xff08;…

【MySQL系列】 第二章 · SQL(中)

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…

PCA(主成分分析)数据降维技术代码详解

引言 随着大数据时代的到来&#xff0c;我们经常会面临处理高维数据的问题。高维数据不仅增加了计算复杂度&#xff0c;还可能引发“维度灾难”。为了解决这一问题&#xff0c;我们需要对数据进行降维处理&#xff0c;即在不损失太多信息的前提下&#xff0c;将数据从高维空间…

pyTorch Hub 系列#2:VGG 和 ResNet

一、说明 在上一篇教程中,我们了解了 Torch Hub 背后的本质及其概念。然后,我们使用 Torch Hub 的复杂性发布了我们的模型,并通过相同的方式访问它。但是,当我们的工作要求我们利用 Torch Hub 上提供的众多全能模型之一时,会发生什么? 在本教程中,我们将学习如何利用称为…

C语言——打印1000年到2000年之间的闰年

闰年&#xff1a; 1、能被4整除不能被100整除 2、能被400整除 #define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> int main() {int year;for(year 1000; year < 2000; year){if((year%4 0) && (year%100!0) || (year%400 0)){printf("%d ",ye…

Python的基础语句大全

以下是Python的基础语句大全&#xff1a; 变量定义语句&#xff1a; var_name var_value输出语句&#xff1a; print(var_name)输入语句&#xff1a; var_name input()条件语句&#xff1a; if condition:// do something if condition is True elif condition:// do somethi…

数据结构与算法—归并排序计数排序

目录 一、归并排序 1、主函数 2、递归实现 3、优化递归 4、非递归实现 5、特性总结&#xff1a; 二、计数排序 1、代码&#xff1a; 2、特性总结&#xff1a; 三、各种排序稳定性总结 一、归并排序 基本思想&#xff1a; 归并排序是建立在归并操作上的一种有效的排序…

算法通关村第十五关白银挑战——海量数据场景下的热门算法题

大家好&#xff0c;我是怒码少年小码。 最近超级忙&#xff0c;很多实验报告&#xff0c;已经四五天没搞了&#xff0c;但是我还是回来了&#xff01; 海量数据场景下的热门算法题 本篇的题目不要求写代码&#xff0c;面试的时候能很清楚的说出思路就可以了。 1. 从40个亿中…

【Java】详解多线程的概述及三种创建方法

&#x1f33a;个人主页&#xff1a;Dawn黎明开始 &#x1f380;系列专栏&#xff1a;Java ⭐每日一句&#xff1a;身在井隅&#xff0c;心向阳光&#xff0c;眼里有诗&#xff0c;自在远方 &#x1f4e2;欢迎大家&#xff1a;关注&#x1f50d;点赞&#x1f44d;评论&#x1f4…

【JVM系列】- 寻觅·方法区的内容

寻觅方法区的内容 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f31d;分享学习心得&#xff0c;欢迎指正&#xff0c;大家一起学习成长&#xff01; 文章目录 寻觅…

Pyside6/PYQT6如何实现无边框设计,解决无边框窗口无法移动的问题

文章目录 💢 问题 💢💯 解决方案 💯🍔 准备工作🐾 操作步骤🐾 窗口无边框🐾 窗口透明🐾 实现窗口可移动⚓️ 相关链接 ⚓️💢 问题 💢 有时候我们需要一个无边框的UI设计来实现/美化一些功能,如:制作一个桌面时钟,进度条展示等,要实现无边框其实很简…

【 第十一章】软件设计师 之 面向对象设计与结构化分析设计

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 备考资料导航 软考好处&#xff1a;软考的…

【Proteus仿真】【Arduino单片机】LCD1602液晶显示

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用LCD1602液晶等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602液晶显示各种效果。 二、软件设计 /* 作者&#xff1a;嗨小易&#x…

MSF图形化工具Viper快速安装

简介 Viper(炫彩蛇)是一款图形化内网渗透工具,将内网渗透过程中常用的战术及技术进行模块化及武器化. Viper(炫彩蛇)集成杀软绕过,内网隧道,文件管理,命令行等基础功能. Viper(炫彩蛇)当前已集成70个模块,覆盖初始访问/持久化/权限提升/防御绕过/凭证访问/信息收集/横向移动等…

【MySQL系列】 第二章 · SQL(下)

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…