自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(45)
  • 问答 (1)
  • 收藏
  • 关注

原创 映射模式详解

1、视口、窗口GDI绘图中设计两个坐标系:逻辑坐标系和设备坐标系。逻辑坐标系对应窗口,设备坐标系对应视口。GDI绘图函数中坐标参数和尺寸参数都是基于逻辑坐标系的。所以,从程序员角度看是以逻辑坐标系绘图,windows负责根据映射模式、窗口原点、窗口范围、视口原点、视口范围,把逻辑坐标系中的图像映射到设备坐标系中显示。2、映射模式windows提供了8种映射模式:映射模式逻辑单位x轴方向y轴方向MM_TEXT像素右下MM_LOMETRIC...

2021-06-03 15:40:09 1280 2

原创 14、位图

1、位图位图是点阵图形,由像素组成。位图的大小由图像尺寸和颜色深度决定。图像尺寸决定了像素的数量,颜色深度决定了每个像素的位数(bits)。2、位块传输位块传输是指,把源设备环境中的一个区域复制到目标设备环境中。实际不是简单的复制,是源位图、目标位图和目标设备环境的背景画刷三者进行一种三元光栅操作的结果。windows定义了10多种三元光栅操作:/* Ternary raster operations */#define SRCCOPY (DWO...

2021-05-30 21:19:02 297

原创 12、剪贴板

1、内存分配使用剪贴板时,程序必须申请一个内存块用于存储数据,并把内存块交给剪贴板。申请内存块可以使用GlobalAlloc函数,GlobalAlloc的返回值是一个HGLOBAL类型的句柄。如果GlobalAlloc调用时指定了GMEM_FIXED标志位,内存块地址是固定不变的,句柄值实际是一个内存块指针;如果指定了GMEM_MOVEABLE标志位,那么windows会在需要情况下移动该内存块(虚拟内存),以防止内存碎片化。由于内存块可以移动,返回值自然不是固定的内存块指针,而就是一个句...

2021-05-25 15:27:55 293

原创 11、对话框

1、对话框对话框是一种特殊的窗口,通常包含各种子窗口控件。特殊的地方在于,它的窗口过程属于windows,程序员拥有的被称作"对话框过程",windows窗口过程内部会调用对话框过程,把一些消息交给程序员处理。2、设计对话框可以在资源管理界面中设计对话框,把各种子窗口控件布局在对话框中。需要注意的是,对话框设计中使用的坐标值和尺寸并不是以像素为单位,它们的大小基于对话框当前使用的字体大小:x坐标和宽度以字符平均宽度的1/4为单位y坐标和高度以字符高度的1/8为单位...

2021-05-18 15:33:13 380

原创 10、菜单和其他资源

1、资源编译程序时,所有资源都会被保存到exe文件或者dll文件中,所以加载资源的API函数第一传参都是程序实例句柄hInstance。在进程启动时,资源并不会被加载到内存中,只有在需要使用时才调用函数,显式把资源加载到内存中。每个资源都拥有一个标识符,标识符可以是数字,也可以是字符串。加载资源的函数需要的标识符传参都是字符串类型,可以使用MAKEINTRESOURCE宏把数字标识符转换为字符串类型。2、图标图标最开始是在注册窗口类时使用,如果窗口带有标题栏,那么注册窗口...

2021-05-13 15:54:07 176

原创 9、子窗口控件

