DXFViewer进行中 : ->封装OpenGL -> 解析DXF直线

DXFViewer进行中,目标造一个dxf看图工具。.

目标1:封装OpenGL,实现正交相机及平移缩放功能

Application.h

cpp 复制代码
#pragma once
#include <string>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "../Core/TimeStamp.h"
#include "../Core/OrthoCamera.h"
class Application
{
public:
	Application();
	virtual ~Application();
	virtual void  Initialize(int width, int height, const char* title);  // 1.初始化
	virtual void  Run();	  
	virtual void  Startup();        // 1.准备数据
	virtual void  Render();         // 2.渲染数据
	virtual void  Shutdown();       // 3.关闭

private:
	// 系统回调函数
	static void  ErrorCallback(int error, const char* description);
	static void  KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
	static void  MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
	static void  CursorPositionCallback(GLFWwindow* window, double xpos, double ypos);
	static void  WindowSizeCallback(GLFWwindow* window, int width, int height);
	static void  ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);

	static Application* GetWindow(GLFWwindow* window); 
 

protected:
	int           m_winWidth = 0;
	int	          m_winHeight = 0;
	GLFWwindow* m_pWindow = nullptr;
	OrthoCamera   m_camera;        // 相机 
	 
	double m_LastCursorX = 0.0;
	double m_LastCursorY = 0.0;
	bool m_MiddleButtonPressed = false;

};

Application.cpp

cpp 复制代码
#include "Application.h"
#include <algorithm>
#include <iostream>

Application::Application() {}

Application::~Application()
{
    glfwDestroyWindow(m_pWindow);
    glfwTerminate();
    exit(EXIT_SUCCESS);
}

void Application::ErrorCallback(int error, const char* description)
{
    std::cerr << "Error: " << description << std::endl;
}

void Application::KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    // 键盘事件处理逻辑
}

void Application::MouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
{
    Application* app = GetWindow(window);

    if (button == GLFW_MOUSE_BUTTON_MIDDLE)
    {
        if (action == GLFW_PRESS)
        {
            app->m_MiddleButtonPressed = true;
            glfwGetCursorPos(window, &app->m_LastCursorX, &app->m_LastCursorY);
            
            // 设置抓手光标
            // glfwSetCursor(window, glfwCreateStandardCursor(GLFW_HAND_CURSOR));
        }
        else if (action == GLFW_RELEASE)
        {
            app->m_MiddleButtonPressed = false;

            // 恢复默认箭头光标
            // glfwSetCursor(window, glfwCreateStandardCursor(GLFW_ARROW_CURSOR));
        }
    }
}

void Application::CursorPositionCallback(GLFWwindow* window, double xpos, double ypos)
{
    Application* app = GetWindow(window);

    if (app->m_MiddleButtonPressed)
    {
        double dx = xpos - app->m_LastCursorX;
        double dy = ypos - app->m_LastCursorY;

        app->m_LastCursorX = xpos;
        app->m_LastCursorY = ypos;
       
        glm::vec3 pos = app->m_camera.GetPosition();

        pos.x -= (dx / app->m_camera.GetZoom() * 0.5);
        pos.y += (dy / app->m_camera.GetZoom() * 0.5);
      
		//printf("pos.x = %f, pos.y = %f  \r\n", pos.x, pos.y);
    
        app->m_camera.SetPosition(pos);
    }
}

void Application::WindowSizeCallback(GLFWwindow* window, int width, int height)
{
    Application* app = GetWindow(window);
    app->m_winWidth = width;
    app->m_winHeight = height;   
    app->m_camera.SetView(width, height);
}

