推荐观看视频教程 一、图的连通性 1. 无向图的连通性
在无向图G=(V,E)中:
①连通:若节点u和v能够互相到达,则称u,v是连通的;
②连通图:若图中任何节点之间都是可互相到达的,则称G是连通图,否则称G是非连通图;
这是一个连通图这不是一个连通图,
③连通分量(连通分支):我们可以看出上面右图有两个部分连通的图,叫做连通分量(或连通分支)
④无向图的连通性判定:并查集、DFS、BFS、WARSHALL 算法;
⑤非连通的无向图求连通分量:可通过额外设置计数器count(初始值0)统计出图的连通分量,每调用dfs(或bfs)遍历一次,计数器count增1。当遍历完无向图时,若count=1,则图连通,若count>1,图非连通,count的值就是该图的连通分量数。
需要注意的是,连通分量的提出是以"整个无向图不是连通图"为前提的,因为如果无向图是连通图,则其无法分解出多个最大连通子图,因为图中所有的顶点之间都是连通的。
2.有向图的连通性
①强连通:在有向图中,若节点 u 和节点 v 能互相到达(不必是同一路径),则称 u,v 强连通;
节点1可以通过(1,2,3)到达3,节点3可以通过(3,4,1)到达1,所以3和1是强连通;
②强连通图:在有向图 G=(V,E) 中,若对于V 中任意两个不同的顶点 u 和 v,都存在从 u 到 v 以及从 v 到 u 的路径,则称 G是强连通图。
这是一个强连通图
③强连通分量SCC(strongly connected components):非强连通图的极大强连通子图,称为强连通分量。强连通图只有一个强连通分量,即是其自身;非强连通的有向图有多个强连分量。
这个有向图中有两个强连通分量(2,3,1)和(7,6,4,5)。
小提示:“连通图” 是在无向图 的基础上对图中顶点之间的连通做了更高的要求,而“强连通图” 是在有向图 的基础上对图中顶点的连通做了更高的要求。
④有向图的连通性判定算法:
方法一:可以调用DFS搜索 V 次,V是顶点的个数,就是对每个顶点都做一次DFS搜索,判断是否可达。这样的复杂度为O(V*(V+E))。
方法二:可以参考求解连通分量的算法Tarjan算法,我们可以在O(V+E) 的时间内找到所有的连通分量,如果连通分量的个数为1,则说明该图是强连通的。
⑤有向图求强连通分量算法:Kosaraju 算法和Tarjan算法
二、Tarjan算法 Tarjan(音译为塔扬)算法的核心其实是dfs,主要是通过维护两个数组来完成强连通分量的计算:
dfn[]数组:负责记录每个节点的dfs顺序(简称为dfs序)。
low[]数组:负责记录从每个节点的出发沿可行边所能到达的点中dfs序号最小的序号。
第一个数组好理解:
对于下面左图的有向图进行dfs,并产生dfs序应该是右边的结果
第二个数组费解一点:
P2863 [USACO06JAN]牛的舞会
//P2863 [USACO06JAN]牛的舞会The Cow Prom #include <cstdio> #include <stack> using namespace std; const int maxn=10005; const int maxm=50005; struct Edge{ int v,w,nxt; }edge[maxm]; int n,m,cnt=1,head[maxn],instack[maxn]; int scctot; int index; int dfn[maxn];///节点的dfs序 int low[maxn];///dfs时,节点能到达的最小dfs序 int scc[maxn];///每个节点所属的强连通分量 int num[maxn];///记录每个强连通分量中节点个数 stack<int>s; inline void adedge(int u,int v,int w) { edge[++cnt].
node 的fs文档密密麻麻的 api 非常多,毕竟全面支持对文件系统的操作。文档组织的很好,操作基本分为文件操作、目录操作、文件信息、流这个大方面,编程方式也支持同步、异步和 Promise。
本文记录了几个文档中没详细描写的问题,可以更好地串联fs文档思路:
文件描述符同步、异步与 Promise目录与目录项文件信息stream 🔍 关注公众号“心谭博客” / 👉 前往 xxoo521.com / 欢迎交流和指正
文件描述符 文件描述符是一个非负整数。它是一个索引值,操作系统可以根据它来找到对应的文件。
在 fs 的很多底层 api 中,需要用到文件描述符。在文档中,描述符通常用fd来代表。例如:fs.read(fd, buffer, offset, length, position, callback)。与这个 api 相对应的是:fs.readFile(path[, options], callback)。
因为操作系统对文件描述符的数量有限制,因此在结束文件操作后,别忘记 close:
const fs = require("fs"); fs.open("./db.json", "r", (err, fd) => { if (err) throw err; // 文件操作... // 完成操作后,关闭文件 fs.close(fd, err => { if (err) throw err; }); }); 同步、异步与 Promise 所有文件系统的 api 都有同步和异步两种形式。
同步写法 不推荐使用同步 api,会阻塞线程。
前提 前置文章:
《基于Netty和SpringBoot实现一个轻量级RPC框架-协议篇》《基于Netty和SpringBoot实现一个轻量级RPC框架-Server篇》《基于Netty和SpringBoot实现一个轻量级RPC框架-Client篇》 前一篇文章简单介绍了通过动态代理完成了Client端契约接口调用转换为发送RPC协议请求的功能。这篇文章主要解决一个遗留的技术难题:请求-响应同步化处理。
需要的依赖如下:
JDK1.8+Netty:4.1.44.FinalSpringBoot:2.2.2.RELEASE 简单分析Netty请求-响应的处理流程 图中已经忽略了编码解码器和其他入站出站处理器,不同颜色的线程代表完全不相同的线程,不同线程之间的处理逻辑是完全异步,也就是Netty IO线程(n-l-g-1)接收到Server端的消息并且解析完成的时候,用户调用线程(u-t-1)无法感知到解析完毕的消息包,那么这里要做的事情就是让用户调用线程(u-t-1)获取到Netty IO线程(n-l-g-1)接收并且解析完成的消息包。
这里可以用一个简单的例子来说明模拟Client端调用线程等待Netty IO线程的处理结果再同步返回的过程。
@Slf4j public class NettyThreadSyncTest { @ToString private static class ResponseFuture { private final long beginTimestamp = System.currentTimeMillis(); @Getter private final long timeoutMilliseconds; @Getter private final String requestId; @Setter @Getter private volatile boolean sendRequestSucceed = false; @Setter @Getter private volatile Throwable cause; @Getter private volatile Object response; private final CountDownLatch latch = new CountDownLatch(1); public ResponseFuture(String requestId, long timeoutMilliseconds) { this.
常用的三种方式 第一种:
vim +n file eg: vim +3 test.py 查看test.py文件,光标定位到第三行 第二种:
vim 进入查看文件,命令行下输入
:n 回车以后就可以见到光标跳转到第 n 行 第三种:
vim 进入查看文件,esc模式下输入
ngg 或者 nG n 是行号,输完以后可以马上看到光标跳转 另外,如果你想查看行号 参见 查看行号
图片自动重命名实现 作用:当我们在进行上传图片时,这些图片都是要存在数据库当中。它们是以地址的方式存在数据库之中;这个地址可能会重复,假如说在数据库中已经有一个图片是xxxxxxxx地址,再存进来一个这样的地址的话,就会进行覆盖。会丢失之前的图片,所以:我们需要对上传图片进行重新命名,防止我们的图片丢失
下面直接上代码:
工具类 package com.util; import java.util.Random; /** * @author life * @create 2020-01-06 13:38 */ public class GenerateIdUtil { private static char[] constant = { '0','1','2','3','4','5','6','7','8','9', 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z', 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z' }; public static String GenerateRandomNumber(int Length){ StringBuilder newRandom = new StringBuilder(50); Random rd = new Random(); for (int i = 0; i < Length; i++) { newRandom.append(constant[rd.nextInt(62)]); } return newRandom.toString(); } public static void main(String[] args) { System.out.println(GenerateRandomNumber(60)); } } package com.
05 ElasticSearch集群 1 集群的相关概念 1.1 集群 cluster 一个集群就是由一个或多个节点组织在一起,它们共同持有整个的数据,并一起提供索引和搜索功能。一个集群由 一个唯一的名字标识,这个名字默认就是“elasticsearch”。这个名字是重要的,因为一个节点只能通过指定某个集 群的名字,来加入这个集群
1.2 节点 node 一个节点是集群中的一个服务器,作为集群的一部分,它存储数据,参与集群的索引和搜索功能。和集群类似,一 个节点也是由一个名字来标识的,默认情况下,这个名字是一个随机的漫威漫画角色的名字,这个名字会在启动的 时候赋予节点。这个名字对于管理工作来说挺重要的,因为在这个管理过程中,你会去确定网络中的哪些服务器对 应于Elasticsearch集群中的哪些节点。
一个节点可以通过配置集群名称的方式来加入一个指定的集群。默认情况下,每个节点都会被安排加入到一个叫 做“elasticsearch”的集群中,这意味着,如果你在你的网络中启动了若干个节点,并假定它们能够相互发现彼此, 它们将会自动地形成并加入到一个叫做“elasticsearch”的集群中。
在一个集群里,只要你想,可以拥有任意多个节点。而且,如果当前你的网络中没有运行任何Elasticsearch节点, 这时启动一个节点,会默认创建并加入一个叫做“elasticsearch”的集群。
1.3 分片和复制 shards&replicas 一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具有10亿文档的索引占据1TB的磁盘空间,而任 一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢。为了解决这个问题,Elasticsearch提供 了将索引划分成多份的能力,这些份就叫做分片。当你创建一个索引的时候,你可以指定你想要的分片的数量。每 个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上。分片很重要,主 要有两方面的原因: 1)允许你水平分割/扩展你的内容容量。 2)允许你在分片(潜在地,位于多个节点上)之上 进行分布式的、并行的操作,进而提高性能/吞吐量。
至于一个分片怎样分布,它的文档怎样聚合回搜索请求,是完全由Elasticsearch管理的,对于作为用户的你来说, 这些都是透明的。
在一个网络/云的环境里,失败随时都可能发生,在某个分片/节点不知怎么的就处于离线状态,或者由于任何原因 消失了,这种情况下,有一个故障转移机制是非常有用并且是强烈推荐的。为此目的,Elasticsearch允许你创建分 片的一份或多份拷贝,这些拷贝叫做复制分片,或者直接叫复制。
复制之所以重要,有两个主要原因: 在分片/节点失败的情况下,提供了高可用性。因为这个原因,注意到复制分 片从不与原/主要(original/primary)分片置于同一节点上是非常重要的。扩展你的搜索量/吞吐量,因为搜索可以 在所有的复制上并行运行。总之,每个索引可以被分成多个分片。一个索引也可以被复制0次(意思是没有复制) 或多次。一旦复制了,每个索引就有了主分片(作为复制源的原来的分片)和复制分片(主分片的拷贝)之别。分 片和复制的数量可以在索引创建的时候指定。在索引创建之后,你可以在任何时候动态地改变复制的数量,但是你 事后不能改变分片的数量。
默认情况下,Elasticsearch中的每个索引被分片5个主分片和1个复制,这意味着,如果你的集群中至少有两个节 点,你的索引将会有5个主分片和另外5个复制分片(1个完全拷贝),这样的话每个索引总共就有10个分片。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MrxVdsOK-1578492475518)(F:\learning\javaee\笔记\第五阶段\ElasticSerach\集群\img\image-20191222182711558.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mk4FMg6n-1578492475518)(F:\learning\javaee\笔记\第五阶段\ElasticSerach\集群\img\image-20191222183133119.png)]
2 集群的搭建 2.1 准备三台elasticsearch服务器 创建elasticsearch-cluster文件夹,在内部复制三个elasticsearch服务
2.2 修改每台服务器配置 修改elasticsearch-cluster\node*\config\elasticsearch.yml配置文件
node1-3节点配置信息:
#节点1的配置信息: #集群名称,保证唯一 cluster.name: my‐elasticsearch #节点名称,必须不一样 node.name: node‐1 #必须为本机的ip地址 network.host: 127.0.0.1 #服务端口号,在同一机器下必须不一样 http.
/** * 本地图片转换Base64的方法 * * @param imgPath */ private static String ImageToBase64(String imgPath) { byte[] data = null; // 读取图片字节数组 try { InputStream in = new FileInputStream(imgPath); data = new byte[in.available()]; in.read(data); in.close(); } catch (IOException e) { e.printStackTrace(); } // 对字节数组Base64编码 BASE64Encoder encoder = new BASE64Encoder(); // 返回Base64编码过的字节数组字符串 return encoder.encode(Objects.requireNonNull(data)); } public static boolean GenerateImage(String imgStr, String photoname) { //对字节数组字符串进行Base64解码并生成图片 //图像数据为空 if (imgStr == null) return false; BASE64Decoder decoder = new BASE64Decoder(); try { //Base64解码 byte[] b = decoder.
一.产生的原因
一般进程 正常情况下:子进程由父进程创建,子进程再创建新的进程。父子进程是一个异步过程,父进程永远无法预测子进程的结束,所以,当子进程结束后,它的父进程会调用wait()或waitpid()取得子进程的终止状态,回收掉子进程的资源。
2)孤儿进程
孤儿进程:父进程结束了,而它的一个或多个子进程还在运行,那么这些子进程就成为孤儿进程(father died)。子进程的资源由init进程(进程号PID = 1)回收。
3)僵尸进程
僵尸进程:子进程退出了,但是父进程没有用wait或waitpid去获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中,这种进程称为僵死进程。
二.问题危害
注意:unix提供了一种机制保证父进程知道子进程结束时的状态信息。
这种机制是:在每个进程退出的时候,内核会释放所有的资源,包括打开的文件,占用的内存等。但是仍保留一部分信息(进程号PID,退出状态,运行时间等)。直到父进程通过wait或waitpid来取时才释放。
但是这样就会产生问题:如果父进程不调用wait或waitpid的话,那么保留的信息就不会被释放,其进程号就会被一直占用,但是系统所能使用的进程号是有限的,如果大量产生僵死进程,将因没有可用的进程号而导致系统无法产生新的进程,这就是僵尸进程的危害
孤儿进程是没有父进程的进程,它由init进程循环的wait()回收资源,init进程充当父进程。因此孤儿进程并没有什么危害。
补充:任何一个子进程(init除外)在exit()之后,并非马上就消失掉,而是留下一个称为僵尸进程的数据结构,等待父进程去处理。如果父进程在子进程exit()之后,没有及时处理,出现僵尸进程,并可以用ps命令去查看,它的状态是“Z”。
三.解决方案
1)kill杀死元凶父进程(一般不用)
严格的说,僵尸进程并不是问题的根源,罪魁祸首是产生大量僵死进程的父进程。因此,我们可以直接除掉元凶,通过kill发送SIGTERM或者SIGKILL信号。元凶死后,僵尸进程进程变成孤儿进程,由init充当父进程,并回收资源。
或者运行:kill -9 父进程的pid值、
2)父进程用wait或waitpid去回收资源(方案不好)
父进程通过wait或waitpid等函数去等待子进程结束,但是不好,会导致父进程一直等待被挂起,相当于一个进程在干活,没有起到多进程的作用。
3)通过信号机制,在处理函数中调用wait,回收资源
通过信号机制,子进程退出时向父进程发送SIGCHLD信号,父进程调用signal(SIGCHLD,sig_child)去处理SIGCHLD信号,在信号处理函数sig_child()中调用wait进行处理僵尸进程。什么时候得到子进程信号,什么时候进行信号处理,父进程可以继续干其他活,不用去阻塞等待。
ps -A -o stat,ppid,pid,cmd | grep -e '^[Zz]' 显示:(状态Z代表僵尸进程)
S PID PPID CMD
S 3213 2529 ./pid1
Z 3214 3213 [pid1]
Z 3215 3213 [pid1]
Z 3219 3213 [pid1]
Z 3220 3213 [pid1]
Z 3221 3213 [pid1]
R 3223 3104 ps -a -o state,pid,ppid,cmd
在Ubuntu上基于源码安装PCL-1.8时遇到如下一些问题,加以记录。
问题1:不能获得锁 问题详细提示如下:
E: Could not get lock /var/lib/dpkg/lock-frontend - open (11: Resource temporarly unavailable) E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is an other process using it? 解决方案如下:
(1)首先查看是否有apt-get这个程序在运行
ps aux|grep apt-get (2)如果发现存在这样的程序在运行那么就kill掉,否则执行第三步删除锁文件。
(3)直接删除锁文件
sudo rm /var/lib/dpkg/lock-frontend sudo rm /var/lib/dpkg/lock 问题2:缺少PCAP文件 问题详细提示如下:
Could Not find PCAP (missing: PCAP_LIBRARIES PCAP_INCLUDE_DIRS), Could NOT find GLEW (missing: GLEW_INCLUDE_DIR GLEW_LIBRARY) 解决方案便是安装libpcap
(1)到网站“http://www.tcpdump.org/#latest-release”下载PCAP源码文件。
(2)源码安装PCAP
tar -zxvf libpcap-1.9.1.tar.gz cd libpcap-1.9.1 sudo ./configure sudo make sudo make install 在执行sudo .
引用与转义 '用于引用,\用于转义特殊字符'本身不能被引用,需要转义前导和尾随的空格字符由引号引用或者转义,否则在解析字符串时移除 日期 YYYY-MM-DD|YYYYMMDD等now 表示当前时间 持续时间 ‘55’ 表示55秒‘12:03:45’ 表示12小时3分钟45秒‘23.189’ 表示23.189秒 前面都可选’-'号,表示负数持续时间
视频尺寸 指定视频源的尺寸大小,它可以是一些表示特定(预设)尺寸的字符串名或者widthxheight(其中width和height都是数字值)的字符串,下面是一些常见的预定义的表示尺寸的字符串名及其对应分辨率:
ntsc’ 720x480pal’ 720x576sntsc’ 640x480‘spal’ 768x576‘cif’ 352x288‘vga’ 640x480‘hd480’ 852x480‘hd720’ 1280x720‘hd1080’ 1920x1080‘2k’ 2048x10804k’ 4096x2160 视频帧率 指定视频的帧速率,除了用每秒帧数表示外,还可以用frame_rate_num/frame_rate_den这样的格式字符串表示,此外还有一些预定义的帧率名字符串,下面就是一些常用的预定义的帧率名及对应的帧率:
‘ntsc’ 30000/1001‘pal’ 25/1‘sntsc’ 30000/1001‘spal’ 25/1‘film’ 24/1‘ntsc-film’ 24000/1001 颜色 允许采用下面预定义的颜色名或者一个[0x|#]RRGGBB[AA]这样序列的16进制数字值,可以通过@来附加透明度表示,透明度分量(alpha)可以是”0x”后面跟一个16进制数或者0到1之间的十进制字符串,它代表不透明度值(’0x00’或者’0’表示完全透明,’0xFF’或者’1’表示完全不透明),如果没有专门指定透明分量,则默认为’0XFF’。
‘random’字符串会随机一个颜色,下面是常用的预定义的颜色名以及对应的颜色值:
‘Blue’ 0x0000FF‘Green’ 0x008000‘Gray’ 0x808080‘Red’ 0xFF0000‘Yellow’ 0xFFFF00 通道布局 对于多音频通道的流,一个通道布局可以具体描述其配置情况。为了描述通道布局,ffmpeg采用了一些特殊的语法。除了可以采用ID标识外,下面是一些常用的预定义:
‘FL’ front left 左前‘FR’ front right 右前‘FC’ front center 前中‘LFE’ low frequency 重低音 下面使一些常用的标准的通道布局定义:
‘mono’ FC‘stereo’ FL+FR‘2.1’ FL+FR+LFE‘3.0’ FL+FR+FC
堆内存 Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象。
在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。
这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象,包括内存的分配以及回收。
堆的内存模型大致为:
从图中可以看出: 堆大小 = 新生代 + 老年代。其中,堆的大小可以通过参数 –Xms、-Xmx 来指定。
(本人使用的是 JDK1.6,以下涉及的 JVM 默认值均以该版本为准。)
默认的,新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 ),即:新生代 ( Young ) = 1/3 的堆空间大小。老年代 ( Old ) = 2/3 的堆空间大小。其中,新生代 ( Young ) 被细分为 Eden 和 两个 Survivor 区域,这两个 Survivor 区域分别被命名为 from 和 to,以示区分。
gadget 利用gadget是做pwn题时控制程序流程一种重要且常用的方法。
rop是什么?
参考链接
https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/basic-rop-zh/
我今天主要写我对通用gadget的原理的理解
通用 gadget 大家要先了解pop ret call等汇编指令,以便更好理解。
通用gadget之所以叫通用,说明这是可以广泛使用的。
说明: 程序编译的过程中,会自动加入一些通用函数做初始化的工作,这些初始化函数都是相同的, 所以我们可以考虑在这些函数中找到一些通用的 gadget, 在64位的链接库中就有一个这样的gadget,存在于__libc_csu_init() __libc_csu_init()
x64 程序的前六个参数依次通过寄存器 rdi、rsi、rdx、rcx、r8、r9 进行传递,我们所找的 gadget 自然也是针对这些寄存器进行操作的。
函数 __libc_csu_init() 用于对 libc 进行初始化,只要程序调用了 libc,就一定存在这个函数。
下面是函数 __libc_csu_init()的反汇编
gdb-peda$ disassemble /r __libc_csu_init Dump of assembler code for function __libc_csu_init: 0x00000000004007d0 <+0>: 41 57 push r15 0x00000000004007d2 <+2>: 41 56 push r14 0x00000000004007d4 <+4>: 49 89 d7 mov r15,rdx 0x00000000004007d7 <+7>: 41 55 push r13 0x00000000004007d9 <+9>: 41 54 push r12 0x00000000004007db <+11>: 4c 8d 25 16 06 20 00 lea r12,[rip+0x200616] # 0x600df8 0x00000000004007e2 <+18>: 55 push rbp 0x00000000004007e3 <+19>: 48 8d 2d 16 06 20 00 lea rbp,[rip+0x200616] # 0x600e00 0x00000000004007ea <+26>: 53 push rbx 0x00000000004007eb <+27>: 41 89 fd mov r13d,edi 0x00000000004007ee <+30>: 49 89 f6 mov r14,rsi 0x00000000004007f1 <+33>: 4c 29 e5 sub rbp,r12 0x00000000004007f4 <+36>: 48 83 ec 08 sub rsp,0x8 0x00000000004007f8 <+40>: 48 c1 fd 03 sar rbp,0x3 0x00000000004007fc <+44>: ff 15 f6 07 20 00 call QWORD PTR [rip+0x2007f6] # 0x600ff8 0x0000000000400802 <+50>: 48 85 ed test rbp,rbp 0x0000000000400805 <+53>: 74 1f je 0x400826 <__libc_csu_init+86> 0x0000000000400807 <+55>: 31 db xor ebx,ebx 0x0000000000400809 <+57>: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0] 0x0000000000400810 <+64>: 4c 89 fa mov rdx,r15 0x0000000000400813 <+67>: 4c 89 f6 mov rsi,r14 0x0000000000400816 <+70>: 44 89 ef mov edi,r13d 0x0000000000400819 <+73>: 41 ff 14 dc call QWORD PTR [r12+rbx*8] 0x000000000040081d <+77>: 48 83 c3 01 add rbx,0x1 0x0000000000400821 <+81>: 48 39 dd cmp rbp,rbx 0x0000000000400824 <+84>: 75 ea jne 0x400810 <__libc_csu_init+64> 0x0000000000400826 <+86>: 48 83 c4 08 add rsp,0x8 0x000000000040082a <+90>: 5b pop rbx 0x000000000040082b <+91>: 5d pop rbp 0x000000000040082c <+92>: 41 5c pop r12 0x000000000040082e <+94>: 41 5d pop r13 0x0000000000400830 <+96>: 41 5e pop r14 0x0000000000400832 <+98>: 41 5f pop r15 0x0000000000400834 <+100>: c3 ret End of assembler dump.
Install Node.js & Git & npm sudo apt install nodejs git npm # 安装版本查看 node --version git --version npm --version Install Hexo sudo npm install hexo-cli -g # 查看安装的版本 hexo --version Starting… 初始化博客的工作目录 hexo init Blog # 本地检验 cd Blog; hexo s # 浏览器输入 localhost:4000 测试 Ctrl+C 结束 新建一篇文章 # 尝试新建自己的第一篇文章 hexo n "基于-Hexo-GitHub-搭建自己的博客" # 编辑 source/_posts/基于-Hexo-GitHub-搭建自己的博客.md hexo clean hexo g hexo s # 浏览器输入 localhost:4000 本地测试, Ctrl+C 结束 部署自己博客到GitHub sudo npm install --save hexo-deployer-git 安装hexo部署功能的插件
这次在VMware上装archlinux,开始时在网上百度了几篇安装教程,分区、装系统、grub等等,一路很顺利,然后reboot。
屏幕闪了几下后出现 :
Grub>
不能引导。
有点晕,仔细看了几遍教程,好像没错啊。
然后网上再去找grub不能引导的文章,看了几遍,也试了几遍,还是不能引导。
问题到底在哪里?
后来仔细查看/boot下文件,发现居然没内核文件。
赶忙到archlinux查文档,(https://wiki.archlinux.org/index.php/Installation_guide)
原来还需要安装linux内核,官方文档的安装命令如下:
# pacstrap /mnt base linux linux-firmware 而自己看的文档里都只有 base和base-devel。
晕了,一个大教训,以后找文档还是别百度了,直接官方文档为上!切记切记
1.启动httpd服务失败 2.重新启动httpd服务 3.查看Selinux,并且关闭Selinux 4.查看防火墙firewalld是否关闭 5.启动httpd服务
只需要在下载URL前加入 wget --content-disposition
wget --content-disposition url
转盘这个东西在游戏中见多了 抽奖啥的都可以用到 我们也可能被它坑过好多次
这篇博客带大家用unity实现一下转盘
1.创建场景 首先整一个转盘的模型 (图片即可)
然后把它弄进unity的相关文件夹中 修改一下格式 改成Sprite(UI and 2D)
用UGUI创建一个Image 把它贴上去 即可
然后创建一个指针类型的图片
2.实现转盘的旋转 我的思路是让转盘旋转 也可以让指针旋转
对于旋转 我们在游戏中见到的转盘都是 开始速度比较大 然后慢慢停下来的
我们就用速度的随着时间的递减来实现,也可以用时间来限制
我们创建一个按钮来点击的时候 转盘开始旋转
private float RotateSpeed;//旋转速度 private void Start() { RotateSpeed = 0; } private void Update() { RotateSpeed -= Time.deltaTime * 100;//随着时间递减 transform.Rotate(Vector3.forward * Time.deltaTime * RotateSpeed); if (RotateSpeed <= 0) { RotateSpeed = 0; Time.timeScale = 0;//为了实现旋转速度为0之后不再乱动 } } public void StartButton()//开始按钮 { RotateSpeed = Random.
c语言要点 有C语言都必须要有的框架 printf()
输出函数 system(“pause”)
是让输出的代码暂停一下 \n是换行符
printf(“ni \n hao”),这里的“\n”表示让光标“换行”。 system(“color f5”)
如果在color 后只加了一位数字那是文字的颜色 如果在“5”之前加了一位数字那是背景色的颜色注意:color和参数之间有一个空格 int 变量1,变量2,变量3;
int用于定义数据的类型(int为整型)注意:int和第一个参数之间有一个空格,末尾有一个分号表示结束 printf("%d",c)
"%d"相当于一个接受数据的介质在介质和变量之间要用“,”隔开然后在把变量传入穿中 float 变量1,变量2,变量3;
float为浮点型,对应的printf("%f",c) "="和“==”
“=”为赋值“==”为等于 printf("%d+%d=%d",a,b,c);
printf(“d”,c)只输出一个数字3printf("%d+%d=%d",a,b,c)他输入的是计算的式子 1+2=3 scanf()
scanf()为输入函数第一种:
scanf("%d", &a);
scanf("%d", &b);
第二种:
scanf("%d%d", &a, &b); 当除号“/”左右两边都是整数时,商 也只有整数部分。例如,5/3的商是1,2/3的商是0
c的数据类型
double 可以比float表示得更精确,double的大小范围要比float的要大.
char为存放字符,对应的介质为%c ,scanf("%c",&a);%c只能输入一个字符
用scanf读入double类型数据时所用的占位符是“%lf”(注意此处不是数字 1而是字母l)而不是“%f”。
char a;
scanf("%c",&a);
printf(“你刚才输入的字符为%c\n”,a+1);
“a+1”为在26个字母中在“a”的基础上再往后的一个字母也就是“b”
定义变量的省略形式
如果希望计算4+(6-3)×7的值,可以直接这样写:
printf("%d",4+(6-3)*7);printf("%d+%d=%d", a, b, a+b); 变量a和变量b中的值
t=a;
a=b;
b=t; b对a赋值,a要先赋值给一个变量要不就被b的赋值给覆盖了 a=b-a;
b=b-a;
a=b+a; 一名优秀的程序员要养成一个良好的编码习惯,用Tab来调整你的代码格式
“//”表示注释,通常用来对一行代码进行解释说明或备注
给变量赋值初值
原文:Eigen官网-The Matrix class
在Eigen中,所有的矩阵Matrix和向量Vector都是由Matrix类构造的。向量只不过是矩阵的特殊形式,只有一列(列向量)或者一行(行向量)。
Matrix类的参数 Matrix有6个模板参数,主要使用前三个参数,剩下的三个参数有默认值。
Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime> Scalar是表示元素的类型,取值可以是 float ,int, double 等;RowsAtCompileTime为矩阵的行,在程序编译的时候就已经知道的;ColsAtCompileTime为矩阵的列,在程序编译的时候就已经知道的。 Eigen 提供了一些常用的 定义好的类型。比如,Matrix4f表示一个类型为float的4*4矩阵,在Eigen中定义如下:
typedef Matrix<float, 4, 4> Matrix4f; Vectors向量 列向量是默认向量。
Eigen中定义的包含3个float元素的列向量如下:
typedef Matrix<float, 3, 1> Vector3f; 行向量定义如下:
typedef Matrix<int, 1, 2> RowVector2i; Dynamic Eigen并没有限制矩阵的尺寸必须在编译的时候就要确定下来。如果矩阵的尺寸在编译的时候是不确定的,而在运行的时候才能确定,Eigen提供了定义动态大小的方法,称为dynamic size ;将在编译时候就能确定的尺寸称为fixed size.
MatrixXd表示一个具有动态大小的矩阵,定义如下:
typedef Matrix<double, Dynamic, Dynamic> MatrixXd; VectorXi表示一个具有动态大小的向量,定义如下:
typedef Matrix<int, Dynamic, 1> VectorXi; 还可以定义行数固定而列数是动态大小的矩阵:
Matrix<float, 3, Dynamic> 构造函数 (1)默认的构造函数不执行任何空间分配,也不初始化矩阵的元素。
Matrix3f a; MatrixXf b; a是一个3*3的矩阵,分配了float[9]的空间,但未初始化内部元素;b是一个动态大小的矩阵,现在它的尺寸是0*0,还未分配空间。 (2)带参数的构造函数。
对于矩阵,行数在列数前面,对于向量,只有向量的大小。当对矩阵或向量指定大小时,只是分配相应大小的空间,未初始化元素。
练习题:我有一个猜数字小游戏的程序,请写一个程序实现在测试类中只能用5次,超过5次提示:游戏试玩已结束,请付费。 public class PropertiesTest2 { public static void main(String[] args) throws IOException { // 读取某个地方的数据,如果次数不大于5,可以继续玩。否则就提示"游戏试玩已结束,请付费。" // 创建一个文件 // File file = new File("count.txt"); // if (!file.exists()) { // file.createNewFile(); // } // 把数据加载到集合中 Properties prop = new Properties(); Reader r = new FileReader("count.txt"); prop.load(r); r.close(); // 我自己的程序,我当然知道里面的键是谁 String value = prop.getProperty("count"); int number = Integer.parseInt(value); ` if (number > 5) { System.out.println("游戏试玩已结束,请付费。"); System.exit(0); } else { number++; prop.setProperty("count", String.valueOf(number)); Writer w = new FileWriter("