1、基础windows提供了多种预定义控件,这些控件是已经注册的窗口类,只需要调用CreateWindow函数直接创建即可。CreateWindow的传参和创建普通窗口时稍有不同:CreateWindow( _In_opt_ LPCWSTR lpClassName, // 窗口类名称 _In_opt_ LPCWSTR lpWindowName, // 窗口文本 _In_ DWORD dwStyle, // 窗口样式,需包含WS_CHILD以及...

2021-05-10 11:11:29 314

原创 8、定时器

1、定时器实现windows定时器通过一个称为“时间滴答”的硬件中断实现。windows为每一个定时器维护一个计数值,时间滴答中断出现时,计数值减1。当计数值为0时,windows把WM_TIMER消息插入到窗口消息队列中,同时计数值复位。前面提到,windows是以同步的方式处理消息的,定时器实现依赖于消息,所以定时器也是同步的,定时器不会中断当前程序的运行。另外,windows不会在消息队列中插入多条WM_TIMER消息。2、定时器使用当需要一个定时器时,使用Set...

2021-05-07 15:40:43 116

原创 7、鼠标

鼠标消息1、鼠标客户区消息当鼠标经过客户区或在客户区内点击时,windows就会向窗口过程发送鼠标客户区消息。windows定义了10种客户区鼠标消息:WM_MOUSEMOVE消息队列中只能存放一条WM_MOUSEMOVE消息。所以,消息队列中有未处理的WM_MOUSEMOVE消息时,windows不会再把WM_MOUSEMOVE加入消息队列,即使鼠标在移动。WM_LBUTTONDBLCLK、WM_MBUTTONDBLCLK、WM_RBUTTONDBLCLKDBLCLK双击

2021-05-06 15:18:22 140 1

原创 6、键盘

键盘基础1、焦点键盘被正在运行的所有程序共享,键盘消息会被当前拥有焦点的窗口接收,窗口获取焦点时窗口过程会收到WM_SETFOCUS消息,而失去焦点时会接收到WM_KILLFOCUS消息。2、同步键盘消息产生后,首先被暂时存储在系统消息队列中,只有当窗口过程处理完上一条键盘消息后,才会从系统消息队列取出下一条键盘消息放入程序消息队列中。这一机制是为了避免键盘消息被发送到错误的窗口过程。假如没有系统消息队列:一个特殊的键盘消息可能导致焦点的转移,则其后面的键盘消息应该发送

2021-04-29 15:59:07 74

原创 5、绘图基础

设备环境1、CreateIC《4、文本输出》中介绍了设备环境句柄的获取方法。但有时并不需要绘图,只是获取一些设备环境句柄相关的信息,可以使用CreateIC。CreateIC也是返回一个HDC,但是不能对其进行绘制。2、GetDeviceCapsGetDeviceCaps用于获取设备环境的一些显示能力,比如: - HORZSIZE:以毫米为单位的物理屏幕宽度 - VERTSIZE:以毫米为单位的物理屏幕高度 - HORZRES:水平方向像素数 - VERTRES:垂直方向像素数 - LOG

2021-04-28 14:02:11 221

原创 4、文本输出

无效矩形需要重绘的区域被称为“无效区域”,windows会计算出一个包含无效区域的最小矩形,这个最小矩形被称为“无效矩形”,调用windows函数可以获取到这个无效矩形。当窗口中出现无效区域时,windows把WM_PAINT消息发送到窗口消息队列。消息队列中不会出现多条WM_PAINT消息,windows会根据新出现的无效区域,计算一个新的无效矩形。设备环境句柄1、BeginPaint和EndPaint调用GDI函数基本都需要一个设备环境句柄参数。获取设备环境句柄的一个方法是调用BeginPai

2021-04-25 16:59:16 283

原创 3、窗口的创建

窗口应用程序是消息驱动的。用户对窗口的输入最终以消息的形式传递给窗口,窗口间的通信也依赖于消息。所谓“传递给窗口”是指系统调用了我们提供的、被称为窗口过程的函数,窗口过程负责对消息作出响应。窗口过程和窗口类绑定,创建窗口前必须注册窗口类。1、注册窗口类调用RegisterClass注册窗口。该函数只需要一个WNDCLASS指针传参。typedef struct tagWNDCLASSA { UINT style; // 窗口类样式 WNDPROC lpfnW

2021-04-23 17:00:59 483

原创 并发实践:线程池

class ThreadPool{ std::queue<std::function<void()>> _tasks; // 任务队列 std::vector<std::thread> _threadPool; // 线程池 int _cntThread; // 线程数 std::mutex _mutex; std::condition_variable _cv; std::atomic<bool> _stop;public: Thr

2021-03-05 15:33:30 60

原创 同步控制:condition_variable

条件变量条件变量(condition_variable)用来实现多线程间的同步操作,控制多个线程的执行顺序。操作作用conditon_variable cv默认构造函数~conditon_variable()析构函数cv.notify_one()唤醒一个等待线程cv.notify_all()唤醒所有等待线程cv.wait(ul)使用unique_lock来等待通知cv.wait(ul, pred)使用unique_lock来等待通知,直到唤醒

2021-03-01 14:58:36 134

原创 独占资源:mutex和lock_gurad

mutexmutex互斥量用来以独占方式访问资源。操作作用mutex m默认构造函数,构建一个未锁定的mutex对象~mutex()析构函数m.lock()尝试锁住mutex。如果mutex已是锁定状态,会造成阻塞m.try_lock()尝试锁住mutex,成功则返回truem.try_lock_for(dur)尝试在时间段dur内锁住mutex,成功则返回truem.try_lock_until(tp)尝试在时间点tp之前锁住mutex,成

2021-02-25 17:10:06 261

原创 并发高层接口:async和future

asyncasync是一个辅助函数,它以同步或异步的方式执行一个函数,具体方式由发射策略决定future async(std::launch::async, F func, args…)async尝试启动一个线程,以异步的方式执行func,args是func的实参。如果启动线程失败,抛出std::system_error异常,错误码为std::errc::resource_unavailable_try_again。future async(std::launch::deferred, F fun

2021-02-25 14:16:01 146

原创 并发低层接口:thread和promise

threadthread是C++11引入的一个处理并发的低层接口。支持的操作操作作用thread t默认构造函数,创建一个没有关联线程(nonjoinable)的thread对象thread t(f, …)创建一个关联到线程(joinable)的thread对象。这是一个可变参模板函数,f 是线程函数,f后面的函数参数是f的传参;或抛出std::system_errorthread t(rv)移动构造函数,取rv的状态并使rv变成nonjoinable~th

2021-02-24 16:19:04 285

原创 最短路径dijkstra算法

基本思路1、维护一个距离表数组dis,dis[i] 表示通过已访问节点从起点到节点i 的最短路径。2、每次访问dis最小、且未访问的节点,更新dis表。例子用邻接矩阵graph存储:过程演示1、初始起点0为已访问,同时初始dis表2、dis[2]最小且节点2未访问,故访问节点2,并更新dis表。节点2和节点3、5邻接,且节点3、5未访问,且通过节点2到达节点3、5路径更短,故更新dis[3]、dis[5]。2、dis[1]最小且节点1未访问,故访问节点1,并更新dis表。节点1和节

2021-02-04 11:58:15 119

原创 最小生成树kruskal算法

基本思路1、选择权重最小的边加入最小生成树。2、如果加入的边使最小生成树构成回路,则舍弃这条边。判断是否构成回路需要使用并查集。3、重复上述步骤,直至完成。例子使用边集数组存储并按权重排序:算法过程1、选择权重最小的edges[0]加入最小生成树2、选择权重最小的edges[1]加入最小生成树3、选择权重最小的edges[2]加入最小生成树4、选择权重最小的edges[3]加入最小生成树5、现在,权重最小的边是edges[4]。如果把这条边加入最小生成树会构成回路,所以舍弃

2021-02-03 17:04:04 98

原创 最小生成树prim算法

基本思路1、每次选择一个节点加入最小生成树,选择节点的原则是贪心,和已选节点邻接的未选节点中,选择边权重最小的节点。2、维护一个代价数组lowcost,lowcost[i]表示所有已选节点和节点 i 相连的边中最小的权重:标题例子使用邻接矩阵存储:算法过程1、初始状态把节点0加入已选节点,未选节点还有 [1, 2, 3, 4, 5],更新lowcost数组。由于已选节点只有节点0,lowcost[i]等于节点0和节点i直连边的权重值。2、节点2加入已选节点 [0, 2], 同时更新lo

2021-02-03 11:38:38 91

原创 leetcode - 11. 盛最多水的容器

题目描述基本思路假设有两个坐标点(i, ai)和(j, aj),且j > i,aj > ai。另有坐标点(k, ak),i < k < j。坐标点i和坐标点j形成的容器容积比坐标点 i 和坐标点 k 形成的容器容积大。如果 ai > ak,宽度变小,高度也变小(容积取决于较小边),容积变小;如果 ai < ak,宽度变小,高度不变,容积变小。所以,可以使用首尾指针,移动首尾指针中高度小的。int maxArea(vector<int>&

2020-12-17 22:42:45 67 1

原创 leetcode - 234. 回文链表

题目描述基本思路1、利用快慢指针,快指针每次走两步,慢指针每次走一步,找到链表中点。2、把后半部分逆序。3、比较前后两部分。奇数长度的链表和偶数长度的链表操作不同点:查找中点:奇数链表结束时,以fast->next为空结束;偶数链表以fast为空结束。逆序:代码实现中没有把前半部分链表最后一个元素的next指针设为空。结果是偶数链表前半部分链表比后半部分链表长度多1。bool isPalindrome(ListNode* head) { if (!head) retur

2020-12-17 22:09:58 54

原创 leetcode - 763. 划分字母区间

题目描述基本思路双指针滑动窗口。读取第一个字符,记录下标位置为first,找到该字符最后出现的位置,记录下标为last。遍历[first + 1, last - 1]区间内字符,如果字符最后出现位置在last后面,则更新last。遍历结束后,完成一个子区间划分。vector<int> partitionLabels(string S) { vector<int> vec(26, 0); for (int i = 0; i < S.length(); i+

2020-12-17 10:08:11 52

原创 剑指 Offer 22. 链表中倒数第k个节点

题目描述基本思路快慢指针。慢指针指向第k个节点时,快指针指向最后一个节点,快指针比慢指针快k-1步。快指针的next为null判断结束。struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(NULL) {}};ListNode* getKthFromEnd(ListNode* head, int k) { ListNode *fast = head; for (int i =

2020-12-16 21:29:37 61

原创 刷题历程 - 导航

堆leetcode-1054. 距离相等的条形码

2020-12-16 21:10:23 65

原创 leetcode-1054. 距离相等的条形码

题目描述基本思路1、从下标0位开始放置数字,直到结尾2、从剩余数字中选择出现次数最多的数字m和次多的数字n,依次放置到结果列表3、重复步骤2直到放置完毕static bool cmp(std::pair<int,int> &p1, std::pair<int,int> &p2){ return p1.second < p2.second;}vector<int> rearrangeBarcodes(vector<int&gt

2020-12-16 20:57:43 98

原创 Lambda表达式

语法定义:[capture] (parameters) mutable -> return-type {statement}[capture]:捕捉列表。[]是lambda表达式的引出符。capture描述了上下文能供函数体使用的变量及其使用方式(值传递或引用传递)。[capture]有以下几种基本形式:表达式意义[var]值传递方式捕捉var变量[=]值传递方式捕捉lambda表达式所在函数位置可以访问到的所有局部变量,和lambda表达式所在类的所有成员变

2020-12-04 15:16:44 300

原创 函数对象

STL中,很多算法提供通过回调函数的方式来定义内部的具体实现细节。说回调函数其实不准确,因为模板实参不一定是函数指针,模板函数的内部只是通过模板实参调用了operator(),模板实参只需要支持operator()就可以。所以,除了函数外,函数对象、Lambda表达式等可调用对象也可以用于算法,定义其内部实现细节1、函数对象函数对象是指内部实现了operator()的类对象,可以提供类似函数的行为:class Print{public: void operator() (string s) {

2020-12-03 16:38:55 123

原创 迭代器适配器

1、插入型迭代器 insert iterator使用 insert iterator 对容器元素进行赋值操作时,实际进行的是插入操作。赋值和插入操作一个明显的区别在于,赋值动作必须确保目标容器有足够的空间。插入的位置根据不同的 insert iterator有所不同:back_inserter:内部调用 push_back(),在容器末端插入元素。所以使用back_inserter的容器必须支持 push_back(),这些容器包括 vector、deque、list 和 string。front_i

2020-11-30 16:21:07 147

原创 迭代器分类

迭代器分类迭代器能力提供output迭代器向前输出Ostream、inserterinput迭代器向前输入Istreamforward迭代器向前输入输出forward list、unordered containersbidirectional迭代器向前、向后输入输出list、set、multiset、map、multimaprandom-access迭代器随机输入输出array、vector、deque、string纯粹的 outp

2020-11-30 16:08:44 186

原创 stl vector

vector表现出来的是一个大小可变、内存连续的数组。类模板定义:template <typename T, typename Allocator = allocator<T> >class vector;vector支持下列操作:操作作用vector c默认构造函数,构造一个没有任何元素的空vectorvector c(c2)复制构造函数vector c(rv)移动构造函数vector c(n)构造一个大小为n的vector

2020-11-27 16:02:29 53

原创 STL 概述

容器:用来管理某类对象的结合迭代器:用来遍历容器的元素算法:用来处理容器的元素基本容器分类:1、序列式容器序列式容器是一种有序容器。这里的有序不是指容器里的元素一定是按从小到大或从大到小等排列规则排序好;而是指元素插入容器后,若不人为改动元素间的相对位置,那它的位置就不会改变。STL提供了5中序列式容器:array、vector、deque、list 和forward_list,内部存储结构一般为array或linked list。vectorvector相当于一个动态数组,其内部存储结构就是

2020-11-26 14:32:48 113 1

原创 stl array

array支持的操作:操作作用array<Elem,N> c默认构造函数,元素进行默认初始化array<Elem,N> c拷贝构造函数,拷贝数组每一个元素array<Elem,N> c = c2赋值操作符,拷贝数组每一个元素array<Elem,N> c(rv)移动构造函数array<Elem,N> c = rv移动赋值操作符array<Elem,N> c = initlis

2020-11-26 14:23:51 123

原创 type trait

type trait是一系列模板,描述了类型的特征,定义在<type_traits>。类型判断trait作用is_void是否voidis_integral整数类型(包括bool、char、char16_t、char32_t、wchar_t)is_floating_point浮点数类型is_arithmetic整数(包括bool、char、char16_t、char32_t、wchar_t)或浮点数is_signed带符号is_un

2020-11-23 11:16:53 398

原创 unique_ptr

unique_ptr提供的语义是独占资源,支持下列操作:函数作用unique_ptr up默认构造函数,up为空unique_ptr up(ptr)构造函数,指定资源unique_ptr up(ptr, del)构造函数,指定资源和deleterunique_ptr up(move(up2))移动语义构造函数,up2是一个unique_ptr对象,up2的资源所有权转移到upunique_ptr up(move(ap))移动语义构造函数,ap是一个au

2020-11-18 21:39:06 71

原创 shared_ptr和weak_ptr

程序中需要管理各种各样的资源,为了避免内存泄露,必须确保在资源再也不需要时释放资源,智能指针提供了这一功能。C++标准提供了两大类智能指针,这里主要介绍shared_ptr。多个shared_ptr可以共享同一个资源,并在最后一个拥有资源的shared_ptr被销毁时释放资源。1、deleter2、weak_ptr...

2020-11-18 15:42:10 1543

原创 tuple

tuple是一个异质数据集合,是pair的扩展,支持任意数量元素。tuple是TR1引入的,由于当时语言不支持不定参模板,所以最初的tuple元素个数是有限的。C++11引入不定参模板后,tuple得到重新实现。tuple支持下列操作:函数作用tuple<T1,T2,…,Tn> t默认构造函数tuple<T1,T2,…,Tn> t(v1,v2,…,vn)构造函数,以给定值完成初始化tuple<T1, T2> t§构造函数,以pa

2020-11-06 14:21:10 273

原创 pair

pair是用来处理类型相同或不同的一对值的数据结构,定义于,支持下列操作:函数作用pair<T1, T2> p默认构造函数pair<T1, T2> p(val1, val2)构造函数,用val1和val2为初值pair<T1, T2> p(rv1, rv2)移动语义构造函数,rv1和rv2为右值引用pair<T1, T2> p(piecewise_construct, t1, t2)构造函数,t1和t2是tupl

2020-11-06 10:43:18 278

原创 常用字符串处理函数

C/C++常用字符串处理函数:功能ANSI版本UNICODE版本通用版本备注转换为双精度浮点数atof_wtof_tstof转换为整型atoi_wtoi_tstoi转换为长整型atol_wtol_tstol判断字符是不是数字或字母isalnumiswalnum_istalnum判断字符是不是字母isalphaiswalpha_istAlpha判断字符是不是ascii字符isasciiiswasciiist

2020-10-29 17:22:17 513

原创 中文乱码问题分析

在平时处理中文字符时经常会遇到乱码问题,为了弄清楚其中原因,做了个实验。在实验前需要先了解几个概念:1、ANSI编码ANSI不是一种具体的编码方式,它依赖于当前系统使用的码表,在命令行中使用chcp命令可以获取到系统当前使用的码表。VS新建的项目默认使用ANSI编码。2、源文件编码VS新增的文件默认为ANSI编码,我们可以把源文件编码方式改为utf8。但前面提到VS项目默认使用ANSI编码,所以我们还需要修改项目属性,以告诉编译器用utf8编码来解析源文件。项目属性修改:项目属性 -&gt

2020-10-26 11:08:35 1951

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除