void Application::ScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
{

    Application* app = GetWindow(window);

    // 1. 获取鼠标在窗口中的位置
    double mouseX, mouseY;
    glfwGetCursorPos(window, &mouseX, &mouseY);

    // 2. 将鼠标屏幕坐标转换为世界坐标
    float ndcX = (2.0f * static_cast<float>(mouseX)) / app->m_winWidth - 1.0f;
    float ndcY = 1.0f - (2.0f * static_cast<float>(mouseY)) / app->m_winHeight;

    glm::vec4 ndcPos = glm::vec4(ndcX, ndcY, 0.0f, 1.0f);
    glm::mat4 invVP = glm::inverse(app->m_camera.GetViewProjectionMatrix());
    glm::vec4 worldPosBeforeZoom = invVP * ndcPos;

    // 3. 执行缩放
    float zoom = app->m_camera.GetZoom();
    if (yoffset > 0)
        zoom *= 1.15f;
    else
        zoom *= 0.85f;
    app->m_camera.SetZoom(zoom);

    // 4. 重新计算世界坐标
    invVP = glm::inverse(app->m_camera.GetViewProjectionMatrix());
    glm::vec4 worldPosAfterZoom = invVP * ndcPos;

    // 5. 保持鼠标位置不变:调整相机位置
    glm::vec3 camPos = app->m_camera.GetPosition();
    glm::vec3 offset = glm::vec3(worldPosBeforeZoom - worldPosAfterZoom); 
    app->m_camera.SetPosition(camPos + glm::vec3(offset.x*0.5,offset.y*0.5,offset.z*0.5));

}
// 获取窗口的用户数据
Application* Application::GetWindow(GLFWwindow* window)
{
    void* userdata = glfwGetWindowUserPointer(window);
    return reinterpret_cast<Application*>(userdata);
}

void Application::Initialize(int width, int height, const char* title)
{
    if (!glfwInit())
    {
        exit(EXIT_FAILURE);
    }

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);

    m_pWindow = glfwCreateWindow(width, height, title, NULL, NULL);
    m_winWidth = width;
    m_winHeight = height;

    if (!m_pWindow)
    {
        glfwTerminate();
        exit(EXIT_FAILURE);
    }

    glfwDefaultWindowHints();



    GLFWmonitor* primary = glfwGetPrimaryMonitor();
    const GLFWvidmode* mode = glfwGetVideoMode(primary);    
	// 设置窗口位置为屏幕中心
    glfwSetWindowPos(m_pWindow, (mode->width- width)/2, (mode->height - height) / 2);

	// 窗口的物理尺寸
    int widthMM, heightMM;
    glfwGetMonitorPhysicalSize(primary, &widthMM, &heightMM);

	// 计算 DPI
	float dpiX = static_cast<float>(mode->width) / (static_cast<float>(widthMM) );    
    float dpiY = static_cast<float>(mode->height) / (static_cast<float>(heightMM));

    glfwShowWindow(m_pWindow);
    // 设置 glfw 回调函数
    glfwSetKeyCallback(m_pWindow, KeyCallback);
    glfwSetMouseButtonCallback(m_pWindow, MouseButtonCallback);
    glfwSetCursorPosCallback(m_pWindow, CursorPositionCallback);
    glfwSetWindowSizeCallback(m_pWindow, WindowSizeCallback);
    glfwSetScrollCallback(m_pWindow, ScrollCallback);

    glfwMakeContextCurrent(m_pWindow);

    gladLoadGL();
    glfwSwapInterval(1); // 垂直同步
    glEnable(GL_DEPTH_TEST); // 开启深度测试

    // 设置相机
    m_camera.SetView(width, height);   
        
    glfwSetWindowUserPointer(m_pWindow, this);
}

void Application::Run()
{
    Startup(); // 准备工作

    while (!glfwWindowShouldClose(m_pWindow))
    {
        glfwGetFramebufferSize(m_pWindow, &m_winWidth, &m_winHeight);

        glViewport(0, 0, m_winWidth, m_winHeight);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

        Render(); // 渲染数据

        glfwSwapBuffers(m_pWindow);
        glfwWaitEvents(); // 等待事件
    }

    Shutdown(); // 关闭程序
}

void Application::Startup()
{
    // 初始化数据
}

void Application::Render()
{
    
}

void Application::Shutdown()
{
    // 清理资源
}

OrthoCamera.h

cpp 复制代码
#pragma once

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

