不知道你有没有抢到一只呢?
本文使用 Three.js + React
技术栈,实现冬日和奥运元素,制作了一个充满趣味和纪念意义的冬奥主题 3D
页面。
实现效果如以下 👇
动图所示,页面主要由 2022
冬奥会吉祥物 冰墩墩
、奥运五环、舞动的旗帜 🚩
、树木 🌲
以及下雪效果 ❄️
等组成。按住鼠标左键移动可以改为相机位置,获得不同视图。
👀
在线预览:https://dragonir.github.io/3d/#/olympic(部署在GitHub
,加载速度可能会有点慢😓
)
本文涉及到的知识点主要包括:TorusGeometry
圆环面、MeshLambertMaterial
非光泽表面材质、MeshDepthMaterial
深度网格材质、custromMaterial
自定义材质、Points
粒子、PointsMaterial
点材质等。
首先引入开发页面所需要的库和外部资源,OrbitControls
用于镜头轨道控制、TWEEN
用于补间动画实现、GLTFLoader
用于加载 glb
或 gltf
格式的 3D
模型、以及一些其他模型、贴图等资源。
import React from 'react'; |
页面 DOM
结构非常简单,只有渲染 3D
元素的 #container
容器和显示加载进度的 .olympic_loading
元素。
<div> |
初始化渲染容器、场景、相机。关于这部分内容的详细知识点,可以查阅我往期的文章,本文中不再赘述。
container = document.getElementById('container'); |
本示例中主要添加了两种光源:DirectionalLight
用于产生阴影,调节页面亮度、AmbientLight
用于渲染环境氛围。
// 直射光 |
使用 THREE.LoadingManager
管理页面模型加载进度,在它的回调函数中执行一些与加载进度相关的方法。本例中的页面加载进度就是在 onProgress
中完成的,当页面加载进度为 100%
时,执行 TWEEN
镜头补间动画。
const manager = new THREE.LoadingManager(); |
本示例中凹凸起伏的地面是使用 Blender
构建模型,然后导出 glb
格式加载创建的。当然也可以只使用 Three.js
自带平面网格加凹凸贴图也可以实现类似的效果。使用 Blender
自建模型的优点在于可以自由可视化地调整地面的起伏效果。
var loader = new THREE.GLTFLoader(manager); |
现在添加可爱的冬奥会吉祥物熊猫冰墩墩 🐼
,冰墩墩同样是使用 glb
格式模型加载的。它的原始模型来源于这里,从这个网站免费现在模型后,原模型是使用 3D max
建的我发现并不能直接用在网页中,需要在 Blender
中转换模型格式,还需要调整调整模型的贴图法线,才能还原渲染图效果。
原模型:
冰墩墩贴图:
转换成 Blender 支持的模型,并在 Blender 中调整模型贴图法线、并添加贴图:
导出 glb 格式:
📖
在Blender
中给模型添加贴图教程传送门:在 Blender 中怎么给模型贴图
仔细观察冰墩墩 🐼
可以发现,它的外面有一层透明塑料或玻璃质感外壳,这个效果可以通过修改模型的透明度、金属度、粗糙度等材质参数实现,最后就可以渲染出如 👆 banner图
所示的那种效果,具体如以下代码所示。
loader.load(bingdundunModel, mesh => { |
奥运五环由基础几何模型圆环面 TorusGeometry
来实现,创建五个圆环面,并调整它们的材质颜色和位置来构成蓝黑红黄绿顺序的五环结构。五环材质使用的是 MeshLambertMaterial
。
const fiveCycles = [ |
💡
TorusGeometry 圆环面TorusGeometry
一个用于生成圆环几何体的类。
构造函数:
TorusGeometry(radius: Float, tube: Float, radialSegments: Integer, tubularSegments: Integer, arc: Float) |
radius
:圆环的半径,从圆环的中心到管道(横截面)的中心。默认值是 1
。tube
:管道的半径,默认值为 0.4
。radialSegments
:圆环的分段数,默认值为 8
。tubularSegments
:管道的分段数,默认值为 6
。arc
:圆环的圆心角(单位是弧度),默认值为 Math.PI * 2
。💡
MeshLambertMaterial 非光泽表面材质一种非光泽表面的材质,没有镜面高光。该材质使用基于非物理的 Lambertian
模型来计算反射率。这可以很好地模拟一些表面(例如未经处理的木材或石材),但不能模拟具有镜面高光的光泽表面(例如涂漆木材)。
构造函数:
MeshLambertMaterial(parameters : Object) |
parameters
:(可选)用于定义材质外观的对象,具有一个或多个属性。材质的任何属性都可以从此处传入。旗面模型是从 sketchfab 下载的,还需要一个旗杆,可以在 Blender
中添加了一个柱状立方体,并调整好合适的长宽高和旗面结合起来。
旗面贴图:
旗面添加了动画,需要在代码中执行动画帧播放。
loader.load(flagModel, mesh => { |
为了充实画面,营造冬日氛围,于是就添加了几棵松树 🌲
作为装饰。添加松树的时候用到一个技巧非常重要:我们知道因为树的模型非常复杂,有非常多的面数,面数太多会降低页面性能,造成卡顿。本文中使用两个如下图 👇
所示的两个交叉的面来作为树的基座,这样的话树只有两个面数,使用这个技巧可以和大程度上优化页面性能,而且树 🌲
的样子看起来也是有 3D
感的。
材质贴图:
为了使树只在贴图透明部分透明、其他地方不透明,并且可以产生树状阴影而不是长方体阴影,需要给树模型添加如下 MeshPhysicalMaterial
、MeshDepthMaterial
两种材质,两种材质使用同样的纹理贴图,其中 MeshDepthMaterial
添加到模型的 custromMaterial
属性上。
let treeMaterial = new THREE.MeshPhysicalMaterial({ |
实现效果也可以从 👆
上面 Banner
图中可以看到,为了画面更好看,我取消了树的阴影显示。
📌
在3D
功能开发中,一些不重要的装饰模型都可以采取这种策略来优化。
💡
MeshDepthMaterial 深度网格材质一种按深度绘制几何体的材质。深度基于相机远近平面,白色最近,黑色最远。
构造函数:
MeshDepthMaterial(parameters: Object) |
parameters
:(可选)用于定义材质外观的对象,具有一个或多个属性。材质的任何属性都可以从此处传入。特殊属性:
.depthPacking[Constant]
:depth packing
的编码。默认为 BasicDepthPacking
。.displacementMap[Texture]
:位移贴图会影响网格顶点的位置,与仅影响材质的光照和阴影的其他贴图不同,移位的顶点可以投射阴影,阻挡其他对象,以及充当真实的几何体。.displacementScale[Float]
:位移贴图对网格的影响程度(黑色是无位移,白色是最大位移)。如果没有设置位移贴图,则不会应用此值。默认值为 1
。.displacementBias[Float]
:位移贴图在网格顶点上的偏移量。如果没有设置位移贴图,则不会应用此值。默认值为 0
。💡
custromMaterial 自定义材质给网格添加 custromMaterial
自定义材质属性,可以实现透明外围 png
图片贴图的内容区域阴影。
创建雪花 ❄️
,就要用到粒子知识。THREE.Points
是用来创建点的类,也用来批量管理粒子。本例中创建了 1500
个雪花粒子,并为它们设置了限定三维空间的随机坐标及横向和竖向的随机移动速度。
// 雪花贴图 |
💡
Points 粒子Three.js
中,雨 🌧️
、雪 ❄️
、云 ☁️
、星辰 ✨
等生活中常见的粒子都可以使用 Points
来模拟实现。
构造函数:
new THREE.Points(geometry, material); |
BoxGeometry
、SphereGeometry
等作为粒子系统的参数;💡
PointsMaterial 点材质通过 THREE.PointsMaterial
可以设置粒子的属性参数,是 Points
使用的默认材质。
构造函数:
PointsMaterial(parameters : Object) |
parameters
:(可选)用于定义材质外观的对象,具有一个或多个属性。材质的任何属性都可以从此处传入。💡
材质属性 .blending材质的.blending
属性主要控制纹理融合的叠加方式,.blending
属性的值包括:
THREE.NormalBlending
:默认值THREE.AdditiveBlending
:加法融合模式THREE.SubtractiveBlending
:减法融合模式THREE.MultiplyBlending
:乘法融合模式THREE.CustomBlending
:自定义融合模式,与 .blendSrc
, .blendDst
或 .blendEquation
属性组合使用💡
材质属性 .sizeAttenuation粒子的大小是否会被相机深度衰减,默认为 true
(仅限透视相机)。
💡
Three.js 向量几维向量就有几个分量,二维向量 Vector2
有 x
和 y
两个分量,三维向量 Vector3
有x
、y
、z
三个分量,四维向量 Vector4
有 x
、y
、z
、w
四个分量。
相关 API:
Vector2
:二维向量Vector3
:三维向量Vector4
:四维向量controls = new OrbitControls(camera, renderer.domElement); |
🔗
完整代码:https://github.com/dragonir/3d/tree/master/src/containers/Olympic
💡
本文中主要包含的新知识点包括:
TorusGeometry
圆环面MeshLambertMaterial
非光泽表面材质MeshDepthMaterial
深度网格材质custromMaterial
自定义材质Points
粒子PointsMaterial
点材质.blending
、.sizeAttenuation
Three.js
向量进一步优化的空间:
如此硬核的项目,真的是膜拜 dragonir
大牛。
]]>声明:本文转载自 dragonir,侵删致歉
原文链接:https://juejin.cn/post/7060292943608807460
👲👲作者主页:🔗杰森的博客
📒📒本文摘要:用前端的知识实现立体滚动照片墙
💖💖感觉本文还不错的话,还请各位小伙伴👍点赞➕收藏⭐➕评论💭支持杰森呀✌️
话不多说,直接上源码!!!
<!-- |
/* |
/* |
完整项目地址:
]]>https://github.com/PDPENG/share-code
以下为新手错误,大神请绕道,谢谢!
今天在看一个 Java 的小游戏时,遇到项目图片资源无法加载的问题,运行显示界面如图
但是代码一定是没有问题的,逻辑之类的肯定都是通的,毕竟是人家写好的,咱拿来看看是吧
最后发现问题原来如此简单!!!大家看到这样的问题,首先应该想到的都是图片资源路径问题
首先我尝试的是在路径前面加 ./ 或 ../
,甚至用上了绝对路径(但是不推荐,兼容性太差),发现更改绝对路径后显示是没有问题的
然后又回归到了相对路径上,因为在学习数据库部分时,同样遇到过路径问题,那时候是让程序显示当前路径解决的,因为会涉及到添加包名的问题
最后解决
为了避免路径引用这类的错误,直接复制图片在项目中当前的位置,操作在这里
查看路径
对比源代码,发现少了 sxt
,加入后,资源正常加载,问题解决
Image bg = Toolkit.getDefaultToolkit().getImage("sxt/imgs/bg.jpg"); |
👲👲作者主页:🔗杰森的博客
📒📒本文摘要:攻城狮杂谈,谈谈对创作的感受
💖💖希望对你有所帮助👍点赞➕收藏⭐➕评论💭支持杰森呀✌️
今天咱们不聊技术,不谈知识要点,单纯聊聊✒️写博客✒️这件事情,分享下我的收获
现在是 2022 年 5 月 8 日 23:00:51,为什么是这个时间来写下这篇博客呢?
当然是贴心的 CSDN 官方记录下了杰森的第一篇博客,记得当时是学习 C++ 编程语言时写下的
杰森的第一篇博客:拷贝构造函数剖析【C++】
那时的我不会排版,不懂专业知识(虽然现在也不懂,hah),更别说什么 Markdown 了,直接用富文本编辑的文章
没有炫酷的页面,缺乏逻辑性的文字,构成了残缺的第一篇博客。一路走来,成长、收货了许多……许多……
杰森目前是一名计算机专业在校学生,偶然在学习 C++ 时发现第一个我认为比较重要的问题,并且是争论了好久才搞明白的问题
然后为了整理思路,就想着以网络笔记的形式写下来。奈何不知道用什么去写,在我学习过程中,浏览器输入任何专业词汇及知识,弹出的前三个标签页中总有一个叫 CSDN
于是我便注册了账号,在 CSDN 平台下笔耕不辍到现在,一发不可收拾***
首先是专业知识,我们在学习完一个知识点后,可能自己并不是很清楚。但是如果你可以写下来,并尝试着让别人看懂,那么才是真正的学到了。我也一直在用这样的方法 去巩固专业重点知识,效果那叫一个 NICE !
然后就是知识面的快速扩充,写博客时你会发现,可能本来是在解决问题 A ,但是解着解着发现 B 问题也不会,这样一连串下去。解决完一个问题后你会发现收获的远远不止这些,无形中触类旁通又学到了很多
最后就是 CSDN 的社交圈,这个圈子里可以认识到很多大佬,可以和他们一起交流,共同进步。同时也欢迎大家加入 全栈攻城狮论坛,一起冲击大厂哦!
在这个平台中,每天都可以接触到最新的技术,全新的领域内容以及行业大咖独到的看法。时不时还有小伙伴👍点赞➕收藏⭐➕评论💭,激励自己不断学习心的知识
两年来,在 C 站也收获许多,结识了很多志同道合的朋友。感谢你们,是你们的支持让我继续前行,不断奋斗
未来杰森也会持续输出,不断向前哒~~
学习与创作的关系,我觉得他俩更像是好朋友,一个负责输入,另一个负责输出,相辅相成,齐头并进
目前,有限的学习生活中,创作已经成为日常学习生活中的一部分,不断的正向反馈反向刺激我接触更多的知识领域,学习更多的专业技能
有限的精力下,如何平衡创作和工作学习??关于这个问题呢,我想引用鱼皮大佬的一句话
相信会有,那么你就真的会有!
确实,我们的精力是有限的,时间也是有限的。但比起每天浑浑噩噩、打打游戏、刷刷剧的平凡生活,我更愿意深耕在专业技能上
我们真正投下的有价值的筹码,是时间。面对着足以改变你人生轨迹的黄金时间,你是否感到了它的沉重?你又是否想过要如何计划这笔巨额投资?
如果你是一名乖孩子,每天从早晨开始好好上课,好好做作业,好好预习、复习,直到熄灯时间好好睡觉,过着这种积极健康,平稳中庸的生活,但是缺乏有效自我支配的生活。如果按照学校的规划,你会发现你可以自由支配的业余时间少得可怜。
那么,你这样退守下去,无异于把自己的青春放在保险箱里让他随着时间而凋谢。摘自《上海交通大学学生生存手册》
你觉得,他说的对吗?你又是如何看待的呢?欢迎评论区留言📝
一句话:打铁必须自身硬,BAT 更要本领强!
友友们,一起加油吧,未来有更多的挑战与困难等着你我来攻克👊👊
现在到了晚上 23:33:52,时间就是海绵里的水,大家都是一天 24h ,想要多学多做,就得多付出,加油鸭!!
题目来源:【欧拉计划第 12 题】 高度可除的三角数 Highly divisible triangular number
这道题我们在枚举完三角数后,最重要的是去判断何时某个三角数约数的个数大于 500
下面我们来看下,针对计算约数的个数问题,用不同的算法解决,逐步求得最优解
最简单,更是非常容易理解的方法
复杂度:$\large O_{\left ( n^{2} \right )}$
主要思想:定义变量,使其在小于传入判断值的条件下从 1 开始自增,如果判断值和该变量进行模取运算后的值为 0,则说明该变量此时的值是判断值得一个约数。那么,程序计数器自增,记录下此值。循环结束后,输出计数器保存的值即为判断值约数的个数
这种方法优点除易于理解外,怕是没有优点了。缺点当然就是时间复杂度太高,一个值就需要去从 1 一直判断到该值。试想,如果数据量呈指数增长,这种方法恐怕在一般的计算机上不容易很快得到答案
实现代码如下
int check(long long n) |
复杂度:$\large O_{\left ( \sqrt{n} \right )}$
主要思想:对比可以看出,方法一和方法二差别不大,但影响最关键的是它们的复杂度,直接由 $O_{\left ( n^{2} \right )}$ 降至 $O_{\left ( \sqrt{n} \right )}$
同样,仍然是暴力枚举,只不过这里的判断条件由 i < = n
变为 i * i < = n
,复杂度优化了些许。进入 for()
循环后,如果 n % i == 0
,那么说明此时的 i
值是 n
的一个约数
大家在这里要注意的是 if...else
语句内容,这里主要解释下此处和方法一的差别
举个例子,如果 n = 4
,i = 2
,满足 2 × 2 = 4
的条件,但此时 4
的两个约数 2
相当于一个,程序计数器只能自增 1
,而不是 2
当然,如果进入 for()
循环后,不满足条件 i * i = n
,那么自然是两个不同的约数,此时程序计数器需要增加 2
,而不是 1
int check(long long n) |
试除法求解
vector<int> get_divisors(int n) |
LeetCode 题解思路
约数个数定理
设一个数可以表示为其素数幂的乘积,即:
$$
\large n={p_{1}}^{e_{1}} \cdot {p_{2}}^{e_{2}} \cdot\cdot\cdot {p_{m}}^{e_{m}}
$$
则该数的约数个数为:
$$
\large \left ( e_{1}+1 \right )\cdot \left ( e_{2}+1 \right )\cdot \cdot \cdot \left ( e_{m}+1 \right )
$$
参考代码:
|
API 是一组封装好的函数,通过 API,你可以为应用快速扩展功能,而无需理解它们是如何实现的,从而提升开发效率
1、调用API时,由于API服务商设置的用户流控值导致被流控,这种情况返回的错误码是( )【D】
A.400
B.401
C.402
D.403
2、关于API,下面说法错误的是( )【C】
A. 可以避免重复开发,提高开发效率
B. 减低代码的耦合度
C. 无论何时,都应该优先考虑使用API
D. 调用API实现某个功能时,无需了解该功能的原理和源码
3、关于JSON数据,以下哪个是错误的?【D】
A. 并列的数据之间用“,”分隔
B. 映射用:表示
C. 映射的集合(对象)用大括号{}表示
D. 并列数据的集合(数组)用大括号{}表示
4、关于API授权,说法错误的是()【D】
A. 可以通过从数据市场购买API服务以及提供方主动授权方式获得API的授权
B. 购买了API服务就意味着已经获得了授权
C. 账号获得了授权,不代表每个APP都获得了授权,需要手动操作将已购买的API授权给哪些APP
D. 用户有权操作购买的API与APP的授权和解除授权,也可以解除由服务提供方授权给APP的API
5、通过Java代码调用阿里云市场中提供的ip查询API在应用中实现ip查询功能,这种API属于()【C】
A. 系统API
B. 编程语API
C. Web API
D. 框架API
6、下面的JSON格式,写法正确的是()【B】
A.{ firstName = “Johm” }
B.{ “firstName” : “John” }
C.{ firstName : ‘John’ }
D.{ firstName : “John” }
7、阿里云API网关中,默认调用API的流控限制为单个IP的QPS不超过()【B】
A.50
B.100
C.200
D.500
8、调用API,表示服务器端错误的返回码是()【D】
A.2XX
B.3XX
C.4XX
D.5XX
9、HTTP/HTTPS请求的返回结果包含()(正确答案的数量:3)【BCD】
A. 请求方式
B. 状态码
C. 返回头(Header)
D. 返回体(Body)
10、调用云市场API需要的基础条件是()(正确答案的数量:3)【ABD】
A. 即将要调用的API,明确API参数定义
B. 应用APP,作为调用API时的身份,有AppKey和AppSecret用于验证身份
C. API协议
D. API和APP的权限关系
11、通过阿里云API网关API需要的条件是?()(正确答案的数量:3)【ABD】
A. 即将要调用的API,明确API参数定义。
B. 应用app(作为调用API时的身份,有AppKey和AppSecret用于验证身份)
C. API协议
D. API和App的权限关系
12、关于常用的API请求方式,下面说法正确的有()(正确答案数量:3个)【ABD】
A. GET:请求服务器获取一个资源
B. POST:请求服务器创建一个新的资源
C. UPDATE:请求服务器编辑或更新一个已存在的资源
D. DELETE:请求服务器删除一个资源
13、关于HTTP请求响应模型,下面说法正确的有()(正确答案的数量:2)【AB】
A. 客户端发起请求,服务器返回响应信息
B. 同一个客户端的这次请求和上次请求没有对应关系
C. 即时客户端没有发起请求,服务器也能将消息推送给客户端
D. 客户端发送请求时,请求类型可以省略
14、调用云市场API,可以使用下面哪些身份认证方法()(正确答案的数量:2)【AC】
A. APPCODE简单身份认证
B. SSL身份认证
C. AppKey & AppSecret签名认证
D. HTTP Basic认证
15、调用云市场中的图像识别API前,应该了解哪些元素()(正确答案的数量:2)【AD】
A. 调用地址和请求方式
B. 图像识别功能的源码
C. 深度学习相关知识
D. APPCODE或者AppKey/AppSecret
16、在调用阿里云市场中的Web API时,为构造有效的HTTP请求,报文中一般包含哪几个部分?(正确答案数量:4个)【ABDE】
A.URL(API调用地址)
B.请求方式
C.状态码
D.Headers(请求头)
E.Body(请求体)
作为软件工程和计算机科学与技术专业的基本课程,课程设计不仅涵盖了C++语言的知识体系,又与工程的实际需要切实相关。通过课程设计的综合性训练,对开发者解决实际问题能力,编程能力,动手能力有很大的提升,更有助于样成良好的编程习惯
某高校为更好的管理图书馆,现需设计一简易图书管理系统,实现新书录入,图书资料查询,显示总图书信息功能。要求开发的系统需要具备以下功能:
1.实现读者借阅图书;
2.实现读者归还图书;
3.实现对图书信息的综合管理: (设置二级子目录实现信息的增,删,改,查等操作)
4.实现对读者信息的综合管理: (设置二级子目录实现信息的增,删,改,查等操作)
5.显示用户信息:显示所有用户信息,含学号、姓名、借阅状况等信息;
6.返回主界面;
本部分设计内容包括:类的设计、数据成员设计、成员函数设计,以及主程序设计(模块函数实现,主函数) 【源码中详细解释,此处不作赘述】
|
|
|
|
|
|
|
注:本程序在Visual Studio 2019正常运行,其他配置环境可能有所差异,有问题的朋友可以留言 / 私信解决,欢迎交流学习
]]>本篇主要叙述如何为站点配置 cdn 加速服务,大家可以选择合适的服务供应商
当我配置完成后,我发现:为什么站点的打开速度还不如从前呢?不是 cdn 加速吗?这怎么还降速呢?
于是我便开始了复盘,最后的结果是:CNAME 解析错误,就是跟没没有解析到供应商。我天呐,原来我开了近一个月的服务,都是未开启的状态啊,瞬间崩溃,下面我们就来看看如何正确开启 cdn 全站加速服务
为了让大家了解的更清楚呢,这里搬运一波词条的解释,然后通俗讲解
域名解析(Domain Name System)是把域名指向网站空间 IP,让人们通过注册的域名可以方便地访问到网站的一种服务。IP 地址是网络上标识站点的数字地址,为了方便记忆,采用域名来代替 IP 地址标识站点地址。域名解析就是域名到 IP 地址的转换过程。域名的解析工作由 DNS 服务器完成。
域名解析也叫域名指向、服务器设置、域名配置以及反向 IP 登记等等。说得简单点就是将好记的域名解析成 IP,服务由 DNS 服务器完成,是把域名解析到一个 IP 地址,然后在此 IP 地址的主机上将一个子目录与域名绑定。
通俗来讲就是用一串你自己可以定义的域名,来解析到复杂、不便记忆的IP 地址上。互联网中的地址是数字的 IP 地址,域名解析的作用主要就是为了便于记忆。
CDN(Content Delivery Network),即内容分发网络。CDN 是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN 的关键技术主要有内容存储和分发技术。
简言之,用户访问服务器资源时,不同地区的用户根据距离服务器的远近有着不同的响应速度,你可以理解成双十一秒杀购物,如果你就在服务器旁边,理论上你秒杀到对应商品的概率是远大于其他用户的
cdn 的供应商有很多台分布在不同地区的服务器,当你需要访问的资源加入 cdn 后,cdn 服务器会定期从你的服务器拷贝资源。这样当用户访问你服务器上的资源时,cdn 会自动让用户访问到距离他们最近的一台 cdn 服务器上的资源
根据距离的远近,将用户的请求分配到不同的服务器上,从而实现加速的作用,也就是 内容分发网络
HTTPS (Hyper Text Transfer Protocol over SecureSocket Layer),是以安全为目标的 HTTP 通道,在 HTTP 的基础上通过传输加密和身份认证保证了传输过程的安全性。HTTPS 在 HTTP 的基础下加入 SSL,HTTPS 的安全基础是 SSL,因此加密的详细内容就需要 SSL。 HTTPS 存在不同于 HTTP 的默认端口及一个加密/身份验证层(在 HTTP 与 TCP 之间)。这个系统提供了身份验证与加密通讯方法。它被广泛用于万维网上安全敏感的通讯,例如交易支付等方面。
看图,相信你一定遇到过这样的网站
出现这样的情况,表示这个网站使用了 HTTP 协议传输数据,提醒用户谨慎访问网站。 HTTP 协议是明文传输协议,无法加密传输数据或校验数据完整性,也无法进行身份验证,这时候就有必要了解下 SSL 证书
SSL(Secure Sockets Layer 安全套接字协议),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层与应用层之间对网络连接进行加密。
个人使用的话,没有更高的要求,我们到供应商处申购免费的证书就好,下文配置会详细讲到
这里以又拍云为例,演示配置过程,其他供应商类比操作即可
这里提醒大家,使用一个新的产品时一定要仔细阅读官方文档,不然怎么会有:没有好文档的产品不是合格产品的说法呢?有关于 upyun 资源的绑定和注册,请直接访问官方文档
这里我主要想强调的一点就是 dns 记录的添加,大家在这里获取到对应的 CNAME 域名 后,到域名的供应商出添加解析记录,这里我以万网接入为例
在 云解析 DNS 控制台 找到 添加记录
主机记录 位置处要特别注意,有以下两种情况
synopsis.coder-jason.cn
这个二级域名,主机记录处填写 synopsis
其余项按照下图配置就好
我们在本地打开命令行工具,输入 ping
指令到自己的域名,查看 dns 配置是否生效,得到图示响应即配置成功,也可以通过官方方法测试配置
大家在域名的提供商处可以找到 数字证书管理服务控制台 ,填写信息后提交申请即可
待审核通过后,我们下载部署就好,这里以 Nginx 部署为例。服务器安装 宝塔面板 后(详细步骤请参考文),点击 ssl 证书,在对应窗口粘贴我们下载好的证书就可以了,注意区分文件后缀,不要粘贴错误
因为使用了又拍云的 cdn 服务,所以也需在图示位置添加证书
至此,网站就实现加密访问啦,您可以通过ssl 状态检测工具查看配置状态
upyun cdn 管理控制台 下拉找到 Ip 访问限制
点击管理添加限制规则
点击保存
在 upyun cdn 管理控制台 访问控制中找到CC 防护,添加防护规则
点击保存
如果不介意站点下方添加服务商 logo ,可以加入又拍云联盟免费获取每月 10GB 存储空间 + 15GB 流量
点击这里预览添加效果
配置教程
ASCII是美国(国家)信息交换标准(代)码,一种使用7个或8个二进制位进行编码的方案,最多可以给256(2^80)
个字符 (包括字母、数字、标点符号、控制字符及其他符号)分配(或指定)数值。基本的 ASCII 字符集共有 128
个字符,其中有 96
个可打印字符,包括常用的字母、数字、标点符号等,另外还有 32
个控制字符。
文件中每一个字都是美标形象码或空格码,这类文件称为“美标文本文件”,或略为“文本文件”,通常可在不同电脑系统间直接交换。 文件中含有控制码或非美标码的文件,通常不能在不同电脑系统间直接交换。这类文件有一个通称,叫“二进制文件”
为了扩充ASCII编码,以用于显示本国的语言,不同的国家和地区制定了不同的标准,由此产生了GB2312
, BIG5
, JIS
等各自的编码标准。这些使用 2 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI
编码,又称为MBCS(Muilti-Bytes Charecter Set,多字节字符集)
。在简体中文系统下,ANSI
编码代表 GB2312
编码,在日文操作系统下,ANSI
编码代表 JIS
编码,所以在中文 windows下要转码成GB2312
,GBK
(gb2312的扩展)只需要把文本保存为ANSI
编码即可。 不同 ANSI
编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI
编码的文本中。一个很大的缺点是,同一个编码值,在不同的编码体系里代表着不同的字。这样就容易造成混乱
GB2312
是ANSI
编码里的一种,对ANSI
编码最初始的ASCII
编码进行扩充,为了满足国内在计算机中使用汉字的需要,中国国家标准总局发布了一系列的汉字字符集国家标准编码,统称为GB码,或国标码。其中最有影响的是于1980年发布的《信息交换用汉字编码字符集 基本集》,标准号为GB 2312-1980,因其使用非常普遍,也常被通称为国标码。GB2312编码通行于我国内地;新加坡等地也采用此编码。几乎所有的中文系统和国际化的软件都支持GB2312
。 GB2312
是一个简体中文字符集,由6763
个常用汉字和682
个全角的非汉字字符组成
GB 2312
的出现,基本满足了汉字的计算机处理需要,但对于人名、古汉语等方面出现的罕用字,GB 2312
不能处理,这导致了后来GBK
及GB 18030
汉字字符集的出现 GBK
共收入21886个汉字和图形符号,其中汉字(包括部首和构件)21003
个,图形符号883
个。GBK
编码标准兼容GB2312
,共收录汉字21003
个、符号883
个,并提供1894
个造字码位,简、繁体字融于一库。GB2312
码是中华人民共和国国家汉字信息交换用编码,全称《信息交换用汉字编码字符集——基本集》,1980年由国家标准总局发布。基本集共收入汉字6763
个和非汉字图形字符682
个,通行于中国大陆。新加坡等地也使用此编码。GBK是对GB2312-80的扩展.
在台湾、香港与澳门地区,使用的是繁体中文字符集。而1980年发布的GB2312
面向简体中文字符集,并不支持繁体汉字。在这些使用繁体中文字符集的地区,一度出现过很多不同厂商提出的字符集编码,这些编码彼此互不兼容,造成了信息交流的困难。为统一繁体字符集编码,1984年,台湾五大厂商宏碁、神通、佳佳、零壹以及大众一同制定了一种繁体中文编码方案,因其来源被称为五大码,英文写作Big5,后来按英文翻译回汉字后,普遍被称为大五码。大五码是一种繁体中文汉字字符集,其中繁体汉字13053
个,808
个标点符号、希腊字母及特殊符号。
为什么电子邮件和网页都经常会出现乱码,就是因为信息的提供者可能是日文的ANSI编码体系和信息的读取者可能是中文的编码体系,他们对同一个二进制编码值进行显示,采用了不同的编码,导致乱码。这个问题促使了unicode码的诞生。 如果有一种编码,将世界上所有的符号都纳入其中,无论是英文、日文、还是中文等,大家都使用这个编码表,就不会出现编码不匹配现象。每个符号对应一个唯一的编码,乱码问题就不存在了。这就是Unicode编码。
unicode
,中文叫万国码,统一码,是统一码联盟为了世界上大多数文字系统进行整理和编码。 和unicode
类似,iso组织也在做同样的事情,iso开展了 ISO/IEC 10646
项目,名字叫“ Universal Multiple-Octet Coded Character Set”
,简称UCS
。 后来,双方意识到时间上不需要2套通用的字符集,所以双方开始进行整合,到unicode2.0
时,unicode
的编码和ucs
的编码都基本一致。 但是又略有不同。
Unicode
深入人心,且UTF-8
(Unicode中的一种)大行其道,UCS
编码基本被等同于UTF-16
,UTF-32
了,所以目前UCS基本谈出人们的视野中。
Unicode
固然统一了编码方式,但是它的效率不高,比如UCS-4
(Unicode的标准之一)规定用4个字节存储一个符号,那么每个英文字母前都必然有三个字节是0,这对存储和传输来说都很耗资源。 为了提高Unicode
的编码效率,于是就出现了UTF-8
编码。UTF-8
可以根据不同的符号自动选择编码的长短。比如英文字母可以只用1个字节就够了。
UTF-16
是Unicode
的其中一个使用方式,UTF-16
比起UTF-8
,好处在于大部分字符都以固定长度的字节 (2字节) 储存,但UTF-16
却无法兼容于ASCII
编码。
有的电子邮件系统(比如国外信箱)不支持非英文字母(比如汉字)传输,这是历史原因造成的(认为只有美国会使用电子邮件?)。因为一个英文字母使用ASCII编码来存储,占存储器的1个字节(8位),实际上只用了7位2进制来存储,第一位并没有使用,设置为0,所以,这样的系统认为凡是第一位是1的字节都是错误的。而有的编码方案(比如GB2312)不但使用多个字节编码一个字符,并且第一位经常是1,于是邮件系统就把1换成0,这样收到邮件的人就会发现邮件乱码。
为了能让邮件系统正常的收发信件,就需要把由其他编码存储的符号转换成ASCII码来传输。比如,在一端发送GB2312编码->根据Base64规则->转换成ASCII码,接收端收到ASCII码->根据Base64规则->还原到GB2312编码。
UCS-4根据最高位为0的最高字节分成2^7=128个group。每个group再根据次高字节分为256个plane。每个plane根据第3个字节分为256行 (rows),每行包含256个cells。当然同一行的cells只是最后一个字节不同,其余都相同。 group 0的plane 0被称作Basic Multilingual Plane, 即BMP。或者说UCS-4中,高两个字节为0的码位被称作BMP。 将UCS-4的BMP去掉前面的两个零字节就得到了UCS-2。在UCS-2的两个字节前加上两个零字节,就得到了UCS-4的BMP。而目前的UCS-4规范中还没有任何字符被分配在BMP之外
]]>声明:本文仅供技术交流使用,阅读本文需具备一定的开发能力
在你的域名服务商新建二级域名并绑定服务器主机IP
上传下面的python文件到你的服务器,并修改代码段中相应位置代码(token、api-key、port)
import time |
使用宝塔是比较快捷的配置方式,安装宝塔面板后,进入软件商店,安装下面两个插件
打开 python 项目管理器 ,简单配置下我们要启动的项目
启动后映射项目域名,顶级域和二级域都可以,比如我这里填入的是 chatgpt.coder-jason.cn
进入公众号后台,找到设置与开发,进入基本配置,由于我这里已经配置好了,这里仅演示下怎么添加启用
点击添加配置
token 值就是在上述代码段中填入的值,自定义字母和数字组合即可
点击提交后,如果服务器中的项目启动无误,则会提示 token校验成功
接下来就可以回到公众号和 chatGPT 愉快的交流啦~,欢迎来公粽号 攻城狮杰森 体验
如果你对 chatGPT 感兴趣或配置过程中遇到任何问题,欢迎与我取得联系,vx:jasoni996
]]>环境配置完成后,使用如下的命令快速完成代码推送
git init //初始化本地仓库 |
git push -f --set-upstream origin master |
如果是协同开发,为了避免后期出现问题,还是不要用的好
如果在开发过程中遇到了文件”丢失”的问题,可以这样解决
纳入版本控制的文件并不会“丢失”,这里所说的丢失只是因为你的操作在本地看不到了,但是远端仓库都会保留,只是暂时性“隐藏”
git
会记录你每一步的操作,这也正是我们将代码纳入版本控制的原因之一
比如我早上刚刚提交的代码,过了个周末就不见了,真是吓得我出了一身冷汗,莫慌,我们这样解决
项目名称位置右键找到本地历史,选中修改的版本完成回退
]]>马上圣诞节了,祝大家圣诞快乐,快来看看程序员的圣诞节都做了什么
''' |
/* |
/* |
package com.christmasTree; |
解释:拷贝构造函数是一种特殊的构造函数,它具有一般构造函数的所有特性,但其形参是本类对象的引用
作用:使用一个已经存在的对象(由拷贝构造函数参数指定)去初始化同类的一个新对象
定义格式:构造函数名 (&类名);
三种使用情况
注意
该例重点阐述:为什么拷贝构造函数的参数必须为同类对象的引用?
|
程序运行结果
调用两个参数的构造函数 |
如何实现 在线课程 字体下方的 短横线 样式效果
看到这样的样式效果,大多数人首先想到的一定是 border-bottom
吧,但是真正写在 css
中,你会发现,效果是这样的
实现了,却又好像没实现,无法设置长度,那么下面我们试着换一种思路去实现这个效果
我们不要把这个短横线看做 border ,使用 伪元素 实现,可以随意更改大小、宽度、长度等,非常的方便
伪元素
用于设置元素指定部分的样式,可用于设置元素的首字母、首行的样式,在元素的内容之前或之后插入内容等
selector::pseudo-element { |
.box h1::after { |
抽象上述代码为通用格式,日后可应用在其他场景下
selector:after { |
参考资料:
还在傻傻分不清?Java、JSP、JavaScript ,本文带你辨析其区别与联系
文件格式: .java
Java 是印度尼西亚“爪哇岛”的英文名,因气候环境,地理位置等因素盛产咖啡而闻名。Java 语言中的许多命名都与其有关:如JavaBeans。所以 Sun 和 Java 的 Logo 是个非常形象的图标—冒热气儿的咖啡
早期的 Java 只是Sun MicroSystems公司在 1990 年 12 月开始研究的一个内部项目。Sun 公司一位名为帕特里克·诺顿的工程师因为其公司难于操作的 C++/C 语言编译器而决定改用NeXT,同时他也获得了研究公司的一个叫做 “Stealth 计划” 的项目的机会
“Stealth 计划”后来改名为“Green 计划”,詹姆斯·高斯林和 Mike Sheridan 也加入了帕特里克的工作小组。根据有限资金,乔伊决定开发一种集 C 语言和 Mesa 语言大成的新语言,在一份报告上,乔伊把它叫做“未来”。他将要创造出一种全新的语言,被他命名为 “Oak”,以办公室外的橡树命名
总结:
Java
是一种广泛使用的计算机编程语言,广泛应用于企业级 Web 应用开发和移动应用开发
文件格式: .jsp
JSP(JavaServer Pages)由 Sun Microsystems 公司主导创建的一种动态网页技术标准。JSP 部署于网络服务器上,可以响应客户端发送的请求,并根据请求内容动态地生成 HTML、XML 或其他格式文档的 Web 网页,然后返回给请求者
从上面的两张图片也可看出来,JSP 和 Java 编程语言存在联系,没错,JSP 技术以Java语言作为脚本语言,为用户的 HTTP 请求提供服务,并能与服务器上的其它 Java 程序共同处理复杂的业务需求
总结:
JSP
主要部署在服务器,构建动态网页
文件格式: .js
JavaScript(通常缩写为JS)是一种高级的、解释型的编程语言,是 Web 编程语言,几乎所有现代的 HTML 页面都使用 JavaScript,人们通常将 html
、css
、javascript
称为前端三件套
==JavaScript 不缩写为 JSP,这里一定不要弄混淆了!!!==
JS 中有一条比较有意思的定律:
Atwood’s Law: any application that can be written in JavaScript, will eventually be written in JavaScript .
意思是说,任何可以用 JavaScript 编写的应用程序,最终都会用 JavaScript 编写
这足以体现它的重要性
总结:
JavaScript
是一种脚本,一种计算机编程语言,用于在网页上实现复杂的功能
参考资料:
声明一个误区:Git并不是我们常用的GitHub,GitHub是基于Git的代码托管服务平台,而Git则是分布式版本控制系统。相信不少人都认为他们是同一个东西,最开始我也这么认为。
既然要使用Git,那么我们首先就要安装并配置Git的环境,点击这里下载(Windows操作系统),点击Download按钮即可
安装过程不再叙述,直接使用默认配置,一“Next(站)” 到底
下面我们配置环境变量信息(前段时间的博客中已经详细解释过,不了解的朋友可以点击这里查看),打开 Path 变量后,添加本地环境安装目录【确认好文件到达 cmd 】
安装完成后,你可能没有看到桌面的快捷方式,不要着急。我们在Windows搜索框中搜索Git就可以看到这样几个图标
可以直接点击 Git Bash 或者在桌面任意位置右键,打开 Git Bash Here
Git 提供了一个叫做 git config 的工具,用来配置、读取相应的工作环境变量。我们使用
git config --global user.name "你的昵称" |
命令配置个人的用户名称和电子邮件信息。
使用命令
git config --list |
查看已有配置信息
列举一些常用命令:
git init //初始化仓库 |
虽然我忠爱GitHub,但是由于网络问题,使用Gitee还是较多;首先你需要有一个码云账号,点击这里注册,进去之后右上角头像位置找到SSH公钥添加位置。
我们在桌面右键进入git bash here,运行命令:
ssh-keygen -t rsa -C "你的邮箱" |
因为我已经添加过了,所以提示:“是否再次写入?”,注意:这里输入邮箱回车后,==不要输密码,不要输密码,不要输密码!!!==(重要的事情说三遍)不然你会发现以后每次上传时仍然需要输入密码【不是吧,不是吧,不会还有人想每次提交都输一遍密码吧(有的话请略过该条)emmm..】
在本地路径下找到 id_rsa.pub 文件,记事本打开后复制里面的内容
然后粘贴在Gitee这里,标题可以更改(一般输入的邮箱就是标题,自动生成),保存即可
现在就可以去体验Git的妙用啦!!
Tips:IDEA中的使用都会有对应的按钮进行操作,比命令行更方便,使用方法一致,不同的状态还有不同的颜色标识提示,快去试试吧。
]]>写给刚刚入坑 Java 的各位,无论你是计算机领域从业者,亦或是科班出身的专业人才。当然也包括我在内,Hello World 相信大家都不陌生,找了好久才找到我入行以来的第一段程序
有没有让你回想起当年用 VC ++ 6.0 码代码的日子呢?像 Python、C、C++、VB 等编程语言,它们有着不同的语法结构,实现方式各不相同,今天使用 Dos命令实现 Java 版 Hello World
在这之前请确保设备已安装好 JDK,配置详情参阅这里
D盘下建立 HelloWorld.txt 文件,输入代码
public class HelloWorld{ |
另存文件格式为 .java
组合键 Windows+R,输入 cmd 打开命令提示工具 cmd.exe
依次输入命令
d: //切换到该目录下 |
Emmet (前身为: Zen Coding) 是一个能大幅度提高前端开发效率的一个工具。在前端开发的过程中,一大部分的工作是写 HTML、CSS 代码。特别是手动编写 HTML 代码的时候,效率会特别低下,因为需要敲打很多尖括号,而且很多标签都需要闭合标签等
于是,就有了 Emmet,它可以极大的提高代码编写的效率,它提供了一种非常简练的语法规则,然后立刻生成对应的 HTML 结构或者 CSS 代码,同时还有多种实用的功能帮助进行前端开发(源:Wikipedia)
简单来说,Emmet
能帮助我们快速进行前端代码的编写,在主流开发工具 Vscode
中也已集成。我们只需要键入相应标签的缩略语,按 Tab
键就可快速生成对应代码,下面介绍几组开发中常用的语法
名称 | Emmet 格式 | 效果 |
---|---|---|
类选择器 | .blue | <div class="blue"><div> |
id 选择器 | #test | <div id="test"><div> |
子代选择器 | ul>li | <ul><li></li></ul> |
交集选择器 | p.blue#test | <p class="blue" id="test"></p> |
标签名称 | span | <span></span> |
多层级样式 | ul>li*3 | <ul><li></li><li></li><li></li></ul> |
内嵌文本 | ul>li{ li 文本内容 } | <ul><li> li 文本内容 </li></ul> |
换行 | br | <br> |
分割线 | hr | <hr> |
btn | ul>li{ li 文本内容 } | <button></button> |
Emmet 格式 | 效果 |
---|---|
input | <input type="text"> |
input:radio | <input type="radio" name="" id=""> |
input:checkbox | <input type="checkbox" name="" id=""> |
input:email | <input type="email" name="" id=""> |
input:password | <input type="password" name="" id=""> |
inp | <input type="text" name="" id=""> |
input:hidden / input:h | <input type="hidden" name=""> |
Emmet 格式 | 效果 |
---|---|
btn | <button></button> |
btn:r | <button type="reset"></button> |
btn:s | <button type="submit"></button> |
Emmet 格式 | 效果 |
---|---|
html:4s | 生成 html4 严格文档类型,DOCTYPE 为 html 4.01 |
html:5 | 生成 html5 标准的包含 body 为空基本 DOM |
html:xt | 生成 html 过渡文档类型,DOCTYPE 为 xhtml |
Emmet 格式 | 效果 |
---|---|
a:link | <a href="http://"></a> |
a:mail | <a href="mailto:"></a> |
link | <link rel="stylesheet" href=""> |
base | <base href=""> |
Emmet 格式 | 效果 |
---|---|
form:get | <form action="" method="get"></form> |
option | <option value=""></option> |
bq | <blockquote></blockquote> |
label | <label for=""></label> |
base | <base href=""> |
bgi | background-image: url(); |
bgr | background-repeat: no-repeat; |
bgc | background-color: #fff; |
bgp | background-position: 0 0; |
!
+ Tab
快速生成 Html
主体框架
部分常用标签演示
]]>编写程序,将一个数组中的值按逆序重新存放。例如原来顺序为:8,6,5,4,1,要求改为:1,4,5,6,8。
(1)建立两个存放数据的数组;
(2)for循环输出原数据顺序;
(3)逆序;
(4)复制;
(4)for循环输出新数据顺序;
public class Demo1 { |
public class Demo2 { |
src:源数组 srcPos:源数组复制的起始位置 dest:目标数组 destPos:目标数组放置的起始位置 length:复制的长度
for (int k = 0; k < 5; k++) { |
对于步骤(4)复制,本质上就是拷贝了数组1中的数据到数组2中。最开始有这步的原因是在最后一个for循环中,输出的数组为 array1(Demo1 Line14),这时候就需要使用array2中交换后的数据”覆盖“array1中的原数据,实现输出结果。但是我们可以直接输出array2的数据(Demo2),这样使程序更为简单。
|
接收用户输入值时,使用
scanf();
不要忘记加&
符。当然,使用printf();
也不要多加。
]]>
- C语言版,最重要的是数据顺序的交换,考虑常量N的奇偶性。中间变量temp设定为数组起点,由于数组从0开始分配下标的特性,数组中最后一个元素指定为 N - i - 1。
- 此处需要的交换顺序只是位置上的改变,并不考虑队列中各个元素大小的比较。因此,只考虑一半的数据可提高程序运行速度。
编写一个判断素数的函数,在主函数输入一个整数,输出该数是否为素数的信息。
(1)函数思想;
(2)素数定义;
(3)变量定义;
(4)接收用户输入;
(5)判断输出;
import java.util.Scanner; |
- 调用数学函数
sqrt()
时,注意不同数据类型之间的转换;- 使用布尔型函数判断是否为素数,注意这时的返回值不再是 0 和 1,而是
true
和false
。
|
素数又名质数,是指一个大于1的自然数,除了1及其自身外,不能整除其他自然数的数。
]]>
- 判断一个自然数是否为素数,我们可以这么想:什么样的数不是素数?答案是:负数、0、1以及任何“除1和它本身外还能被其他数整除的数”;
- 这样我们的条件就非常明确:排除负数、0、1,利用“不是素数的数都满足小因数<=sqrt(n)<=大因数“这个条件进行判断,其中,n 是待判断的数;
- 只需要判断一个数能否被小于或等于sqrt(n) 的数整除即可,降低了算法的时间复杂度。
(1)分别定义不同功能变量;
(2)输出主页面;
(3)分功能实现;
(4)使用系统函数;
(5)分类输出计算结果;
|
- 完整包含所使用函数的头文件;
- “阶乘” 功能使用递归思想解决,找到计算过程中的递归体
e * function(e - 1)
,并注意特殊位置的处理,如 0 和 1;- 定义
char
类型变量时,若参与比较,本质是比较其 ASCII码 值大小,使用==
符号判断是否相等时需要加单引号‘’
;- “累加“ 功能实现中,第一次及第二次接收数据合并处理,都放入循环。否则输出结果和实际运算结果存在偏差,且差值为第一次数据计算结果,此处使用
result += (c + d)
保留上次计算结果。
不知道机智的你有没有发现,如果按照题目的要求,我们只需要输出界面,很easy。额,后知后觉,写完才发现,权当练手啦!
]]>输入一行字符,分别统计出其中英文字母,空格,数字和其他字符的个数。
(1)定义变量接收输入;
(2)定义特定变量;
(3)循环计算;
(4)多分支结构判断;
(5)输出结果;
|
]]>
- C语言中没有字符串变量,因此一次只能接收一个字符并放入缓存区中;
- 这里我们接收用户输入的一行字符,并不知道用户输入的长度以及开始位置是什么,所以 for 循环中循环变量的声明和更新都无需设定,即从开始位置进入,结束位置输出。
设圆半径 r=1.5,圆柱高 h=3,求圆周长、圆面积、圆球表面积、圆球体积、圆柱体积。取小数点后2位数字,请编写程序。
(1)变量、常量定义;
(2)函数定义;
(3)函数调用;
(4)输出结果;
|
]]>
- 对需求进行拆分,在一个个函数中 “逐个击破”,“分而治之”思想;
- 使用C语言中
<math.h>
头文件下的数学函数pow()
计算次方,例如pow(x,y)
表示 x 的 y 次方;
从键盘输入n (个数不限)个整形数字,放入数组PArray, 调用函数 int *Calc(int *PA,int Num); 计算数组中所有元素的和返回到 main 函数,输出计算结果。
(1)定义数组、变量;
(2)接收设定值;
(3)分配内存空间;
(4)元素求和;
(5)输出;
|
]]>
- 使用指针,及时初始化;
- 动态分配内存空间,包含头文件
<stdlib.h>
,函数原型void* malloc (size_t size);
返回值类型是void *
,void 表示返回未知指针类型。- 通常,
malloc()
使用时需要进行强制类型转换,如(int *)malloc(Total * sizeof(int));
修改 void 指针为所需类型;Calc()
为指针类型函数,值 sum 返回主函数时不可直接返回。将 sum 值存入数组首地址,也就是作为第一个元素,返回数组首地址即可;- 动态申请的内存空间最后要使用
free()
释放;
有一组数12,56,45,78,90,80,23,16,8,63 保存在一个数组中,从键盘任意接收一个数,并在数组中查找该数给出是否找到的信息。如果找到了,要求输出该数在数组中所处的位置;如果找不到,输出没有找到的提示信息。
(1)接收;
(2)查找数据;
(3)对比;
(4)输出结果;
import java.util.Scanner; |
|
- 本题关于“未找到信息的输出”,我们还可以这样想:如果一组数据,比对到最后一个都没有满足条件的,那么就认定为队列中没有该数据。
- 用这样的思想我们可以进行这样的改动:删除Tag标签,增加条件判断直接输出。这里注意变量
i
的自增,为了在i=10
时仍能进入循环输出信息,判断条件应修改为i <= 10
。
|
- 本题中最重要的是如何将已有数据和用户输入数据进行对比,也就是 “查找” 这一操作,代码1给出的是查找算法中最简单的 “顺序查找” 。
- 由于每次进入循环,变量
i
依次自增、逐个查找,如果我们仅仅只将单一的输出信息放在语句中而不进行其它判断的话,就会造成输出错误。所以增加变量Tag
用于判断条件:如果数据相等(找到了),Tag
值置 1 。如果没有找到,Tag
值置0,循环外进行一次判断输出没有找到的提示信息。- 我竟然试图用二分法解决,但是却忽略了使用二分(折半)查找的前提必须是有序表顺序存储。这里给出两种版本的二分法,注意算法适用条件。
int Search1(int a[], int value, int n) |
有一个3*4矩阵,数据为{1, 2, 3, 4}, {9, 8, 7, 6}, {-10, 10, -5, 2},编写程序,通过比较输出最大元素的值及其所在的行标和列标。
(1)理解 3 * 4 矩阵;
(2)循环求最大值;
(3)保存行列标;
(4)输出;
public class Demo { |
array=new type[][]{值 1,值 2,值 3,…,值 n}; |
|
]]>重在如何保存下标,循环的确是每个数据都进行比较,但是,若队列后面的数据不满足
array[i][j]>Max
条件的话,也不会保存它们的下标。所以,直接在循环中增加赋值,以起到保留最大值下标的效果。
编写程序,从键盘上输入N个学生的考试成绩存入一维数组中,求该数组中成绩的最高分、最低分及平均分并输出到屏幕。
(1)定义常量N值;
(2)建立用于存放数据的一维数组;
(3)接收用户输入;
(4)查询 / 计算特定值;
(5)输出结果;
import java.util.Scanner; |
注意Java中接收用户输入的方法,同时考虑对一维数组“动态赋值”的操作。
|
`scanf()`中别丢弃 `& `取地址符(异常:输入数据后无输出)。求平均值无需增加变量`Sum`,可将变量`Average`放入循环体内求总和,在循环体外进行平均值求算。]]>
编写程序,从键盘上任意接收10个整数存入一维数组中(无序),利用冒泡排序将该数组元素由小到大进行排序,并输出排序后数组。
(1)建立用于存放数据的一维数组;
(2)接收用户输入;
(3)冒泡排序;
(4)输出结果;
import java.util.Scanner; |
|
- 冒泡排序是一种简单直观的排序算法。通过”重复性地比较需要排序的数列,一次比较两个元素,若顺序错则交换”的方法完成排序。
- 算法步骤:
(1)比较相邻位置的两个元素,若前者大于后者,则交换顺序;
(2)重复步骤一,对所有数据遍历走访,此时,末尾元素最大;
(3)对除末尾元素外的其他元素重复以上操作;
(4)上述步骤重复次数逐渐减少,直到没有任何数据需要进行比较;
for (i = 0; i < N - 1; i++) //i控制比较趟数 |
编写程序,有一维数组数据为:23,34,45,60,67,88,96,从键盘上输入一个数据,将数据插入到数组,使得插入后的数组元素依然保持有序并输出到屏幕。
(1)数组建立;
(2)接收用户输入数据;
(3)查找位置;
(4)移动元素;
(5)插入(赋值);
(6)输出结果;
import java.util.Scanner; |
Java处最关键的是分清楚插入数据前后,数组元素的下标值以及数组的建立过程。
|
]]>
- 难点在于如何找到待插入数据合适位置以及如何移动数组元素位置。这里使用循环求解:
for
循环实现位置查找功能,判断条件为待插入数据<=
数组元素值。若满足条件,则退出循环并保留位置下标给location
。- 找到位置后需要插入数据,并且不能覆盖掉原数据,这时候需要对原数据整体移动。同样使用
for
循环实现,i=7
就相当于指针指向了数组中最后一个元素,所有在location
之后的元素都得为它 “让位”,即后移。最后location
位置便是空值,只需对它赋值(用户输入值)便实现数据插入。
编写程序,实现如下功能:一个学习小组有5个人,每个人有Math,C,Database三门课的考试成绩,求该组各科成绩的平均分及所有成绩的平均分并输出到屏幕。
(1)给出结构体;
(2)分析变量;
(3)计算总 / 各科成绩平均分;
(4)输出结果;
import java.util.Scanner; |
- Java是一种高级语言,它舍弃了C/C++中容易出错的指针、一些莫须有的语言结构(其中就包含结构体),所以这道题如果我们用Java语言解决,就需要用到类和对象。
- 我们在类中包含其属性和方法,不太容易想到的是三门科目的成绩从键盘接收并且需要循环五次的操作:使用对象数组
Student[] student = new Student[5];
并对其进行实例化实现动态接收数据。- 在类和对象中,只要有需求,我们就添加方法解决问题。例如本题中设置返回三个科目成绩的方法实现单科成绩平均分、总成绩平均分求算。
- 对象数组需要进行实例化
student[i] = new Student();
,否则报错:空指针错误!!!
|
- 关键点在于如何将不同科目的成绩和同学进行区分。这里我们采用结构体数组的方式解决:有5个元素的结构体数组
student[5]
包含Math
、C
和Database
三个变量对应不同科目成绩。考虑到这点,题目就变得非常简单,只要接收输入值,计算方可。- 计算中,要考虑周全,成绩有可能是
float
类型。而计算平均值时用到的/
号,结果为整型,所以我们做除法的时候,除数应该是5.0
而不是5
。
下面这道题目和本题类似,需要注意的点是使用
scanf()
时,若结构体中包含数组,就需要关注&
是否需要存在。对比源码,进一步加深理解。
|
用指针方法编写一个程序,输入3个整数,将它们按由小到大的顺序输出。
(1)定义指针;
(2)接收输入值;
(3)排序;
(4)输出结果;
import java.util.Scanner; |
- 在C/C++中,指针的作用是:通过指针间接访问内存,保留地址,可以理解为指针就是一个地址。同样地,指针就是用于取得地址的,那么这里就有疑问了(Java中没有指针啊?这怎么做?)。
- 从表面上看,Java的确没有明确给定 “指针” 这个概念。但是,深入分析,Java中引用类型本质上就是对 “指针” 的封装。使其不能直接操作内存,只能指向对象,这里我们用数组—比较方便大家理解的方式解决。
|
|
]]>使用指针时要注意这样几点:
(1)避免使用未初始化的指针,多数情况下程序运行错误都与指针未初始化有关,但是由于这种错误不能被编译器检查发现的特殊性,就需要我们格外注意。最好的解决办法就是使用指针时对它进行定义。当然,早早定义的话也不要忘记初始化,在进行初始化时可以使用cstdlib
中定义的NULL
赋值为0。
(2)因为指针类型给定指针所指向对象的数据类型,所以指针赋值要确保数据类型匹配,才可以对指针进行操作。
(3)不要误以为int *p , a ;
是声明了两个int
型指针,实际是定义了一个int
型指针p
和一个int
型变量a
,为了进行区分我们可以在定义时分开写,详见C语言-2。
写一个简单的函数实现下面的功能:具有三个参数,完成对两个整型数据的加、减、乘、除四种操作,前两个为操作数,第三个参数为字符型的参数。
(1)定义变量;
(2)接收用户输入;
(3)函数计算;
(4)输出结果;
import java.util.Scanner; |
switch (c) { |
- 注意
switch-case
语句中case
处的数据类型,因为设定了变量c
为char
类型,所以需要使用 c = input.next().charAt(0) 语句接收用户键盘上的单个字符输入,charAt()
方法用于返回指定索引处的字符,索引范围为从 0 到length() - 1
。- Java 中引入增强型
switch
结构,给出参考代码。主要特点如下:需要返回值、无需break
、使用箭头->
、可进行 case 间的合并,以逗号分隔。
|
]]>因为有四种计算类型,所以我们使用
switch-case
语句解决,注意除法计算中除数不为 0 的条件判断,且case
后需为常量,这里使用字符做判断条件,加上单引号‘’
变为字符常量。
刷算法题过程中遇到了平面解析几何中,直线方程的相关知识点,正好来复习下吧
适用于所有直线
$$
\large A_{x}+B_{y}+C=0(\large A^{2}+B^{2}\neq 0)
$$
其中,斜率
$$
\large K=-\frac{A}{B}
$$
横、纵截距
$$
\large a=-\frac{A}{C},\large b=-\frac{C}{B}
$$
并且有两直线平行
$$
\large \frac{A_{1}}{A_{2}}= \frac{B_{1}}{B_{2}}\neq \frac{C_{1}}{C_{2}}
$$
两直线重合
$$
\large \frac{A_{1}}{A_{2}}= \frac{B_{1}}{B_{2}}= \frac{C_{1}}{C_{2}}
$$
适用于不垂直于 $\large x$ 轴的直线
$$
\large y-y_{0}=k\left ( x-x_{0} \right )
$$
表示过定点
$$
\large P\left ( x_{0},y_{0} \right )
$$
斜率为 $\large k$ 的直线
适用于不过原点或不垂直于 $\large x$ 轴、$\large y$ 轴的直线
$$
\large \frac{x}{a}+\frac{y}{b}=1
$$
表示与 $\large x$ 轴、$\large y$ 轴相交,且与 $\large x$ 轴截距为 $\large a$、与 $\large y$ 轴截距为 $\large b$ 的直线
适用于不垂直于 $\large x$ 轴的直线
$$
\large y=kx+b
$$
表示斜率为 $\large k$ ,且与 $\large y$ 轴截距为 $\large b$ 的直线
适用于不垂直于 $\large x$ 轴、$\large y$ 轴的直线
$$
\frac{\left ( y-y_{1} \right )}{\left ( y_{2}-y_{1} \right )}=\frac{\left ( x-x_{1} \right )}{\left ( x_{2}-x_{1} \right )}\large \left ( x_{1}\neq x_{2},y_{1}\neq y_{2} \right )
$$
表示过点
$$
\large \left ( x_{1},y_{1} \right ),\left ( x_{2},y_{2} \right )
$$
的直线
适用于所有直线
$$
\large \frac{\left ( x-x_{0} \right )}{u}=\frac{\left ( y-y_{0} \right )}{v}\left ( u\neq 0,v\neq 0 \right )
$$
表示过定点
$$
\large P\left ( x_{0},y_{0} \right )
$$
且方向向量为
$$
\large \left ( u,v \right )
$$
的直线
适用于所有直线
$$
\large f_{1}\left ( x,y \right )*m+f_{2}\left ( x,y \right )=0
$$
表示过两直线
$$
\large \left\{\begin{matrix} \large f_{1}\left ( x,y \right )=0\\ \large f_{2}\left ( x,y \right )=0 \end{matrix}\right.
$$
的交点的直线
适用于不平行于坐标轴的直线
$$
\large x\cdot cos \alpha +y\cdot sin \alpha -p=0
$$
经过原点向已知直线做一条垂线段,垂线段所在直线倾角为 $\large \alpha$ ,线段长度为 $\large p$ ,表示过定点
$$
\large P\left ( x_{0},y_{0} \right )
$$
且方向向量为
$$
\large \left ( u,v \right )
$$
适用于所有直线
$$
\large \left ( x-x_{0} \right )+b\left ( y-y_{0} \right )=0
$$
表示经过定点
$$
\large P\left ( x_{0},y_{0} \right )
$$
且与向量
$$
\large \left ( a,b \right )
$$
垂直的直线
适用于所有直线
$$
\large f\left ( x,y \right )-f\left ( x_{0}-y_{0} \right )=0
$$
表示过点
$$
\large \left ( x_{0},y_{0} \right )
$$
且与直线
$$
\large f \left ( x,y \right )=0
$$
平行的直线
]]>前几天收到大哥的礼物,一只罗技 G502 Lightspeed 鼠标,对这款鼠标不大了解。但使用一段时间后感觉这个宏定义还是蛮不错的,成功让我打造成了开发利器,快来看我的C-V大法
唉,可惜好景不长,没几天我就发现鼠标驱动软件出了问题。客服让我致电罗技售后,结果可想而知,无奈只好自己解决
刚刚接触的我,以为它就是需要加载,还在想是不是电脑配置较低引起的,后来发现根本不是……
关闭驱动后台服务项,管理员运行升级文件后重启驱动
“治标不治本”的方法——卸载重装
如果你像我一样也是刚刚接触罗技或者是小白,请参阅下方详细教程
下载直达
网络原因可能导致加载缓慢,备用下载地址,提取码:peng
首先确保是从官网下载的驱动软件,官方网站,进入产品支持主页
进入下载
找到 Logitech G HUB 驱动程序
选择合适的版本点击 Download Now下载,默认版本为 Windows 10
进入图示目录
修改①为管理员方式运行
然后按顺序①-③依次运行程序,失败请尝试下述解决方案
右键尝试启动,正常开启,重启驱动解决
若启动失败,请设置服务项自启动
等待片刻重启驱动解决
进入设置
打开自启
解决项目开发过程中添加的 .gitignore
规则不生效问题
其实这个问题很简单,主要是因为我们的项目不是在构建之前就加入了 ignore
规则,而是在某些文件已经纳入版本控制之后添加的规则,所以规则不生效
我们的解决方案也很容易理解,在本地清理下 git
的缓存,重新提交规则文件就能解决
git
终端,依次键入如下指令
$ 清理缓存 |
推荐
github
项目ignore
,提供多种ignore
文件模板
项目地址
# compile file |
这里以常用开发工具 idea 为例,我们可以在 idea 配置项中添加忽略文件,避免上传开发工具自带的文件
我们在上传项目时,肯定会有一些不需要上传到远程仓库的文件,idea工具的一些生成文件便是如此,例如:
显然这些东西不需要 push 到远程,我们直接 KO 掉
加入.idea
项后,push 的时候 git 就会忽略它了,而且项目中也没有了 idea 文件,非常地简洁
参考资料::
使用 SSH
方式拉取代码
大家在使用 git 拉取代码时,是否曾遇到过类似 OpenSSL SSL_read: Connection was reset, errno 10054 的报错信息,解决方案参考
大概率原因出在网络身上,为避免各种修改代理,本机 host 等繁琐操作,推荐大家使用SSH方式拉取代码。那么首先需要先完成SSH基本配置,下面是详细配置过程
如果你还不了解 git 中的一些基本知识,请参考这里
$ git config --global user.name "用户名" |
首先查看设备上是否已生成过秘钥对
$ cd ~/.ssh //进入指定路径文件夹 |
看一下有没有 id\_rsa
和 id_rsa.pub
等文件,.pub
文件是公钥,另一个文件是密钥
若没有这些文件,或没有 .ssh
目录,则使用 ssh-keygen
命令来创建
$ ssh-keygen -t rsa -C "你的邮箱" |
如有提示信息,点击 enter
即可,==不需要设置密码!== 难道你想在每次提交代码前输入一遍密码吗?
成功后会提示
Your public key has been saved in /home/you/.ssh/id_rsa.pub. |
进入指定路径 .ssh
文件夹中,用记事本打开 id_rsa.pub
,全选复制内容
也可通过指令查看
$ cat ~/.ssh/id_rsa.pub |
例如:
ssh-rsa your secret email@email.com |
下面以 GitHub 为例,演示相关操作过程
1.登陆 github 帐户,点击你的头像,然后 Settings -> SSH and GPG keys -> New SSH key
2、然后你复制上面的公钥内容,粘贴进 key
文本域内。 title
域,自己随便起个名字
3、点击 add key
完成以后,验证下这个key是不是正常工作:
$ ssh -T git@github.com |
如果,看到如下信息提示
Hi xxx! You've successfully authenticated, but GitHub does not # provide shell access. |
恭喜,配置成功!
使用命令 git remote \-v
查看你当前的 remote url
$ git remote -v |
如果是以上的结果那么说明此项目是使用 https
协议进行访问的;如果地址是 git
开头则表示是 git
协议
登陆你的 github
账户,查看项目仓库 ssh
协议的 URL
复制 ssh
链接,使用命令 git remote set-url
修改 remote-url
,例如:
git remote set-url origin git@github.com:username/project.git |
最后使用命令
git remote -v |
检测 URL
是否已修改为 SSH
地址
Git
中 push
报错
OpenSSL SSL_read: Connection was reset, errno 10054 ... |
Git Bash
中,push
时,出现错误
git push -u origin main |
1. 邮箱问题
查看用户名,邮箱
git config user.name |
修改,用户名,邮箱
git config --global user.name "xxx" |
移除仓库,重新添加
git remote rm origin |
2.解除SSL认证
在 Git Bash
中输入以下命令:
git config --global http.sslVerify "false" |
3.更新 DNS 缓存
cmd
窗口输入
ipconfig /flushdns |
4.文件过大,超过上限
修改为 500MB,在 Git Bash
中输入以下命令:
git config http.postBuffer 5242880003 |
多数情况下国内访问 Github
会被…,或因网络波动问题推送失败。推荐使用 SSH
方式拉去代码或者参考 开源项目 修改本机 hosts
文件解决访问问题
HelloGitHub 项目 开源镜像站
]]>打开 Git bash 工具
查看当前 git 版本信息
git --version |
输入命令
git update //旧版 |
等待完成即可
记录下第一个 pull request 被 merge 的过程
前些天在逛 Github 时,发现了一个有趣的项目 Github 漫游指南,其作者经验非常的丰富,用自己的亲身经历为我们讲述了如何使用 Github 以及如何找到好的项目,感兴趣的小伙伴可以阅读学习
因为我没有下载其他专门的格式去阅读,而是采用了 在线阅读 的方式,但在这过程中我发现了很多的问题,阅读体验很差劲
于是我便想为这个项目做些什么……
查阅了很多资料,最终我找到了 docsify,这样一款文档神器,以下介绍来自官方文档
docsify是一个神奇的文档网站生成器。他可以快速帮你生成文档网站。不同于GitBook、Hexo的地方是它不会生成静态的.html文件,所有转换工作都是在运行时。如果你想要开始使用他,只需要创建一个index.html就可以开始编写文档并直接部署在GitHub Pages 。
大家在使用命令
npm i docsify-cli -g |
全局安装 docsify-cli
工具时,如果你在安装 node.js
时修改了默认的路径: node_global
和 node_cache
,在运行全局安装命令之后可能会出错,这里需要找到默认的脚本 docsify.cmd
,将其路径添加到环境变量
避免后续系统无法识别 docsify
命令,其他的我们按照文档配置就好啦,如果需要完全卸载重新安装,请使用命令
npm uninstall -g docsify |
怎么样,是不是非常的简洁,有木有爱上读文档呢?大家感兴趣的话,可以点击这里在线阅读
首先 fork 仓库
然后 clone 到本地,推荐安装 github desktop 工具,点我下载,用本地编辑器打开
默认 vscode
创建一个新的分支,用于添加你想要实现的功能,这里我选择创建一个全新的 空分支,因为改动比较大,不用一步步删除
使用 git checkout
中 -orphan
参数:
git checkout --orphan emptybranch |
该命令会生成一个名为 emptybranch
的分支,该分支会包含父分支的所有文件。但新的分支不会指向任何以前的提交,无任何历史,你当前的提交将会成为该分支的首次提交记录
删除全部文件
git rm -rf . //结尾有 . |
若无任何文件提交,则无法查看分支,所以我们创建一个新的文件,然后提交
echo '# creat new branch' >> README.md |
push
到远程仓库,完成空分支的创建
git push origin emptybranch |
这里不做详细解释,主要以应用 docsify
为例介绍下 PR 过程,根据文档配置好本地环境
本地预览无误后发布分支,我们在 github desktop 中可以很轻易的完成
因为我已经提交过了,就不在回退展示
我们的空分支中已经实现了想要的功能,但是 git 中创建 PR 请求必须有一个父节点,否则会有(您所选的分支和想要合并分支间无任何关联)的类似提示,所以我们需要将这个空分支合并到仓库原来的分支上再做 PR
切换到 master 分支
git checkout master |
拉取远端的 master,保证最新
git pull origin master |
将空分支合并到 master
git merge emptybranch |
合并分支时可能会遇到这样的报错
fatal: refusing to merge unrelated histories |
主要是两个分支尚未取得联系
我们在操作的命令后加上 --allow-unrelated-histories
来解决这个报错,例如:
git merge emptybranch --allow-unrelated-histories |
其实你也可以直接建立 branch,无需建立空分支,从而省去解决
fatal: refusing to merge unrelated histories
错误的操作
现在返回网页端中你 clone 仓库的位置,就会有提示 Compare & Creat a pullrequest ,点击选中分支,记录下你实现的功能,确认无误提交后等待被仓库的主人合并就好啦
或者你也可以直接到源仓库地址找到 PR 入口,开始创建
这里放上 merge 后的截图,hah,我也非常感谢作者哈,PR address
在一个技术社区和其他开发者交流,就像写博客可以得到一些回应一样,我们都将不断进步,比昨天的自己更强一些
看到自己所做的东西被认可是一件很棒的事情,虽然我也只是用了其他的工具做了一些简单的修改罢了。总之,Github 上真的有很多有趣的事情,你也可以通过学习《Github 漫游指南》来找到一些自己喜欢的东西,开源大法是真滴好诶
]]>GitHub
对大家来说一定不陌生,无论是学习还是交
(爬)朋
(项)友
(目)。但是今天,我好像和它失联了……
当我像往常一样clone
项目时,却得到了这样的报错
$ git clone git@github.com:appletdevelop/full-stack.git |
什么都不能阻止打工人搬砖,必须要解决。经过一番排查,终于找到了问题的根源。分享两种解决方案,大家注意避坑。
因为错误信息显示 Connection refused
,所以我们需要去看看建立连接时发生了什么,为什么会出错。查看日志,果然发现端倪
$ ssh -vT git@github.com |
日志显示,IPv6
和 IPv4
的 localhost
地址分别为 ::1
和 127.0.0.1
,这意味着我们在连接 github
时,其域名将会被解析为 localhost
地址,当然也就无法连接。
打开查询网站,找到 github.com
的 IP
地址
Windows
下,打开本机 hosts
文件
C:\Windows\System32\drivers\etc
添加域名映射,并在 cmd
窗口刷新 DNS
配置
140.82.112.4 github.com |
重新拉取,成功。
从上面的报错信息中可以发现,重点在这一句
ssh: connect to host github.com port 22: Connection refused |
ssh
连接 GitHub
的 22
号端口被拒绝。但是 ping
一下 github.com
能通,浏览器访问也没有问题,那有可能是该端口被防火墙蔽掉了。既然 22
端口拒绝访问,我们不妨尝试使用 443
端口进行连接。
使用 vim
指令编辑 ssh
配置文件,添加以下端口信息
$ vim ~/.ssh/config |
测试访问是否成功,通常不出意外的话意外就来了……
$ ssh -T git@github.com |
这与 ssh
的运行机制有关,ssh
会将本机访问过的计算机的 public key
记录在 ~/.ssh/known_hosts
下。当下次访问相同计算机时,若公钥不同则会发出警告,避免受到攻击。这里只需要找到 known_hosts
文件中对应 ip
的 RSA
并删除便可解决。
再次测试,看到以下信息则表示访问成功
$ ssh -T git@github.com |
这样访问 GitHub
时,ssh
就会连接 443
端口,不会报错。
总结下本次踩坑的原因,主要有两点:
DNS
解析;总之:“网上冲浪也要注意暗礁,低头走路也要抬头看路”,以上就是本期分享啦,希望可以帮到您!
]]>在介绍鸿蒙系统前,我们有必要了解下鸿蒙系统应运而生的时代背景。近年来,我国在电子信息技术领域中愈发觉需要“独立”,资源的匮乏,人才的稀缺正是当务之急
犹记得前段时间网络上流传着这样的言论:华为终端设备存在通信安全的威胁,终端系统存在 ”后台” ,这样的情况下,我们就更需要用实力证明自己。于是,2021年6月2日,华为正式公布了其自主研发的操作系统—HarmonyOS,也就是鸿蒙
发布会上,令我印象最深刻的莫过于HarmonyOS万物互联、分布式的强大特性以及其Feature Ability(元服务)的用户界面展现形式,这使得它与用户的交互更加流畅、简洁、方便。下面我们就来细品HarmonyOS的 “服务卡片” 功能
在此之前呢,我们不得不去了解下与 “服务卡片” 有着密切关系的原子化服务。原子化服务是由HarmonyOS 提供的一种面向未来的服务提供方式,它拥有独立、非驱动、轻便(无需安装)等特性,旨在为用户提供一种效率极佳的服务方式
它具有随处可见、跨设备、服务直达等特性:
(1)服务发现:原子化服务可在服务中心发现并使用;
(2)智能推荐:原子化服务可以基于合适场景被主动推荐给用户使用;用户可在服务中心和小艺建议中发现系统推荐的服务;
(3)服务卡片:支持用户无需打开原子化服务便可获取服务内重要信息的展示和动态变化,如天气、关键事务备忘、热点新闻列表;
(4)支持跨设备分享:例如接入华为分享后,用户可分享原子化服务给好友,好友确认后打开分享的服务;
(5)支持多端协同:例如手机用作文档翻页和批注,配合智慧屏显示完成分布式办公;手机作为手柄,与智慧屏配合玩游戏;
相信不少朋友第一次听到 “服务卡片” 这个词汇,都会在想:这不就是我手机屏幕上的 “小组件” 吗?哎!你还别说,它们之间还真有不同之处,但又有异曲同工之妙
首先呢,大家可以回想一下我们日常使用电子产品的操作习惯,我们在使用小组件的时候:比如在主屏幕上新添加一个 “照片” 的小组件,这个小组件可以实现不定期的自动更换、主题筛选、人物分类等等这些功能。那么如你恰巧看到了一张非常感兴趣的照片,想要查看它,是不是需要点击照片进入详情查看呢?这样的交互方式相信大家都非常了解。但是你是否思考过,它可以更加地 “人性化”,更加 ”懂你“ 呢?
没错,这就是HarmonyOS,它做到了。在鸿蒙的设计中,服务卡片的引入是与以往EMUI最大的不同,在屏幕上我们只需要找到图标下方有 “小横线” 的app,当然,这些也正是那些支持HarmonyOS的app。我们只需要在图标位置处,轻轻上划,就能呼出相对应的应用卡片,这些卡片还可以实现自定义大小 、固定在主屏幕等功能
相较于封闭式的IOS系统来说,我个人认为就是把3DTouch功能变得不需要 ”3D“ 了,无需用力,仅需轻扫。 又更像是小组件的父类,承接其外。这样的设计方式在使用上显得尤为灵活,并不需要在特定的位置才能使用。可以这么说,只要你屏幕放得下,随便你怎么用
开发者们可以为这些服务卡片 ”量体裁衣“,定制特有的功能,提高日常使用效率。在子菜单能力的加持下,像我们日常使用的某宝支付,打开地铁卡根本无需进入app,只要 “蹦” 出来一张小卡片方可实现功能。这是我们不得不惊叹:这是多么快捷、高效的交互体验啊!
在服务卡片的开发过程中有三者参与,分别是卡片提供方、卡片使用方和卡片管理服务,它们之间相互作用,共同维持着便捷功能的实现
HarmonyOS Developer中我们可以了解到这三者的分工:
提供卡片显示内容的HarmonyOS应用或原子化服务,控制卡片的显示内容、控件布局以及控件点击事件
由卡片提供方开发者实现,开发者实现onCreateForm、onUpdateForm和onDeleteForm处理创建卡片、更新卡片以及删除卡片等请求,提供相应的卡片服务
由HarmonyOS SDK提供,负责与卡片管理服务通信,用于将卡片的更新数据主动推送到卡片管理服务
由卡片提供方开发者实现,负责对卡片管理服务分配的卡片实例进行持久化管理
显示卡片内容的宿主应用,控制卡片在宿主中展示的位置
用于管理系统中所添加卡片的常驻代理服务,包括卡片对象的管理与使用,以及卡片周期性刷新等
在卡片使用方和提供方需要添加/删除/请求更新卡片时,卡片管理服务会拉起卡片提供方获取卡片信息
负责与卡片使用方和提供方进行RPC通信
在卡片添加后,根据卡片的刷新策略启动定时任务周期性触发卡片的刷新
在卡片添加到卡片管理服务后,对卡片的视图信息进行缓存,以便下次获取卡片时可以直接返回缓存数据,降低时延
对于卡片切换到后台或者被遮挡时,暂停卡片的刷新;以及卡片的升级/卸载场景下对卡片数据的更新和清理
对卡片使用方的RPC对象进行管理,用于使用方请求进行校验以及对卡片更新后的回调处理
有关JDK的环境配置,请参考博主前不久的文章。安装好之后,我们到华为官网下载DevEco Studio(官方IDE),无需更改,选择默认配置即可。由于没有具体项目开发,此处不再放置源码,后续学习中将不断更新,还请多多关注,下面实现华为穿戴设备—智能手表中 Hello World 的输出
新建项目
至少选择一个类型
进入之后显示如下界面
单击运行显示 Hello World
简单的鸿蒙版 Hello World 到这里就完成啦,还不赶快动手试试
]]>服务器 快到期了,这几天迁移到 GitHub
上,用免费的 GitHub Pages
重新部署下 杰森的博客 。以下样式及优化配置基于 Hexo
,主题 Next
本文最具价值的配置莫过于此,没有用到 GitHub Actions
前,每次发文需要将 markdown
文件放入 _post
文件夹下,然后执行 hexo clean && hexo g && hexo s && hexo g
一连串命令,执行无报错还好说,万一本地环境出现错误,还得花时间找错,非常麻烦
使用 GitHub Actions
后,发文只需要在博客的源文件仓库中拖拽源文件或者 push
源文件到仓库,GitHub Actions
即可监测仓库状态,自动执行部署操作到指定位置,不必担心本地环境出错等系列问题
效果 预览地址
有关介绍和详细令牌、密钥配置请 参考此处,以下主要是 .github/workflows/deploy.yml
文件 的配置
# Action's Name |
在配置完令牌及密钥后,可以直接复制 该文件 使用,如果仅需要同步 Github
,则不必配置 Gitee
同步字段配置
杰森的仓库分布是
https://github.com/PDPENG/MyBlog 私有仓库 (actions 部署位置) |
配置完成后,GitHub Actions
一旦检测到 MyBlog
仓库下的变动后,将会自动部署至 pdpeng.github.io
仓库
这里默认您已经添加了
RSS
相关插件,站点已具备生成atom.xml
文件能力
效果图,预览地址
将下面的代码
<html> |
插入到 MyBlog\themes\next\layout\_partials\sidebar\site-overview.njk
文件图示位置中
效果图,预览地址
Next
最新版的主题,没有找到引用阿里巴巴图标库的方法(总提示请求无效),如果你有不错的解决方案,欢迎评论区留言
这里给出一个和 CSDN
比较类似的图标
social: |
这个比较简单,在头像的位置添加 <a></a>
标签就好。可能定位比较麻烦,文件位置是 MyBlog\themes\next\layout\_partials\sidebar\site-overview.njk
{%- if theme.avatar.url %} |
效果图,预览地址
文件位置是MyBlog\themes\next\source\css\_schemes\Muse\_sidebar.styl
,找到 a
标签的 css 样式,添加 border-bottom 0px;
即可
效果图,预览地址
如果你的站点开启了侧边栏 始终显示,在进行下述操作后,请隐藏侧边栏后查看效果
图示路径下
加入这段代码
<script src="/live2d-widget/autoload.js"></script> |
然后在主题配置文件末尾加入下列配置项
# 自定义看板娘 https://github.com/PDPENG/live2d-widget |
效果即可显示
如果你需要更高级的自定义,可继续完成下面的配置
切换到主题的 source
文件夹下,克隆项目到本地(删除项目 .git
文件,避免推送报错),项目地址
git clone https://github.com/stevenjoezhang/live2d-widget |
*注意:live2d_path
参数应使用 绝对路径
更多自定义配置参见,live2d-widget 自定义配置
效果图,预览地址
之前部署在服务器时,站点是配置了 404
页面的,但是在 Github Pages
中只有访问 /404
时,才能定向到页面,并不能实现真正的 404
效果
查看了官方文档后,实现也比较容易,只需要在站点资源文件夹(source
目录下)添加 404.md
或 404.html
即可
下面放上杰森的页面配置,供大家参考
--- |
效果图,预览地址
主题配置文件中,该字段配置,详情参考 Math Equations
# Math Formulas Render Support |
如依照上述配置,日后发文请在需要加载数学公式渲染文章的 front-matter
处添加 mathjax: true
。例如
效果图,预览地址
部署完成后,发现本地搜索功能失效,直接 访问站点 search.xml
浏览器显示
这里在保证插件配置正常的前提下,给出排除字符错误的解决方案
我们将 search.xml
保存到本地用 vscode
打开,根据浏览器报错的行、列指示,发现字符转义错误。在文章页面下删除该类字符后重新部署,搜索功能恢复
效果图,预览地址
路径如图,按需修改
效果图,预览地址
hexo
的根目录,然后在 package.json
中添加依赖: "hexo-tag-cloud": "2.1.*"
npm install
命令打开路径 next/layout/_macro/sidebar.swig
,添加如下配置
{% if site.tags.length > 1 %} |
hexo clean && hexo g && hexo s
来进行本地预览, hexo clean 为必须选项。hexo g -d 或者 hexo d -g
这类组合命令,详见项目地址及详细教程参考
效果图,预览地址
当我们为项目配置 README.md
文件时,发布后会发现文件会被 hexo
转义成 .html
文件,详见 Hexo 配置
这里以站点添加中英双语介绍文件为例,将项目 README.md
及 EN.md
放在 source
目录下
然后在图示位置根据 glob
语法规则添加值即可
这样 hexo
就不会渲染匹配到的文件,显示正常
参考资料:
本篇内容主要讲述如何在 idea 和 eclipse 开发工具中配置 Tomcat,记录一些踩坑的地方,帮大家避坑,节约时间
首先,你的电脑中应该默认配置好 java 的开发环境,没有配置的朋友请参考这里
Tomcat是由Apache软件基金会属下Jakarta项目开发的Servlet容器,按照Sun Microsystems提供的技术规范,实现了对Servlet和JavaServer Page(JSP)的支持,并提供了作为Web服务器的一些特有功能,如Tomcat管理和控制平台、安全局管理和Tomcat阀等。由于Tomcat本身也内含了HTTP服务器,因此也可以视作单独的Web服务器。但是,不能将Tomcat和Apache HTTP服务器混淆,Apache HTTP服务器是用C语言实现的HTTPWeb服务器;这两个HTTP web server不是捆绑在一起的。Apache Tomcat包含了配置管理工具,也可以通过编辑XML格式的配置文件来进行配置。(源 : Wikipedia)
总结来说就是免费、开源、轻量的 Web 服务器
这里建议,不要下载最新版!!
大家也可以根据开发环境选择合适的版本
官网地址,找到图示位置下载
下载后解压,放到合适位置(记住路径,后面需要用)
打开系统环境变量,添加表中两项,变量值为 tomcat 文件路径
变量 | 值 |
---|---|
CATALINA_HOME | C:\IDE\apache-tomcat-8.5.77 |
CATALINA_BASE | C:\IDE\apache-tomcat-8.5.77 |
继续打开 Path
变量,追加两项,注意 ;
分隔
%CATALINA_HOME%\lib
%CATALINA_HOME%\bin
在 tomcat 安装目录 bin
目录下,打开终端,运行指令
$ 安装 tomcat 服务 |
Win+R
执行 services.msc
打开服务窗口,修改 tomcat 启动方式为自动
可以在安装目录下启动 tomcat8w.exe
程序控制/查看运行状态
访问 http://localhost:8080/
网址,显示图示页面即配置成功
此部分操作不建议初次上手直接操作,请在实际需求中进行更改,初次配置可略过该项
在实际开发中可能会遇到默认 128MB 内存不够用的情况,我们需要调大默认容量
打开图示路径
打开后搜索 JAVA_OPTS
,将默认位置内容修改为 JAVA_OPTS='-Xms256m - Xmx512m'
,表示初始化内存为 256MB,可用最大内存为 512MB
进入图示目录,打开 tomcat-users.xml
文件
搜索 username
,在 password
处设置密码
一般情况下,我们如果在使用 tomcat 时,打开的文件以中文命名或超链接中下载含中文名,会出现乱码,这时我们修改下对应配置文件解决该问题
打开图示文件
定位到 Connector port ...
位置处添加 URLEncoding="UTF-8"
即可
新建 Java 项目
添加项目路径
添加 web 框架支持
选择 web 标准
查看当前的项目结构
目录文件解释:
编辑项目配置
添加 Tomcat Server
,选择第一个,注意区分版本,否则会有警告信息
选中安装路径,IDE 自动识别版本号、端口号等信息
部署信息
设置项目名称,此处如果配置,那么访问的 URL 则为 http://localhost:8080/[项目名]/...
;若设置为 /
,则访问的 URL 为 http://localhost:8080/...
==建议配置,以免每次系统默认生成的名字造成 Tomcat 访问报 404 错误==
其他信息配置
此时,一个 web 项目的基本配置完成
启动服务
执行信息
打开浏览器访问(执行成功可以自动跳转) http://localhost:8080/
发布成功!
打开首选项
向下滑找到 Server
选择匹配的 tomcat 版本
细节配置
保存退出
文件 -> 新建
配置项目信息
java 类源文件位置,默认就好
单击 finish 完成创建
首先打开 Servers
面板
定义服务
点击 Next
,选中服务名称添加
在 webapp 目录下新建一个 .jsp
文件
写入测试程序(记得保存),测试服务状态
<%-- |
启动服务
可以在 Console
面板下查看到执行信息
浏览器地址栏输入 http://localhost:8080/test/test.jsp
即可访问
文件 test/test.jsp : 第一个 test 即为上述 Web Module 处设置的 Context root 名称
其实花了这么多时间我是比较意外的,最后发现本地 java 版本太多,一开始没有去仔细配置好对应的版本,太过于依赖 IDE
安装 tomcat 时也是首先去进行了 优化配置 像设置缓存、配置密码这些,其实我们首先应该让项目跑起来,日后再去不断提升安全性之类的问题
遇到问题,我们也要学着不断总结,不断试错,不论多么小的错误都不要轻视。因为这点点滴滴都是经验的不断积累。今天错了,日后保证不再出错,效率才会不断提升。遇到问题欢迎大家留言讨论,加油!!
参考资料:
在使用IDEA的时候,忽然发现打开项目变成了这样
怎么点击都无法打开项目结构,只能显示默认的配置文件夹和输出文件夹
非常疑惑,项目结构去了哪里,不能是整个文件丢失了吧,这不白给了嘛,一整个白忙活
还好找到了解决办法,快来一起看看吧
左上角依次找到file->project structure->modules-> +号->import modules,选择导入的项目文件
选择这两项
最后点击 Finish就显示出来啦!
不说了,赶紧码代码去了~~
]]>👲👲作者主页:🔗杰森的博客
📒📒本文摘要:Idea 开发常用快捷键总结,祝你一臂之力,不加班!
💖💖感觉本文不错的话,还请各位小伙伴👍点赞➕收藏⭐➕评论💭支持杰森呀✌️
快捷键 | 含义 |
---|---|
Ctrl+Shift + Enter | 语句完成 |
! | 否定完成,输入表达式时 “!”键 |
Ctrl+E | 最近文件 |
Ctrl+Shift+E | 最近更改的文件 |
Shift+Click | 关闭文件 |
Ctrl+[ OR ] | 可以跑到大括号的开头与结尾 |
Ctrl+F12 | 显示当前文件的结构 |
Ctrl+F7 | 查询当前元素在当前文件中的引用,按 F3 可以选择 |
Ctrl+N | 快速打开类 |
Ctrl+Shift+N | 快速打开文件 |
Alt+Q | 可以看到当前方法的声明 |
Alt+Q | 可以看到当前方法的声明 |
Ctrl+P | 可以显示参数信息 |
Ctrl+Shift+Insert | 可以选择剪贴板内容并插入 |
Alt+Insert | 可以生成构造器/Getter/Setter等 |
Ctrl+Alt+V | 可以引入变量。例如:new String(); 自动导入变量定义 |
Ctrl+Alt+T | 可以把代码包在一个块内 例如:try/catch |
Ctrl+Enter | 导入包,自动修正 |
Ctrl+Alt+L | 格式化代码 |
Ctrl+Alt+I | 将选中的代码进行自动缩进编排,这个功能在编辑 JSP 文件时也可以工作 |
Ctrl+Alt+O | 优化导入的类和包 |
Ctrl+R | 替换文本 |
Ctrl+F | 查找文本 |
Ctrl+Shift+Space | 自动补全代码 |
Ctrl+空格 | 代码提示(与系统输入法快捷键冲突) |
Ctrl+Shift+Alt+N | 查找类中的方法或变量 |
Alt+Shift+C | 最近的更改 |
Alt+Shift+Up/Down | 上/下移一行 |
Shift+F6 | 重构 – 重命名 |
Ctrl+X | 删除行 |
Ctrl+D | 复制行 |
Ctrl+/或Ctrl+Shift+/ | 注释(//或者/**/) |
Ctrl+J | 自动代码(例如:serr) |
Ctrl+Alt+J | 用动态模板环绕 |
Ctrl+H | 显示类结构图(类的继承层次) |
Ctrl+Q | 显示注释文档 |
Alt+F1 | 查找代码所在位置 |
Alt+1 | 快速打开或隐藏工程面板 |
Ctrl+Alt+left/right | 返回至上次浏览的位置 |
Alt+left/right | 切换代码视图 |
Alt+Up/Down | 在方法间快速移动定位 |
Ctrl+Shift+Up/Down | 向上/下移动语句 |
F2 或 Shift+F2 | 高亮错误或警告快速定位 |
Tab | 代码标签输入完成后,按 Tab,生成代码 |
Ctrl+Shift+F7 | 高亮显示所有该文本,按 Esc 高亮消失 |
Alt+F3 | 逐个往下查找相同文本,并高亮显示 |
Ctrl+Up/Down | 光标中转到第一行或最后一行下 |
Ctrl+B/Ctrl+Click | 快速打开光标处的类或方法(跳转到定义处) |
Ctrl+Alt+B | 跳转到方法实现处 |
Ctrl+Shift+Backspace | 跳转到上次编辑的地方 |
Ctrl+O | 重写方法 |
Ctrl+Alt+Space | 类名自动完成 |
Ctrl+Alt+Up/Down | 快速跳转搜索结果 |
Ctrl+Shift+J | 整合两行 |
Alt+F8 | 计算变量值 |
Ctrl+Shift+V | 可以将最近使用的剪贴板内容选择插入到文本 |
Ctrl+Alt+Shift+V | 简单粘贴 |
Shift+Esc | 不仅可以把焦点移到编辑器上,而且还可以隐藏当前(或最后活动的)工具窗口 |
F12 | 把焦点从编辑器移到最近使用的工具窗口 |
Shift+F1 | 要打开编辑器光标字符处使用的类或者方法 Java 文档的浏览器 |
Ctrl+W | 可以选择单词继而语句继而行继而函数 |
Ctrl+Shift+W | 取消选择光标所在词 |
Alt+F7 | 查找整个工程中使用地某一个类、方法或者变量的位置 |
Ctrl+I | 实现方法 |
Ctrl+Shift+U | 大小写转化 |
Ctrl+Y | 删除当前行 |
Shift+Enter | 向下插入新行 |
psvm/sout | main/System.out.println(); Ctrl+J,查看更多 |
Ctrl+Shift+F | 全局查找 |
Ctrl+F | 查找/Shift+F3,向上查找/F3,向下查找 |
Ctrl+Shift+S | 高级搜索 |
Ctrl+U | 转到父类 |
Ctrl+Alt+S | 打开设置对话框 |
Alt+Shift+Inert | 开启/关闭列选择模式 |
Ctrl+Alt+Shift+S | 打开当前项目/模块属性 |
Ctrl+G | 定位行 |
Alt+Home | 跳转到导航栏 |
Ctrl+Enter | 上插一行 |
Ctrl+Backspace | 按单词删除 |
Ctrl+”+/-” | 当前方法展开、折叠 |
Ctrl+Shift+”+/-” | 全部展开、折叠 |
快捷键 | 含义 |
---|---|
Ctrl+F2 | 停止 |
Alt+Shift+F9 | 选择 Debug |
Alt+Shift+F10 | 选择 Run |
Ctrl+Shift+F9 | 编译 |
Ctrl+Shift+F10 | 运行 |
Ctrl+Shift+F8 | 查看断点 |
F8 | 步过 |
F7 | 步入 |
Shift+F7 | 智能步入 |
Shift+F8 | 步出 |
Alt+Shift+F8 | 强制步过 |
Alt+Shift+F7 | 强制步入 |
Alt+F9 | 运行至光标处 |
Ctrl+Alt+F9 | 强制运行至光标处 |
F9 | 恢复程序 |
Alt+F10 | 定位到断点 |
Ctrl+F8 | 切换行断点 |
Ctrl+F9 | 生成项目 |
Alt+1 | 项目 |
Alt+2 | 收藏 |
Alt+6 | TODO |
Alt+7 | 结构 |
Ctrl+Shift+C | 复制路径 |
Ctrl+Alt+Shift+C | 复制引用,必须选择类名 |
Ctrl+Alt+Y | 同步 |
Ctrl+~ | 快速切换方案(界面外观、代码风格、快捷键映射等菜单) |
Shift+F12 | 还原默认布局 |
Ctrl+Shift+F12 | 隐藏/恢复所有窗口 |
Ctrl+F4 | 关闭 |
Ctrl+Shift+F4 | 关闭活动选项卡 |
Ctrl+Tab | 转到下一个拆分器 |
Ctrl+Shift+Tab | 转到上一个拆分器 |
快捷键 | 含义 |
---|---|
Ctrl+Alt+Shift+T | 弹出重构菜单 |
Shift+F6 | 重命名 |
F6 | 移动 |
F5 | 复制 |
Alt+Delete | 安全删除 |
Ctrl+Alt+N | 内联 |
快捷键 | 含义 |
---|---|
Ctrl+F | 查找 |
Ctrl+R | 替换 |
F3 | 查找下一个 |
Shift+F3 | 查找上一个 |
Ctrl+Shift+F | 在路径中查找 |
Ctrl+Shift+R | 在路径中替换 |
Ctrl+Shift+S | 搜索结构 |
Ctrl+Shift+M | 替换结构 |
Alt+F7 | 查找用法 |
Ctrl+Alt+F7 | 显示用法 |
Ctrl+F7 | 在文件中查找用法 |
Ctrl+Shift+F7 | 在文件中高亮显示用法 |
Alt+left/right | 向后、前 |
Ctrl + H | 看类结构 |
Ctrl+z | 后退 |
快捷键 | 含义 |
---|---|
ctr + y | 删除 |
ctr + D | 复制 |
快捷键 | 含义 |
---|---|
ctrl+ space | 提示 |
ctrl + shift + space | 智能提示 |
ctrl + shift + enter | 完成当前语句 |
ctrl + alt + P | 建议提示为参数 |
ctrl + alt + L | 对代码重新排列格式 |
ctrl + alt + O | 对imports进行优化 |
快捷键 | 含义 |
---|---|
F2 / Shift + F2 | 定位到下一个或上一个错误 |
ctr+G (定位到文件行数) | 定位文件头 |
ctr+G | 定位文件尾 |
ctr + [ | 定位到代码块开始 |
ctr + ] | 定位到代码块结束 |
F12 | 回到最近的窗口 |
alt + left | 回到之前的文件 |
alt + right | 回到之后的文件 |
Ctrl + Shift + Backspace | 定位到最后编辑位置 |
esc | 从tool window或其他window切换到文件编辑 |
shift + esc | 关闭最近打开的窗口 |
快捷键 | 含义 |
---|---|
ctr + N | 查找类 |
Ctrl + Shift + N | 查找文件 |
Ctrl + Alt + Shift + N | 符号定位 |
ctrl + F12 | 查看文件结构 |
ctr + E | 最近打开的文件 |
alt + down | 定位下一个方法 |
alt + up | 定位上一个方法 |
ctr + p | 查看方法参数信息 |
ctr + Q | 查看方法、类的doc |
快捷键 | 含义 |
---|---|
ctr + B | 跳到类或方法的声明 |
ctr + U | 定位到类的父类、接口 |
ctr + H | 查看类的继承结构 |
ctr + shift + H | 查看方法的继承结构 |
ctr + alt +H | 查看类或方法被调用情况 |
ctrl + shift + I | 原地参看类、方法的声明 |
快捷键 | 含义 |
---|---|
Ctrl + F9 | Make项目(编译、修改和依赖) |
Ctrl + Shift + F9 | 编译选定的文件、包或模块 |
Alt + Shift + F10 | 选择配置并运行 |
Alt + Shift + F9 | 选择配置和调试 |
Shift + F10 | 运行 |
Shift + F9 | 调试 |
Ctrl + Shift + F10 | 从编辑器运行上下文配置 |
快捷键 | 含义 |
---|---|
F8 | 跳过 |
F7 | 进入 |
Shift + F7 | 自动进入 |
Shift + F8 | 跳出 |
Alt + F9 | 运行到光标 |
Alt + F8 | 计算表达式 |
F9 | 恢复程序 |
Ctrl + F8 | Toggle breakpoint |
Ctrl + Shift + F8 | 查看断点 |
这么详细的总结,记得收藏备用哟
我们在配置好 Tomcat 服务后(详见此处),总是会在控制台看到类似于这样的信息
显然,这是发生了乱码,虽然不影响正常的项目调试,但是看着非常的难受,下面让我们一招来解决这个问题
控制台输出信息
12-Apr-2022 15:45:44.180 璀﹀憡 [main] org.apache.catalina.startup.SetAllPropertiesRule.begin [SetAllPropertiesRule]{Server/Service/Connector} Setting property ‘URLEncoding’ to ‘UTF-8’ did not find a matching property.
12-Apr-2022 15:45:44.213 淇℃伅 [main] org.apache.catalina.startup.VersionLoggerListener.log Server.鏈嶅姟鍣ㄧ増鏈�: Apache Tomcat/8.5.77
12-Apr-2022 15:45:44.213 淇℃伅 [main] org.apache.catalina.startup.VersionLoggerListener.log 鏈嶅姟鍣ㄦ瀯寤�: Mar 13 2022 19:13:33 UTC
12-Apr-2022 15:45:44.213 淇℃伅 [main] org.apache.catalina.startup.VersionLoggerListener.log 鏈嶅姟鍣ㄧ増鏈彿: 8.5.77.0
12-Apr-2022 15:45:44.213 淇℃伅 [main] org.apache.catalina.startup.VersionLoggerListener.log 鎿嶄綔绯荤粺鍚嶇О: Windows 10
……
找了很多的解决方案,但是日志文件和控制台信息只能解决一个,不能兼得,下面给出最佳方案
1.打开 Tomcat 安装目录并找到 conf 文件夹
2.用记事本打开 conf 文件夹下的 logging.properties 文件
3.将文件中所有的 UTF-8 修改为 GBK 并保存
重启 Idea 再次调试,查看控制台信息
乱码情况已解决
]]>开始链接前,请确保本机上安装的 idea 是 Ultimate 专业版,点我下载,JetBrains 旗下 Community 社区版本并未集成数据库开发工具,这一点我们从官网两个版本的下载介绍上也能看到
一般来说,安装V5左右的版本就足够,版本号越大占用后台资源会更多,我们根据实际开发需求,选择合适的就好,这里演示 5.7 版本的安装过程(其他版本基本一致,按钮位置可能有所不同)
进入官方网站后,点击 Looking for previous GA versions 切换到早期版本
在线安装就看你的网速质量了,第二个是完整安装文件,直接下载就好(如果需要验证,登陆 Oracle 账号校验即可)
详细的安装教程请看这里,这里主要讲下配置过程
右键【此电脑】->【属性】->【高级系统设置】->【环境变量】
添加MYSQL_HOME变量,变量值为电脑 MySQL 的安装位置
添加 Path 系统变量
my sql -uroot -p //root表示用户名,-p表示输入用户密码 |
输入安装 MySQL 时的账户密码,出现图示信息则配置正确
以管理员身份打开命令行,分别输入以下命令
net start mysql //开启服务 |
net stop mysql //关闭服务 |
建立项目后,添加 MysQL数据源
找到驱动路径
引入外部库中
成功后,项目结构中也会显示
添加属性
方式1:可视化,图形界面操作
方式2:sql 语句添加
执行结果
请根据注释位置,修改配置信息后再 Execute 执行
import java.sql.*; |
测试类执行结果
参考资料:
MySQL的详细安装教程
Mysql启动后停止的解决方法
MySQL修改root密码的4种方法
姓名 性别 密码等在mysql中都保存为什么类型
通过IntelliJ IDEA软件实现Java项目连接MySQL的详细过程
天气APP图标更新
锁屏界面 “相机” 图标更新
控制中心 “声音识别” 图标更新
iPhone关机信息提示:iPhone关机后仍可被找到,可以临时禁用该功能
Apple在照片、地图、提醒事项等应用中添加了介绍提示,展示新功能
点击下方链接(来源于网络),在自带的Safari浏览器中打开,选择“允许”,下载描述文件。根据提示完成安装,重启设备后在设置中检查更新就可以看到更新推送啦!
升级通道
毕竟是第一个版本,还是会有一定风险的,升级前最好全备份,万一有问题也能回退
现在的测试版基本趋于稳定,表现良好,预计马上就会推出正式版,等不及的小伙伴们 beat 7 这个版本还是值得一试的(2021.8.27)
不定期更新,欢迎讨论!!!
文章部分图片源于网络,侵删致歉
]]>Java是印度尼西亚“爪哇岛”的英文名,因气候环境,地理位置等因素盛产咖啡而闻名。Java语言中的许多命名都与其有关:如JavaBeans。所以Sun和Java的Logo是个非常形象的图标—冒热气儿的咖啡
早期的Java只是Sun MicroSystems公司在1990年12月开始研究的一个内部项目。Sun公司一位名为帕特里克·诺顿的工程师因为其公司难于操作的C++/C语言编译器而决定改用NeXT,同时他也获得了研究公司的一个叫做“Stealth计划”的项目的机会
“Stealth计划”后来改名为“Green计划”,詹姆斯·高斯林和Mike Sheridan也加入了帕特里克的工作小组。根据有限资金,乔伊决定开发一种集C语言和Mesa语言大成的新语言,在一份报告上,乔伊把它叫做“未来”。他将要创造出一种全新的语言,被他命名为“Oak”,以办公室外的橡树命名
(1)标识符包含类名、变量名、常量名、方法名…;
(2)命名规则:字母、下划线、美元符号开头,后可接此三种符号或0-9的数字,注意不要和关键字 重合;
(3)命名“约定”:变量名、方法名首单词小写,其余单词仅首字母大写。类名、接口名首字母大写
常量全都用大写字母、单词命名,下划线常用于常量名单词的分隔。Java严格区分字母大小写,例如aB和Ab是完全不同的合法标识符;
重点标记一些Java中特有的关键字:
(1)数据类型:boolean、byte、char、double、false、true、void、instanceof、float、int、long、new、null、short;
(2)语句:break、case、catch、continue、、return、super、switch、this、throw、try、while、default、do、else、finally、for、if;
(3)修饰:abstract、final、native、transient、volatile、private、protected、public、static、synchronized;
(4)方法、类、接口、包:interface、import、class、extends、 implements、package、throws;
一些不能用做自定义标识符,但又有自己专门用途和意义的 “ 关键字 ” ;形象的来讲就是他们没有成为关键字的权利,但是有享受关键字的“待遇”,像是充值VIP一般,sizeof、goto、const,它们仨就是VIP中的成员。说不定随着语言的发展,慢慢它们也成为关键字了呢?
像C/C++中熟知的空白符(Tab、回车、空格、换行)、普通分隔符(点、分号、逗号……)、单行注释符 // 注释内容
,多行注释符 /* 注释内容 */
就不再详细展开来讲,这里我们主要了解Java中一些不一样的东西—Java文档注释格式,它的格式是/ * *注释内容 * /
注意:这类注释只应用在声明之前,最为方便的是它可以利用JDK中提供的 javadoc 工具,根据注释内容自动生成HTML代码说明文档
那么,何为数据类型或者说数据类型能说明什么呢?它存在的意义就是:表明变量、常量、表达式的性质。在进行运算时,只有符合“相同数据类型”这一条件,才可以继续进行。按照大类区分,Java中有简单、引用两种数据类型。分类如图所示
在使用计算机进行运算时,我们都知道不同的数据类型在其中表示的数值范围、所占内存大小都不相同,下表给出了Java基本数据类型的具体参数
表中,我们仍能对这些数据类型进行划分,比如byte、short、int、long、float、double属于数值型数据,char、boolean属于非数值型数据。Java因其基本数据类型拥有固定长度的特性,而促成了其基本数据类型优良的跨平台移植属性,数值类型的数据都与系统无关
变量是程序中存储单元的标识符,它代表内存中的一块空间。在Java中,变量还具有类型、名称、值、作用域等属性
遵循命名规则:
(1)长度不限,但系统仅承载前32个字符,变量名必须以小写字母开头,且首字符不能为数字;
(2)在同一作用域内,变量名必唯一且区分大小写;
(3)不能是关键字,布尔值或保留字(null);
(4)若多个单词构成变量名,则单词需要连在一起写,且除第一个单词外,其余单词首字母需大写;
两种声明格式:
int a,b,c; |
变量声明后,使用赋值语句进行初始化:
varName1 = [ varName2 = ] 表达式 ; |
允许同时给多个变量赋值:
类型 varName1 = 表达式1 [ , varName2 = 表达式2 ] ; |
变量在声明的同时进行初始化:
类型 变量名=表达式; |
注意:除可以进行自动类型转换的数据外,变量的赋值需要“=”号两边的数据类型一致
变量要先定义后使用,变量定义所在的位置决定了变量的作用域,根据变量定义所处位置,其作用域可以分为:局部变量、类成员变量、方法参数变量、异常处理参数变量
public class TypeDefinition { |
当数值在不同的数据类型之间进行运算时,需要转换为统一类型来进行,不同数据类型之间有对应的转换规则。可以分为 “ 自动类型转换 ” 和 “ 强制类型转换 ” 两种
自动类型转换也称 “ 隐式类型转换 ” ,即编码是不需要程序员操作,系统会自动进行类型转换,一般遵循低精度可以自动转换到高精度的规则
但是,如果数据由高精度转换成低精度呢?那么我们就需要进行强制类型转换
强制转换的格式为:
(数据类型)表达式 ; |
注意:根据变量所占位长的不同,在强制类型转换中可能发生数据丢失的现象,使用需谨慎。下面展示强制转换后数据丢失的例子:
public class TypeConversion { |
常量是在程序中直接给出的一系类符号串,它的作用是为变量赋值或参与表达式的运算。可以是一个具体的数值或字符串。常量在程序执行过程中不可更改
常量标识符命名全部由大写字母组成,多个单词之间使用下划线进行连接,eg:Largest_Integer
可以使计算机表示某个整数值,十进制、十六进制和八进制类型数据。八进制常量以 0 开头,后接 0 - 7 之间的数字(这里常常会设置一些考题,比如问:089 是什么数?千万别傻傻的写八进制数了,它是非法数)。十六进制常量以0x开头后跟多个 0 - 9之间的数字或 a - f ( A - F )之间的字母
byte、short、int、long这四种类型是较为特殊的数据类型。byte 和 short类型主要应用于底层文件处理或在存储空间极其宝贵、又需要保存大型数组的特殊情况。long类型可表示数值较大的整数。int类型是最常用的,默认32位,若需要表示64位的long类型常量则在数字后加上大写字母 L 来区分
两种表示形式:
(1)十进制数:由数字和小数点构成,且必须包含小数点;由于实数表示精度不同(单精度、双精度)。Java中默认实型常量为计算机中占64位的double类型,单精度数后面要加“f”或
“F”。双精度、多精度数后加“d”或“D”
(2)科学计数法:适用于数据过大或过小的情况,字母e或E前必须含有数字,后面的指数只能为整型数据
布尔型常量只有true和false两个值,分别表示真、假两种状态。它们不对应于任何整数值,仅用作逻辑条件的判断。我们在编码时直接使用 true和false 这两个单词,不要加引号。并且注意和C / C++语言不同的地方是,布尔型在Java中用关键字 boolean 单词全称,C/C++中用 bool 表示布尔型数据
boolean i; //建立布尔类型变量i |
字符串常量是用一对双引号括起来的一串字符。它和字符串常量在字符串仅有一个字符的情况下容易混淆:字符串常量包含转义字符 ‘\0’,其实是有两个字符。而字符常量就不一样了,无论字符串含有多少个字符,都是只占一个字符的空间大小
字符常量就是单个ASCII字符用单引号括起来的形式。eg:’a’、’c’。null常量只有一个值,用null表示,表示对象的引用为空
在这个部分呢,来谈谈我的感受以及重点的部分,如果你是一名学生,不论是不是主修计算机专业,相信大部分的学校都会开设《C语言》这门课程(顺便问一问,学的怎么样啊??),课程中的运算符与表达式章节和Java中的类型不能说的上一致,那简直就是完全一样呐
其实和上述内容一样,这些都是属于入门级别的内容。相信我,如果你学过甚至学会了《C语言》这门课程,Java中的这个章节完全可以略过(我是看完感觉没有什么不一样的地方,如有纰漏,实属小的太菜,还望各路大佬告知)
最有用的莫过于运算符的优先级了,这又让我想起了那些“变态”的题目:好多表达式 “ 掺和 ” 在一起,加上各种运算符连接,问你计算结果。仅仅一分的分值不说,最令人头大的是优先级分的也忒明显了,弄一会儿就绕进去了,反正我是很少做对(本人不才)。后来就死记硬背了一些重点的运算符优先级顺序才缓解了这样的窘境
附上一张我背记的表格(图片分页,还望xdm海涵):
public class TestArithmeticOP { |
public class TestLogicOP { |
public class FindMaxMin { |
public class TestBitOperation { |
public class Exchange { |
//实现一个三位数各位数字相加 |
//求圆的面积 |
Java中,程序实现各种各样功能的的原理是:使用类构建程序框架,使用方法实现类的功能,在方法中通过不同的语句结构控制程序流程实现,语句部分主要用例子来描述其使用方法
语句是指程序中的一个完整的执行单元,用于对数据进行加工处理、实现复杂功能。它是Java标识符的集合,由关键字、常量、变量、表达式共同组成。可分为说明性语句和操作性语句两种类型:
(1)说明性语句用来说明包和类的引入、类的声明、变量的声明;
(2)操作性语句包含表达式语句、复合语句、选择语句等;
表达式后接一个分号构成表达式语句,例如:赋值语句、自加自减语句以及方法调用语句等
double variable=100 ; //赋值 |
复合语句又称块(block)语句,由大括号 “{}” 括起来的部分称为语句块。执行复合语句时,实际上是执行该复合语句中所有语句。从语法上讲,无论大括号内有多少语句,都只被看成一条简单语句,多用于选择语句和循环语句中
public class BlockDemo { |
import java.util.Scanner; |
//求出个、十、百、千位数字的四次方的和等于该数本身的所有四位数 |
//求解 x=5时; x+x^2/2!+...+x^n/n!的值 要求x^n/n!的值<1.0 X 10^-8 |
import java.io.* ; //命令编译器载入java_installation/java/io路径下的所有类 |
我们在学习新知识的时候,不要总是抱有一步登天的想法,什么东西都想着要一下子掌握。这些看似细小的知识点很有可能会成为开发过程中你忽视的那一个。从每一个很小的例子开始,懵懂到知道,知道到理解,理解到上机,上机到掌握,逐步积累经验。相信自己,一定能学会,不要放弃。也正所谓 “ 不积跬步无以至千里,不积小流无以成江海 ”
Gitee/GitHub 上我的练习仓库:Gitee地址,GitHub地址,供大家学习参考,希望有所收获。码字不易,后面将会更新Java面向对象部分,如果帮到了您可以收藏学习,不要吝啬您的赞哦,您的支持将是我不断前行的动力!!
]]>JDK,全称 Java Development Kit,是整个 Java 的核心,包含 Java 运行环境、Java 工具以及 Java 基础类库。在 JDK 中,主要包括 Java 编译器、Java虚拟机、Java文档生成器、Java调试器等,包含以下几种常用组件
环境配置之前,首先使用cmd命令查看机器是否配置过 Java 环境,测试命令为( java / javac / java-version)
若出现以上信息,说明已经配置好,无需重复操作!!!反之,进行下述操作
在电脑中安装JDK,下载地址,进入后下滑显示界面
选择适合自己的版本进行下载,此处演示 Windows X64 Installer 下载。在Oracle官网下载涉及到账号注册,也可访问 这里 快速下载,提取码:peng
下载好后,双击程序运行
所有操作无需更改,继续下一步即可
复制JDK安装的路径。继续进行系统环境变量的配置操作
右键此电脑->属性->高级系统设置->环境变量,进入如下界面
粘贴上面电脑安装JDK的路径,路径可以更改,此处按照原路径完成后续操作
单击“新建”,输入以下内容,输入自己电脑JDK的安装路径
JAVA_HOME C:\Program Files\Java\jdk-16.0.1操作同上,继续添加以下信息
CLASSPATH .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar添加Path变量中的指令
创建变量
单击右侧”新建”,添加下面两条指令
%JAVA_HOME%\bin %JAVA_HOME%\jre\bin一路确定下来,最后同样进如cmd窗口,分别输入 java -version,java,javac 命令,显示如下信息即为配置成功
java version //查看java版本信息 |
java //执行.class文件 |
javac //java编译器 |
Vscode是一款轻量化的源代码编辑器,其众多的插件支持也大受好评。下面我们就在Vscode中配置Java的开发环境
首先在Vscode扩展中找到这个插件进行安装
Java Extension Pack是一个扩展包,里面包含了Java开发必要的一些插件,一般基础性的使用安装这个足矣
使用键盘快捷键 Ctrl+Shift+P 打开命令面板,输入 Configure Java Runtime
在②处可以看到自己 JDk 安装的版本,如果是先安装的Vscode也可以点击③处在弹出的网站上下载JDK,按照上文配置即可
快捷键 Ctrl +, 输入settings并单击 Edit in settings.json
在 javahome 出粘贴JDK的安装路径
涉及到转义字符,把 \ 改为 \ 或 / )
Tips:鼠标选中一个 \ 快捷键 Ctrl +D 连续敲击可快速选中所有 \ ,直接在键盘上更改即可
配置完成,下面写一个Java版的HelloWorld进行测试
public class HelloWorld { |
单击左侧调试图标,生成 launch.json 文件
因为已经安装Java开发的插件,直接点击 Run 便可在控制台看到输出结果
配置已完成,希望能帮到大家!
]]>👲👲作者主页:🔗杰森的博客
📒📒本文摘要:升级驱动到 mysql-connector-java 8.0.28 的注意事项
💖💖如果本文对您有帮助的话,还请各位小伙伴👍点赞➕收藏⭐➕评论💭支持杰森呀✌️
升级驱动到 mysql-connector-java 8.0.28
后,部署执行各种报错,但是把连接器切换到 mysql-connector-java-5.1.48
又没有问题,很是疑惑!
报错的信息大都是无法找到该类、无法连接
主要是配置好了,就没有留截图,大家主要注意和旧版本不同的地方就好
官方下载地址
历经种种艰难险阻,终于是解决了,成功连接,下面给出解决方案
第一种是菜鸟的示例,较为全面;如果感觉比较麻烦,可以使用第二种方案
这里引用菜鸟教程示例
-- 建立数据库 demo1 |
这里最最重要的就是 MySQL 版本的问题,新版更新了驱动类的名称为
com.mysql.cj.jdbc.Driver
import java.sql.*; |
执行结果,连接成功
上例考虑全面,使用异常较多,为了方便理解,我们简化下代码量
-- 建立数据库 demo1 |
注意版本、资源释放的顺序(最先调用,最后释放,释放顺序和调用顺序相反)
package com.jason.jdbc; |
执行结果,连接成功
毕竟是更新,多少会有一些改动,我们要学会去看更新了什么、学会去官方找解决方案
比如这次的报错就可以从最新的 jar 包中找到
在 5.x
版本之后,注册驱动的代码可以省略不写,就是这一段
//1. 注册驱动 |
原因是:驱动 jar
包下,默认 META-INF services
目录下记录了对应驱动类名,无需再次书写
可能是我用的版本太老了,跟不上时代的发展辽~~
]]>本来计划好的各种复习方案,却因为种种原因没有执行,不找借口,就是不想学
阶段性心理活动状态:
直到今天下载了准考证,才知道事情的严重性!!!但,好歹努个力吧,至少不能轻言放弃
想想 300 块大洋的报名费,用来干什么不香,不能打水漂。突击训练搞起来,肝算法,刷题~冲冲冲,恶补 +1 +1
计算机基础知识,主要考察不同数据存储单位之间的转换
需要知道如下单位转换关系
1 mb = 1024 kb = 1024 * 1024 b ; 1 byte(字节) = 8 bit(位)
那么,256 mb 的内存共有 256 * 1024 * 1024 * 8 bit,所以,共能存放 (256 * 1024 * 1024 * 8)÷ 32 = 67108864 个 32 位二进制整数
计算的话可以用计算器,或者代码。当然,你也可以选择手工计算,但我觉得你应该不至于这么做
/* |
首先,数字 0~9,每个数字又有 2021 个,显然需要存放于数组中,每次拼凑数字用掉一张卡片,对应卡片数量减一。等到某个数字卡片数量中出现剩余 0 张的情况,则无法继续拼凑
事实上,题目举例显而易见,拼出数字 1~9 时,只剩下 1 张卡片 1 ,无法继续拼出数字 11 。实际情况中,数字 1 也是使用最多的,也就是用的最快,最先没有剩余的
其中,在数组判断哪个数字减一时涉及到数位截取的知识点
名字高深,实质很简单:用
/
和%
提取出组合数据中的数字,eg:截取数字 206 中的 6,206 % 10 即可
/* |
由于是第一时间发布,题解还没来的及写,大家可以先看下真题题目
本文最初发表于 CSDN,可能同 NEXT 渲染引擎存在差异,为保证阅读体验,您可以在此处访问
使用最多6个
#
号实现层级标题
空格1 空格2
空格1
空格3
一个
空格
+enter
=换空行
斜体 * *
斜体 _ _
粗体 ** **
粗体 __ __
粗斜体 ***
或___
强调
符号 `
三个以上字符
*
或- - -
或--------------
这是删除线
文字两端加波浪线 ~~
这是下划线
符号
<u>
和</u>
之间添加文本
[^这是脚注]
脚注测试[^Team]
[^Team]
:这是脚注
这时候光标放在Team处就有脚注提示,单击 1 跳转到文末
格式:[^内容]
+[^内容]:释义
*
号+
号-
号符号
*
、+
、-
都能实现
放入一个
Tab
或四个空格
引用区块
引用2
引用3
符号> + 空格 嵌套加入多个> 即可
第一项
嵌套内容 符号
*
+>
实现
cout<<
两端加 ` 号
for(i=0;i<5;i++){ |
格式:三个 ` 号 +语言选择
结尾:对应前者
[链接名称]和(链接地址) 这里是网址
<直接放置链接地址> https://网址
这是单元格1 | 这是单元格2 |
---|---|
使用符号
|
和-
-
用于分隔行|...|...|
制表
符号 -
: 右对齐
符号:-
左对齐
符号:-:
居中对齐
掌握几种常见的HTML标签,实现更多文本格式
例如:标签 <kbd>
和标签</kbd>
我们可以按住Windows+Shift+S启动截图功能
示例代码:我们可以按住
<kbd>
Windows</kbd>
+<kbd>
Shift</kbd>
+<kbd>
S</kbd>
启动截图功能
$x+y=2$
$\sqrt{c x^2 + d}$
使用一对
$ $
符号 嵌入LaTeX格式数学公式,Markdown会自动进行渲染
<font face="微软雅黑">这是微软雅黑字体</font> |
这是微软雅黑字体
color=red size=5
更多格式请参考:RGB颜色对照表
在图片引入编辑器后生成的代码某位添加 #pic_center
![](https://img-blog.csdnimg.cn/6270ace20bfe4c62b19a45f107e2bc54.png) |
替换为
![](https://img-blog.csdnimg.cn/6270ace20bfe4c62b19a45f107e2bc54.png#pic_center) |
看效果:
拷贝生成的源码
放入下面的 “链接” 处
<img src="这里放置链接" width="70%"> |
自定义 width 后的数值实现等比例缩放
为避免文字后插入图片显示间距过大,可以使用官方方法
注意是 空格= 后面的不是乘号,是 小写字母 x
删除部分生成的源码,只留下图片URL,像这样
https://img-blog.csdnimg.cn/7aa6a23a91eb4d098904845f4fbd479a.png |
即可实现图片去水印的效果
由于不同的项目使用的 JDK 版本不一致,实际应用中会存在版本切换的问题
准备好两个版本的 JDK(更多个版本同理)
打开环境变量,新建或编辑三个 JAVA_HOME
变量名 | 值 |
---|---|
JAVA_HOME | %JAVA8_HOME% |
JAVA8_HOME | C:\Program Files\Java\jdk1.8.0_221 |
JAVA17_HOME | C:\Program Files\Java\jdk-17.0.2 |
其中 JAVA_HOME
变量值修改为当前使用的版本号即可
Path
变量开始的位置添加 %JAVA_HOME%\bin
这一项,如果存在则无需添加,==注意删除原来版本的路径配置==
cmd
打开命令行,输入 path
,查看第一条
跳转到该目录下,删除 java.exe javaw.exe javaws.exe
再次新建 cmd
,输入命令
java -version |
查看版本号,可以看到已经切换成功
如果需要更多个版本,比如三个版本的 JDK 切换,则在第一步的时候继续新建 JAVAxxx_HOME
,我们只要在第一个 JAVA_HOME
变量值的位置,修改为当前使用的版本号即可 %JAVAxxx_HOME%
有关 Mysql 的详细安装过程,请参考这里
启动 MySQL 服务时,遇到无法启动的报错信息,最后发现是输入命令mysqld --initialize-insecure
进行初始化时的问题,data 目录初始化错误
特此记录下解决方案
控制台输入命令 net start mysql
控制台输出信息:
MySQL 服务正在启动 . MySQL 服务无法启动。 服务没有报告任何错误。 请键入 NET HELPMSG 3534 以获得更多的帮助。
WIN
+ R
输入 cmd
打开命令行
切入到 Mysql 安装目录
进入到 bin
目录下,依次执行下列命令
# 注册服务 |
如果报错拒绝访问,那就是权限不够
我们使用管理员身份打开即可
以后可以当做一个小技巧,一般 Windows cmd 中关于类似问题首先考虑下权限不够,管理员打开,再思考其他方面的错误
使用管理员身份打开后,控制台显示
问题解决,服务正常启动
]]>图片来源网络!
大家在刷题时,常见的
OJ
平台(例如:洛谷)都会遇到测试点提示的信息,为了清楚的知道自己错在哪里,非常有必要了解下OJ
系统的提示信息
缩略语 | 英文全称 | 中文全称 |
---|---|---|
OJ | Online Judge | 在线判题系统 |
AC | Accepted | 通过 |
WA | Wrong Answer | 答案错误 |
TLE | Time Limit Exceed | 超时 |
OLE | Output Limit Exceed | 超过输出限制 |
MLE | Memory Limit Exceed | 超出内存限制 |
PE | Presentation Error | 格式错误 |
RE | Runtime Error | 运行出错 |
CE | Compile Error | 编译错误 |
希望我们刷题过程中遇到的都是 AC
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
如果我们列出所有小于 10 且是 3 或 5 的倍数的自然数,我们会得到 3、5、6 和 9。这些倍数之和是 23。
求 1000 以下所有 3 或 5 的倍数之和。
常规思路,找到 1000 以内所有 3 或 5 的倍数,分别求和解决
由于暴力解法的算法执行效率很低,需要重复遍历 1000 次,自然效率低下。我们只需要枚举 3 的倍数之和、5 的倍数之和,最后减去它们的最小公倍数之和,便可节省不少时间
1000 以内 k 的倍数和为
$$
\large \frac{\left (1000-1 \right)}{k}
$$
/* |
/* |
答案:233168
通过啦,既然是第一次,还是截个图记录下叭。以后也要继续加油啊,数学的优雅永不过时!!
]]>Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, …
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
斐波那契数列中的每个新项都是通过添加前两项来生成的。从 1 和 2 开始,前 10 个术语将是:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, …
通过考虑斐波那契数列中值不超过四百万的项,求偶数项之和。
首先清楚什么是斐波那契数列
斐波那契数(Successione di Fibonacci),又译为菲波拿契数、菲波那西数、斐氏数、黄金分割数。所形成的数列称为斐波那契数列
数学上,使用递归的方法定义
通俗来讲,斐波那契数列由 0(第零项) 和 1 开始,之后的斐波那契数由之前的两数相加得出,举例
1、 1、 2、 3、 5、 8、 13、 21、 34、 55、 89、 144、 233、 377……
看到这么多数字,并且有一定规律,我们自然而然会联想到数组。利用其数学定义解决,关键在于第三个斐波那契数值等于前两个数值相加,而后一直如此,实现如下
/* |
仔细思考下,常规解决方案中,我们开辟了很大的内存空间,但实质上每次增加(记录下一个斐波那契数)的却只是用到了三个元素来进行求和运算,所以我们仅开辟一个三个元素的数组就好,节省了很大的内存开销
/* |
]]>答案:4613732
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
13195 的质因数是 5、7、13 和 29。
数字 600851475143 的最大质因数是多少?
首先要理解清楚质因数的概念
质因数,在数论中是指能整除给定正整数的质数。除了1以外,两个没有其他共同质因子的正整数称为互质。因为1没有质因子,1与任何正整数(包括1本身)都是互质
正整数的因数分解可将正整数表示为一连串的质因子相乘,质因子如重复可以用指数表示。根据算术基本定理,任何正整数皆有独一无二的质因子分解式。只有一个质因子的正整数为质数
如果一个质数是某个数的因数,那么就说这个质数是这个数的质因数,并且这个因数一定是一个质数
每个合数都可以写成几个质数相乘的形式,这几个质数均称为该合数的质因数
例如:6 的质因子是 2 和 3(6 = 2 × 3);10 的质因子是 2 和 5(10 = 2 × 5)
求解质因数的方法中,比较常见的事短除法,它的具体求解步骤是
整体思路并没有问题,但是由于题目中给定数值已经超过了一般的执行范围,总是报错 stackoverflow,并未计算到最终结果,或许可以考虑用一台性能更好的机器测试下
该 C++ 版本代码编译速度很快,供参考
|
答案:6857
参考资料:
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
Find the largest palindrome made from the product of two 3-digit numbers.
回文数的两种读法都是一样的。由两个 2 位数字的乘积构成的最大回文数是 9009 = 91 × 99。
找出由两个 3 位数字的乘积构成的最大回文数。
回文数就是一个从左往右读和从右往左读都是一样的数字,例如数字:9009
、101
其实这道题没有什么更好的技巧,暴力可解
解题步骤:
/* |
judge() 判断数字是否为回文数时,用到了数位截取,和 2021 年蓝桥杯省赛 C++ 组 B 题有类似思想,详情参考
]]>答案:906609
2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
2520 是可以除以 1 到 10 的每个数字而没有任何余数的最小数字。
能被 1 到 20 的所有数整除的最小正数是多少?
引用下百科的解释:
两个或多个整数公有的倍数叫做它们的公倍数,其中除 0 以外最小的一个公倍数就叫做这几个整数的最小公倍数
整数 $a,b$ 的最小公倍数记为 $[a,b]$ ,同样的, $a,b,c$ 的最小公倍数记为 $[a,b,c]$ ,多个整数的最小公倍数也有同样的记号
那如何计算最小公倍数呢?
首先,把这几个数的质因数写出来,最小公倍数等于它们所有的质因数的乘积(如果有几个质因数相同,则比较两数中哪个数有该质因数的个数较多,乘较多的次数)
例如:
最大公约数,$a,b$ 的最大公约数记为 $(a,b)$
即:短除寻找公因数数,直到找不出公因数,左侧公因数乘积即为最大公约数
两个数的乘积等于这两个数的最大公约数与最小公倍数的乘积
若有两数 $a,b$,它们的最大公约数是 $p$,最小公倍数是 $q$
那么
$$
\large a×b=p×q
$$
该公式可改写为
$$
\large a×b=gcd\left (a,b \right)×q
$$
那么,我们给出最小公倍数的计算公式
$$
\large lcm(a,b)=\frac{ab}{gcd(a,b)}=q
$$
又称辗转相除法,用于计算两个非负整数 $a,b$ 的最大公约数
计算公式
$$
\large gcd\left (a,b \right)
$$
根据欧几里得算法计算公式,计算得到两数最大公约数,再由最小公倍数计算公式得出最小公倍数。然后让两个数的最小公倍数和第三个数计算最小公倍数,迭代求算即可
/* |
]]>答案:232792560
The sum of the squares of the first ten natural numbers is:
$$
\large 1^2+2^2+3^2+\cdots+10^2=385
$$
The square of the sum of the first ten natural numbers is:
$$
\large (1+2+3+\cdots+10)^2=55^2=3025
$$
Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is:
$$
\large 3025 - 385 = 2640
$$
Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.
前十个自然数的平方的和为:
$$
\large 1^2+2^2+3^2+\cdots+10^2=385
$$
而前十个自然数和的平方为:
$$
\large (1+2+3+\cdots+10)^2=55^2=3025
$$
因此,前十个自然数的平方和与和的平方之间的差是:
$$
\large 3025 - 385 = 2640
$$
求前一百个自然数的平方和与和的平方之间的差
自然数的平方的和通项公式
$$
\large S(1)=\frac{n(n+1)(2n+1)}{6}
$$
自然数和的平方通项公式
$$
\large S(2)=\left ( \frac{n(n+1)}{2} \right )^2
$$
则和的平方与平方和差值通项公式为
$$
\large S(n)=S(2)-S(1)=\left ( \frac{n(n+1)}{2} \right )^2-\frac{n(n+1)(2n+1)}{6}
$$
$$
\large =\frac{n(n-1)(n+1)(3n+2)}{12}
$$
/* |
]]>答案:25164150
By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
What is the 10 001st prime number?
通过列出前六个素数:2、3、5、7、11 和 13,我们可以看到第 6 个素数是 13。
第10001个质数是多少?
读完题目,发现题目还是比较容易的。枚举出范围内所有的素数,加入循环判断,等到判断条件是第 100001 个质数时输出就好
另外需要知道质数的概念
质数(又称素数),指在大于1的自然数中,除了1和该数自身外,无法被其他自然数整除的数
下面介绍一种比较容易理解的,在程序中判断数字是否为质数的方法
因为,一个数如果可以进行因数分解,那么分解后,得到的两个数一定是一个小于等于 $sqrt(n)$,一个大于等于 $sqrt(n)$
所以,我们并不需要从 2 一直判断到 $n-1$ ,而只需遍历到 $sqrt(n)$ 即可。既然在左侧都找不到因数,那么右侧一定不存在咯
贴下实现的代码,帮助理解
bool is_prime(int num) |
/* |
]]>答案:104743
The four adjacent digits in the 1000-digit number that have the greatest product are $9×9×8×9=5832$.
Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?
1000 位数字中乘积最大的相邻四个数字是 $9×9×8×9=5832$。
找出 1000 位数字中乘积最大的 13 个相邻数字。这个数字的乘积是什么?
数字文件
73167176531330624919225119674426574742355349194934 |
本题用 Python 效率会高一些,且思路更简单
我们将所有数字存放到本地的 txt 文件中,使用 Python 导入程序并存放在一个 List 中,此时,从 List 的第 0 位一直到最后,求出十三位数字的乘积并存方到另一个 List 中(结果集),在结果集中找出最大值并输出
下面附上两段代码供参考
''' |
''' |
]]>答案:23514624000
A Pythagorean triplet is a set of three natural numbers, $a < b < c$, for which,
$$
\large a^2+b^2=c^2
$$
For example,
$$
\large 3^2+4^2=9+16=25=5^2
$$
There exists exactly one Pythagorean triplet for which $a + b + c = 1000$.
Find the product $abc$.
毕达哥拉斯三元组是一组三个自然数的集合,且 $a < b < c$,其中
$$
\large a^2+b^2=c^2
$$
例如:
$$
\large 3^2+4^2=9+16=25=5^2
$$
恰好存在一个 $a + b + c = 1000$ 的毕达哥拉斯三元组,求积 $abc$
题目中提到了毕达哥拉斯三元组,我们首先理解下其数学定义
在一个边长为 $a、b、c$ 的直角三角形中,$a²+b²=c²$。理想的情况是 $a、b、c$ 均为整数,则称为毕达哥拉斯三元数组
如题目中给出的例子,$3、4、5$ 就符合条件
根据题目叙述,我们要满足 $a < b < c$ 和 $a²+b²=c²$ 的条件
那么只需要分别定义三个变量 $a、b、c$,分别给它们赋值为 $1、2、3$ 并符合比较关系,用来满足第一个条件
然后从变量 $c$ 开始,三层循环,最后一层中去判断 $a + b + c = 1000$ 和 $a²+b²=c²$ 条件
如果满足,则输出此时的乘积即为所求
这并不是唯一的解决方案,但是是我认为比较简单,最容易理解的一种
/* |
]]>答案:31875000
The sum of the primes below $10$ is
$$
\large 2 + 3 + 5 + 7 = 17
$$
Find the sum of all the primes below two million.
$10$ 以下的质数之和为
$$
\large 2 + 3 + 5 + 7 = 17
$$
求两百万以下的所有质数之和
首先单看题目知识点,涉及到素数(质数),和第七题 10001st prime一定会有类似之处
我们采用最直接的方法求解(暴力),枚举范围内的所有质数,然后求和
注意,像这样的解决方案并非最佳,只适用于小规模数据,规模的调整对于对应算法的要求很高
比如说,这个题目你可以用暴力枚举解决它。但是,如果我把数据量级调整到亿,这种方法就未必可以使用,需要更高级的算法来解决,具体请参考文末代码段
总之,大家要根据实际情况采用最优的方案来解决对应的问题,没有什么办法可以一劳永逸,适用于所有情况
/* |
答案:142913828922
原理:从 $2$ 开始,将每个素数的各个倍数,标记成合数。一个素数的各个倍数,是一个差为此素数本身的等差数列,此筛法是列出所有小素数最有效的方法之一
这里使用埃氏筛法解决亿级数据量级问题,实现代码段如下,供参考学习
/* |
更多关于本题的解决方案,详见 求十亿内所有质数的和,怎么做最快?
]]>In the $20×20$ grid below, four numbers along a diagonal line have been marked in red.
The product of these numbers is $26 × 63 × 78 × 14 = 1788696$.
What is the greatest product of four adjacent numbers in the same direction (up, down, left, right, or diagonally) in the $20×20$ grid?
在下面的 $20×20$ 网格中,沿对角线的四个数字被标记为红色。
这些数字的乘积是 $26 × 63 × 78 × 14 = 1788696$。
在 $20×20$ 的网格中,沿相同方向(上、下、左、右或对角线)的四个相邻数字的最大乘积是多少?
将数据表中的数字存入到二维数组中,依次计算相同方向的四个相邻数字乘积并暂存
比较所有乘积 ,找出最大值即所求
/* |
]]>答案:70600674
The sequence of triangle numbers is generated by adding the natural numbers. So the 7th triangle number would be $1 + 2 + 3 + 4 + 5 + 6 + 7 = 28$. The first ten terms would be:
$$
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, …
$$
Let us list the factors of the first seven triangle numbers:
We can see that $28$ is the first triangle number to have over five divisors.
What is the value of the first triangle number to have over five hundred divisors?
三角数由依次排列的自然数的和生成。所以第 $7$ 个三角数是 $1 + 2 + 3 + 4 + 5 + 6 + 7 = 28$。前十项是:
$$
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, …
$$
让我们列出前七个三角数的因数:
我们可以看到 $28$ 是第一个有五个以上除数(因子)的三角数。
第一个有超过 $500$ 个除数(因子)的三角数的值是多少?
拿到题目,我们首先做的要理解清除题目含义,对于从未听过的陌生概念、术语(一般会举例说明),我们也要试着首先理解示例
这里解释下题目中的三角数是如何得出的,请看下表计算过程
第 x 个 | 三角数值 | 计算过程 |
---|---|---|
1 | 1 | 1 |
2 | 3 | 1+2=3 |
3 | 6 | 1+2+3=6 |
4 | 10 | 1+2+3+4=10 |
5 | 15 | 1+2+3+4+5=15 |
6 | 21 | 1+2+3+4+5+6=21 |
7 | 28 | 1+2+3+4+5+6+7=28 |
… | … | … |
依然是老朋友,暴力枚举,从 $1$ 开始依次枚举每个数字并判断它有多少个约数
当约数个数大于 $500$ 时,退出循环并输出该值
/* |
答案:76576500
本题在完成三角数的枚举后,最重要的一步是如何判断一个数约数的个数
从基本思想不断优化,降低算法的时间复杂度,详请参考快速计算约数的个数——从基础到高级
]]>Work out the first ten digits of the sum of the following one-hundred $50$-digit numbers.
Data file see end
计算以下 $100$ 个 $50$ 位数字和的前十位数
数据文件见文末
大家看到题目,首先不要被这一堆数字给吓到,觉得它很难,我们仔细阅读下题干,发现并不难,所用知识点都比较容易
将这 $100$ 个 $50$ 位数字写在程序中显得比较冗长,这里我们使用 Python
解决
直接将数据存入 txt
文本文件中,用 Python
打开文件并读取数据
求出总和后将和转化为字符串,最后截取前十位,得解
''' |
答案:5537376230
如果在打开文件时遇到错误 FileNotFoundError: [Errno 2] No such file or directory,请查看这里
37107287533902102798797998220837590246510135740250 |
The following iterative sequence is defined for the set of positive integers:
$$
\large n\rightarrow \frac{n}{2}\ \left ( n\ is\ even \right ) ,n\rightarrow3n+1\ \left ( \ n\ is\ odd \right )
$$
Using the rule above and starting with $13$, we generate the following sequence:
$$
\large 13\rightarrow40\rightarrow20\rightarrow10\rightarrow5\rightarrow16\rightarrow8\rightarrow4\rightarrow2\rightarrow1
$$
It can be seen that this sequence (starting at $13$ and finishing at 1) contains $10$ terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at $1$.
Which starting number, under one million, produces the longest chain?
NOTE: Once the chain starts the terms are allowed to go above one million.
为所有正整数集定义以下迭代序列:
$$
\large n\rightarrow \frac{n}{2}\ \left ( n,是偶数 \right ) ,n\rightarrow3n+1\ \left ( n,是奇数 \right )
$$
使用上面的规则并从 $13$ 开始,生成以下序列:
$$
\large 13\rightarrow40\rightarrow20\rightarrow10\rightarrow5\rightarrow16\rightarrow8\rightarrow4\rightarrow2\rightarrow1
$$
可以看出这个序列从 $13$ 开始并到 $1$ 结束总共包含 $10$ 个数。
考拉兹猜想指出使用以上迭代规则,所有正整数都会最终回到一,虽然这个猜想仍未得到证明。
求在一百万以下,哪个起始数可以产生最长的考拉兹序列?
注意:序列中包含的数的个数可以超过一百万。
考拉兹猜想(Collatz conjecture),又称为奇偶归一猜想、3n+1 猜想、冰雹猜想、角谷猜想、哈塞猜想、乌拉姆猜想或叙拉古猜想,是指对于每一个正整数,如果它是奇数,则对它乘 3 再加 1,如果它是偶数,则对它除以 2,如此循环,最终都能够得到 1
$$
\large f\left ( n \right )=\left\{\begin{matrix}\frac{n}{2} \quad\quad\quad if \, n\equiv 0\\3n+1 \quad if \, n\equiv 1\end{matrix}\right.\left .\quad( mod \,\, 2 \right )
$$
其实当你看到题目的时候,不知到你有没有和我想到一块儿去,那必然又是咱滴老朋友暴力算法啦
显然,我们只要求算出一到一百万之间所有数字的考拉兹序列长度,然后在所有求出的序列长度值中找出最大值就能解决本题
但是可以做一些优化,比如大家都知道当 n
是奇数时,3n+1
一定是偶数。那我们根本没必要让程序重复执行冗余步骤
换言之,当 n
是奇数的时候,在其后追加一步,继续计算 (3n+1)/2
。便可省去很多中间计算步骤,程序执行效率自然得到提高
还有一点是参考其他大神写的题解意识到的,就是程序重复计算的问题。较大的数据量在计算过程中可能会产生重复数据,我们是不是可以将所有计算步骤得到的结果做下缓存。这样在下一步遇到重复值时可以直接调用,避免重复计算,提高程序执行效率
或者也可以使用递归法实现本题
/* |
''' |
答案:837799
参考资料:
最近用 Python 解决欧拉计划第十三题时,打开文件时总是报错
FileNotFoundError: [Errno 2] No such file or directory: '/ProjectEuler/data/013.txt'
map(int,open('data/013.txt')) |
后来查了下,发现是和编辑器有关系,涉及到工作区的概念,下面给出解决方案
首先给大家看下我的工作区,Vscode
编辑器解析打开的整个文件夹为工作区
什么意思呢?就是说,这里编辑器默认我们的工作区是 algorithms
这一整个文件夹,文件位置分布是这样的
algorithms |
如果我们要让程序正确识别文件位置,应该将路径修改为相对工作区的路径,即:
map(int,open('ProjectEuler/data/013.txt')) |
此时再次执行代码,便不会报错
参考资料:
近日,火爆全网的北京2022冬奥会吉祥物冰墩墩一度售罄,既然买不到,那就自己做一个吧!
import turtle |
实现效果如下,可爱的冰墩墩到手啦
]]>今早起来,逛逛朋友圈,看到的全是各种秀。唉,图片咱就不放了,难免戳中某位朋友瘦小的心灵,主要我也怕,你们知道叭
这种时候怎么能让我们的朋友圈是白茫茫的一片呢?必须怼回去,这气可不能受,下面的操作学会了,这波气势也不输,还不快快学起来~~
桌面右击,新建文本文档
将文件命名格式修改为 .css ,保存, js 文件建立同理
html { |
* { |
const blk_pitn = { |
xdm,师弟只能带你到这里了,剩下的修行就靠你们自己了,我先行一步,暂且告退……
]]>做世界级的 OS,让万物互联,信息畅通无阻。
成为未来 AIoT 领域最为主流的操作系统平台。
RT-Thread 是一个集
实时操作系统(RTOS)内核、中间件组件和开发者社区于一体
的技术平台,由熊谱翔先生
带领并集合开源社区力量开发而成,RT-Thread 也是一个组件完整丰富、高度可伸缩、简易开发、超低功耗、高安全性
的物联网操作系统
。
RT-Thread 具备一个 IoT OS 平台所需的所有关键组件,例如GUI、网络协议栈、安全传输、低功耗组件等等。经过11年的累积发展,RT-Thread 已经拥有一个
国内最大的嵌入式开源社区
,同时被广泛应用于能源、车载、医疗、消费电子等多个行业,累积装机量超过 14亿 台,成为国人自主开发
、国内最成熟稳定和装机量最大的开源 RTOS
。
RT-Thread 拥有
良好的软件生态
,支持市面上所有主流的编译工具如 GCC、Keil、IAR 等,工具链完善、友好,支持各类标准接口,如 POSIX、CMSIS、C++应用环境、Javascript 执行环境等,方便开发者移植各类应用程序。商用支持所有主流MCU架构,如 ARM Cortex-M/R/A, MIPS, X86, Xtensa, C-Sky, RISC-V,几乎支持市场上所有主流的 MCU 和 Wi-Fi 芯片。
RT-Thread studio
潘多拉STM32L475
1.头文件
2.宏定义
//按键初始化 |
3.void motor_ctrl(rt_uint8_t turn) //电机控制函数
void motor_ctrl(rt_uint8_t turn) |
4.void beep_ctrl(rt_uint8_t on) //蜂鸣器控制函数
void beep_ctrl(rt_uint8_t on) |
5.void irq_callback(void *args) // 中断回调函数
void irq_callback(void *args) |
6.主函数
int main(void) |
通过按键引脚、电机以及蜂鸣器的输入输出模式,并对按键设置中断编写中断回调函数,在使能中断后。
1.电机控制:当有外部事件触发引脚状态(按下按键)时,中断回调函数对特定的触发引脚进行判断,并执行相应的操作
2.蜂鸣器控制:在主函数中循环执行判断是否WK_UP按键是否按下,按下触发蜂鸣器响,松开停止发声。
按键 | 功能 |
---|---|
KEY0 | 电机左转 |
KEY1 | 电机右转 |
KEY2 | 电机停止 |
WK_UP | 蜂鸣器响 |
由飞利浦公司开发,支持设备间的短距离通信。i2c通信需要的引脚少,硬件实现简单、可扩展性强,被广泛应用在系统内多个集成电路(IC)间的通信。
i2c通信总线可连接多个i2c通信设备,支持多个通信主机和多个通信从机。i2c通信只需要两条双向总线——SDA(串行数据线)和SCL(串行时钟线)。SDA
:用于传输数据SCL
:用于同步数据收发
每个连接到总线的设备都有一个独立地址,共7bit,主机正是利用该地址对设备进行访问
i2c支持多主控,任何时间点都只能有一个主控。
i2c器件的SDA引脚和SCL引脚是开漏电路形式,因此,SDA和SCL总线都需要连接上拉电阻,当总线空闲时,两条总线均为高电平。
各器件的SDA和SCL信号线在总线上都是线与
关系。(即连接到总线上的任意器件输出低电平都会将总线信号拉低)
协议层定义了i2c的通信协议。一个完整的i2c数据传输包含开始信号,器件地址,读写控制,器件内访问地址,有效数据,应答信号和结束信号。
数据传输:当SCL位高电平时,SDA必须保持稳定,SDA上传1位数据。
数据改变:当SCL为低电平时,SDA才可以改变电平i2c位传输时序图
开始信号
:SCL 为高电平时,主机将SDA 拉低,表示数据传输即将开始。结束信号
:在SDA 为低电平时,主机将SCL 拉高并保持高电平,然后在将SDA 拉高,表示传输结束。
主机
发送完每一个字节数据后,释放SDA(保持高电平),被寻址的接收器在成功接收到每一个字节后,必须产生一个应答ACK
(从机将SDA拉低,使它在这个时钟脉冲的高电平期间保持稳定的低电平)从机
接收不到数据或通信故障时,从机
必须使SDA保持高电平,主机
产生一个结束信号终止传输或者产生新的传输。线与
逻辑功能的原理上的。线与
连接。一般情况下MCU 的I2C 器件都是作为主机和从机通讯,在RT-Thread 中将I2C 主机虚拟为I2C 总线设备,I2C 从机通过I2C 设备接口和I2C 总线通讯,相关接口如下所示:
函数 | 描述 |
---|---|
rt_device_find() | 根据I2C 总线设备名称查找设备获取设备句柄 |
rt_i2c_transfer() | 传输数据 |
在使用I2C 总线设备前需要根据I2C 总线设备名称获取设备句柄,进而才可以操作I2C 总线设备,查找设备函数如下所示,
rt_device_t rt_device_find(const char* name); |
参数 | 描述 |
---|---|
name | i2c总线设备名称 |
返回 | – |
设备句柄 | 查找到对应设备将返回相应的设备句柄 |
RT-NULL | 没有找到相应的设备对象 |
一般情况下,注册到系统的I2C 设备名称为i2c0 ,i2c1 等,使用示例如下所示:
|
获取到I2C 总线设备句柄就可以使用rt_i2c_transfer() 进行数据传输。函数原型如下所示:
rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, |
参数 | 描述 |
---|---|
bus | i2c总线设备句柄 |
msgs[] | 待传输的消息数组指针 |
num | 消息数组的元素个数 |
返回 | - |
- | - |
消息数组的元素个数 | 成功 |
错误码 | 失败 |
!!! note “注意事项” 此函数会调用rt_mutex_take(), 不能在中断服务程序里面调用,会导致assertion报错。
I2C 消息数据结构原型如下:
struct rt_i2c_msg |
!!! note “注意事项” RT-Thread I2C 设备接口使用的从机地址均不包含读写位,读写位控制需修改标志flags。
使用示例如下所示:
|
I2C 设备的具体使用方式可以参考如下示例代码,示例代码的主要步骤如下:
首先根据I2C 设备名称查找I2C 名称,获取设备句柄,然后初始化aht10 传感器。
控制传感器的2 的函数为写传感器寄存器write\_reg\(\) 和读传感器寄存器read\_regs\(\)
这两个函数分别调用了rt_i2c_transfer() 传输数据。读取温湿度信息的函数read_temp_humi() 则是调用这两个函数完成功能。
/* |
参考资料:
在日常生活中,我们通常会将一个大的问题拆分细化,拆开成若干个小问题,通过逐个解决小问题,大问题也就解决了。
同样的在RT-Thread多线程操作系统中,开发人员基于这种分而治之的思想,将一个复杂的应用问题抽象成若干个小的、可调度的、可序列化的程序单元。当合理地划分任务并正确地执行时,这种设计能够让系统满足实时系统的性能及时间的要求。
下面看一个例子:我们的任务是读取传感器上的数据,并将相关数据显示出来。通过拆分结构,我们可以发现主要有两个任务:
1.读取数据
2.显示数据
简单来说,就是一个子任务不间断地读取传感器数据,并将数据写到共享内存中,另外一个子任务周期性的从共享内存中读取数据,并将传感器数据输出到显示屏上。
在RT-Thread 中,与上述子任务对应的程序实体就是线程,线程是实现任务的载体
。
它是RT-Thread中最基本的调度单位
,它描述了一个任务执行的运行环境,也描述了这个任务所处的优先等级,重要的任务可设置相对较高的优先级
,非重要的任务可以设置较低的优先级,不同的任务还可以设置相同的优先级,轮流运行。上下文:
当线程运行时,它会认为自己是以独占CPU 的方式在运行,线程执行时的运行环境称为上下文,具体来说就是各个变量和数据,包括所有的寄存器变量、堆栈、内存信息等。
RT-Thread 线程管理的主要功能是对线程进行管理和调度
,系统中总共存在两类线程,分别是系统线程
和用户线程
。系统线程是由RT-Thread 内核创建的线程,用户线程是由应用程序创建的线程,这两类线程都会从内核对象容器中分配线程对象,当线程被删除时,也会被从对象容器中删除。
如图所示,每个线程都有重要的属性,如线程控制块、线程栈、入口函数等。
抢占式
的,主要的工作就是从就绪线程列表中查找最高优先级线程,保证最高优先级的线程能够被运行,最高优先级的任务一旦就绪,总能得到CPU 的使用权。在RT-Thread 中,线程控制块由结构体struct rt_thread 表示,线程控制块是操作系统用于管理线程的一个数据结构,它会存放线程的一些信息,例如优先级、线程名称、线程状态等,也包含线程与线程之间连接用的链表结构,线程等待事件集合等,详细定义如下:
/* 线程控制块*/ |
其中init_priority 是线程创建时指定的线程优先级,在线程运行过程当中是不会被改变的(除非用户 执行线程控制函数进行手动调整线程优先级)。
cleanup 会在线程退出时,被空闲线程回调一次以执行用户设置的清理现场等工作。
最后的一个成员user_data 可由用户挂接一些数据信息到线程控制块中,以提供类似线程私有数据的实现。
线程运行的过程中,同一时间内只允许一个线程在处理器中运行,从运行的过程上划分,线程有多种不同的运行状态,如初始状态、挂起状态、就绪状态等。
在RT-Thread 中,线程包含五种状态,操作系统会自动根据它运行的情况来动态调整它的状态。如下表所示:
状态 | 描述 |
---|---|
初始态 | 当线程刚开始创建还没开始运行时就处于初始状态;在初始状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_INIT |
就绪态 | 在就绪状态下,线程按照优先级排队,等待被执行;一旦当前线程运行完毕让出处理器,操作系统会马上寻找最高优先级的就绪态线程运行。此状态在RT-Thread 中的宏定义为RT_THREAD_READY |
运行态 | 线程当前正在运行。在单核系统中,只有rt_thread_self() 函数返回的线程处于运行状态;在多核系统中,可能就不止这一个线程处于运行状态。此状态在RT-Thread 中的宏定义为RT_THREAD_RUNNING |
挂起态 | 也称阻塞态。它可能因为资源不可用而挂起等待,或线程主动延时一段时间而挂起。在挂起状态下,线程不参与调度。此状态在RT-Thread 中的宏定义为RT_THREAD_SUSPEND |
关闭态 | 当线程运行结束时将处于关闭状态。关闭状态的线程不参与线程的调度。此状态在RT-Thread 中的宏定义为RT_THREAD_CLOSE |
RT-Thread 线程的优先级是表示线程被调度的优先程度。每个线程都具有优先级,线程越重要,赋予的优先级就应越高,线程被调度的可能才会越大。
RT-Thread 最大支持256 个线程优先级(0~255),数值越小的优先级越高,0 为最高优先级。在一些资源比较紧张的系统中,可以根据实际情况选择只支持8 个或32 个优先级的系统配置;对于ARM Cortex-M系列,普遍采用32 个优先级。最低优先级默认分配给空闲线程使用,用户一般不使用。在系统中,当有比当前线程优先级更高的线程就绪时,当前线程将立刻被换出,高优先级线程抢占处理器运行。
每个线程都有时间片这个参数,但时间片仅对优先级相同的就绪态线程有效。系统对优先级相同的就绪态线程采用时间片轮转的调度方式进行调度时,时间片起到约束线程单次运行时长的作用,其单位是一个系统节拍(OS Tick)。
假设有2 个优先级相同的就绪态线程A 与B
,A 线程的时间片设置为10,B 线程的时间片设置为5,那么当系统中不存在比A 优先级高的就绪态线程时,系统会在A、B 线程间来回切换执行,并且每次对A 线程执行10 个节拍的时长,对B 线程执行5 个节拍的时长,如下图。
线程控制块中的entry
是线程的入口函数,它是线程实现预期功能的函数。
线程的入口函数由用户设计实现,一般有以下两种代码形式:
1.无限循环模式
在实时系统中,线程通常是被动式的:这个是由实时系统的特性所决定的,实时系统通常总是等待外
界事件的发生,而后进行相应的服务:
void thread_entry(void* paramenter) |
作为一个实时系统,一个优先级明确的实时系统,如果一个线程中的程序陷入了死循环操作,那么比它优先级低的线程都将不能够得到执行。
所以在实时操作系统中必须注意的一点就是:线程中不能陷入死循环操作,必须要有让出CPU使用权的动作,如循环中调用延时函数或者主动挂起。用户设计这种无线循环的线程的目的,就是为了让这个线程一直被系统循环调度运行,永不删除。
2.顺序执行或有限次循环模式
如简单的顺序语句、do whlie() 或for() 循环等,此类线程不会循环或不会永久循环,可谓是“一次性”线程,一定会被执行完毕。在执行完毕后,线程将被系统自动删除。
static void thread_entry(void* parameter) |
RT-Thread 提供一系列的操作系统调用接口,使得线程的状态在这五个状态之间来回切换。几种状态间的转换关系如下图所示:
- 线程通过调用函数
rt_thread_create/init()
进入到初始状态(RT_THREAD_INIT)
;- 初始状态的线程通过调用函数
rt_thread_startup()
进入到就绪状态(RT_THREAD_READY)
;- 就绪状态的线程被调度器调度后进入运行状态
(RT_THREAD_RUNNING)
;- 当处于运行状态的线程调用rt_thread_delay(),rt_sem_take(),rt_mutex_take(),rt_mb_recv() 等函数或者获取不到资源时, 将进入到挂起状态
(RT_THREAD_SUSPEND)
;
- 处于挂起状态的线程,如果等待超时依然未能获得资源或由于其他线程释放了资源,那么它将返回到就绪状态。
- 挂起状态的线程,如果调用
rt_thread_delete/detach()
函数,将更改为关闭状态(RT_THREAD_CLOSE)
;- 而运行状态的线程,如果运行结束,就会在线程的最后部分执行
rt_thread_exit()
函数,将状态更改为关闭状态。
!!! note “注意事项” RT-Thread 中,实际上线程并不存在运行状态,就绪状态和运行状态是等同的。
系统线程是指由系统创建的线程,用户线程是由用户程序调用线程管理接口创建的线程,在RT-Thread 内核中的系统线程有空闲线程和主线程。
空闲线程
是系统创建的最低优先级的线程,线程状态永远为就绪态
。当系统中无其他就绪线程存在时,调度器将调度到空闲线程,它通常是一个死循环,且永远不能被挂起。
另外,空闲线程在RT-Thread 也有着它的特殊用途:
在系统启动时,系统会创建main 线程,它的入口函数为main_thread_entry(),用户的应用入口函数main() 就是从这里真正开始的,系统调度器启动后,main 线程就开始运行。
过程如下图,用户可以在main() 函数里添加自己的应用程序初始化代码。
可以使用rt_thread_create() 创建一个动态线程,使用rt_thread_init() 初始化一个静态线程。
动态线程与静态线程的区别是:动态线程是系统自动从动态内存堆上分配栈空间与线程句柄(初始化heap 之后才能使用create 创建动态线程),静态线程是由用户分配栈空间与线程句柄。
下图描述了线程的相关操作,包含:创建/ 初始化线程、启动线程、运行线程、删除/ 脱离线程。
一个线程要成为可执行的对象,就必须由操作系统的内核来为它创建一个线程。可以通过如下的接口创建一个动态线程:
rt_thread_t rt_thread_create(const char* name, |
调用这个函数时,系统会从动态堆内存中分配一个线程句柄以及按照参数中指定的栈大小从动态堆内存中分配相应的空间。分配出来的栈空间是按照rtconfig.h 中配置的RT_ALIGN_SIZE 方式对齐。
线程创建rt_thread_create() 的参数和返回值见下图:
对于一些使用rt_thread_create() 创建出来的线程,当不需要使用,或者运行出错时,我们可以使用下面的函数接口来从系统中把线程完全删除掉:
rt_err_t rt_thread_delete(rt_thread_t thread); |
调用该函数后,线程对象将会被移出线程队列并且从内核对象管理器中删除,线程占用的堆栈空间也会被释放,收回的空间将重新用于其他的内存分配。实际上,用rt_thread_delete() 函数删除线程接口,仅仅是把相应的线程状态更改为RT_THREAD_CLOSE 状态,然后放入到rt_thread_defunct 队列中;而真正的删除动作(释放线程控制块和释放线程栈)需要到下一次执行空闲线程时,由空闲线程完成最后的线程删除动作。
线程删除rt_thread_delete() 接口的参数和返回值见下图:
这个函数仅在使能了系统动态堆时才有效(即RT_USING_HEAP 宏定义已经定义了)。
线程的初始化
可以使用下面的函数接口完成,来初始化静态线程对象:
rt_err_t rt_thread_init(struct rt_thread* thread, |
对于用rt_thread_init() 初始化的线程,使用rt_thread_detach() 将使线程对象在线程队列和内核对象管理器中被脱离。线程脱离函数如下:
rt_err_t rt_thread_detach (rt_thread_t thread); |
参数 | 描述 |
---|---|
thread | 线程句柄,它应该是由rt_thread_init 进行初始化的线程句柄。 |
返回 | — |
RT_EOK | 线程脱离成功 |
-RT_ERROR | 线程脱离失败 |
创建(初始化)的线程状态处于初始状态,并未进入就绪线程的调度队列,我们可以在线程初始化/创建成功后调用下面的函数接口让该线程进入就绪态:
rt_err_t rt_thread_startup(rt_thread_t thread); |
当调用这个函数时,将把线程的状态更改为就绪状态,并放到相应优先级队列中等待调度。如果新启
动的线程优先级比当前线程优先级高,将立刻切换到这个线程。
在程序的运行过程中,相同的一段代码可能会被多个线程执行,在执行的时候可以通过下面的函数接口获得当前执行的线程句柄:
rt_thread_t rt_thread_self(void); |
当前线程的时间片用完或者该线程主动要求让出处理器资源时,它将不再占有处理器,调度器会选择相同优先级的下一个线程执行。线程调用这个接口后,这个线程仍然在就绪队列中。
线程让出处理器使用下面的函数接口:
rt_err_t rt_thread_yield(void); |
调用该函数后,当前线程首先把自己从它所在的就绪优先级线程队列中删除,然后把自己挂到这个优先级队列链表的尾部,然后激活调度器进行线程上下文切换(如果当前优先级只有这一个线程,则这个线程继续执行,不进行上下文切换动作)。
在实际应用中,我们有时需要让运行的当前线程延迟一段时间,在指定的时间到达后重新运行,这就叫做“线程睡眠”。
线程睡眠可使用以下三个函数接口:
rt_err_t rt_thread_sleep(rt_tick_t tick); |
- 当线程调用rt_thread_delay() 时,线程将主动挂起;当调用rt_sem_take(),rt_mb_recv() 等函数时,资源不可使用也将导致线程挂起。
- 处于挂起状态的线程,如果其等待的资源超时(超过其设定的等待时间),那么该线程将不再等待这些资源,并返回到就绪状态;或者,当其他线程释放掉该线程所等待的资源时,该线程也会返回到就绪状态。
线程挂起
使用下面的函数接口:
rt_err_t rt_thread_suspend (rt_thread_t thread); |
!!! note “注意事项” 通常不应该使用这个函数来挂起线程本身, 如果确实需要采用rt_thread_suspend() 函数挂起当前任务, 需要在调用rt_thread_suspend() 函数后立刻调用rt_schedule() 函数进行手动的线程上下文切换。
恢复线程就是让挂起的线程重新进入就绪状态,并将线程放入系统的就绪队列中;如果被恢复线程在
所有就绪态线程中,位于最高优先级链表的第一位,那么系统将进行线程上下文的切换。
线程恢复
使用下面的函数接口:
rt_err_t rt_thread_resume (rt_thread_t thread); |
当需要对线程进行一些其他控制时,例如动态更改线程的优先级,可以调用如下函数接口:
rt_err_t rt_thread_control(rt_thread_t thread, rt_uint8_t cmd, void* arg); |
指示控制命令cmd 当前支持的命令包括: |
空闲钩子函数是空闲线程的钩子函数,如果设置了空闲钩子函数,就可以在系统执行空闲线程时,自动执行空闲钩子函数来做一些其他事情,比如系统指示灯。
设置/ 删除空闲钩子的接口如下:
rt_err_t rt_thread_idle_sethook(void (*hook)(void)); |
参数 | 描述 |
---|---|
hook | 设置/删除的钩子函数 |
返回 | — |
RT-EOK | 设置/删除成功 |
-RT_EFULL | 设置失败 |
-RT_ENOSYS | 删除失败 |
!!! note “注意事项” 空闲线程是一个线程状态永远为就绪态的线程,因此设置的钩子函数必须保证空闲线程在任何时刻都不会处于挂起状态,例如rt_thread_delay(),rt_sem_take() 等可能会导致线程挂起的函数都不能使用。
在整个系统的运行时,系统都处于线程运行、中断触发- 响应中断、切换到其他线程,甚至是线程间的切换过程中,或者说系统的上下文切换是系统中最普遍的事件。有时用户可能会想知道在一个时刻发生了什么样的线程切换,可以通过调用下面的函数接口设置一个相应的钩子函数。
在系统线程切换时,这个钩子函数将被调用:
void rt_scheduler_sethook(void (*hook)(struct rt_thread* from, struct rt_thread* to)); |
设置调度器钩子函数的输入参数
如下表所示:
参数 | 描述 |
---|---|
hook | 表示用户定义的钩子函数指针 |
钩子函数hook() 的声明
如下:
void hook(struct rt_thread* from, struct rt_thread* to); |
参数 | 描述 |
---|---|
from | 表示系统所要切换出的线程控制块指针 |
to | 表示系统所要切换到的线程控制块指针 |
!!! note “注意事项” 请仔细编写你的钩子函数,稍有不慎将很可能导致整个系统运行不正常(在这个 钩子函数中,基本上不允许调用系统API,更不应该导致当前运行的上下文挂起)。
参考资料:
windows 下设置双击运行 jar 文件
大家都知道,项目打包的 jar 文件应该是可以直接运行的,虽然我们也可以用指令
java -jar xxx.jar |
运行,但是总归是麻烦些,要是能双击直接打开岂不是很方便,下面我们就来一起看看怎么操作吧
首先确保本地 java
的开发环境配置成功,cmd
执行指令
java -version |
正确显示版本号则配置无误,未配置过的朋友请参考这里
接下来我们找到一个可以执行的 jar
包,右键选择 打开方式 为 jdk
安装目录下的 java\jdk1.8.0_221\bin\javaw.exe
,并勾选 始终用此程序打开
Win + R
组合键输入 regedit
打开注册表编辑器找到HKEY_CLASSES_ROOT\Applications\javaw.exe\shell\open\command
右键修改值,路径后添加 -jar "%1" %*
注意 -
前方有一个空格
修改后返回 jar
包的位置,发现已经改变了,双击即可运行
有时候可能被电脑里的解压程序默认关联了文件格式,这时候如果未生效的话需要到相关软件中取消文件格式关联
]]>记录实际操作中的一些坑,下面放上项目地址,感兴趣的小伙伴请阅读官方文档
https://github.com/coder/code-server
本文配置环境为 : aliyun ECS + Centos 8.2
使用远程工具(推荐 XShell ,有免费的家庭和学生版)链接服务器后,有以下两种方式装载所需包
wget https://github.com/cdr/code-server/releases/download/v4.0.1/code-server-4.0.1-linux-amd64.tar.gz |
# 解压 |
为避免默认 IP 限制问题,我们直接编辑 config 文件,然后再打开访问
# 进入文件中 |
按键盘 i 键进入编辑模式,修改完后按键盘 Esc 键,输入指令 :wq
保存退出
因为默认是只能给 ip 127.0.0.1 端口 8080 访问的,但是我们大部分的电脑没有固定的 ip ,所以我们设置为 0.0.0.0(端口可修改,修改前请在服务器安全组中放行自定义端口,系统防火墙中同样需要放行),让所有的 ip 都能访问到
密码可以在此处修改也可以按下方步骤操作,但注意不要加特殊字符,例如:==@==,启动会报错
添加密码到环境变量
export PASSWORD="your password" |
启动服务前请确保当前目录在解压后的文件夹内,执行如下指令
bin/code-server |
浏览器中输入公网 IP ,测试是否可以正常访问
输入刚才设置的密码,就能进入 云上 IDE 啦
我们现在使用的是链接工具,输入启动命令的方式来运行 code-sesrver ,那我们要是想实现随时随地都能链接到服务的目的,必须让它保持后台进程,这里推荐使用 tmux
使用包管理器安装
# Ubuntu 、 Debian |
创建新会话
tmux new -s vscode_online |
在该会话中执行 code-server 启动命令
bin/code-server --port 8080 --host 0.0.0.0 --auth password |
这样服务就能常驻后台,随时可以访问到了,使用以下命令用于查看/关闭服务
# 接入会话 |
参考资料:
Typora 是一款支持实时预览的 Markdown 文本编辑器,拥有 OS X、Windows、Linux 三大平台版本,且完全免费
它的功能巨多,进入 “偏好设置” 选项卡中,你就会知道这款编辑器设计的有多么地人性化,多么地细节,简直是众多 Markdown 编辑器里的领头羊,像打字机模式、专注模式、源代码模式、实时预览、文件/大纲侧边栏等一系列功能应有尽有
官方特性介绍:Typora为您提供了一个无缝的体验,作为读者和作者。它删除了预览窗口,模式切换器,markdown源代码的语法符号,和所有其他不必要的干扰。相反 ,它提供了一个真实的实时预览功能,以帮助您集中精力于内容本身
对于经常写博客的小伙伴,特别是在多平台分享的朋友,拥有这样一个 “利器” ,搭配上程序猿们忠爱的 GitHub 主题,那感觉简直不要太爽
举个栗子,这篇博客里你所看到的图片,它们存放的位置是哪里呢?图片在我电脑的某个磁盘里,你是怎么看到的呢?显然,你看到的是 “网上” 的图片,图床就是储存图片的服务器,我们发朋友圈、空间、微博里的图片都上传到了各个平台自家的图床,供天涯海角的小伙伴查看
图床有国内和国外之分:国外的图床由于网络、距离等因素访问速度较慢,严重影响图片显示速度,国内也分为单线空间、多线空间和 CDN加速 三种
打开 Typora 中的 “偏好设置”,下载 PicGo(一个用于快速上传图片并获取图片 URL 链接的工具)
GitHub地址 网盘地址,提取码:peng
设定图片插入规则
软件主界面
图床这个东西,还是稳定的好,选择一些老牌子,服务运行久的较为可靠,不然没几天停服可是
打开 SM.MS ,获取Token
Token,就是汉语 “令牌” 的意思,是服务端生成的一串字符串,作为客户端进行请求的一个令牌,当第一次登录后,服务器生成一个 Token 便将此 Token 返回到客户端,日后客户端只需要附带此 Token 前来请求数据即可,无需再次带上用户名和密码
进入 API Token
打开图床设置,粘贴 SM.MS 图床的 Token
好了,现在就可以使用 Typora 这款神仙级 Markdown 编辑器记笔记、写博客了,再也没有发布文章需要一张张重新上传图片的烦恼了
有时候我们总会在想这些图床的服务器到底靠不靠谱,能不能长时间维护,万一哪天崩了,作为使用者的我们岂不是凉凉。这里还有一个方法,那就是用代码托管仓库来建立图床,国内的Gitee在图片上传速度上可能更具优势,但是PicGo工具对于码云的配置更为繁琐,需要安装插件,比较简单的还是直接上手GitHub吧
新建仓库
获取Token
创建Token
创建成功后,注意:Token只显示一次,可以记录在文档中保存下来,忘记的话重新Get一个就好
设置PicGo
测试上传
参考资料
PicGo | PicGo
图片就交给它了
Typora + PicGo 图床配置以及 PicGo 上传失败的解决方案
本站点主题现已更换为 Next,文中除主题外的配置参数均不受影响
偶然间,看到某乎上高赞的一个问题:怎么证明下计算机专业学生的能力?问题下面呢,也是有众多网友评论哈,我记得最清晰、也最现实的一条是:有什么能力的,为了装个 X 罢了
看到这个我就不得不站出来说一句了,证明能力的方式也不是只有建网站这一种方式是吧,那毕竟还是“术业有专攻”呢,对吧。也不知道为什么锻炼下自己的实操能力,拓宽下学识就成了键盘侠下的装 X,咱也喷不过,求饶求饶啊
好了,回归正题,我建立个人网站呢,初衷其实非常简单,说不定你也想过,只是没去做而已。我是想:现在的网络中有好多的写作平台,比如我现在在用的C站,它已经非常成熟,社区讨论、问题发布、Blink动态等等,一应俱全。我在学完相关知识后,为什么不能自己写一个呢?也许更多的是我爱折腾罢了,哈哈
最开始接触是在C站文章发布“板块自定义”模块中,输入几行代码,就能有漂亮的界面。当时因为还没有接触到CSS、Web前端这些,是从网上白嫖来的,更是激起了我深入学习的兴趣
什么是博客,博客是大家分享、交流的一个平台,我们可以从中吸取别人的经验,提升自己。对于看博客的人来说是这样,对于写博客的博主呢,更是对自己所学的总结,能理清自己的思路,便于日后复盘,养成良好的习惯。技术博客,能记录我们遇到的问题,更好的Bug处理方案,在我们日后开发的过程中遇到同样的问题,记忆会更加深刻
有了想法就要动手,当我真正动手去实现的时候,才发现并不是一些标题党发的文章,像“十分钟建立属于你的网站、你还不会自己建网站?”。等到自己真正看着他们的视频、文章去操作的时候,有的是真大神,他默认的一些东西你应该是会的,会写的简单一些。还有一些,就是“伟大的搬运工”了,完完全全就是发布了别人的文章,还不放原文链接那种
正是我没有发现一套完整的,能帮助新手开发一个网站的资源,所以决定写下 UP 建站的过程,分享我从初学到最后实现的一些经验。所以,如果你也想要拥有一个属于自己的网站,可以跟着上手操作下,过程中如果遇到问题可以私信或留言。下面,让我们一起开始吧
思考下,我们查资料用的最多的是什么?有些朋友就会说了:那还用问,必须是“在B站上大学“啦,亦或是搜索引擎了。没错,我想这正是我们大多数人学习新东西、不断探索向前时使用最多的工具了。那,我们搜些什么呢?比如,你可以这样:
或许,你还可以这样:
的确能搜到很多的视频、文章。但是在这部分,我以我是初学者的角度来描述下我的心路历程:因为这东西目前在我的脑子里就是一个初步的想法,我还不知道怎么去实现它。就像是一个人在山里迷路了,我只知道要出去,可我找不到路啊
这一 pa,我们就来聊一些建站,我应该准备什么。网上大多数教程啊,都是一个大长篇,鼠标滑好几下都不带滑完的那种。会给刚入门的朋友一种:”哇,好难啊,这么多东西啊“的感觉,所以这里我对各部分的内容进行了分类,你只要按照顺序,一步步往下走就好啦
这里为什么要强调是”本地“呢,一开始啊,我也是看的教程,跟着别人的思路来走,像什么先买个域名,买台服务器啥的,我都踩过坑。这对刚入门的朋友在购买或者选择上会造成困难,我们莫不如换一种思考方式,现在我自己的电脑上建立一个网站,然后在”发送“出去,让别人都能看到。你看,这不就很明确了吗?
在自己的电脑上实现网站,必须的两个东西浏览器、开发工具,前者大家肯定是都有了,不做赘述(不然你拿什么看到的我这篇文章呢,嘿嘿),我们重点介绍后者
WebStorm 是JetBrains公司旗下一款JavaScript 开发工具。已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能
废话少说,来这里下载 传送门
这儿呢,有个小问题,这玩意是收费的,如果你是一名大学生,可以通过学生认证免费申请到教育账号,如果……(不多说奥,自己去问度娘,能找到方法),直接无脑下一步安装就行,不要慌
Visual Studio Code(简称“VS Code” )是Microsoft在2015年4月30日Build开发者大会上正式宣布一个运行于 Mac OS X、Windows和 Linux 之上的,针对于编写现代Web和云应用的跨平台源代码编辑器,可在桌面上运行,并且可用于Windows,macOS和Linux。它具有对JavaScript,TypeScript和Node.js的内置支持,并具有丰富的其他语言(例如C++,C#,Java,Python,PHP,Go)和运行时(例如.NET和Unity)扩展的生态系统
传送门
这两个工具具体来说就是:前者是全家桶(啥都有,不用你管,直接用就行),后者是一个空壳公司,需要各种员工(插件)去实现一些功能。所以如果你懒得去配置了,就直接下第一个,第二个可能在写博客Markdown语法上更方便一些,这个我后面会说到。此处如果你是新手,我建议你下WebStorm,后文的一些配置上,会更加方便
“框架”这是啥,懵了吧,嘿嘿。遇到事情不要慌,且听杰森娓娓道来。这里咱们看下某度词条的解释:
框架(framework)是一个框子——指其约束性,也是一个架子——指其支撑性。是一个基本概念上的结构,用于去解决或者处理复杂的问题
框架这个广泛的定义使用的十分流行,尤其在软件概念。框架也能用于机械结构
这东西相当于什么呢,比如咱们建房子,你说你怎么建?咱不能没有图纸、没有工人就开始吧,这不是“天方夜谭”嘛。首先肯定是需要设计师根据用户需求设计好这个图纸,然后工人再依据这张图纸开始建房子对吧。这里省略了很多,行业大咖求放过,举个栗子哈
我们搭建网站也一样如此,你真的以为那么多的网站,都是程序猿没日没夜一行一行从零开始写出来的吗?emmm,其实最开始对于这个问题,我的回答是:嗯,是的,那肯定得呀。直到我去实习的时候,才发现企业里的一些东西也并不是全部从零开始开发的。(开源大法好,哈哈哈)难道你想成为这样?
一个产品、项目、网站……只要是有前人做过的东西,我们都可以从中汲取经验啊,学习好的编码,开源的,别人已经实现的我们何必浪费时间再去搞一遍呢?尤其是下文要将的WordPress,简直就是“无脑式操作”,你可能都不知道自己做了什么,但一个属于你的网站就那么出来了
博客框架通俗的说就是别人写好的一套源码,你拿过来会用就行,改一改自己的配置啊,配上想要的主题啊,这种就足够了(大佬请绕路)。所以下面我会给大家分享一些在搭建我的个人网站时,了解到的一些框架,并简单分析,供大家选择
还是老话,此专栏受众对象是刚接触的朋友,所以一些复杂,不需要知道的参数我并不会提及,只涉及到最关键的部分,方便大家快速找到适合自己的那一个
提前声明,杰森用的框架是 ==Hexo== ,各位可以和我选择不同,但配置不尽相同,同理可得的那种
Hexo 是一个快速、简单且功能强大的博客框架。你用Markdown(或其他标记语言)写帖子,Hexo 会在几秒钟内生成带有漂亮主题的静态文件。>点我直达<
Hexo特性:
如果你喜欢配置,对代码操作后完成一定的配置,这款符合你胃口。放上配置截图供参考:
WordPress是基于PHP和MySQL的免费开源内容管理系统(CMS)。 是全球使用最广泛的CMS软件,从最开始一款简单的博客系统,发展成为现在具有数千款插件,小工具和主题功能完整的CMS系统。> 点我直达 <
WordPress特性:
如果你并不像看那些代码,可以用这款,WordPress自带后端管理,选择自己想要的主题,然后拖拽所需控件(比如你想实现显示时间这个功能,会有一个像手机端桌面小组件一样的东西,拖拽到想显示的位置即可实现)。另外最重要的是,使用它你需要先搞一台服务器
为了大家能更快速的找到合适的,我不会给大家很多的可选项,更不会告诉大家还有什么(不然你会觉得,我现在的可能不是最好的,我要尝试更多的。倘若这样的话,不知不觉间你就会浪费很多时间,莫不如跟着一个先搭建下来,等日后熟悉了,再更换其他的。)等到自己独立上手时,也能有个清晰的思路,不至于在某一点上花太多时间
这一块呢,不用过多的介绍,可以理解为我们建房子需要水泥、铲子等工具和原料一样,本地的环境就是我们用到的铲子,是工具。而Hexo的博客框架就是水泥这样的原材料,我们需要用工具才开始干活,不然你***用手干啊……
简单描述下它用来做什么,Look Here:
Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持
不必理会上面你从未听过的词汇,这么来。某度网盘用过吧,是不是有个自动备份,你选中本地的某个文件夹,当本地文件发生改变时,只要软件在后台运行,是不是云上也会和本地自动保持一致。过程就是这么个情况,但是git的操作目前你就可以相像成一个云,用一些命令你就可以把本地的代码“发送/备份”到云上
我并未深入展开讲git的分布式特性,命令等内容,这里推荐入门的朋友可以> 看这里 <的教程,方便快速入门
既然要使用Git,那么我们首先就要安装并配置Git的环境,点击这里下载(Windows操作系统),点击Download按钮即可
安装过程不再赘述,直接使用默认配置,一“Next(站)” 到底
下面我们配置环境变量信息,详情参考此处,打开 Path 变量后,添加本地环境安装目录(确保文件位置到达 cmd )
安装完成后,你可能没有看到桌面的快捷方式,不要着急。我们在Windows搜索框中搜索Git就可以看到这样几个图标
可以直接点击 Git Bash 或者在桌面任意位置右键,打开 Git Bash Here 就可以使用啦
> 下载直达 <
很多朋友纠结这两个版本,看下这个解释相信就知道需要哪个了,杰森用的是LTS版本
LTS代表“Long Term Support(长期支持)”,Current代表“当前的”
Current就代表最新发布的版本(每6个月一次的),它可能是奇数版本也可能是偶数版本
桌面右击,打开git bash here输入命令安装(默认位置即可,方面后续配置,不建议修改)
npm install -g hexo-cli |
这里我已经装过了,可能显示的和你的不一样,执行完后关闭窗口就行,此时本地已经有了hexo的环境。怎么样,是不是很简单呢?
在你本地任意位置(但要记住路径)方便起见建议直接在除C盘的任意盘符下的跟目录新建,命名任意,比如我这里是在D盘新建的 hexo-jason-blog 文件夹,可以参考下
本来我想用自己已经搭好的本地环境给大家演示,但是为了能真实体现“新手”的操作环境,杰森决定重新建立,一步步重新操作,只为大家能走好每一步,直到成功
在该文件夹下打开 git bash here 输入命令
hexo init |
此时你可能会遇到这个错误,不要慌张,是从GitHub克隆时网络原因,多试几次就好
关于此类问题的解决方案请> 参考这里 <
成功效果:
根文件目录下多了这些文件
简单介绍下hexo的文件结构:
我们日常写文的操作都在 source/_post下,既然我们已经有了建房子时“和泥”的工具——WebStorm,为什么不用呢?
在WebStorm中打开根目录 hexo-jason-blog (直接将该文件拽到桌面WebStorm的快捷方式打开就行),打开终端并输入命令
hexo s |
点击链接 http://localhost:4000(图中黄色下划线位置)进行本地预览,默认是hexo内置的landscape 主题
光标停留在 Terminal 位置,组合键 Ctrl + C 停止本地预览,这就是本地最简单的一个网站啦
emmm,默认的页面朋友们也预览成功了,大概呢,就是这样,嘿:
但总感觉,还是差了点什么东西。没有一些博客、网站该有的东西,那怎么能让它更像一个网站呢?
这里我们介绍下主题和框架,我们现在使用的Hexo是一款快速、简单的博客框架,主题就是开发者根据此框架开发的功能更加完备、页面样式、栏目更多的一种”配件“。就像你用的手机,换上手机壳,选手机壳时需要匹配自己手机的型号,不然也不配套啊是吧
再举个“栗子”,像Android手机(IOS闭源,除非越狱),厂家生产时默认的桌面主题,在主题商店这个app里你能根据自己的喜好选择更好看的图标、背景、字体。就像是“换上新衣”,可以从这个角度理解我们下面要做的操作
提及主题,肯定就会有很多啦。还是那句话,大家根据自己的喜好选择就好,这里是官方主题库,我比较喜欢Butterfly这款主题,下面带大家给自己的网站“换新衣”
先给大家看下主题的页面
博客主页
博文页面
从主题的文档中看,作者也是一直在维护的,时间很近。正所谓好的产品必须要有好的文档嘛,作者也是相当用心,大家可以跟着文档一步一步配置,非常简单,只是把一些工具组成链条罢了
git clone -b master https://gitee.com/immyw/hexo-theme-butterfly.git themes/butterfly |
等待安装完成,themes文件夹下显示了butterfly主题的一些文件
安装 pug 以及 stylus 的渲染器,如果没有安装,预览界面是这样的
控制台输入命令,回车等待安装即可
npm install hexo-renderer-pug hexo-renderer-stylus --save |
网站根目录下找到**_config.yml文件,修改主题为butterfly(注意yml**文件格式)
hexo clean //执行此命令后继续下一条 |
效果图
可能看上去还是那么的“简陋”,额,这个问题呢,会涉及到后续的”主题美化“(其实就是加上了一些好看的图片而已,也很简单)。我的博客也没有优化的很细节,非常粗糙,时间有限,后面再说吧,可以看下,留个”念想“,相信你做的会比我更好
这是个ma玩意啊???不要慌,大家不是看咱们默认主题的网站一点儿都不好看么,那是因为没图片啊,你要是给它换上一套配图,优化一下,是不是就好多了呢?那在网络中我们引用图片一种是本地上传,代码里放上路径引用;另一种则是通过网址,显然后者更方便(如果类比到后面要用到的服务器上,随着图片量日渐增多、存储空间慢慢减少,每次发文都需要连同图片一起上传,那得占用多大的空间呐)
然而,如果我们自己有一个地方,能把本地图片转换成链接(人人通过这个链接都能访问到你发布的照片)是不是就很棒了nie。Picgo和一些其他插件就能实现
前些时候更新过一片文章,使用GitHub和SM.MS。如果有不能类比操作的朋友,> 看这里 <由于GitHub毕竟是国外的,访问速度上会有点儿慢,SM.MS倒是一个运行了很久的老牌子了,但它俩在访问速度上都略慢
杰森强烈推荐国内的码云(Gitee),配合Picgo使用。稳定、快速,还不容易丢失。(ps:此处就会有些朋友问了,我公开了我的仓库,里面全放的是我的照片,会不会隐私存在隐私泄露什么的)对于这类问题,我只能说
谁天天闲的没事去看你仓库啊??再者说,你能上传到仓库里XXX(自行想象)照片么??所以说,放心用,不要想辣么多真的是
另外,友情提示:Gitee对免费版账户存储容量最大为5G,仓库满了记得从软件中改下路径,使用后不要乱改自己Gitee账户的名称(不是昵称,英文那个名称),不然就等404吧
直接放上官方文档,朋友们可以先配置一下,非常简单。你看到的页面可能是繁体中文,不要用浏览器自带的翻译引擎(可能翻译后,部分内容不显示)贴心的作者,早已想到了,我们只要在网站右下角设置中切换一下就好
杰森在后面会专门出一期,来讲下主题配置中的一些问题,相信看到这里的小伙伴已经迫不及待想要把自己的网站发不到网上了吧,我们重点讲这个问题
GitHub Pages是一种由GitHub中的仓库/项目直接创建的网页。管理简单,在本地编辑仓库中的内容,上传到GitHub上,GitHub Pages就能快速完成更新,重点是不花钱,不花钱,不花钱
新建仓库,填写内容如下,特别注意红框位置
保证仓库public,名称填写正确用户名.github.io,系统自动变更为Pages
在仓库设置中找到Pages
记住仓库地址,我们会将本地的文件上传到仓库
如果你是在电脑上第一次使用git,请先配置SSH公钥(一种安全协议,你可以理解为登陆某网站需要的验证码)
在WebStorm中链接到远程,添加仓库地址,这里不是发布网站需要的仓库(非“用户名”+github.io仓库,新建一个,为了管理本地代码)
因为这里都是基本的git命令,前面也提到过,不清楚的小伙伴可以看这个专栏里的资料,都是一些基础操作,非常容易上手
修改网站部署设置
在网站本地根目录下打开 git bash here 依次执行以下命令
hexo clean //执行此命令后继续下一条 |
执行完毕后,所有人就能通过你的用户名+github.io这个域名访问你的网站了。到这儿,我们就成功上线了自己的网站
如果感觉GitHub访问速度慢(嗯,其实就是慢,还会有打不开的情况)可以部署到Gitee,都是一样的操作,还是中文,不要太简单ei
额,发布确实是发布了,那你觉得像用户名+github.io这样的名称方便记忆吗??我想,如果是一个新手(可能都不知道GitHub是什么的用户,肯定是很困难了)
那,怎么样方便记忆,而且足够个性化呢?
当然,这部分肯定是不免费的了,哪儿有什么都白嫖的道理呢?对吧,推荐在阿里云或腾讯云完成下面的操作哦,如果你使用其他的平台,不是不行,但是建议购买域名和服务器都在相同的平台,方便管理
国内的大厂,都有保障,无脑冲就可以啦。从经济性角度来看,哪个有活动,更实惠就选哪个,杰森是看到了阿里云当时的活动比腾讯云更实惠,so~~
收到有些朋友反应:那么多入口,都找不到从哪里买/找不到活动入口。这里讲下怎么查看最新的活动,平台会有哪些优惠,入口在哪里
账号中心完成学生认证购买更优惠
最新活动 > 戳我直达 <
不得不说,两家界面基本一致,熟悉一个就行,所以位置差不多都一样
学生党查看这里 > 戳我直达 <
最新活动 > 戳我直达 <
域名(英语:Domain Name),又称网域,是由一串用点分隔的名字组成的Internet上某一台计算机或计算机组的名称,用于在数据传输时对计算机的定位标识(有时也指地理位置)
由于IP地址具有不方便记忆并且不能显示地址组织的名称和性质等缺点,人们设计出了域名,并通过网域名称系统(DNS,Domain Name System)来将域名和IP地址相互映射,使人更方便地访问互联网,而不用去记住能够被机器直接读取的IP地址数串
如果你没有看懂,没关系,那听杰森细细道来。简单来说,在公网上访问的资源都有其固定地址IP,但是如果你要访问特定的IP,就需要记住它。但是呢,它不方便记忆,人们就想出了域名这东西
给IP起了一个个性化的名称,比如攻城狮杰森是全称,朋友们喊我森森、阿森、小森,都是别名,但都指向“攻城狮杰森”这个人。那在网络中如何实现起别名呢?这里介绍下DNS,它是互联网中的一项服务,实域名和IP的相互映射,也就是说,你输入域名访问的就是域名所对应的IP地址
既然理解了什么是域名,那我们先来买个域名吧!
> 点击此处 < 查询你想要的域名
举个栗子,输入后查询,选好后加入清单,付款购买即可。不同的后缀价格不同,凭个人喜好
域名后缀,亦被称为顶级域名,是指代表一个域名类型的符号。 不同后缀的域名有不同的含义。域名共分为两类:国别域名(ccTLD),例如中国的.cn、美国的.us、俄罗斯的.ru、以及国际通用域名(gTLD),例如.com、.xyz、.top、.wang、pub、.xin、.net等1000多种,所有域名后缀作用无差异,仅外观和本身含义不同,但只有少数例如举例中的域名后缀可以在国内支持网站的备案
更多域名后缀信息,查看这里
因为我们现在已经有了用户名.github.io这样一个网站,为了简单易记,我们将“用户名.github.io“解析”到所购买的域名,这样,网站就有了所有域名和username.github.io两个网址了
打开仓库,找到设置,进入pages设置,添加域名
你还可以使用免费的强制HTTPS
HTTPS (全称:Hyper Text Transfer Protocol over SecureSocket Layer),是以安全为目标的 HTTP 通道,在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性
HTTPS 在HTTP 的基础下加入SSL,HTTPS 的安全基础是 SSL【SSL(Secure Sockets Layer 安全套接字协议),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层与应用层之间对网络连接进行加密】
因此加密的详细内容就需要 SSL。 HTTPS 存在不同于 HTTP 的默认端口及一个加密/身份验证层(在 HTTP与 TCP 之间)。这个系统提供了身份验证与加密通讯方法。它被广泛用于万维网上安全敏感的通讯,例如交易支付等方面
打开这个选项
在阿里云官网进入域名控制台
若没有,在此处搜索
找到需要与username.github.io绑定的域名,点击“解析”
进入后,点击“添加记录”,需添加两次记录
第一次
第二次
DNS解析需要时间,稍等片刻后,若在浏览框中输入你的域名,正常访问则解析成功
这里为什么要说是正式上线呢,毕竟网站到了服务器看得才,才正规一点儿是吧,像GitHub Pages,倒是免费,但是在国内,DNS解析后需要时间,总会有无法访问或者断连的情况,太不方便
先来看看,服务器是何方神圣?
服务器是计算机的一种,它比普通计算机运行更快、负载更高、价格更贵。服务器在网络中为其它客户机(如PC机、智能手机、ATM等终端甚至是火车系统等大型设备)提供计算或者应用服务。服务器具有高速的CPU运算能力、长时间的可靠运行、强大的I/O外部数据吞吐能力以及更好的扩展性
根据服务器所提供的服务,一般来说服务器都具备承担响应服务请求、承担服务、保障服务的能力。服务器作为电子设备,其内部的结构十分的复杂,但与普通的计算机内部结构相差不大,如:cpu、硬盘、内存,系统、系统总线等
简单理解:一台不断电,有空间的主题在“天上(云端)”一直在为你放置(部署)上去的资源而服务,能处理各种请求(比如你在导航栏输入域名访问网站)
有两种类型的服务器国内和国外的,根据我国法律规定,中国大陆的网站需要备案,等待的时间可能会长一点。国外的到时不需要备案,但是稳定性和访问速度就不敢保证了,各位小伙伴自己衡量,杰森用的是阿里云的轻应用服务器部署的个人博客网站
这是我的服务器配置,大家可以参考下
如果你是初学者,这个入门级的配置已经足够学生机,可免费领取,具体规则详见社区 > 戳我直达 <
开发者-> 成长计划
学生专享(体验后即可得到半月免费ECS服务器,社区内发表使用感受(发一篇博客)可免费续费两月),具体规则请查看官网
账号中心-> 基本信息位置完成学生认证即可
最新活动 位置购买优惠力度会更大
在图示位置出更改远程连接密码,保存好
虽然可以用浏览器远程连接,但是并不建议,因为有一些键盘上的快捷键会被系统误认为是对浏览器的操作,而不是对话框
为避免这样的问题出现,我们选择使用第三方工具Putty,具体操作步骤,阿里云的帮助文档已经非常详细,这里不再重复
从这里开始看,根据提示完成操作
启动Putty工具,链接服务器,登陆用户名为root,密码就是在服务器位置设置的密码(Linux操作系统中输入密码为了安全不显示,不必担心)出现以下界面时,说明配置正常,继续下一步即可
1.输入命令,安装git
yum install git |
中途如果暂停,则根据提示输入 yes / y / Y,表示继续安装,知道最后出现complete表示安装成功
2.创建git账户
adduser git |
3.添加git账户权限
chmod 740 /etc/sudoers |
4.执行最后一条命令后,点击键盘 i键进入编辑模式,找到图示位置代码
在下面加入一行
git ALL=(ALL) ALL |
按 Esc 键并输入 ==:wq==(含义:保存后退出)
5.回改权限
chmod 400 /etc/sudoers |
6.设置git账户密码
sudo passwd git |
输入命令回车后连续输入两次密码即可(不显示,正常),出现图示即成功
7.切换至git账户
su git |
创建 ~/.ssh 和 ~/.ssh/authorized_keys 文件
mkdir ~/.ssh |
点击键盘 i 键进入编辑模式,粘贴本地电脑生成的SSH公钥,文件位置如图
粘贴后,按 Esc 键并输入 ==:wq==(含义:保存后退出)
赋予权限
chmod 600 /home/git/.ssh/authorized_keys |
8.本地 git bash here 中测试是否免密登陆成功
ssh -v git@服务器公网IP |
出现图示内容表示连接成功
9.服务器中创建仓库并完成配置
切换到root账户
sudo su root |
创建repo仓库目录
mkdir /www/repo |
赋予权限
|
建立网站根目录hexo
mkdir /www/hexo |
赋予权限
chown -R git:git /www/hexo |
新建空白的git仓库并初始化
cd /www/repo |
10.创建 Git 钩子,用于自动部署
vim /www/repo/hexo.git/hooks/post-receive |
同上,进入编辑模式,粘贴下面代码并保存退出
|
修改权限
chown -R git:git /www/repo/hexo.git/hooks/post-receive |
仓库建立完毕
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好
Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务,其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、简单的配置文件和低系统资源的消耗而闻名
yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && bash install.sh |
中途输入 y,表示继续安装(和上面一样)等待安装完成,会显示登陆网址和初始密码
注意红框位置,如果两个网址都无法访问,请在服务器安全组 / 防火墙中放行8888端口
输入初始账户名、密码登陆
进入后,搜索Nginx点击安装(我这里已经装过了)
网站–> 添加站点,域名形式xxx.com 无需任何前缀
设置–> 配置文件,修改红框内容
设置–> 网站目录,修改为 ==/www/hexo== 并保存
服务器终端,重启服务
service bt restart |
至此,服务器端配置完成
进入本地博客根目录,修改 _config.yml 文件部署位置
GitHub Pages 设定
服务器设置
源码如下
# Deployment |
打开Putty工具,连接服务器赋予权限
chown -R git:git /www/repo/ |
本地根目录下打开 git bash here执行命令
hexo clean //清除缓存 |
出现图示内容表示部署成功,等到备案完成后就可以通过域名访问了
杰森的网站也是最近才备案下来,所以如果你等不及,就另寻他路吧,在国内,咱可不敢造次啊啊啊
你会经历以下几个阶段
购买服务器后,绑定域名后系统会提示你没有备案,根据提示完成即可
英文全称:Internet Content Provider,中文全称:网络内容提供商
ICP可以理解为向广大用户提供互联网信息业务和增值业务的电信运营商,是经国家主管部门批准的正式运营企业或部门
进入官网 在阿里云完成ICP备案后,系统也会提示你操作
部署完成后,选择联网备案登陆
提交网站所有人信息和一些基本材料等待审核通过,最后在网页底部插入代码即可,效果如图
到这里,你的个人网站就成功上线了,也部署到了服务器。内容会根据大家的反馈情况持续更新!!!
最后,放上杰森的小破站地址,欢迎到访 haha
参考资料
技术小白如何建站
Picgo+Gitee搭建个人免费图床
Git 错误:OpenSSL SSL_read: Connection was reset, errno 10054
学校资料
设计一个单周期CPU,该CPU至少能实现以下指令功能操作。指令与格式如下:
==> 算术运算指令
1. add rd , rs, rt (说明:以助记符表示,是汇编指令;以代码表示,是机器指令)
000000 | rs(5位) | rt(5位) | rd(5位) | reserved |
---|
功能:rd←rs + rt。reserved为预留部分,即未用,一般填“0”。
2. addi rt , rs ,immediate
000001 | rs(5位) | rt(5位) | immediate(16位) |
---|
功能:rt←rs + (sign-extend)immediate;immediate符号扩展再参加“加”运算。
3. sub rd , rs , rt
000000 | rs(5位) | rt(5位) | rd(5位) | reserved |
---|
功能:rd←rs - rt
==> 逻辑运算指令
4. ori rt , rs ,immediate
010000 | rs(5位) | rt(5位) | immediate(16位) |
---|
功能:rt←rs | (zero-extend)immediate;immediate做“0”扩展再参加“或”运算。
5. and rd , rs , rt
010001 | rs(5位) | rt(5位) | rd(5位) | reserved |
---|
功能:rd←rs & rt;逻辑与运算。
6. or rd , rs , rt
010010 | rs(5位) | rt(5位) | rd(5位) | reserved |
---|
功能:rd←rs | rt;逻辑或运算。
==>移位指令
7. sll rd, rt,sa
011000 | 未用 | rt(5位) | rd(5位) | sa | reserved |
---|
功能:rd<-rt<<(zero-extend)sa,左移sa位 ,(zero-extend)sa
==>比较指令
8. slti rt, rs,immediate 带符号
011011 | rs(5位) | rt(5位) | immediate(16位) |
---|
功能:if (rs <(sign-extend)immediate) rt =1 else rt=0, 具体请看表2 ALU运算功能表,带符号
==> 存储器读/写指令
9. sw rt ,immediate(rs) 写存储器
100110 | rs(5位) | rt(5位) | immediate(16位) |
---|
功能:memory[rs+ (sign-extend)immediate]←rt;immediate符号扩展再相加。即将rt寄存器的内容保存到rs寄存器内容和立即数符号扩展后的数相加作为地址的内存单元中。
10. lw rt , immediate(rs) 读存储器
100111 | rs(5位) | rt(5位) | immediate(16位) |
---|
功能:rt ← memory[rs + (sign-extend)immediate];immediate符号扩展再相加。
即读取rs寄存器内容和立即数符号扩展后的数相加作为地址的内存单元中的数,然后保存到rt寄存器中。
==> 分支指令
11. beq rs,rt,immediate
110000 | rs(5位) | rt(5位) | immediate(16位) |
---|
功能:if(rs=rt) pc←pc + 4 + (sign-extend)immediate <<2 else pc ←pc + 4
特别说明:immediate是从PC+4地址开始和转移到的指令之间指令条数。immediate符号扩展之后左移2位再相加。为什么要左移2位?由于跳转到的指令地址肯定是4的倍数(每条指令占4个字节),最低两位是“00”,因此将immediate放进指令码中的时候,是右移了2位的,也就是以上说的“指令之间指令条数”。
12. bne rs,rt,immediate
110001 | rs(5位) | rt(5位) | immediate(16位) |
---|
功能:if(rs!=rt) pc←pc + 4 + (sign-extend)immediate <<2 else pc ←pc + 4
特别说明:与beq不同点是,不等时转移,相等时顺序执行。
==>跳转指令
13. j addr
111000 | addr[27…2] |
---|
功能:pc <-{(pc+4)[31..28],addr[27..2],2{0}},无条件跳转。
说明:由于MIPS32的指令代码长度占4个字节,所以指令地址二进制数最低2位均为0,将指令地址放进指令代码中时,可省掉!这样,除了最高6位操作码外,还有26位可用于存放地址,事实上,可存放28位地址了,剩下最高4位由pc+4最高4位拼接上。
==> 停机指令
14. halt
111111 | 00000000000000000000000000(26位) |
---|
功能:停机;不改变PC的值,PC保持不变。
单周期CPU指的是一条指令的执行在一个时钟周期内完成,然后开始下一条指令的执行,即一条指令用一个时钟周期完成。电平从低到高变化的瞬间称为时钟上升沿,两个相邻时钟上升沿之间的时间间隔称为一个时钟周期。时钟周期一般也称振荡周期(如果晶振的输出没有经过分频就直接作为CPU的工作时钟,则时钟周期就等于振荡周期。若振荡周期经二分频后形成时钟脉冲信号作为CPU的工作时钟,这样,时钟周期就是振荡周期的两倍。)
单周期CPU,是在一个时钟周期内完成这五个阶段的处理。
MIPS指令的三种格式:
控制信号名 | 状态“0” | 状态“1” |
---|---|---|
Reset | 初始化PC为0 | PC接收新地址 |
PCWre | PC不更改,相关指令:halt | PC更改,相关指令:除指令halt外 |
ALUSrcA | 来自寄存器堆data1输出,相关指令:add、sub、addi、or、and、ori、beq、bne、slti、sw、lw | 来自移位数sa,同时,进行(zero-extend)sa,即 {{27{0}},sa},相关指令:sll |
ALUSrcB | 来自寄存器堆data2输出,相关指令:add、sub、or、and、sll、beq、bne | 来自sign或zero扩展的立即数,相关指令:addi、ori、slti、sw、lw |
DBDataSrc | 来自ALU运算结果的输出,相关指令:add、addi、sub、ori、or、and、slti、sll | 来自数据存储器(Data MEM)的输出,相关指令:lw |
RegWre | 无写寄存器组寄存器,相关指令:beq、bne、sw、halt、j | 寄存器组写使能,相关指令:add、addi、sub、ori、or、and、slti、sll、lw |
InsMemRW | 写指令存储器 | 读指令存储器(Ins. Data) |
mRD | 输出高阻态 | 读数据存储器,相关指令:lw |
mWR | 无操作 | 写数据存储器,相关指令:sw |
RegDst | 写寄存器组寄存器的地址,来自rt字段,相关指令:addi、ori、lw、slti | 写寄存器组寄存器的地址,来自rd字段,相关指令:add、sub、and、or、sll |
ExtSel | (zero-extend)immediate(0扩展),相关指令:ori | (sign-extend)immediate(符号扩展),相关指令:addi、slti、sw、lw、beq、bne |
PCSrc[1..0] | 00:pc<-pc+4,相关指令:add、addi、sub、or、ori、and、slti、sll、sw、lw、beq(zero=0)、bne(zero=1);01:pc<-pc+4+(sign-extend)immediate,相关指令:beq(zero=1)、bne(zero=0);10:pc<-{(pc+4)[31:28],addr[27:2],2{0}},相关指令:j;11:未用 | - |
ALUOp[2..0] | ALU 8种运算功能选择(000-111),看功能表 |
相关部件及引脚说明:
表2 ALU运算功能表
ALUOp[2:0] | 功能 | 描述 |
---|---|---|
000 | Y = A + B | 加 |
001 | Y = A – B | 减 |
010 | Y = B << A | B左移A位 |
011 | Y = A ∨ B | 或 |
100 | Y = A ∧ B | 与 |
101 | Y =(A < B)? 1: 0 | 比较A与B 不带符号 |
110 | 比较A与B 带符号 | |
111 | Y = A ⊕ B | 异或 |
设计思路以及流程:
表3是依据表1控制信号的作用以及表2 ALU运算功能表完成的,某些指令无需用到部分模块,则相对应模块的使能控制信号与其无关。例如,对于跳转指令而言,其无需对数据寄存器进行读写操作,则数据寄存器相关的控制信号mRD,mWR设为0,防止修改里面的数据。部分指令执行不需要所有的模块都参与,故有些模块的控制信号与其没有直接关系,为了防止出现一些不必要的错误,统一将指令相对应的无关的使能控制信号默认设置为低电平(0),无需ALU运算的(例如跳转指令)默认将其操作变成(000)。**
表3 控制信号与相对应指令之间的相互关系
指 令 | 控制信号量 | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
PCWre | ExtSel | InsMemRW | RegDst | RegWre | ALUSrcA | ALUSrcB | PCSrc(zero:0/1) | ALUOp | mRD | mWR | DBDataSrc | |
addi | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 00 | 000 | 0 | 0 | 0 |
ori | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 00 | 011 | 0 | 0 | 0 |
add | 1 | 0 | 1 | 1 | 1 | 0 | 0 | 00 | 000 | 0 | 0 | 0 |
sub | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 00 | 001 | 0 | 0 | 0 |
and | 1 | 0 | 1 | 1 | 1 | 0 | 0 | 00 | 100 | 0 | 0 | 0 |
or | 1 | 0 | 1 | 1 | 1 | 0 | 0 | 00 | 011 | 0 | 0 | 0 |
sll | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 00 | 010 | 0 | 0 | 0 |
bne | 1 | 1 | 1 | X | 0 | 0 | 0 | 01/ 00 | 001 | 0 | 0 | 0 |
slti | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 00 | 101 | 0 | 0 | 0 |
beq | 1 | 1 | 1 | X | 0 | 0 | 0 | 00 / 01 | 001 | 0 | 0 | 0 |
sw | 1 | 1 | 1 | X | 0 | 0 | 1 | 00 | 000 | 0 | 1 | 0 |
lw | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 00 | 000 | 1 | 0 | 1 |
j | 1 | 0 | 1 | X | 0 | X | X | 10 | 000 | 0 | 0 | 0 |
halt | 0 | 0 | 0 | X | 0 | X | X | 00 | 000 | 0 | 0 | 0 |
完成控制信号与相对应指令之间的关系以后该表后,对于如何实现单周期依旧感到很模糊,不知道相对应的信号量具体的控制意义,因此尝试结合实验原理中的图2单周期CPU数据通路和控制线路图,思考三种类型的指令,R型、I型、J型指令的CPU处理过程。对于R型指令而言,主要是一些算术运算指令和逻辑运算,主要为取指令,解析指令,执行指令,将运算结果写回寄存器组,其不需要访问数据寄存器,下一条指令顺序下一条,即pc←pc+4,其中的一些运算则由控制单元得到指令的操作码以后,设置控制信号,控制各个模块执行不同操作或者数据选择器选择相对应的输入作为输出;对于I型指令,其包含指令种类比较多,存储器指令,需要对存储器进行读或写的操作,对于pc没有别的特别影响,而分支指令则下一个pc可能不是pc+4,需要依据其运算结果做相对应的跳转操作或者顺序执行操作;对于J型指令,其是跳转指令,跳转到指令中相对应的地址中,主要对pc进行操作。不同类型的指令,其进行的过程并非完成相同的,不同类型指令所使用的模块并不是一样的,所有的指令也不是都需要完整的五个处理阶段。结合CPU数据通路图以及指令相对应的控制信号后,对于每种指令的数据通路有了一个比较清晰的了解,对于每个控制信号与相对应的功能模块更加熟悉和了解,理清了如何设计单周期CPU,即将其模块化,并且在控制单元中依据指令的操作码,对各个模块的控制信号进行一定的设定,执行指令相对应的操作。
依据图2 单周期CPU数据通路和控制线路图,将CPU划分为9个模块,没有完全依据单周期CPU数据通路图进行划分,主要依据数据通路图进行划分太冗余,因此将一些数据选择器合并进了部分功能模块中,实现简化。模块划分结果如图三所示。
模块功能:根据控制信号PCSrc,计算获得下一个pc以及控制信号Reset重置。
实现思路:首先先决定何时引起触发,决定敏感变量,该模块选择将时钟的下降沿以及控制信号Reset的下降沿作为敏感变量,主要是为了能够确保下一条pc能够正确得到。
`timescale 1ns / 1ps |
模块功能:根据控制信号PCWre,判断pc是否改变以及根据Reset信号判断是否重置
实现思路:将时钟信号的上升沿和控制信号Reset作为敏感变量,使得pc在上升沿的时候发生改变或被重置。
主要实现代码:
`timescale 1ns / 1ps |
模块功能:依据当前pc,读取指令寄存器中,相对应地址的指令
实现思路:将pc的输入作为敏感变量,当pc发生改变的时候,则进行指令的读取,根据相关的地址,输出指令寄存器中相对应的指令
`timescale 1ns / 1ps |
模块功能:对指令进行分割,获得相对应的指令信息
实现思路:根据各种类型的指令结构,将指令分割,得到相对应的信息
`timescale 1ns / 1ps |
模块功能:控制单元,依据指令的操作码(op)以及标记符(ZERO),输出PCWre、ALUSrcB等控制信号,各控制信号的作用见实验原理的控制信号作用表(表3),从而达到控制各指令的目的.
`timescale 1ns / 1ps |
模块功能:寄存器组,通过控制单元输出的控制信号,进行相对应的读或写操作
`timescale 1ns / 1ps |
模块功能:算术逻辑单元,对两个输入依据ALUOp进行相对应的运算
实现思路:依据实验原理中的ALU运算功能表(表2)完成操作码对应的操作
`timescale 1ns / 1ps |
模块功能:数据存储器,通过控制信号,对数据寄存器进行读或者写操作,并且此处模块额外合并了输出DB的数据选择器,此模块同时输出写回寄存器组的数据DB。
`timescale 1ns / 1ps |
模块功能:根据指令相关的控制信号ExtSel,对立即数进行扩展。
实现思路:根据控制信号ExtSel判断是0扩展还是符号扩展,然后进行相对应的扩展
`timescale 1ns / 1ps |
`timescale 1ns / 1ps |
`timescale 1ns / 1ps |
地址 | 汇编程序 | 指令代码 | |||
---|---|---|---|---|---|
op(6) | rs(5) | rt(5) | rd(5)/immediate (16) | ||
0x00000000 | addi $1,$0,8 | 000001 | 00000 | 00001 | 0000 0000 0000 1000 |
0x00000004 | ori $2,$0,2 | 010000 | 00000 | 00010 | 0000 0000 0000 0010 |
0x00000008 | add $3,$2,$1 | 000000 | 00010 | 00001 | 0001 1000 0000 0000 |
0x0000000C | sub $5,$3,$2 | 000010 | 00011 | 00010 | 0010 1000 0000 0000 |
0x00000010 | and $4,$5,$2 | 010001 | 00101 | 00010 | 0010 0000 0000 0000 |
0x00000014 | or $8,$4,$2 | 010010 | 00100 | 00010 | 0100 0000 0000 0000 |
0x00000018 | sll $8,$8,1 | 011000 | 00000 | 01000 | 0100 0000 0100 0000 |
0x0000001C | bne $8,$1,-2 (≠,转18) | 110001 | 01000 | 00001 | 1111 1111 1111 1110 |
0x00000020 | slti $6,$2,8 | 011011 | 00010 | 00110 | 0000 0000 0000 1000 |
0x00000024 | slti $7,$6,0 | 011011 | 00110 | 00111 | 0000 0000 0000 0000 |
0x00000028 | addi $7,$7,8 | 000001 | 00111 | 00111 | 0000 0000 0000 1000 |
0x0000002C | beq $7,$1,-2 (=,转28) | 110000 | 00111 | 00001 | 1111 1111 1111 1110 |
0x00000030 | sw $2,4($1) | 100110 | 00001 | 00010 | 0000 0000 0000 0100 |
0x00000034 | lw $9,4($1) | 100111 | 00001 | 01001 | 0000 0000 0000 0100 |
0x00000038 | j 0x00000040 | 111000 | 00000 | 00000 | 0000 0000 0001 0000 |
0x0000003C | addi $10,$0,10 | 000001 | 00000 | 01010 | 0000 0000 0000 1010 |
0x00000040 | Halt | 111111 | 00000 | 00000 | 0000 0000 0000 0000 |
0x00000044 | |||||
0x00000048 | |||||
0x0000004C |
使用上面程序段进行测试CPU正确性,将其中的指令写入一个romData.txt文件中。 在模块InsMEM中进行读入(使用的路径为绝对路径)
(源码和实验报告)
本次实验中遇到的问题比较多。首先是关于CPU的设计,其次就是verilog语言。一开始不知道如何实现,感觉无从下手。主要通过分析实验原理中的图2 单周期CPU数据通路和控制线路图,分析各种指令的处理过程,学会将CPU内各个部分模块化,各个模块分别实现一定的功能,然后通过相对应的控制信号连接起来,这样就实现cpu设计。完成模块的划分以后,按照先前对每个模块功能预设进行完成,但是每个模块的敏感信号的选择还是很重要的,有些模块程序要在时钟信号上升沿触发,而有些模块要在时钟信号的下降沿触发,有些则将电平信号作为敏感信号,每个模块里面的敏感信号的选择都十分的重要,一开始没有太过注意导致出现了很多的问题,后面重新仔细的想指令的处理过程,重新规定了各个模块always@里面的敏感信号。
其次就是verilog里面的wire和reg两种变量类型,感觉这是比较大的坑。一开始不了解两者的区别,导致后面一堆报错。现在大致的清楚了二者的区别,wire主要起信号间连接的作用,例如顶层模块中,需要将各个模块连接起来,这时候只能用wire连接,不能使用reg,wire不保存状态,它的值的随时可以改变,不受时钟信号的影响,而reg则是寄存器的抽象表达,可以用于存储数值,例如指令寄存器和寄存器组以及数据寄存器里面的存储器必须为reg类型,用于保留数据。其次wire类型只能通过assign进行赋值,而reg类型只能在always里面被赋值,而涉及到always又有阻塞赋值和非阻塞赋值这个大坑,一开始也不知道怎么弄,就混用了,后面也是出现乱七八糟的问题,后面仔细学习了一下,敏感信号为电平信号的时候,采用阻塞赋值(=),而敏感信号为时序信号的时候,采用非阻塞赋值(<=)。
再者就是烧板的时候的消抖问题。一开始没有进行消抖,然后总是按一下运行了几条指令,后面上网学习了一下如何消抖,顺利的解决了该问题。
还有比较疑惑的问题就是使用vivado进行Implemention的时候,有时候进行Running place_design这一部分的时候就一直在此处运行,没有任何进度了,网上也没有合理的解释,然后新新建个项目,将里面的代码复制进去又可以正常的运行了,这个问题目前尚未解决。
本次单周期CPU设计实验,将计组理论课上所讲的指令处理过程自己重复并实现了单周期CPU的设计,加深了CPU处理指令过程理解,之前由于计组理论学的不是特别清楚,本次实验加深了印象,也更加了解每条指令的处理过程以及单周期CPU是如何工作的,同时本次实验也更加了解verilog语言,之前学的懵懵懂懂的,最重要的是学会模块化,将一项工作分成多个模块进行完成,先简化成小部分,然后再将其组合起来。
SQL(Structured Query Language),结构化查询语言
T-SQL
和 SQL
的区别:
T-SQL
是 SQL
语言的一种版本,且只能在 SQL SERVER
上使用。是 ANSI SQL
的加强版语言、提供了标准的 SQL
命令。另外,T-SQL
还对 SQL
做了许多补允,提供了类似 C
、Basic
和 Pascal
的基本功能,如变量说明、流控制语言、功能函数等SQL
由甲骨文发布,T-SQL
由微软发布SQL
是一种标准,T-SQL
是 SQL
在 SQL SERVER
上的实现主要功能:
主要文件:
.mdf
.ndf
.ldf
CREATE DATABASE db_test |
ALTER DATABASE db_test |
EXECUTE Sp_helpdb db_test --查看数据库 |
EXECUTE Sp_detach_db db_test --分离数据库 |
注:数据库的分离与附加一般发生在数据库在不同机器迁移的情况下使用,当使用 Management Studio 操作时,可能会因权限问题导致附加失败,下面演示如何修改*控制权限
本地找到数据库主文件(.mdf)右键修改属性,勾选完全控制
打开 Management Studio 选中数据库节点,进入附加数据库窗口
选择数据库文件位置,添加执行即可
DROP DATABASE db_test |
*注:SQL 指令常用大写,减少后台指令转换执行时间,提升速度,影响较小,基本可忽略
实验任务 1
要求设计一个数据库,数据库名为 db_HX(要求利用 SQL Server Management
Studio 平台,T-SQL 语句两种方式创建数据库);数据库名为 db_HX;数据库中包含一
个数据文件,逻辑文件名为 HX_DATA,物理文件名为 HX_DATA.MDF,文件的初始容量为
5MB,最大容量为 15MB,文件容量递增值为 2MB
事务日志文件的逻辑文件名为 HX_LOG,物理文件名为 HX_LOG.LDF,初始容量为
3MB,最大容量为 10MB,文件容量递增值为 1MB;
实验任务 2
利用 SQL Server Management Studio 平台,T-SQL 语句两种方式修改数据库,按
要求对数据库进行修改在数据库 db_HX 中添加一个数据文件,逻辑文件名为 HX_DATA1,
文件的初始容量为 3MB,最大容量为 15MB,文件容量递增值为 2MB;
将事务日志文件的最大容量改为 20MB,文件容量递增值为 2MB;
实验任务 3
利用 SQL Server Management Studio 平台,T-SQL 语句两种方式修改数据库,按
要求对数据库文件进行删除,将数据库 db_HX 中刚添加的 HX_DATA1 数据库文件删除。
实验任务 4
利用 SQL Server Management Studio 平台,T-SQL 语句两种方式,将数据库 db_HX
进行分离和附加操作。
实验任务 5
使用 T-SQL 语句删除数据库 db_HX
任务拓展
创建一个包含多个数据文件和日志文件的数据库 db_MNS,该数据库包含两个初始大小
为 15MB 的数据文件和两个 5MB 的日志文件。
--任务1 |
Tips:
]]>选中代码,点击执行可以执行 部分指令
数据类型 | 含义 |
---|---|
CHARACTER(n) | 字符/字符串。固定长度 n。 |
VARCHAR(n) 或 CHARACTER VARYING(n) | 字符/字符串。可变长度。最大长度 n。 |
BINARY(n) | 二进制串。固定长度 n。 |
BOOLEAN | 存储 TRUE 或 FALSE 值 |
VARBINARY(n) 或 BINARY VARYING(n) | 二进制串。可变长度。最大长度 n。 |
INTEGER(p) | 整数值(没有小数点)。精度 p。 |
SMALLINT | 整数值(没有小数点)。精度 5。 |
INTEGER | 整数值(没有小数点)。精度 10。 |
BIGINT | 整数值(没有小数点)。精度 19。 |
DECIMAL(p,s) | 精确数值,精度 p,小数点后位数 s。例如:decimal(5,2) 是一个小数点前有 3 位数,小数点后有 2 位数的数字。 |
NUMERIC(p,s) | 精确数值,精度 p,小数点后位数 s。(与 DECIMAL 相同) |
FLOAT(p) | 近似数值,尾数精度 p。一个采用以 10 为基数的指数计数法的浮点数。该类型的 size 参数由一个指定最小精度的单一数字组成。 |
REAL | 近似数值,尾数精度 7。 |
FLOAT | 近似数值,尾数精度 16。 |
DOUBLE PRECISION | 近似数值,尾数精度 16。 |
DATE | 存储年、月、日的值。 |
TIME | 存储小时、分、秒的值。 |
TIMESTAMP | 存储年、月、日、小时、分、秒的值。 |
INTERVAL | 由一些整数字段组成,代表一段时间,取决于区间的类型。 |
ARRAY | 元素的固定长度的有序集合 |
MULTISET | 元素的可变长度的无序集合 |
长度 N
、精度 P
、小数位数 S
numeric(P,[S])
表示数据精度为 P,小数位数为 S
数据精度:能精确到小数点后的位数,小数点右侧位数
建立表格其实就是定义每一列的过程
数据库表节点,新建
定义列属性,完成建表操作
-- SQL指令建立学生表 |
数据完整性
保证数据库中数据的正确性、有效性、相容性,完整性机制主要有:
- 约束 Constraint
- 默认 Default
- 规则 Rule
- 触发器 Trigger
- 存储过程 Stotred Procedure
==NULL 值表示“不知道、不确定、没有数据”==,仅当某字段值
必须输入
才有效时可设置NOT NULL
(eg:主键),仅用于定义列约束
定义约束名称后(若不定义,系统将自动创建),若数据录入错误,系统将提示报错信息,无 NOT NULL
约束下,系统缺省值为 NULL
-- NOT NULL 约束 |
唯一约束,定义某一列或多列组合取值
必须唯一
,被 UNIQUE 定义的列称为唯一键
,最多只能有一个 NULL 值,列约束、表约束均可
-- UNIQUE 列约束 |
-- UNIQUE 表约束 |
主键约束,其值不能重复,不能为 NULL,既可表约束又可列约束
PRIMARY KEY UNIQUE 区别:
-- PRIMARY KEY 列约束 |
-- PRIMARY KEY 表约束 |
外键约束,约束某一列或几列作为外部键,包含外键的表称为从表(或参照表),主键所在表称为主表(或被参照表)。既可表约束又可列约束
为保证参照完整性,系统保证外键的取值为:
- 空值
- 主键取值
换言之,外键存在至少需要两张表,在第一张表中作为主键的属性在第二张表(从表,参照表)中做普通属性,则此键称为第一张表(主表,被参照表)的外键
-- FOREIGN KEY 列约束 |
-- FOREIGN KEY 表约束 |
检查约束,限定某字段只能录入允许范围内的值,既可表约束又可列约束
注意:
-- CHECK 列约束 |
-- CHECK 列约束 |
ADD 方式为新加列自动填充 NULL 值,不可指定 NOT NULL
-- ADD |
注意:
-- ALTER |
仅用于删除完整性约束定义
-- DROP |
右键 表 ,属性
查看表信息
表存在依赖对象时,不可删除
仅可删除匹配用户建立的表,用户权限要对应
-- 删除基本表 |
结合基础知识,实际操作,巩固提升,加深记忆
利用 T-SQL 完成书籍信息表(tb_BookInfo)的设计与创建
按要求完成数据表完整性的设计,要求利用 T-SQL 在书籍信息表(tb_BookInfo)中添加以下约束:
利用 T-SQL 完成数据表 2、数据表 3 、数据表 4 的设计与创建
利用 T-SQL 语句,在借书信息表(tb_LentInfo)表中加入一列 colBZ(备注),数据类型 varchar,长度 100
利用 T-SQL 语句删除 colBZ(备注)列
利用 T-SQL 语句删除借书信息表(tb_LentInfo)中应还书日期字段上的检查约束
-- 数据库建立 |
其中,由于 tb_LentInfo 借书信息表中日期字段的检查(CHECK)约束,我们并未指定约束名称,所以在删除约束时可以通过下述方法查看系统默认约束名称
1.打开对象资源管理器
2.依次找到对应列约束
3.查看约束名称
根据以下提供的数据库、表结构、表中记录等信息完成相应的 Transact-SQL 语句。产品销售数据库,数据库名为 db_CPXS。数据库 db_CPXS 包含下列 3 个表:
各表的结构分别如表 1-表 3 所示,表中约束自行设计:
请设计数据表 1-表 3 的约束,并写出创建数据表的 T-SQL 语句
-- 拓展提升 |
查询结果仍为表,WHERE
、SELECT
分别相当于关系代数中的 选取
、投影
操作
SQL 指令功能强大,无需规定投影、选取、连接执行顺序
仅包含
SELECT……FROM
查询,等价于对关系做投影
操作
USE db_student -- 指定数据库 |
计算成绩表中学生年龄,并用学号、姓名、年龄做表头
方法:当前日期减去生日日期求得年龄,用别名修改生成表表头信息
use db_student20 |
SELECT * |
可以看到显示了表中所有学生的所有属性信息
不使用 WHERE 子句的无条件查询称投影查询,SQL中只有使用
DISTINCT
关键字才会消去重复列,关系代数投影运算自动消去
SELECT distinct polity |
可以查看到数据表中所有身份信息,并已删除重复列
查询信息表中,我校开设的所有专业信息
select distinct major |
如果不加 distinct
,查询结果将会显示所有符合结果(含重复列),不易阅读
SELECT sno , sn , polity -- 逗号分隔不同属性值 |
常用比较运算符
运算符 | 含义 |
---|---|
=、>、< 、<= 、>= 、!= 、<> |
比较大小 |
AND、OR、NOT | 复合条件 |
BETWEEN AND | 确定范围 |
IN | 确定集合 |
LIKE | 字符匹配 |
IS NULL | 空值 |
*注:<>
表示(否定,不,反义)
查询所有学生中是党员的学生学号和姓名
SELECT sno,sn |
查询成绩表中,学生成绩不及格的学生学号
SELECT sno |
优先级由高到低:
NOT
、AND
、OR
常用在复合逻辑表达式中
查询学生信息表中,软件学院男生是党员的学生信息
select sex,dept,polity |
查询成绩表中,成绩段在
70~90 之间的学生学号和学分信息
select sno,xf |
*注:某些 DBMS 中 BETWEEN AND 不包含边界值等号
查询成绩表中,成绩段不在
70~90 之间的学生学号和学分信息
select sno,xf |
查询成绩表中,选修
c03、c17 课号学生的学分和学号信息
select cno,sno,xf |
查询成绩表中,未选修
c03、c17 课号学生的学分和学号信息
select cno,sno,xf |
*注:重点注意 <>
符号
当我们在不能清楚的知道所查询数据的精确值时,可以使用模糊查询的方式检索数据,利用如下通配符以实现模糊搜索
字符中可加通配符
通配符 | 功能 | 示例 |
---|---|---|
% |
代表0或多个字符 | ‘%ab’ 后可接任意字符串 |
_ |
代表一个字符 | ‘a_b’ 间有一个字符 |
[ ] |
表示在某范围的字符 | [0~10] 范围字符,仅匹配一个字符 |
[^ ] |
表示不在某范围的字符 | 不在 [0~10] 范围内字符 |
查询所有姓王的学生姓名和学院信息
select sn,dept |
查询所有学生信息中,姓名第二个字是明的学生姓名和学院信息
select sn,dept |
==NULL 值表示“不知道、不确定、没有数据”==,和 0 值要注意区分
查询没有考试成绩(未参加考试,不是考试成绩为 0 分)的学生学号及课程号信息
select sno,cno |
常用库函数(聚合函数):
函数名称 | 功能 |
---|---|
AVG | 按列求平均值 |
SUM | 按列求和 |
MAX | 求列最大值 |
MIN | 求列最小值 |
COUNT | 按列求个数 |
count(*)
对表中数目进行计数,无论是否为空count(colum)
对特定列中具有的值计数,忽略 NULL
查询学号为 XXX 的学生总成绩和平均成绩
select SUM(score) AS totalscore,AVG(score) AS avgscore |
*注:如果 AS 后不写别名,查询后的表没有表头(无列名)
查询软件学院学生总数
select COUNT(*) from tb_student |
*注:COUNT(*)
统计元组个数,不消除重复行,不可用 DISTINCT
关键字
select
中既有基本字段又有聚合函数时需要group by
,否则将会出现语法错误
空值作为单独分组返回值
查询选修两门课以上课程的学生学号和选课总数
select sno,COUNT(*) AS sc_num |
查询成绩表中成绩不及格的学生信息,并给出每门课程需要重修的人数(人数大于 5 )
select cno as 课程号,COUNT(*) as 补考人数 |
*注:各子句顺序 WHERE
、GROUP BY
、HAVING
ORDER BY
查询排序结果,位置必须在其他子句后,指定缺省默认为升序 ASC
[DESC 降序 / ASC 升序]
==NULL
在排序时认为是最小值==
查询成绩表中,选修 c10 课程的学生学号,并按成绩降序排列
select sno,score |
成绩表中,查询选修 c10,c03,c09 或 c20 课程的学号和成绩,结果按学号升序排列
select sno,cno,score |
根据数据库 db_Book
中的 tb_BookInfo
表、tb_ReaderInfo
表、tb_BookType
表、tb_LentInfo
表,完成下列查询操作
查询 tb_BookInfo(书籍信息表)中的所有书籍的书籍编号、书籍名称、是否借出字段的信息。
use db_book |
查询 tb_ReaderInfo(读者信息表)中所有读者的信息。
use db_book |
使用别名定义的三种方法(括号内为别名)查询每个读者的 DZBH (编号)、DZXM(姓名)和 LXDH (联系电话)。
use db_book |
查询 tb_BookInfo(书籍信息表)中前 5 条记录的书籍编号、书籍名称。
use db_book |
查询 tb_BookInfo(书籍信息表)表中已借出的书籍信息。
use db_book |
查询 tb_BookInfo(书籍信息表)中 2017 年 4 月份登记的图书名称和登记日期。
use db_book |
查询 b_BookInfo(书籍信息表)中人民邮电出版社书籍的信息。
use db_book |
查询 b_BookInfo(书籍信息表)中 2017 年 4 月 1 日前登记的书籍信息。
use db_book |
查询名为《数据库原理与应用》的书籍的基本信息。
use db_book |
查询 tb_BookType(书籍类别表)中书籍类别为文学类的书籍信息。
use db_book |
查询在 2017-3-1 到 2017 年 4-1 之间借出的书籍编号、读者编号。
use db_book |
查询人民邮电大学出版社、上海交通大学出版社的书籍信息。
use db_book |
查询不是清华大学出版社、大连理工大学出版社出版的书籍信息。
use db_book |
查询出版社是清华大学出版社并已借出的图书信息。
use db_book |
查询 tb_ReaderInfo(读者信息表)表中姓“田”的读者。
use db_Book |
在 tb_ReaderInfo(读者信息表)中找到所有姓名中姓李并且带飞字的读者。
use db_book |
查询 tb_BookInfo(书籍信息表), 按书籍名称升序显示书籍编号,书籍名称,是否借出字段。
use db_book |
查询书籍信息表,按书籍名称降序排序,书名相同按登记日期先后顺序排列。
use db_book |
返回 tb_BookInfo(书籍信息表)中的出版社信息。
use db_book |
按读者姓名降序显示 tb_ReaderInfo(读者信息表)中的信息。
use db_book |
查询 tb_BookInfo(书籍信息表),按书籍类别统计各类书籍的数量。
use db_book |
统计 tb_BookInfo(书籍信息表)中的书籍数量。
use db_book |
按书籍名称统计各种书籍的数量,并按书籍名称升序排序。
use db_book |
按出版社统计各个出版社的书籍数量,并显示数量超过 100 本的出版社名称。
use db_book |
统计人民邮电出版社书籍的数量。
use db_book |
统计 2017 年 4 月份借出书籍的数量,并按数量降序排列。
use db_book |
重视基础练习,每日进步亿点点
]]>连接查询:一个查询需要对多张表操作,查询结果称表之间的连接;连接关系通过字段值体现,称为连接字段
当我们查询的数据、字段值分布在不同的表中时,这种情况下需要使用多关系表的连接查询
连接类型:内连接(INNER JOIN)、外连接(OUTER JOIN)、交叉连接()、自然连接()
连接谓词:连接两个表的条件
关键字(INNER JOIN),功能:仅返回连接条件为真的行,有
from
和where
字句两种方式
这里要注意,两张表连接时,同名属性需要使用前缀区分(列名唯一不需要)
实现内连接的三种方式举例:
-- method1 |
以上方法中,method1 比较简单且常用 ,建议重点掌握
查询每位学生及选修课程信息
1.from 子句实现
select * |
以上代码可简化为
select * |
执行结果中发现存在相同列(学号),说明为等值连接,未删去重复列
2.where 子句实现
select * |
查询每名同学成绩,包含学号,课程编号,成绩,课程名称信息
select sno,sc.cno,cn,score |
1.from 子句
select s.sno,sn,cn,score |
2.where 子句
select s.sno,sn,cn,score |
外连接中,符合连接条件的数据返回到结果集,不符合连接条件的列会被系统用 NULL
填充,再返回结果集
*注:bit
类型无 NULL
值,会填充 0 后返回结果集中
使用主表所在的方向位置判断连接类型,例如:主表在左,即为左外连接
复习下关系运算中,连接的相关知识
那么上图两张表分别进行外、左外、右外连接后的结果为
举例:查询所有学生选课情况,包括未选课学生信息
-- left join |
-- right join |
-- full join |
又称 “笛卡尔乘积” 连接,实际应用中很少使用
考虑到计算机性能,执行效率也不大相同
这里主要知道关键字为 CROSS JOIN,结果集行数为两张表行数乘积,列数为两表列数总和,然后参考下下方示例即可
-- 对学生表和成绩表进行 交叉查询 |
如果我们要查询的结果集中,所包含的信息均在同一张信息表中,这样的查询方式称为自连接查询
示例:查询工资表中,所有比 XXX 工资高的同事姓名、工资和 XXX 的工资
-- method1 |
又称嵌套查询,形式是在 WHERE 中再次包含 SELECT - FROM - WHERE 的查询
程序从内向外执行 SQL 语句,外部查询称为父查询,父查询需要接收子查询(嵌套查询)的结果
普通子查询仅执行一次
该例子解释父级查询需要子查询结果的概念
select tno,tn |
示例中,prof
的值由子查询查出结果后返回给父查询做结果,上述语句等价为
select tno,tn |
比较运算符仅适用于查询所需返回值为单个值得情况,当返回结果为集合时不再使用,可使用如下方式
ANY:任何一个
示例:查询讲授课程号为 c5 的教师姓名
select tn -- 姓名 |
首先执行子查询,找到讲授 c5 课程的教师号,父级查询根据教师号再查询教师姓名
意思是,tno
是子查询结果集中的任(ANY)一个
和 ANY 一样的例子,我们也可以使用 IN 实现
select tn -- 姓名 |
这里的意思是,tno
在(IN)子查询结果集中
ALL:全部
示例:查询其他系中比计算机系所有教师工资都高的教师姓名和工资
-- 使用 ALL |
由上面的内容我们知道,子查询程序执行顺序是由内到外,也就是说父级需要子级的消息返回
但是,我们同样会遇到子查询需要父查询相关信息的情况,这样的情况我们称之为相关子查询
示例:查询不讲授课程号为 c5 的课程的教师姓名
-- method1 <> ALL |
该例中,子查询判断课程号 cno 时,需要数据表 t 中教师号 tno 信息,为相关子查询
在各个子查询对应数据条目和数据类型一致的条件下,可以使用 UNION
关键字将不同的查询得到的数据组合起来
且 UNION
会自动删除重复数据行
使用方法比较简单,给出一个例题供参考
select sno,sum(score) |
上面的 SQL
语句实现:将从 tb_a
中查询出学号为 001 同学的学号和总成绩信息和从 tb_b
中查询出学号为 002 同学的学号和总成绩信息合并为一个结果集
此处“存储”的含义是指将 A 表中查询的数据结果集存储到其他表,B 表中
我们使用 SQL 语句查询到的结果,仅临时导出让用户(我们)看到,并未真正影响(存储)到对应数据库中,那如何实现查询结果的存储呢?
语法格式为:
SELECT ... INTO ... |
具体实现如下
selelct sno,sum(score) -- 学号,总成绩 |
上面的 SQL
语句实现从 tb_a
中查询出学号和总成绩信息并存放到 tb_b
表中
根据数据库
db_student
中的tb_student
表、tb_score
、tb_course
,完成下列查询语句
表结构如下:
查询学生的性别信息, 并去掉重复记录。
use db_student20 |
查询 tb_student 表中共有几个系别
use db_student20 |
计算 tb_student 表中各个系的人数。
select dept as 系别名称,COUNT(*) as 总人数 |
查询你所在班级的人数。
-- 方法一 |
显示每名同学的成绩,要求显示学号、姓名、课号和成绩
select stu.sno as 学号,sn as 姓名,cno 课程号,score 成绩 |
显示 90 分以上每名同学的成绩,要求显示学号、姓名、课号和成绩
select stu.sno as 学号,sn as 姓名,cno 课程号,score 成绩 |
每科成绩最高最低分,要求显示科目名称。
select cn 课程名,MAX(score) as 最高分,MIN(score) as 最低分 |
每科有多少人需要补考,要求显示科目名称。
select cn 课程名,COUNT(*) as 补考人数 |
每班计算机基础科成绩最高、最低分。
select LEFT(sno,8) as 班级,cn 课程名,MAX(score) 最高分,MIN(score) 最低分 |
查询所有学生的选课情况,包括没选课的学生(使用左连接、右连接 2 种方法实现)
--left join |
列出 tb_student 表中和“XXX”系别相同的学生的学号和姓名
--子查询 |
查询选修 c03 课程的学生姓名
--子查询 |
查询不选 c04 课程的学生的学号和姓名
select sno,sn |
查询每科最高分的学生的学号和科目
select sno 学号,cn 课程名,score 成绩 |
显示需要进行补考的科目编号和名称
-- 子查询 |
不及格人数多于 1 人的科目及人数。
select cn,COUNT(*)as 不及格人数 |
显示 c01 科成绩不及格的学号,对应学生表中所有列的信息。
select * from tb_student |
列出成绩表中各个科目成绩的最高分、最低分和平均分, 并显示成绩表中平均分大于 75 分的科目名称,并按平均分降序排序
select cn,MAX(score) 最高分,MIN(score) 最低分,AVG(score) 平均分 |
查询选修了“数据库原理与应用”的学生的学号和姓名。
-- 子查询 |
査询课程号为“C02”、成绩高于“王磊”的学生的学号和成绩。
select sno,score from tb_score |
查询和“王磊”的“数据库原理及应用”课程分数相同的学生的学号。
select distinct sno from tb_score sc,tb_course c |
根据数据库
db_student
中的tb_student
表、tb_score
、tb_course
,完成下列更新语句
向学生表中插入一条记录,学号为 00000000,姓名为 XXX,性别为 X 的记录。
INSERT INTO tb_student(sno,sn,sex) |
向学生有中插入一条记录,各字段值依次为:00000000,name,sex,department,XXXX-XX-XX,polity。
INSERT INTO tb_student(sno,sn,sex,dept,birthday,polity) |
在课程表中添加一门新课程,其信息为:(’C8’,’计算机新技术’,’XXX’)。
ALTER TABLE tb_course |
在选修关系表 SC 中添加所有学生对’C8’课程的选修关系记录,成绩暂定为 60,请用一条命令完成本批量添加任务。
INSERT INTO tb_score(sno,cno,score) |
将女生的所有数据形成一张新表,表名为 student_girl。
select * |
将学生表中姓名为 XX 同学,性别改为女,出生日期为 1998-1-1。
UPDATE tb_student |
将 tb_score 表中的 c04 的课程折合为 60%并加上 40 分。
UPDATE tb_score |
将选修数据结构课程的学生成绩增加 15 分。
UPDATE tb_score |
把选“计算机新技术”课程的男学生的成绩暂全部初始化重新设置为 0。
UPDATE tb_score |
删除学生表中所有姓张的同学。
DELETE FROM tb_student |
删除 student 表中不及格同学的所有信息。
DELETE FROM tb_student |
XXX 同学的学生信息及其选课情况等全部删除。
-- 删除顺序颠倒会导致成绩表中无法找到XXX学生学号 |
删除学生表中所有学生信息(两种方法)。
-- method1 |
在修改表信息书写 SQL
语句时,遵循 SET
、UPDATE
、WHERE
的书写顺序
即首先设置值,然后选定作用范围,最后增加限制条件。这样思路会更加清晰
]]>在
studen
数据库中,以tb_student
、tb_course
和tb_score
表为基础完成下列视图的设计与创建
创建学生的基本情况视图 V_STU。
CREATE VIEW V_STU |
创建视图 V_Sco,显示学生成绩信息。
CREATE VIEW V_Sco |
创建视图 V_SCORE, 要求只显示学生的学号、姓名、系别、课号、课程名称及成绩。
CREATE VIEW V_SCORE |
各系学生人数、平均年龄创建视图 V_NUM_AVG。
CREATE VIEW V_NUM_AVG |
创建一个反映学生出生年份的视图 V_YEAR。
CREATE VIEW V_YEAR |
将各位学生选修课程的门数及平均成绩创建视图 V_AVG_S_G。
CREATE VIEW V_AVG_S_G |
将各门课程的选修人数及平均成绩创建视图 V_AVG_C_G。
CREATE VIEW V_AVG_C_G |
创建视图 V_YEAR_RJ,显示软件工程系出生日期在 2001 年之后出生的学生信息。
CREATE VIEW V_YEAR_RJ |
基于视图 V_STU,创建视图 V_SEX,查看男党员的信息。
CREATE VIEW V_SEX |
修改视图 V_YEAR,显示软件工程系出生日期在 2000 年之前出生的学生信息,并删除视图 V_YEAR。
ALTER VIEW V_YEAR |
向视图 V_Sco 中添加学号为‘xxx’,课程号为‘10002’,成绩为87 的信息。
INSERT INTO V_Sco(sno,cno,score) |
修改视图 V_Sco,将学号为‘XXX’的学生,选修的课程号为10002 的成绩更改为 90。
UPDATE VIEW V_Sco -- 修改值,实质为更新视图,关键字 UPDATE |
在视图 V_Sco 中,将学号为‘XXX’的学生,选修的课程号为10002 的记录删除。
DELETE FROM V_Sco |
查询以上所建视图结果
-- (1) 查询平均成绩为 90 分以上的学生的学号、姓名和成绩。 |
在
student
数据库中,以tb_student
、tb_course
和tb_score
表为基础完成下列索引的设计与创建。
-- (1) 对学生信息表 tb_student 中的学号 sno 创建聚集索引,并按降序排列。 |
1.查看与删除索引
-- 查看索引 |
2.索引类型
类型名称 | 关键字 |
---|---|
普通索引 | INDEX |
唯一索引 | UNIQUE INDEX |
聚集索引 | CLUSTERED INDEX |
非聚集索引 | NONCLUSTERED INDEX |
全文索引 | FULLTEXT |
3.索引分析
索引相当于一本书的目录,优缺点分析如下:
虽然索引很大程度上提高了查询速度,但同时也会降低更新表的速度,如:对表进行 insert
、update
和 delete
。这是因为更新表时,不仅要保存数据,还要保存一下索引文件
索引只是提高效率的一个因素,如果有大数据量的表,则需要花时间研究建立最优秀的索引,或优化查询语句
建立索引会占用磁盘空间的索引文件。如果在一个大表上创建了多种组合索引,索引文件的增速会很快
4.查看视图创建源码
Sp_helptext name -- name:视图名 |
定义格式:
static 类型名 静态数据成员名 ;
详解:由于静态数据成员属于本类的所有对象共享,不属于特定类对象,因此在未产生类对象时作用域就可见,即:在未产生类的实例时,就可以对它进行操作
初始化:
类型 类名 :: 静态数据成员 = 初始化值 ;
详解:静态数据成员必须在类外初始化,不可在类体内,因为:构造函数中,如果可以,则每次建立对象,都会对静态数据成员的值进行修改,这违背静态数据成员的使用目的;类内也不可以初始化,不要忘记,类只是一种数据类型,数据类型中怎么能赋初值呢?
定义格式:
static 返回类型 静态成员函数名 (参数表) ;
调用方式:
类名 :: 静态成员函数名 (实参表) ;
对象名 . 静态成员函数名 (实参表) ;
注意:
类外定义静态成员函数时,定义格式和普通成员函数定义格式相同,不再使用static修饰;
使用对象名和成员运算符(.)调用成员函数时,并非该函数属于某一对象,只是类与对象间的桥梁,为了能处理静态数据成员;
静态成员函数不能默认引用本类非静态数据成员的原因:
当调用一个对象的非静态成员函数时,系统会将该对象的起始地址赋予成员函数的this指针。然而,静态成员函数不属于对象,无this指针。所以静态成员函数不能访问类的默认非静态成员(非静态成员函数和非静态数据成员)
举例说明一种静态成员函数访问非静态数据成员的方式:
|
程序运行结果:
x=5 |
对运行结果的分析,最后一次对静态数据成员y更新后,y=15所以两次输出y的值都是15
只要对静态数据成员的值更新一次,就可以保证所有对象都会存取更新后的值由本例可知:静态成员函数不能引用本类非静态成员并非绝对,只是不可以进行默认的访问,因为编译器不知道应该去寻找哪一个对象。若必须要访问,则有两种方式,且一般使用第二种居多
对象名 . 非静态成员 ;
类名 :: 非静态成员 ;
故:实例化对象即可完成对非静态数据成员的访问
]]>来自阿里的一道测试题目,刚好了解下 SVN 中修订版本关键字,评论留言你的答案
【单选题】关于SVN中修订版本关键字,描述错误的是?
A. HEAD工作拷贝中的最新的版本
B. BASE工作拷贝中一个条目的修订版本号,如果这个版本在本地修改了,则“BASE版本’就是这个条目在本地未修改的版本
C. COMMITTED项目最近修改的修订版本,与BASE相同或更早
D. PREV一个项目最后修改版本之前的那个版本,技术上可以认为是COMMITTED-1
The Subversion client understands a number of revision keywords. These keywords can be used instead of integer arguments to the --revision (-r)
option, and are resolved into specific revision numbers by Subversion:
Subversion客户端可以理解一些修订版本关键字,这些关键字可以用来代替 --revision (r)
的数字参数,这会被Subversion解释到特定修订版本号:
The latest (or “youngest”) revision in the repository .
版本库
中最新的(或者是“最年轻的”)版本
The revision number of an item in a working copy . If the item has been locally modified, this refers to the way the item appears without those local modifications.
工作拷贝
中一个条目的修订版本号,如果这个版本在本地修改了,则“BASE版本”就是这个条目在本地未修改的版本
The most recent revision prior to, or equal to, BASE, in which an item changed.
项目最近修改的修订版本,与 BASE 相同或更早
The revision immediately before the last revision in which an item changed. Technically, this boils down to COMMITTED-1.
一个项目最后修改版本 之前 的版本,技术上可以认为是 COMMITTED -1
As can be derived from their descriptions, the PREV , BASE , and COMMITTED revision keywords are used only when referring to a working copy path—they don’t apply to repository URLs. HEAD, on the other hand, can be used in conjunction with both of these path types.
因而可以从描述中得到,关键字PREV
,BASE
和COMMITTED
只在引用工作拷贝路径时使用,而不能用于版本库URL, 而关键字 HEAD
则可以用于两种路径类型
参考资料
👲👲作者主页:🔗杰森的博客
📒📒本文摘要:TCP 三次握手,四次挥手知识点精析。备考、面试前看两眼,加深记忆,祝你一臂之力。顺利通过考试、拿到 offer。
💖💖如果本文帮助到你的话,还请各位小伙伴👍点赞➕收藏⭐➕评论💭支持杰森呀✌️
“什么是三次握手,四次挥手?”,该问题作为计算机网络学科中常见问题之一,无论是面试还是考研,我们都有必要细细参透其中的奥妙
在学习之前,我们首先需要了解一些基本的概念
传输控制协议(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,在 OSI 模型中完成传输层指定功能。
TCP 使用校验和函数检验数据是否出现错误,在数据发送和接收时均需要计算校验和。
1.TCP 是面向连接的传输层协议
应用程序在使用 TCP 协议前,必须首先完成 TCP 连接的建立。在数据传输结束后,必须释放先前已建立的 TCP 连接
2.每一条 TCP 连接只能有两个端点
TCP 连接只能是点对点,一对一的
3.TCP 提供可靠交付服务
通过 TCP 连接传送的数据,无差错、不丢失、不重复,且按序到达
4.TCP 提供全双工通信
TCP 允许通信双方的应用进程在任何时候都可以发送数据,TCP连接的两端都设有发送、接收缓存,用于临时存放双向通信的数据,上层应用进程在时机恰当时会读取缓存中的数据
5.TCP 面向字节流
流是指:流入到进程或从进程流出的字节序列
TCP 把应用程序回传的数据看做一连串的无结构的字节流,不保证接收方应用程序所收到的数据块和发送方应用程序所发出的数据块具有对应大小的关系
接收方应用程序收到的字节流必须和发送方应用程序发出的字节流完全一致,且接收方的应用程序必须具有识别接收字节流,并将其还原为有意义的应用层数据的能力
这里需要了解 TCP 报文首部的格式,相关控制位非常重要
由于 TCP 报文段首部的前 20 个字节是固定的,其后 4n 个字节是根据需要增加的选项,所以 TCP首部的最小长度是 20 字节
1.源端口和目的端口
各占 2 字节,分别写入源端口号、目的端口号
2.序号字段
占 4 字节,范围为
[0,2 ^ 32-1]
,序号使用mod2^32
运算,在一个TCP连接中传送的字节流中的每一个字节都按顺序编号。整个要传送的字节流的起始序号必须在连接建立时设置,首部中的序号字段值则指的是本报文段所发送的数据的第一个字节的序号
3.确认号字段
占4字节,是期望收到对方下一个报文段的第一个数据字节的序号。若确认号等于 N,则表明:到序号 N-1 为止数据均己正确接收
4.数据偏移字段
占 4 位,指出 TCP 报文段的数据起始处和 TCP 报文段的起始处的距离。此字段实际上指出了 TCP 报文段的首部长度
5.保留字段
占 6 位,保留为今后使用,目前应置为0
6.紧急 URG
URG=1时,表明紧急指针字段有效,它告诉系统此报文段中有紧急数据,应尽快传送,即提高数据传送的优先级
7.确认 ACK
仅当 ACK=1 时确认号字段才有效,TCP 规定,在连接建立后所有传送的报文段必须将 ACK 置为 1
8.推送 PSH
接收 TCP 收到 PSH=1 的报文段后,将尽快交付接收的应用进程,不再等到缓存都填满后再继续向上交付
9.复位 RST
当 RST=1 时,表明 TCP 连接中出现严重差错,必须释放连接,然后再重新建立传输连接。也可以用于拒绝一个非法的报文段或拒绝打开一个连接
10.同步 SYN
连接建立时用来同步序号,SYN=1就表示这是一个连接请求或连接接受报文
11.终止 FIN
用于释放一个连接,当 FIN=1 时,表明此报文段的发送方的数据己发送完毕,并要求释放传输连接
12.窗口字段
占 2 字节,窗口值范围为
[0,2^16-1]
之间的整数。窗口是指发送本报文段的一方的接收窗口,窗口值作为接收方让发送方设置其发送窗口的依据
13.检验和字段
占 2 字,检验和字段检验的范围包括首部和数据两部分
14.紧急指针
占 2 字节,仅当 URG=1 时才有意义,含义是:本报文段中的紧急数据的字数,紧急指针指出了紧急数据的末尾在报文段中的位置
当所有紧急数据都处理完时,TCP就告诉应用程序恢复到正常操作。注意:即使窗口为零时也可发送紧急数据
15.选项字段
长度可变,最长可达 40 字节。未使用“选项”时,TCP 首部长度为 20 字节
TCP
建立连接的过程称为握手,握手需要在客户端和服务器之间交换三个 TCP
报文段
我们举一个简单的例子帮助大家理解这个问题:试想下面这个场景
你出门在外没带钥匙,而房屋钥匙又仅有一把,在不考虑钥匙丢失在哪里的情况下,今晚你还会回家吗?
虽然此例子并不那么恰当,但是可以类比到三次握手的原因上。如果客户端和服务端有一方出现了问题,那么它们之间的通讯、资源传输必定会出问题
因此,TCP
三次握手的作用就是使客户端和服务端双方都明确自己的责任,保证双方都具有资源接收和发送的能力
字符释意:
ACK
:确认报文段ack
:确认号SYN
:发送连接请求 / 接收报文段`seq
:发送数据的第一个字节的序号客户端与服务端资源收发的三次握手过程如下:
*注:图例中的 Ss
、Sa
分别表示 Server send
、Server accept
(服务端发送能力、服务端接收能力);Cs
、Ca
分别表示 Client send
、Client accept
(客户端发送能力、客户端接收能力)
1.第一次握手
第一次握手由客户端发送资源包给到服务端,若该过程正常,则得出结论:服务端接收、客户端发送服务正常
2.第二次握手
第二次握手由服务端发送资源包给到客户端,若该过程正常,则得出结论:服务端发送、客户端接收服务正常
3.第三次握手
这里大家可能就会有疑问了?为什么还需要进行第三次握手呢?前两次不是已经得出结论客户端、服务端接收、发送资源包能力正常了吗?
其实并不是,第一、二次握手只是在单独的过程中得出服务正常的结论,但是在第二次握手结束后,==服务端的接收能力和客户端的发送能力未知==,这时候便有了 TCP
的第三次握手过程
第三次握手由客户端发送资源包给到服务端,若该过程正常,则得出结论:服务端接收、客户端发送服务正常
通过这三次的握手过程我们可以分析得到:第二次是对第一次握手的补充,第三次是对第二次握手的补充,最终正好形成闭环,客户端和服务端都确认了自己的接收、发送能力正常,之后方可进行通信
并且,要完成两者状态的监测,这之间至少需要三次过程,两次并不足以判断自身的服务状态。每一个步骤都相互关联,下一次握手的“响应”由上一次“请求“触发,每次握手得出的结论都是对上一次结果的补充,从而得出最终结果
三次握手过程中,客户端和服务端交换 Initial Sequence Number (ISN
),为了使对方清除下一步接收到的数据信息应以何序列号进行数据整合
并且,ISN 在此过程中是动态生成的。假如 ISN 固定不变,入侵者非常容易就能得出后续数据的确认号,这将会危机到数据信息的安全
当成功建立一个 TCP
连接, 服务端在 LISTEN
状态下,收到建立连接请求的 SYN
报文后,将 ACK
和 SYN
存放到同一个报文中一起发送给客户端
而关闭连接时,服务端收到客户端的 FIN
报文时,仅表示对方不再发送数据,但仍然能够接收数据。此时,服务端不一定将全部数据都发送给了客户端
因此服务端关闭有两种方式:
FIN
报文给客户端(表示同意关闭连接),是否立刻关闭发送数据通道,需交由上层应用决定所以,客户端的 ACK
和 FIN
一般都会分开发送,这里就会导致次数增加一
数据传输完毕后,双方均可释放连接。起初,客户端和服务端均处于 ESTABLISHED
状态,然后是客户端主动关闭,服务器被动关闭
整个过程请参考下图:
字符释意:
FIN
:连接终止位seq
:发送的第一个字节的序号ACK
:确认报文段ack
:确认号四次挥手过程:
客户端发送第一次挥手,之后由 ESTABLISHED
状态转为 FIN_WAIT1
状态
服务器收到客户端的第一次挥手之后,发送第二次挥手给服务器,服务器进入 CLOSE_WAIT
状态,等待服务器自身的 SOCKET
关闭等处理
客户端收到服务器的第二次挥手,进入 FIN_WAIT2
状态,等待服务器关闭
服务器发送第三次挥手,然后进入 LAST_ACK
状态
客户端收到第三次挥手,发送第四次挥手,客户端进入 TIME_WAIT
状态;
服务器收到第四次挥手,进入 CLOSED
状态,客户端等待 2MSL 后,进入 CLOSED
状态
TCP 状态转换过程见下图:
TCP
建立连接的三次握手是指发送了三个报文段,而 TCP
断开连接进行四次挥手是指发送了四个报文段,在此过程中,SYN
和 FIN
均利用重传进行可靠传输
连接的释放本质上两次就可以完成,但若想要完全释放,则需要四次挥手,请看下图
打电话即将结束时,路人甲说完信息“OK,我没事了”后,路人乙回复到“嗯,知道啦”。这是就是完成了 TCP 四次挥手的前两次过程;路人乙马上要挂断电话时,路人甲又忽然想起来某件事,说了很多。这时路人乙又回复到“好的好的”。至此,TCP 四次挥手的后两次过程完毕
前端入门实战练习之腾讯云页面实现
实现后的样子如图所示,ps:量的尺寸最开始肯定是没有的,都是写一步,测一步,最后就成这样啦
使用的工具是 PxCook,方便我们量取图片设计尺寸
初步实现大致样式,明日进行细节优化,2022.4.3
图中标识位置尚未优化,下面是该部分实现源码
<!-- |
* { |
后期重点解释下过程中出现的问题及解决方案,源码相应位置均有注释。初次上手,恳请各位大佬斧正
注:以上练习题目来自黑马程序员,仅供学习交流使用,侵删致歉
参考资料:
对导航栏、列表进行细节优化
初稿我们的样式中,导航栏的显示效果并不完美,logo 位置正常,但是显然后侧的文字效果并未实现精准定位,首先给出实现后的样式效果,清除需要优化的位置
分析源码可知,初稿中将 img-logo
和 container
合并布局,造成无法留出间隔距离的情况
这次我们单独布局并设置浮动效果,留出间隔
<div class="nav"> |
在原来单独的 img
标签嵌套格式中,为 img
标签添加 h1
标签,并一定注意显示模式的转换,否则后侧文字会靠下显示(如图)
注释掉的颜色方便我们实现精准定位,清除标签的位置,定位完成后注释掉即可,可以当做小技巧来用
/* 导航 */ |
优化位置示意
不知道大家有没有发现,Tencent-logo
下方列表对应字体后方有个装饰性的小标签,英文状态下的 >
符号,初稿使用伪元素实现,但是装饰元素和字体间的距离并没有控制
今天换一种思路解决该问题
在字体后添加装饰元素:英文状态下的 >
符号,添加浮动效果,设置 margin-right
尺寸即可
不再使用伪元素控制,更新为添加 float:right
浮动
<div class="top"> |
控制浮动、边距尺寸
量取边距像素值
.top .list span { |
两处细节优化完成 ing~
]]>今天给大家分享几个我们开发、学习中必不可少的工具,有了它们效率倍增。你用过几个呢(评论区见)?如果你有更好的开发工具或实用软件,欢迎留言/私信!
Everything是一款输入文件名可快速搜索到资源的搜索引擎,对Windows平台的用户支持非常友好。它的界面简洁,后台资源占用低,能够实现文件的快速索引,以及磁盘文件实时更新等功能。上千个的文件,它仅用一秒就能精准定位,显示文件路径,毫不夸张。使用方式也非常简单,在搜索框中填入待查找文件即可
你是否也曾遇到过这样的情况:软件卸载不干净?捆绑软件卸了又来?注册表冗杂?那么恭喜你找到了它们的克星—Geek Uninstaller
在卸载软件时,它不仅能使用常规操作执行相关软件的卸载程序,而且在卸载程序执行完毕后还能自动扫描系统注册表,检索并选择删除残留无效信息。对于一些流氓软件,它也支持 “强制删除” 操作,一个不留
虽说官方对该软件的支持早已停止,但是软件使用方面对于刚入门的初学者还是非常友好的。可以设置中文模式,不至于被一下子 “劝退” ,它对于新手更加友好体现在编译出错信息可以自动翻译为中文,现在能有这样功能的IDE实属稀少。不得不说,英语还是要好好学啊!
现在能找到的最新版本是由国人自主优化的一个版本,版本号为 5.15 ,支持常用的调试、自动保存、代码格式化等功能,集成Mingw64的编译器、GDB调试器、优秀的源码编辑器,界面同官方公布的版本也有较大更新
Vscode是微软官方于2015年4月30日在Build开发者大会上正式宣布推出的一款轻量化代码编辑器,它免费、开源且功能强大
支持几乎所有主流的程序语言的语法高亮、智能代码补全、自定义热键、括号匹配、代码片段、代码对比 Diff、GIT 等特性,支持插件扩展,并针对网页开发和云端应用开发做了优化。对于跨平台的支持也是非常兼容,可在 Linux、MacOS X、Windows操作系统上正常运行
个人最喜欢的还是其对于 C++、Java、Python、C#、PHP、Go 等编程语言扩展工具的强大支持,只有想不到,没有找不到
点我下载所有资源,提取码:peng
]]>不得不说,VS这款宇宙第一IDE的实力属实强劲。但也正是它如此强大的能力,才让我有些 “无法驾驭”,完全卸载便是其中之一。
既然你看到了这篇博客,说明你已经遇到了常规方法不能解决的问题,这里我们直接给出正常卸载无法进行的解决方案。
%programfiles(x86)%\Microsoft Visual Studio\Installer\resources\app\layout\InstallCleanup.exe”
;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio
;工作还得继续啊!不聊了,马上重装继续找错去了,bai~~
首先打开vivado2017.4
点击create project
点击next
为新建的工程起名字,路径和名字都不要有中文
起好名字后点击next
选择RTL project,勾选do not specify sources at this time, 表示以后再配置资源文件
选好了之后点击next
输入你的FPGA板的型号,我的是xc7a100tcsg424
然后点击next
finish之后,如图所示,可以配置语言,这里选择的是VHDL
然后我们开始新建/添加文件,点击+
选择add or create design sources
双击你所建立的source之后,就可以开始写程序了
在这里我提供一个简单的程序
library IEEE; |
然后我们开始写仿真程序, 同样建立一个仿真文件
仿真文件的命名通常为test_bench
这里我也提供对应的仿真程序,以供参考
library IEEE; |
写完之后点击保存
仿真界面的上方有三个键:a是重新开始仿真,b是开始仿真直到点击break(F5), c是仿真指定的时间,我这里设置的是100ms
点击红色圆圈里的是看到所有仿真波形
仿真波形没有错误,开始综合
点击 run synthesis, 等待一段时间
跳出一个对话框,点击cancel
如果你没有现成的约束文件,就自己约束了
先点击 open synthsized design
打开开发板的使用指南
例如:我想约束为
led对应LD0(H17)
switch对应switch0(J15)
约束之后,保存CTRL+S,跳出来对话框,点击确定
然后为约束文件命名
然后重新执行综合
实现
生成二进制文件
然后 open hardware manager
点击open target
点击device program
程序下载完毕后观察实验现象
不知道你是否和我有过同样的感受,《计算机组成原理》这门学科学起来如此的艰难:一节课下来,教室黑板上留下了满满的 “足迹”,看上去也挺简单的,不就是 0 和 1 嘛。但这些看起来简简单单的 0 1 码却成为了我当时学习路上的绊脚石。源码、反码、补码等等等等,各种的码制转换令我一头雾水,我曾一度怀疑这就是计算机干的活儿吗?
随着后面慢慢了解《计算机组成原理》后,我愿称计算机为世界上最麻烦的电子产品。也形象的将计算机描述为一套有电源、有身体、有框架,但就是没有思想的空壳儿。这时候,我们的人类社会才萌生了许许多多“ 利用 ”它们的主人—程序“ 猿 ”
程序员就是要为计算机这个富有 ” 聪明 “潜质的伙伴编写一套一套的 “程序” ,告诉它们应该去做什么亦或是怎么去做。正是由于它们能吃苦、不怕累的精神再加上完美程序的契合,我们的生活质量得以大幅度提升
即使你不是计算机专业的学生,相信对于CPU你也有所了解。正所谓CPU(Central Processing Unit),也就是中央处理器。负责解释计算机指令以及处理计算机软件中的数据。中央处理器主要包含控制器、运算器两部分,其中还包括cache以及实现它们之间信息互换的数据、总线
可千万别小看这个不起眼的 “小东西” ,它可是程序执行、机器正常运转必不可少的元器件。作为电子计算机三大核心部件(CPU、内存、I/O设备)之一的CPU,在计算机体系结构中承载着控制调配硬件资源、执行通用运算等重要职责。下面我们来了解较为简单的单周期CPU功能指令
分析实现单周期CPU的14条指令计算结果,比较理论与实践结果的正确性
分析第一个周期,指令地址为041008,在程序测试段中,可以看到,本条指令为addi,那么现在开始检验指令addi的实现过程:指令addi的功能是rt←rs + (sign-extend)immediate; immediate符号扩展再参加“加”运算
首先找到rs在本周期中存放的源操作数地址,rs=00;然后在Objects中添加immediate组件,找到立即数的值,immediate=8;最后进入ALU分析计算结果,在ALU的代码文件中有两个引脚,ALUSrcA和ALUSrcB,它们在第一个周期中的值分别是0和1,则A端口进行ReadData1,B端口进行extend,计算结果为result=8,指令执行正确,可以实现数据相加功能
分析第二个周期,指令地址为40020002,在程序测试段中,可以看到,本条指令为ori,那么现在开始检验指令ori的实现过程:指令ori的功能是rt←rs | (zero-extend)immediate; immediate符号扩展再参加“或”运算。寄存器源操作数地址:rs=0,immediate=2;
进行zero-extend后,值为2
进行“或”运算,ALU两个引脚输入端口值为
计算结果为
指令计算结果无误,指令运行正常
分析第三个周期,指令地址为0411800,在程序测试段中,可以看到,本条指令为add,那么现在开始检验指令add的实现过程:指令add的功能是rd←rs + rt。源操作数地址:rs=2,rt=1;ALU两个引脚值都是0,读寄存器中的值,此时存入结果为03,程序运行正常,功能实现
分析第四个周期,指令地址为08622800,在程序测试段中,可以看到,本条指令为sub,那么现在开始检验指令sub的实现过程:指令sub的功能是rd←rs - rt。源操作数地址:rs=3,rt=2;ALU两个引脚值皆为0,程序读取寄存器中的值,此时存入结果为5,程序运行正常,功能完好
分析第五个周期,指令地址为44a22000,在程序测试段中,可以看到,本条指令为and,那么现在开始检验指令and的实现过程:指令and的功能是rd←rs & rt;(逻辑与运算)。源操作数寄存器地址:rs=5,rt=2;ALU引脚值为0,读取ALU计算结果为00000000,分别对源操作数5和2转为2进制为:0101、0010按位与后值为0,结果吻合,该单元工作正常,功能实现
分析第六个周期,指令地址为48824000,在程序测试段中,可以看到,本条指令为or,那么现在开始检验指令or的实现过程:指令or的功能是rd←rs | rt;(逻辑或运算)。源操作数寄存器地址:rs=04,rt=02;ALU双引脚值为0,读取寄存器堆中的值,可以看到存放真值为0和2(取最后结果)。读取值为2
分别对源操作数4和2转为2进制并按位或后值为2,与程序运行结果吻合,该单元工作正常,功能实现
分析第七个周期,指令地址为60084040,在程序测试段中,可以看到,本条指令为sll,那么现在开始检验指令sll的实现过程:指令sll的功能是rd<-rt<<(zero-extend)sa,左移sa位 ,(zero-extend)sa。源操作数寄存器地址:rt=08 ,寻求真值,移位数sa=1,程序运行后 。在二进制数据计算中,左移一位就相当于乘以2,故程序结果正确,该单元工作正常
分析第八个周期,指令地址为c501fffe,在程序测试段中,可以看到,本条指令为bne,那么现在开始检验指令bne的实现过程:指令bne的功能是:if(rs!=rt) pc←pc + 4 + (sign-extend)immediate <<2 else pc ←pc + 4【与beq不同:不等时转移,相等时顺序执行。】在寄存器堆中找到源操作数地址,寻得真值,找寻计算结果,结果吻合,单元工作正常
分析第九个周期,指令地址为6c460008,在程序测试段中,可以看到,本条指令为slti,那么现在开始检验指令slti的实现过程:指令slti的功能是:if (rs <(sign-extend)immediate) rt =1 else rt=0,源操作数地址找到后,对立即数进行sign-extend,然后判断是否满足if()中的给定条件,程序结果完整无误,本单元工作正常
第14个周期中,指令地址为c0e1fffe,在程序测试段中,可以看到,本条指令为beq,那么现在开始检验指令beq的实现过程:指令beq的功能是:if(rs=rt) pc←pc + 4 + (sign-extend)immediate <<2 else pc ←pc + 4,immediate是从PC+4地址开始和转移到的指令之间指令条数
immediate符号扩展之后左移2位再相加。左移2位是由于跳转到的指令地址肯定是4的倍数(每条指令占4个字节),最低两位是“00”,因此将immediate放进指令码中的时候,已经右移两位,这与上文 “指令之间指令条数”相契合。运算结果符合事实,单元工作正常
第19个周期中,指令地址为98220004,在程序测试段中,可以看到,本条指令为sw,那么现在开始检验指令sw的实现过程:指令sw的功能是:memory[rs+ (sign-extend)immediate]←rt;immediate符号扩展再相加
将rt寄存器的内容保存到rs寄存器内容和立即数符号扩展后的数相加作为地址的内存单元中。同样的依次找到源操作数在寄存器中的值,进入ALU运算后,检验结果,过程图展示如下,结果无误,单元功能实现完好
第20个周期中,指令地址为9c290004,在程序测试段中,可以看到,本条指令为lw,那么现在开始检验指令lw的实现过程:指令lw的功能是:rt ← memory[rs + (sign-extend)immediate];immediate符号扩展再相加
读取rs寄存器内容和立即数符号扩展后的数相加作为地址的内存单元中的数,然后保存到rt寄存器中。同样的依次找到源操作数在寄存器中的值,进入ALU运算后,检验结果,过程图展示如下,结果无误,单元功能实现完好
第21个周期中,指令地址为e0000010,在程序测试段中,可以看到,本条指令为j,那么现在开始检验指令j的实现过程:指令j的功能是:pc <-{(pc+4)[31..28],addr[27..2],2{0}},无条件跳转
由于MIPS32的指令代码长度占4个字节,所以指令地址二进制数最低2位均为0,将指令地址放进指令代码中时,可省掉!这样,除了最高6位操作码外,还有26位可用于存放地址,事实上,可存放28位地址了,剩下最高4位由pc+4最高4位拼接上。指令验证过程如下,最后结论为:单元工作正常,功能实现完好
第22个周期中,指令地址为fc000000,在程序测试段中,可以看到,本条指令为Halt,那么现在开始检验指令Halt的实现过程:指令Halt的功能是:停机;不改变PC的值,PC保持不变。从仿真后的波形图中,可以清晰看到,波形图在本指令后,电平恒定,不再发生变化,所以本指令功能实现,模块单元工作正常
深刻了解了一个简单单周期CPU的设计方法,无论是复杂亦或是简单的系统,最好的办法就是采用分层和模块化的设计方法。在众多信号状态中,首先从最高层开始梳理逻辑,划分模块,进而到每个模块的内部核心处继续划分,这样就避免了在信号条件变动很多的情况下不能够清晰的理清的问题
硬件设施的不足让人感觉整个课程在“云端”,讲授的内容不能很好的和现有知识的应用契合,虽然第一次接触VerilogHDL硬件描述语言,但是这门语言的思想和我所学的C++语言使用了同样的逻辑架构,采用了自顶向下、分而治之的思想逐步剖析,正所谓“大厦的建立绝非一朝一夕”,采用“分步”的设计思想完成最终单周期CPU的设计与实现
有些许遗憾的是未能在硬件上实现,如果能在开发板上烧写程序,接触到实物,应该能有更为深刻的理解,在模块调用使用端口绑定时,有一个小技巧:勿完全按照顺序赋值;因为这样的方法可以尽量减少程序出错的概率,而对于我们后期检查源文件时也无需完全分辨每一个参数的值,减少工作量
维基百科、谷歌学术是非常不错的平台
]]>将士出征,怎能没有一把利器,本文基于 VSC 搭建 C++ 开发环境
相信多数计算机专业的同学都和我一样,步入大学首先要学习的就是 C 语言。那么,我想下面这个东西你一定见过
记得当时令我好奇的就是,为什么这个 VC++6.0 里,行号、插件、快捷键……什么都没有呢??于是,历经 CodeBlocks、DevC++、VC++6.0 等编辑器后,我找到了致胜的法宝,今天的主角——VScode,这款工具在之前的博文中就有过推荐,点我直达
下面我们来一起配置下 C++ 的开发环境
编辑器就是你写代码的地方,一款好的编辑器支持语法高亮、超多快捷键、代码提示等诸多功能
访问官网下载,不做细节介绍,一个字“好”
傻瓜式操作,直接下一步即可安装成功
将源码文件编译为计算机能够执行的二进制代码文件,简单来说,代码是写给人看的,二进制文件是电脑看的,代码是人和机器交流的通道
访问链接,下载编译器
将下载下来的文件解压后,放到 C:\Program Files
文件夹下
添加环境变量 Path ,系统->关于->高级系统设置
编辑 Path 变量
加入 C:\Program Files\mingw64\bin
,然后一路确定下去
cmd
窗口键入 gcc --version
验证配置状态
显示图示信息则配置成功
安装 C++ 语言支持拓展包
安装 coderunner (一键执行源程序)
打开 vscode,导入一个空文件夹
点击新建文件夹按钮
命名为 .vscode
,然后点击新建文件按钮,依次建立图示文件结构
其实对应的文件名称在后期编译时,vscode 会自动生成,但由于默认配置不太友好(比如生成的 exe 文件都在源文件下方,非常混乱),我们对此进行优化配置,==注意对应的路径请填写你的配置路径==
下面给出常用的配置文件(包含 .exe 重定向),可直接保存使用,定向 详细参考
{ |
{ |
{ |
输入经典的 HelloWorld 程序,测试下环境
/* |
如果你是用了上方的配置文件,请在根目录下新建 build
文件夹,exe
文件会自动归类到此文件下
如果没有新建 build 文件夹,系统会提示你没有这样的文件夹,也就是找不到输出目录
]]>今天在写C语言练习题时,发现Vscode工作区中出现了这样的情况
程序运行产生的可执行文件和源码混在一起,作为一名强迫症,我怎能容忍它 “如此放肆”,特意查看了一波官方文档后终于找到了解决办法,这是对.exe
文件位置重定向后的工作区文件目录
怎么样?看起来是不是舒服多了?emmm……强迫症表示非常友好哦,下面就带大家看看我是如何解决的
现在关闭Vscode,在桌面新建一个文件夹,命名随意,然后直接拖拽到Vscode图标处打开,这个文件就是我们的工作区
打开之后我们新建文件夹 Demo ,其下新建文件 Hello.c ,输入代码以便我们后续测试
|
点击左侧的调试按钮->创建launch.json
文件
选择C++(GDB/LLDB)
选择gcc.exe-生成和调试活动文件
返回工作区文件目录,发现生成了.vscode文件夹,包含launch.json
和tasks.json
文件。简单了解下:tasks
用于编译,launch
用于执行编译后的文件,详情点击这里
为了方便大家修改,直接给出文件,修改位置有特殊标注。可以使用 Ctrl +F 组合键搜索,简单粗暴的可以直接删除生成的文件内容,复制下面对应文件操作
{ |
(1)将命令
"${fileDirname}\\${fileBasenameNoExtension}.exe" |
替换为
"${workspaceFolder}\\build\\${fileBasenameNoExtension}.exe" |
(2)将命令
"cwd": "${fileDirname}" |
替换为
"cwd": "C:\\Program Files\\mingw64\\bin" |
{ |
将命令
"program": "${fileDirname}\\${fileBasenameNoExtension}.exe", |
替换为
"program": "${workspaceFolder}\\build\\${fileBasenameNoExtension}.exe", |
点击Edit in settings.json
打开配置项,由于Code Runner中配置文件较多,我们只修改相关部分即可
(1)将命令
"c": "cd $dir && gcc $fileName -o $fileNameWithoutExt && $dir$fileNameWithoutExt", |
替换为
"c": "cd $dir && gcc $fileName -o $workspaceRoot/build/$fileNameWithoutExt && $workspaceRoot/build/$fileNameWithoutExt", |
(2)将命令
"cpp": "cd $dir && g++ $fileName -o $fileNameWithoutExt && $dir$fileNameWithoutExt", |
替换为
"cpp": "cd $dir && g++ $fileName -o $workspaceRoot/build/$fileNameWithoutExt && $workspaceRoot/build/$fileNameWithoutExt", |
最后在工作区新建文件夹build,作为Test文件子项,确定好文件从属关系
完成,强迫症表示很su服~~
]]>组合键 Ctrl
+ ,
打开设置,搜索 Shell: Windows
打开 settings.json
配置文件,尾部添加这一行代码
"terminal.integrated.shell.windows": "C:\\IDE\\Git\\bin\\bash.exe" |
注意:
IDE
位置配置为你的 git 安装路径,
\
修改为\\
如图,打开终端
可以发现已经显示了 bash
👲👲作者主页:🔗杰森的博客
📒📒本文摘要:微信分身(多开)教程
💖💖如果本文帮助到你的话,还请各位小伙伴👍点赞➕收藏⭐➕评论💭支持杰森呀✌️
系统环境:Windows 11
微信,相信已经是我们生活中离不开的东西之一了,但随着使用时间增多,我们添加的好友也越来越多。本来想着分分类,让工作和生活分离开来。但看着近千人的通讯录列表实在是苦于操作,于是我们注册了另一个账户。亦称,“小号”、“工作号”
但随之而来的麻烦又来了,电脑只能登录一个微信账户。那这时候就有同学说了:“来回切换账户发消息,不累么?”
当然,伟大的程序猿们怎么能浪费时间在这种事情上呢!那今天杰森教大家微信分身,一台电脑同时登录多个微信账户
桌面找到微信快捷方式,快捷键 alt
+ enter
查看快捷方式 目标位置 并复制路径
桌面空白位置右击,新建 文本文档,需要同时登录几个微信就复制几条以下命令
start C:\IDE\SoftWare\WeChat\WeChat.exe -- 修改为你的微信目标路径 |
组合键 ctrl
+ shift
+ s
另存为 WeChat.bat
,此处 注意编码格式
将 WeChat.bat
文件放在 除 C 盘外的其他盘符下 ,右键 WeChat.bat
文件选择 发送到桌面快捷方式
找一个自己喜欢的图标文件 (.ico
格式),选中桌面快捷方式, alt
+ enter
键更改快捷方式图标
网站推荐:
- 阿里巴巴矢量图标库
- 在线图片格式转换(
.png
~.ico
)
选中快捷方式,F2
重命名,效果如下
双击 杰森 图标,拖拽登录框(重叠),分别登录就可以双开啦
正式踏入 linux 学习历程,记录日常 BUG,总结提升
作为学习 Linux 的小白来说,无论什么样的操作,必须不能影响到主机的健全,为此,专门搞了台服务器来耍一耍
连接服务器肯定是需要终端的,不错的软件推荐来啦。XShell,大家都说好那必须是没毛病,闭眼冲
如果你是学生(其实不用验证,发下邮件就好啦),是可以免费使用 XShell 的,进入官网后下滑,找到这里
然后你就会收到官方的邮件,点击里面的下载链接,安装就好
今天使用 XShell 连接服务器的时候,总是弹出这么一个警告信息,很是烦人
WARNING:The remote SSH server rejected X11 forwarding request.
解决办法如下,非常简单就能解决,强迫症患者滴福音诶
在会话管理器中找到当前会话
右键选择属性
点击隧道取消选中转发X11连接到(X)
点击确定,双击会话重新连接
警告消失,问题解决
]]>