- 博客(55)
- 收藏
- 关注
原创 字符输入验证函数
查找输入的字符串是否符合要求,通常用于限制用户在编辑框(如 CEdit)中只能输入特定格式的数据,例如数字、小数、时间格式等。**m_nDecialNum:**一个成员变量,表示允许的小数点后数字的位数(如设为2,则小数最多有两位小数)。**GetWindowText(strContent):**获取当前编辑框的内容。**GetSel(nStart, nEnd):**获取当前选中的文本范围。**m_bMinus:**一个成员变量,表示是否允许输入负号(负数)。
2025-04-20 15:27:59
136
原创 C#: 日志函数
1.常见的官方日志模块项目过于复杂,且配置过于繁琐,针对这种现象,实现在大型项目中快速定位错误问题;1.设置当前日志文件路径(获取到当前文件应用程序路径 + \ErrorLog)4.判断当前文件是否存在,如果不存在则创建,如果存在则增加。2.判断当前日志文件路径是否存在,不存在则创建。3.在当前日志文件路径下创建日志文本。
2025-02-23 22:14:38
306
原创 C#: 创建Excel文件并在Excel中写入数据库中的数据
4.创建 Excel 应用实例。7.保存 Excel 文件。8.释放 Excel 资源。3.删除已存在的同名文件。1.检查数据是否可导出。2.弹出文件保存对话框。
2025-02-18 20:01:50
374
原创 LeetCode:两个数组的交集--哈希表实现
349.两个数组的交集思路:1.利用哈希表存储nums1、nums2中元素2.判断哪个哈希表长,然后遍历较小的集合,判断其中的每个元素是否在另一个集合中,如果元素也在另一个集合中,则将该元素添加到返回值class Solution {public: vector<int> intersection(vector<int>& nums1, vector<int>& nums2) { //1.利用哈希表存储nums1、nums
2022-05-26 09:05:09
217
原创 LeetCode:二叉树层序遍历
102.二叉树的层序遍历思路:用队列实现层序遍历1.创建二维数组最终存放二叉树的每一层的元素2.创建队列实现每一层的遍历3.遍历3.1 先存放第一层节点3.2 遍历每一层的节点先确定每一层节点的个数,然后通过队列存储到一维数组中,最后插入到二维数组将每一层的元素存放到新的一维数组中3.3 将新数组元素插入到二维数组中4.返回二维数组/** * Definition for a binary tree node. * struct TreeNode { * int val
2022-05-25 09:43:24
368
原创 LeetCode:二叉树的中序遍历
94.二叉树的中序遍历方法一:递归/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), left(nullptr), ri
2022-05-17 22:02:03
354
原创 LeetCode:144.二叉树的前序遍历
144.二叉树的前序遍历二叉树的前序遍历:按照访问根节点——左子树——右子树的方式遍历这棵树,而在访问左子树或者右子树的时候,我们按照同样的方式遍历,直到遍历完整棵树。因此整个遍历过程天然具有递归的性质。方法一:递归/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() :
2022-05-17 10:33:31
131
原创 Leetcode设计链表---单(双)链表
问题:7.7。设计链表问题分析:1.创建了结构体节点struct ListNode,成员变量有数据域和next指针域ListNode含有三种初始化列表(无参、单参、双参)2.创建了自定义链表MyLinkedList,成员变量有struct ListNode *head作为头结点, int size保存链表长度MyLinkedList无参构造函数–新建头结点,size初始化get(int index)–顺序遍历到索引为index的节点,返回valvoid addHead(int val)–先断
2022-04-28 16:35:03
964
原创 删除链表的倒数第N个节点----双指针解法
删除链表的倒数第N个节点思路:设有两个指针 p 和 q,初始时均指向头结点。首先,先让 p 沿着 next 移动 k 次。此时,p 指向第 k+1个结点,q 指向头节点,两个指针的距离为 k 。然后,同时移动 p 和 q,直到 p 指向空,此时 q 即指向倒数第 k 个结点。加个哑结点,可以方便删除,因为单链表删除需要知道删除节点前的那个节点/** * Definition for singly-linked list. * struct ListNode { * int val;
2022-04-27 09:32:53
588
1
原创 LRU缓存--C++官方解法分析
LRU原理: 每次访问的数据都会放在栈顶,当访问的数据不在内存中,且栈内数据存储满了,我们就要选择移除栈底的元素,因为在栈底部的数据访问的频率是比较低的。所以要将其淘汰。题目分析:键值: 哈希表顺序存储: 想到栈、队列、链表如果关键字 key 已经存在,则变更其数据值 value ;可知:数据需要随机访问、需要把数据插入到头部或者尾部链表:实现数据插入到头部或者尾部哈希:实现随机访问在双向链表的实现中,使用一个伪头部(dummy head)和伪尾部(dummy tail)标记界限,这样在添加节
2022-04-27 09:25:12
423
原创 哈希表实现线性检测(超详细)
哈希表的线性检测:思路分析:1.哈希表定义 ----成员定义(private):存储方式(哈希节点的数组)、元素空间的大小、哈希表构造函数2.哈希表存入的数据类型: 哈希节点:哈希函数需要知道键值,因此键值数据设置成KV函数,同时哈希删除为假删除,因此需要定义状态3.哈希表的插入(插入哈希节点)3.1 检查容量载荷因子大于设置的0.7就扩容(哈希数组的有效元素比上空间大小 _size*10/_ht.size()),或者无空间(哈希数组_ht.size())扩容大小开辟新的哈希空间插入元素,
2022-04-04 22:19:15
1817
原创 LeetCode----80. 删除有序数组中的重复项 II
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度。80. 删除有序数组中的重复项 II不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。方法1:双指针class Solution {public: int removeDuplicates(vector<int>& nums) { /* 最多出现两次,表示前两位一定存在于nums数组中
2022-03-31 16:46:39
512
原创 leetcode---349.两个数组的交集
给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。输入:nums1 = [1,2,2,1], nums2 = [2,2]输出:[2]两个数组的交集方法1:排序+双指针class Solution {public: vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
2022-03-30 17:35:35
286
原创 leetcode---206.反转链表
206.反转链表给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。class Solution {public: ListNode* reverseList(ListNode* head) { //1.迭代法 //1->2->3->4->5 ListNode* prev=nullptr; //定义1位置之前的前指针 ListNode* curr=head; //定义1位置的当前指针 while(curr)
2022-03-29 17:31:48
1904
原创 动态规划--斐波那契数列(剑指offer)
DP定义:动态规划是分治思想的延伸,通俗一点来说就是大事化小,小事化无的艺术。在将大问题化解为小问题的分治过程中,保存对这些小问题已经处理好的结果,并供后面处理更大规模的问题时直接使用这些结果。动态规划具备了以下三个特点把原来的问题分解成了几个相似的子问题。所有的子问题都只需要解决一次。储存子问题的解。动态规划的本质:是对问题状态的定义和状态转移方程的定义(状态以及状态之间的递推关系)动态规划问题一般从以下四个角度考虑:状态定义状态间的转移方程定义状态的初始化返回结果状态定义的要求
2022-03-29 16:50:59
282
原创 多线程通信---解决TCP通信阻塞问题
TCP通信阻塞原因:accept与recv以及send都是阻塞接口,任意一个接口的调用,都有可能会导致服务端流程阻塞本质原因:当前的服务端,因为不知道什么时候有新连接到来,什么时候那个客户端有数据到来,因此流程只能固定的去调用接口,但是这种调用方式有可能会造成阻塞解决方案:多执行流并发处理为每个客户都创建一个执行流负责与这个客户端进行通信好处:1.主线程卡在获取新建连接这里,但是不影响客户端的通信2. 某个客户端的通信阻塞,也不会影响主线程以及其他线程在主线程中,获取新建连接,一旦获取到来
2022-01-04 11:13:26
7079
原创 socket---TCP通信
TCP通信流程的编写:通信流程:Server:1.创建套接字2.为套接字绑定地址信息3.开始监听告诉系统可以开始处理客户端的连接请求。系统会为每一个新客户创建一个新的套接字4.获取新建连接5. 收发数据(使用的是新建的套接字)6. 关闭套接字Client:1.创建套接字2. 为套接字绑定地址信息(不推荐主动绑定)3.向服务端发起连接请求(开始监听之后)4.收发数据5.关闭套接字接口认识:1.创建套接字:int socket(int domain, int type, in
2021-12-29 15:31:45
1251
原创 socket---UDP通信
通信流程:Server:1.创建套接字 — 在内核中创建一个socket结构体2.为套接字绑定地址信息在创建套接字创建的socket结构体中加入IP+PORT信息1.告诉操作系统主机收到的哪些数据应该交给当前的这个socket2.确定发送数据的源端地址信息3.接收数据当前进程从指定的socket接收缓冲区中取出数据4.发送数据将要发送的数据放到socket发送缓存区中,内核选择合适时候封装发送5.关闭套接字Client:1.创建套接字2.为套接字绑定地址信息 (大多数情况下会
2021-12-09 19:21:31
2203
原创 进程信号---阻塞信号
阻塞: 信号依然可以注册,只是暂时阻止信号被处理。在pcb中还有一个信号集合—阻塞集合;哪个信号在这个集合中被标记,则表示这个信号要阻塞,收到了这个信号则暂时不去处理。int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);//how:操作类型---要对阻塞集合进行的操作//SIG_BLOCK:将set集合中的信号添加到阻塞结合;block|=set//SIG_UNBLOCK:从阻塞结合中移除set中的信号 block &a
2021-12-07 10:41:25
968
原创 进程信号----自定义处理方式
处理: 说白了就是打断进程当前操作,然后执行信号的处理函数,执行完毕后回到原来的主控流程继续运行。处理方式:默认处理方式:执行默认的处理方式忽略处理方式:信号依然会注册只是处理方式变为空操作自定义处理方式:自己定义信号处理函数,修改信号的处理函数指针 #include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<signal.h> void sigcb(int no)
2021-11-28 22:56:56
337
原创 进程信号---kill命令
进程信号:原理:是一种中断机制,或者说是一种事件通知机制,在这里讲的是软件中断,通过信号通知进程发生了某个事件,打断进程当前的操作,去处理事件。一个信号对应一个事件,并且信号必须能够被识别Linux下信号种类:使用kill -l命令进行查看,62种1~31号:非可靠信号;34-64号:可靠信号信号的生命周期:产生,注册,注销,处理产生:硬件产生: ctrl+c,ctrl+\,ctrl+z软件产生: kill命令发送一个信号给进程;示例: kill -sigid pidkill杀死进程
2021-11-28 22:25:16
959
原创 进程间通信---共享内存
共享内存:目的: 用于进程间的数据共享原理: 开辟一块物理内存空间,各个进程将同一块物理内存空间映射到自己的虚拟地址空间中,通过虚拟地址进行访问,进而实现数据共享共享内存是最快的进程间通信方式,因为通过虚拟地址空间映射后,直接通过虚拟地址访问物理内存,相较于其他方式少了两部数据拷贝操作。操作流程:1.创建或打开共享内存int shmget(key_t key, size_t size, int shmflg);key:标识符—通过相同的标识符,多个进程可以打开同一块共享内存;size:要创建
2021-11-15 16:39:39
191
原创 进程间通信--命名管道
命名管道:可以用于同一主机上任意进程间通信—管道缓冲区具有标识符命名管道:mkfifo filename 创建一个管道文件命名管道本质上依然是内核中的一块缓存区,但是命名管道有名字具有标识符,而这个标识符就是一个可见于文件系统的管道类型文件,多个进程可以通过打开同一个管道文件访问同一块内核中的缓冲区实现通信代码操作:int mkfifo(char *path,int mode);对管道的读写操作,仍然是IO操作打开特性:若以只读方式打开命名管道文件,则会阻塞,直到这个管道文件被以写的方式打开
2021-11-09 17:01:15
273
原创 C++:string类
1.标准库中的string类1.构造函数的使用方式#include<string>using namespace std;void test(){ /*default (1) string(); //无参构造*/ //创建空的string对象 string str; /*copy(2) //拷贝构造 string(const string& str);*/ string copy(str); /*from c - string(4) s
2021-11-06 11:30:00
80
原创 系统调用接口---IO
*int open(const char pathname, int flags, mode_t mode);open(文件名,选项标志,权限)pathname:文件路径名flags:标志位必选其一:O_RDONLY ,O_WRONLY, O_RDWR可选项:O_CREAT:如果文件不存在,则创建O_EXCL:跟O_EXCL一起使用,如果文件已经存在报错返回。O_TRUNC:打开文件时截断文件长度为0—清空内容O_APPEND:将写入设置为追加写。w+:O_RDWR| O_CREAT|
2021-11-04 21:27:02
107
原创 linux:进程概念
进程概念:理解进程是什么?进程:运行中的程序时间片:cpu调度运行程序的时间段,时间片过后,就该切换调度下一个进程了并发:一种轮询处理的方式并行:同时运行通过程序的运行描述,操作系统就可以调度哪个程序可以占用cpu去运行指令要运行哪个程序,则操作系统找到对应程序的PCB,在pcb取出程序的运行所需信息,加载到cpu上,cpu就开始运行这个程序了对于操作系统而言,进程就是一个程序运行的描述,通过这个描述,操作系统可以进行程序的调度运行管理实际上对于操作系统而言,进程就是pcb这个程序运行
2021-11-03 16:19:06
157
原创 匿名管道----实例
ps -ef | grep pipeps -ef:将所有进程信息写入到标准输出grep pipe:不断循环从标准输入读取数据进行字符串匹配过滤shell进程中创建两个进程,一个进程运行ps,一个进程运行grep要将ps进程的数据,交给grep进程只能通过进程间通信完成—匿名管道流程:创建管道创建两个进程(不同进程,程序中体现为2个子进程,子进程通过父进程获得句柄),在各自进程中进行程序替换在程序替换之前,ps进程应该标准输出重定向到管道写入端,grep进程应该标准输入重定向到管道读取端父
2021-11-03 15:44:19
163
原创 模拟实现xshell(1)
流程1.捕捉用户键盘输入 [ ls -a -l]2.解析输入信息—得到命令名称,运行参数 [ls] [-a] [-l]3.创建子进程,在子进程通过命令名称进行程序替换(让子进程运行命令)4.进程等待,等待子进程退出,防止出现僵尸进程 #include<stdio.h> //printf
2021-11-02 22:16:06
366
原创 进程间通信--匿名管道
管道:ipc特性:半双工通信----可以选择方向的单向通信本质:系统内核中的一块缓存区(内核空间中开辟的一块内存)通信原理:多个进程只要能够访问同一块内核中的缓冲区(管道)就能实现通信。分类:匿名管道,命名管道匿名管道:只能用于具有亲缘关系的进程间通信命名管道:可以用于同一主机上任意进程间通信匿名管道:管道缓冲区没有标识符,无法被其他进程找到,因此只能通过子进程复制父进程的方式获取到管道的操作句柄,进行通信代码操作:int pipe(int pipefd[2]);pipefd[0]
2021-11-02 17:39:58
304
原创 Linux:库
库的使用:使用-l选项指定要连接的库名称:gcc main.c -o main -ltestlib但是链接器在链接库文件生成可执行程序的时候,回到指定的一些路径下去找库文件,炸到了就会链接,找不到就会报错生成可执行程序时链接使用:1.库文件放在指定路径下: /usr/lib642.设置环境变量:export LIBRARY_PATH=$LIBRARY_PATH:./3.使用gcc的-L选项:gcc main.c -o main -L./ -ltestlib运行可执行程序时加载使用:仅针对动
2021-04-18 15:49:48
74
原创 C++:函数模板
1.函数模板函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。2.函数模板格式template<typename T1, typename T2,…,typename Tn>返回值类型 函数名(参数列表){}template<typename T>void Swap( T& left, T& right){T temp = left;left = right;right = temp;}注
2021-04-09 19:50:23
92
原创 Linux:进程等待
等待:父进程等待子进程退出。获取退出子进程的返回值,释放退出子进程资源,避免子进程成为僵尸进程。代码操作:int wait(int *status);int waitpid(pid_ t pid, int *status,int options)可以设置为非阻塞默认都是阻塞接口,等待子进程退出,如果没有退出,就一直等待。返回值:使用低1 6位,其中高8位返回值,低7位异常退出信号。WIFEXITED(status)--------判断WEXITSTATUS(status)--------获取
2021-04-08 20:57:24
98
原创 Linux :环境变量
环境变量:保存运行环境参数的变量;使程序运行环境配置更加灵活;以及可以通过环境变量实现进程间的小量数据通信(父子进程的传递)命令操作: env-查看环境变量,set 查看所有变量,echo-查看指定变量, export- 设置环境变量,unset-删除环境变量典型环境变量:PATH:程序运行的默认搜索路径-在命令行终端中输入命令名称可以直接执行对应名称的命令程序,实际上是因为shell捕捉到输入的命令名称之后,然后去PATH环境变量指定的路径下去找这个程序,找到了就运行,找不到就报命令没有找到的错误
2021-04-07 21:57:55
102
原创 Linux:工具的使用
1.软件包管理工具:yum :类似于手机应用商店(管理当前系统中能够安装的工具以及可以卸载的工具,并且实现安装以及卸载操作)lrzsz::实现主机与虚拟机之间的联系1、查看所能安装的软件工具: yum list. 显示所有工具yum search keyword 根据关键字查找指定工具2、安装一个指定工具: yum install package name安装git:. sudo yum install gcc gcc-c++ gdb git3、卸载一个指定工具: yum remov
2021-03-24 14:33:26
137
1
原创 linux基本操作
1.linux发展史:操作系统:是一个软件, 说白了就是一个程序,管理计算机上的软硬件资源(按照程序逻辑控制计算机硬件,在合适的时候进行合适的操作)linux是一个类unix操作系统。unix操作系统:肯汤普森玩飞机大战游戏,开发出了单元化,模块化,小巧的操作系统叫做unix,后来与丹尼斯里奇使用C语言重写了unixunix是收费的,收费之后有一个教授开发 了一个类unix系统叫做minix,授权只能用于教学1990年芬兰的赫尔辛基大学-有个研究生-李纳斯:托瓦斯,学习计算机操作系统的过程中编写代码
2021-03-24 09:35:55
174
1
原创 C++:内存管理
1.C++内存管理方式C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。1.1 new/delete操作内置类型#include<iostream>using namespace std;void test(){ //申请和释放的方式保持一致 //malloc---->free int* mptr = (int*)malloc(sizeof(int));
2021-03-20 10:54:42
123
原创 C++:类与对象(3)
1.赋值运算符重载1.1 运算符重载C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。函数名字为:关键字operator后面接需要重载的运算符符号。函数原型:返回值类型 operator操作符(参数列表)#include<iostream>using namespace std;class Date{public: Date(int y = 1, int m = 1,
2021-02-23 13:45:17
76
原创 C++:类与对象(2)
1.this指针1.1 this指针的引出我们先来定义一个日期类Date#include<iostream>using namespace std;class A{ int a;};class Date{public: //每一个非静态成员函数中,都有一个this指针 //作为函数的第一个参数 //this指向当前调用函数的对象 //this类型:类类型* const this void Display() //void Display(this) {
2021-02-21 19:01:32
96
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人