/// <summary>
/// 实现一个用于 2D 渲染的正交相机类。
/// 提供相机的位置、旋转、投影矩阵和视图矩阵等基本功能。
/// </summary>
class OrthoCamera
{
public:
    OrthoCamera();
    ~OrthoCamera();

public: 
    void SetView(int windowWidth, int windowHeight);
    void SetView(float fixedHeight, int windowWidth, int windowHeight);
    void SetPosition(const glm::vec3& pos);
    void SetZoom(float zoom);

    const double& GetZoom() const { return m_Zoom ;} 
    const glm::vec3& GetPosition() const { return m_Position; } 
    const glm::mat4& GetViewProjectionMatrix() const { return m_ViewProjectionMatrix; };

private:
    void RecalculateMatrix();

    glm::vec3 m_Position = { 0.0f, 0.0f, 0.0f };
    double m_Zoom = 200.0f;
    double m_FixedHeight = 1000.0f;

    int m_WindowWidth = 1280;
    int m_WindowHeight = 720;

    glm::mat4 m_ProjectionMatrix = glm::mat4(1.0f);
    glm::mat4 m_ViewMatrix = glm::mat4(1.0f);
    glm::mat4 m_ViewProjectionMatrix = glm::mat4(1.0f);
};

OrthoCamera.cpp

cpp 复制代码
#include "OrthoCamera.h"
 
OrthoCamera::OrthoCamera()
{
}

OrthoCamera::~OrthoCamera()
{
}

void OrthoCamera::SetView(int windowWidth, int windowHeight)
{
    m_FixedHeight = windowHeight;
    m_WindowWidth = windowWidth;
    m_WindowHeight = windowHeight;
    RecalculateMatrix();
}

void OrthoCamera::SetView(float fixedHeight, int windowWidth, int windowHeight)
{
    m_FixedHeight = fixedHeight;
    m_WindowWidth = windowWidth;
    m_WindowHeight = windowHeight;
    RecalculateMatrix();
}

void OrthoCamera::SetPosition(const glm::vec3& pos)
{
    m_Position = pos;
    RecalculateMatrix();
}

void OrthoCamera::SetZoom(float zoom)
{
    m_Zoom = zoom;
    RecalculateMatrix();
}

void OrthoCamera::RecalculateMatrix()
{
    float aspect = static_cast<float>(m_WindowWidth) / m_WindowHeight;
    float halfHeight = (m_FixedHeight * 0.5f) / m_Zoom;
    float halfWidth = halfHeight * aspect;

    float left = m_Position.x - halfWidth;
    float right = m_Position.x + halfWidth;
    float bottom = m_Position.y - halfHeight;
    float top = m_Position.y + halfHeight;

    m_ProjectionMatrix = glm::ortho(left, right, bottom, top, -1000.0f, 1000.0f); // 扩展 zNear/zFar 范围

    // 这里是关键:
    m_ViewMatrix = glm::translate(glm::mat4(1.0f), -m_Position); // x/y/z 都考虑进去

    m_ViewProjectionMatrix = m_ProjectionMatrix * m_ViewMatrix;
}

Triangle.h

cpp 复制代码
#pragma once
#include "Entity.h"
#include "glm/glm.hpp"
#include "../Shader/Shader_P2_C3.h"
#include "../Core/OrthoCamera.h"

class Triangle // : public Entity
{
public:
	Triangle()
	{
		m_vao = -1;
		m_vbo = -1;
	};
	~Triangle()
	{		
		glDeleteVertexArrays(1, &m_vao);
		glDeleteBuffers(1, &m_vbo);		
	};


	virtual void Init()  // 数据准备
	{	
	    // 1.准备Shader
		m_shader.Initialize();

		// 2.准备数据
		typedef struct Vertex
		{
			float x, y;
			float r, g, b;

		} Vertex;

		Vertex vertices[3] =
		{
			{  -1.0f, -1.0f  , 1.f, 0.f, 0.f},
			{   1.0f, -1.0f  , 0.f, 1.f, 0.f},
			{    0.f,  1.0f  , 0.f, 0.f, 1.f}
		};

		// Shader应用绑定顶点缓冲区数据
		glGenVertexArrays(1, &m_vao);

		glBindVertexArray(m_vao);
		// 创建显存并向顶点缓冲填充数据
		glGenBuffers(1, &m_vbo);
		glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
		glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
		glVertexAttribPointer(m_shader.m_position, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
		glEnableVertexAttribArray(m_shader.m_position);
		glVertexAttribPointer(m_shader.m_color, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(2 * sizeof(float)));
		glEnableVertexAttribArray(m_shader.m_color);

	}


	virtual void Render(const OrthoCamera &camera) // 绘制
	{ 
	 
		m_shader.Begin();
		glBindVertexArray(m_vao);
		glUniformMatrix4fv(m_shader.m_mvp, 1, GL_FALSE, (const GLfloat*)&camera.GetViewProjectionMatrix());
		glDrawArrays(GL_TRIANGLES, 0, 3);
		m_shader.End();
	}


public:
	unsigned        m_vao;
	unsigned        m_vbo;
	Shader_P2_C3    m_shader;

};

Shader_P2_C3.h

cpp 复制代码
#pragma once
#include "Shader.h"
class Shader_P2_C3:public Shader
{

public:
    Shader_P2_C3()
	{
		m_mvp      = -1;
		m_position = -1;
		m_color    = -1;
	};

	~Shader_P2_C3()
	{
	};

	virtual bool  Initialize()
	{
       const char* vs = R"(
               #version 330
               uniform mat4 MVP;
               in vec2 vPos;
               in vec3 vCol;

               out vec3 color;
               void main()
               {
                  gl_Position = MVP * vec4(vPos, 0.0, 1.0);
                  color = vCol;
               }
          )";

        const char* ps = R"(
                #version 330
                in vec3 color;
                out vec4 fragment;
                void main()
                {
                     fragment = vec4(color, 1.0);
                    //fragment = vec4(1.0,1,0,0);
                }
          )";

        bool    res = CreateShader(vs, ps);

        if (res)
        {
            m_mvp      = glGetUniformLocation(m_shaderId, "MVP");
            m_position = glGetAttribLocation(m_shaderId,  "vPos");
            m_color    = glGetAttribLocation(m_shaderId,  "vCol");;
        }	

        return true;
	}

public:
	int m_mvp;
    int m_position;
	int m_color;
};

Shader.h

cpp 复制代码
#pragma once
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <assert.h>
#include <map>
#include <glm/gtc/type_ptr.hpp>
#include <string>

class Shader
{
public:
	Shader();
	~Shader();

public:
	bool CreateShader(const char* vertex, const char* fragment);
	virtual void Begin();
	virtual void End();

    void SetVec3(const std::string& name, const float x, const float y, const float z)const
    {
        auto cit = uniform.find(name);
        glUniform3f(cit->second, x, y, z);
    }

    void SetVec3(const std::string& name, const glm::vec3& vec) const
    {
        auto cit = uniform.find(name);
        glUniform3f(cit->second, vec.x, vec.y, vec.z);
    }

    void SetMat4(const std::string& name, const glm::mat4& mat) const
    {
        auto cit = uniform.find(name);
        glUniformMatrix4fv(cit->second, 1, GL_FALSE, glm::value_ptr(mat));
    }

    void SetFloat(const std::string& name, const float x) const
    {
        auto cit = uniform.find(name);
        glUniform1f(cit->second, x);
    }

    void SetInt(const std::string& name, const int d)const
    {
        auto cit = uniform.find(name);
        glUniform1i(cit->second, d);        
    }
public:
	int  m_shaderId;

    std::map <std::string, unsigned> uniform;
};

Shader.cpp

cpp 复制代码
#include "Shader.h"

Shader::Shader():m_shaderId(0)
{
}

Shader::~Shader()
{
	// 删除shader
	glDeleteProgram(m_shaderId);
}

bool Shader::CreateShader(const char* vertex, const char* fragment)
{
	bool error = false;
	int  vertexShader = 0;
	int  fragmentShader = 0;

	do
	{
		if (vertex)
		{
			vertexShader = glCreateShader(GL_VERTEX_SHADER);
			glShaderSource(vertexShader, 1, &vertex, 0);
			glCompileShader(vertexShader);

			GLint   compileStatus;
			glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &compileStatus);
			error = compileStatus == GL_FALSE;
			if (error)
			{
				GLchar messages[256];
				glGetShaderInfoLog(vertexShader, sizeof(messages), 0, messages);
				assert(messages && 0 != 0);
				break;
			}
		}

		if (fragment)
		{
			fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
			glShaderSource(fragmentShader, 1, &fragment, 0);
			glCompileShader(fragmentShader);

			GLint   compileStatus;
			glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &compileStatus);
			error = compileStatus == GL_FALSE;

			if (error)
			{
				GLchar messages[256];
				glGetShaderInfoLog(fragmentShader, sizeof(messages), 0, messages);
				assert(messages && 0 != 0);
				break;
			}
		}
		m_shaderId = glCreateProgram();

		if (vertexShader)
		{
			glAttachShader(m_shaderId, vertexShader);
		}

		if (fragmentShader)
		{
			glAttachShader(m_shaderId, fragmentShader);
		}

		glLinkProgram(m_shaderId);

		GLint linkStatus;
		glGetProgramiv(m_shaderId, GL_LINK_STATUS, &linkStatus);
		if (linkStatus == GL_FALSE)
		{
			GLchar messages[256];
			glGetProgramInfoLog(m_shaderId, sizeof(messages), 0, messages);
			break;
		}
		glUseProgram(m_shaderId);

	} while (false);

	if (error)
	{
		if (fragmentShader)
		{
			glDeleteShader(fragmentShader);
			fragmentShader = 0;
		}
		if (vertexShader)
		{
			glDeleteShader(vertexShader);
			vertexShader = 0;
		}
		if (m_shaderId)
		{
			glDeleteProgram(m_shaderId);
			m_shaderId = 0;
		}
	}

	return true;
}

void Shader::Begin()
{
	glUseProgram(m_shaderId);

}

void Shader::End()
{
	glUseProgram(0);

}

目标2:先解析DXF基础图元(直线)

dxf选用格式为utf-8明文编码,一下是图层组码信息:100 AcDbLine (直线) 。

AutoCAD 2025 Developer and ObjectARX 帮助 | LINE (DXF) | Autodesk

根据官方文档解析直线->以下组码适用于直线图元。

| LINE 组码 ||

组码 说明
100 子类标记 (AcDbLine)
39 厚度(可选;默认值 = 0)
10 起点(在 WCS 中) DXF:X 值;APP:三维点
20, 30 DXF:起点的 Y 值和 Z 值(在 WCS 中)
11 端点(在 WCS 中) DXF:X 值;APP:三维点
21, 31 DXF:端点的 Y 值和 Z 值(在 WCS 中)
210 拉伸方向(可选;默认值 = 0, 0, 1) DXF:X 值;APP:三维矢量
220, 230 DXF:拉伸方向的 Y 值和 Z 值(可选)
cpp 复制代码
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <Windows.h>

using Entity = std::map<std::string, std::string>;
/// <summary>
/// ifstream和getline获取中文乱码解决方案
/// </summary> 
std::string UTF8ToGB(const char* str)
{
    std::string result;
    WCHAR* strSrc;
    LPSTR szRes;

    //获得临时变量的大小
    int i = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
    strSrc = new WCHAR[i + 1];
    MultiByteToWideChar(CP_UTF8, 0, str, -1, strSrc, i);

    //获得临时变量的大小
    i = WideCharToMultiByte(CP_ACP, 0, strSrc, -1, NULL, 0, NULL, NULL);
    szRes = new CHAR[i + 1];
    WideCharToMultiByte(CP_ACP, 0, strSrc, -1, szRes, i, NULL, NULL);

    result = szRes;
    delete[]strSrc;
    delete[]szRes;

    return result;
}

// 去除前后空格
std::string trim(const std::string& str) {
    auto first = str.find_first_not_of(" \t\r\n");
    auto last = str.find_last_not_of(" \t\r\n");
    return (first == std::string::npos) ? "" : str.substr(first, last - first + 1);
}

// 读取组码-值对
bool ReadCodes(std::ifstream& file, std::string& code, std::string& value) {
    if (!std::getline(file, code)) return false;
    if (!std::getline(file, value)) return false; 

    std::string strCode = UTF8ToGB(code.c_str()).c_str();
    std::string strValue = UTF8ToGB(value.c_str()).c_str();
    code = trim(strCode);
    value = trim(strValue);
    return true;
}

 
// 解析 DXF 中所有 LINE 实体的图层和坐标
std::vector<Entity> ParseDXFLines(const std::string& filename) {
    std::ifstream file(filename, std::ios::binary);
    if (!file.is_open()) {
        std::cerr << "无法打开文件: " << filename << std::endl;
        return {};
    }

    std::vector<Entity> lineEntities;
    Entity currentEntity;
    std::string code, value;
    std::string currentLayer;

    while (ReadCodes(file, code, value)) {
        // 处理每个 AcDbEntity 实体
        if (code == "100" && value == "AcDbEntity") {
            // 获取图层信息
            while (ReadCodes(file, code, value)) {
                if (code == "8") {
                    currentLayer = value;  // 保存图层名
                    break;
                }
            }
        }

        // 处理 AcDbLine 实体
        if (code == "100" && value == "AcDbLine") {
            Entity lineEntity;
            lineEntity["Layer"] = currentLayer; // 设置图层信息

            // 获取起点 (10, 20, 30)
            while (ReadCodes(file, code, value)) {
                if (code == "10") lineEntity["StartX"] = value;
                if (code == "20") lineEntity["StartY"] = value;
                if (code == "30") lineEntity["StartZ"] = value;

                // 获取终点 (11, 21, 31)
                if (code == "11") lineEntity["EndX"] = value;
                if (code == "21") lineEntity["EndY"] = value;
                if (code == "31") lineEntity["EndZ"] = value;

                // 检查是否处理完一个线段(可根据需要继续读取更多信息)
                if (lineEntity.size() == 6) {
                    lineEntities.push_back(lineEntity);
                    break;
                }
            }
        }
    }

    file.close();
    return lineEntities;
}


int main()
{ 
    std::string filename = R"(C:\Users\Desktop\Drawing1.dxf)";
    // 解析文件
    auto lines = ParseDXFLines(filename);

    // 输出解析的直线信息
    for (const auto& entity : lines) {
        std::string layer = entity.count("Layer") ? entity.at("Layer") : "(未知图层)";
        std::string x1 = entity.count("StartX") ? entity.at("StartX") : "?";
        std::string y1 = entity.count("StartY") ? entity.at("StartY") : "?";
        std::string x2 = entity.count("EndX") ? entity.at("EndX") : "?";
        std::string y2 = entity.count("EndY") ? entity.at("EndY") : "?";

        std::cout << "图层: " << layer
            << ",起点: (" << x1 << ", " << y1 << ")"
            << ",终点: (" << x2 << ", " << y2 << ")"
            << std::endl;
    }
    return 0;
} 
相关推荐
?!7143 分钟前
数据结构之哈夫曼树
c语言·数据结构·c++·算法
元亓亓亓14 分钟前
Java后端开发day39--方法引用
java·开发语言
CodeWithMe20 分钟前
【中间件】brpc_基础_butex.h
c++·中间件·rpc
.格子衫.1 小时前
014枚举之指针尺取——算法备赛
java·c++·算法
明月看潮生1 小时前
青少年编程与数学 02-018 C++数据结构与算法 24课题、密码学算法
c++·算法·青少年编程·密码学·编程与数学
步行cgn1 小时前
GZIPOutputStream 类详解
java·开发语言·intellij-idea
wuqingshun3141592 小时前
蓝桥杯 17. 通电
c++·算法·职场和发展·蓝桥杯·深度优先·动态规划
HelloZheQ2 小时前
Java:从入门到精通,你的编程之旅
java·开发语言
烦躁的大鼻嘎2 小时前
【Linux】深入理解Linux基础IO:从文件描述符到缓冲区设计
linux·运维·服务器·c++·ubuntu
李匠20242 小时前
C++负载均衡远程调用学习之HOOK注册机制
java·c++·学习·负载均衡