一、背景 接着上一篇文章:单元测试入门篇,本篇文章作为单元测试的进阶篇,主要介绍如何对Springboot Service层代码做单元测试,以及单元测试中涉及外调服务时,如何通过Mock完成测试。
二、Springboot Service层代码单元测试 现在项目都流行前后端代码分离,后端使用springboot框架,在service层编写接口代码实现逻辑。假设现在前端不是你写的,你要对你自己写的后端springboot service层提供的接口方法做单元测试,以确保你写的代码是能正常工作的。
Service层代码单元测试:一个简单的service调mapper查询数据库replay_bug表数据量的接口功能
ReplayBugServiceImpl类代码:
@Service public class ReplayBugServiceImpl implements ReplayBugService { @Autowired ReplayBugMapper replayBugMapper; @Override public int queryBugTotalCount() { return replayBugMapper.queryBugTotalCount(); } } replayBugMapper.queryBugTotalCount代码:
@Select("select count(1) from replay_bug") int queryBugTotalCount(); 单元测试ReplayBugServiceImplTest类代码:
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class ReplayBugServiceImplTest{ @Autowired ReplayBugServiceImpl replayBugService; @Test public void queryBugTotalCount() { int bugCount=replayBugService.queryBugTotalCount(); System.out.println("结果是:"+bugCount); } } 代码很简单,调用这个接口服务,打印输出,测试是否能正确查出数据。其中关键的两个注解解释:
@RunWith(SpringRunner.class)注解:是一个测试启动器,可以加载SpringBoot测试注解。 让测试在Spring容器环境下执行。如测试类中无此注解,将导致service、dao等自动注入失败。 @SpringBootTest注解:目的是加载ApplicationContext,启动spring容器。 测试结果如下:
目录
1.Logistic回归概述
1.1 Sigmoid函数
1.2 基于最优化方法的最佳回归系数确定
1.2.1 极大似然估计
1.2.2 梯度上升法
1.2.3 梯度下降算法
2.Logistic实例分析
2.1准备数据
2.2使用梯度上升算法进行分类
3.实验总结 Logistics回归模型通常被用于处理二分类问题,它是一种用于分析各个影响因素(x1,x2,...xn)与分类结果y之间关系的有监督学习方法。虽然它的名字是“回归”,但实际却是一种分类学习方法。这里的“回归”一词源于最佳拟合,表示要找到最佳拟合参数集,因此,logistic训练分类器时的做法就是寻找最佳拟合参数,使用的是最优化方法。
1.Logistic回归概述 我们都知道使用线性模型可以进行回归学习,但若要做的是分类任务改如何处理?只需要找一个单调可微函数将分类任务的真实标记y与线性回归模型的预测值联系起来。
考虑二分类任务,其输出标记y的取值为0和1,而线性回归模型产生的预测值是实值,于是需将实值z转换为0/1值。通过Sigmoid函数引入非线性因素,可以实现实值z转换为0/1值,处理二分类问题。
1.1 Sigmoid函数 首先我们介绍一下Sigmoid函数,也称为逻辑函数:
其函数曲线如下:
从上图可以看出sigmoid函数是一个s形的曲线,它的取值是[0,1]之间,在远离0的地方函数的值会很快接近0或者1。它的这个特性对于解决二分类问题十分重要。
逻辑回归的假设函数形式如下:
所以:
其中x是我们的输入,w和b为我们要求取的参数
若将y视为样本x作为正例的可能性,则1-y是其反例可能性,两者的比值为称为“几率”,反映了x作为正例的相对可能性
样本作为正例的相对可能性的对数
因此有: 上面两个式子分别表示y=1和y=0的概率。上述过程我们通过sigmoid函数将z值映射到0到1之间,获得数值之后就可以进行分类。如定义阈值为0.5,y*为分类结果,则,实际应用时特定的情况可以选择不同的阈值。接下来我们要解决的问题就是获得最佳回归系数,即求解w和b得值。
1.2 基于最优化方法的最佳回归系数确定 1.2.1 极大似然估计 极大似然估计的方法步骤:
确定待求解的未知参数,如均值、方差或特定分布函数的参数等;计算每个样本的概率密度为;根据样本的概率密度累乘构造似然函数:通过似然函数最大化(求导为0),求解未知参数θ,为了降低计算难度,可采用对数加法替换概率乘法,通过导数为0/极大值来求解未知参数。 我们可通过“极大似然法”来估计w和b,给定数据集,最大化样本属于其真实标记的概率,等同于最大化对数似然函数:
为便于讨论,令则可简化为
令,则上述式中的似然项可重写为 根据sigmoid函数,似然函数可重写为:
最大化对数似然函数等价于最小化,是关于的高阶可导连续凸函数,经典的数值优化算法如梯度下降法可求得其最优解
1.2.2 梯度上升法 梯度上升法基本的思想是:要找到某函数的 最大值,最好的方法是沿着该函数的梯度方向探寻。如果梯度记为∇,则函数f(x,y)的梯度由 下式表示:
这个梯度意味着要沿x的方向移动 ,沿y的方向移动 。其中,函数f(x,y) 必须要在待计算的点上有定义并且可微。如下图:
梯度上升算法到达每个点后都会重新估计移动的方向。从P0开始,计算完该点的梯度,函数就根据梯度移动到下一点P1。在P1点,梯度再次被重新计算,并沿新的梯度方向移动到P2。如此循环迭代,直到满足停止条件。迭代的过程中,梯度算子总是保证我们能选取到最佳的移动方向。我们知道了移动的反向,那移动量的大小是多少。该量值称为步长,记做α。用向量来表示的话,梯度上升算法的迭代公式如下:
该公式将一直被迭代执行,直至达到某个停止条件为止,比如迭代次数达到某个指定值或算法达到某个可以允许的误差范围。
1.2.3 梯度下降算法 梯度下降算法,它与上述的梯度上升算法是一样的,只是公式中的加法需要变成减法。因此,对应的公式可以写成:
梯度上升算法用来求函数的最大值,而梯度下降算法用来求函数的最小值。
2.Logistic实例分析 利用Logistic回归模型根据身高、体重和肺活量预测性别
2.1准备数据 数据部分截图:
2.2使用梯度上升算法进行分类 sigmoid函数:
# sigmoid函数 def sigmoid(inX): return 1.
✨个人主页:bit me
✨当前专栏:数据结构
✨刷题专栏:基础算法
链 表 OJ 🏳️一. 移除链表元素🏴二.反转链表🏁三.链表的中间结点🚩四.链表中倒数第k个结点🏳️🌈五.合并两个有序链表🏳️⚧️六.链表的回文结构🏴☠️七.链表分割🏴八.相交链表🏳️🌈九.环形链表🍹十.环形链表 II 🏳️一. 移除链表元素 简介:
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
示例1:
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]
示例2:
输入:head = [], val = 1
输出:[]
示例3:
输入:head = [7,7,7,7], val = 7
输出:[]
提示:
①:列表中的节点数目在范围 [0, 104] 内
②:1 <= Node.val <= 50
③:0 <= val <= 50
要求:
①:时间复杂度O(n)
②:只遍历单链表一次
首先我们需要知道的是:
删除的核心是 需要找到这个节点的前一个节点是谁
招银测开面经 一面 1.面向对象3大特征
2.java是否能多继承,怎么实现多继承
3.抽象类
4.数据库特性,隔离级别
5.sql语句查找
6.static关键字的使用
7.手撕:寻找字符串出现频率最高的字符
8.代码改进和测试
二面 1.先闲聊了几句,在哪里读书,为啥base深圳,面了哪些公司
2.为啥选择测试
3.数据库sql语句
4.场景题:周五安排你兼容性测试40台机子,你怎么办
5.测试方法,一些理论知识
6.遇到的困难,和别人怎么沟通
7.反问(太少太少了,真的好烦不问八股的
交行西安软件研发中心-9.08 面试情况:3个面试官vs你1个,3个都不开摄像头但是你得开
上来先2分钟的自我介绍
第一个面试官问: 首先问了实习的岗位是测试,为什么来找开发
1、项目相关,你项目里的MySQL索引是怎么设计的
2、顺着项目往下问,如何确定设计索引的字段,索引的缺点
3、索引失效的场景有哪些
4、模糊查询的哪种情况下会导致索引失效
第二个面试官问: 1、Java是自学的吗
补充一下问了个linux的常用命令,然后说grep如何检索3个字母,也就是长度为3的字符,这个我确实不了解。。我直接说不清楚这个
2、实习的时候写的接口自动化用的什么框架
3、实习的时候接口自动化是针对一个服务写了一个自动化还是怎样?
4、实习的时候接口自动化是和开发人员共同完成的吗
5、实习的时候接口自动化有没有获取token的问题?这个问题我没太明白,让他举了个例子,他说就是有些需要验证用户的token是否合法之类的,我就说在请求中把相关的账号信息或者token信息都写上了
6、期望薪资,我说的月薪,然后第三个面试官就问那你的期望年薪呢(我就想你自己不会乘一下嘛)
再补充一下,还问了一嘴成绩排名
总结一下,有项目的话会根据项目中的某一点问,有实习的话会根据实习经历问,基本问的都不难。。听说后续如果面试过了再参加笔试,许愿进一个笔试
兴业数金测试一面 大概进行了约20分钟就结束了吧(可能没啥问的,这个面经是后面回想起来的,忘记录音了,可能不够全
兴业数金一面: 1、实习干了什么,能否讲出测试的流程以及自己所负责的版块
2、金融相关的知识
3、docker相关的了解,如docker的命令行
4、linux日常的使用,以及问了一些命令,其中打开一个文件找到“关键字”的位置
5、Django相关,如MTV
6、用python做了哪些工作,对于装饰器的使用,然后对生成器迭代器的理解,重点问了关于yield相关
7、对于前沿技术的了解(区块链,大数据之类的
2023恒生秋招测试岗面经 笔试:笔试单选、不定项选择、一道数据库大题,两道编程题
一面:线上腾讯会议 20min 自我介绍
自我介绍中提了做过测试,面试官问如何做的
了解数据库吗,问一些数据库的基本知识,还问到了SQL数据库如何对百万级别的数据量进行插入(答得不太好)
熟悉linux操作系统吗,说说linux操作系统常用的命令
编程语言中常用的循环的区别
自我介绍中说用到python编写自动化脚本,具体做了什么,测的UI还是接口
反问
刚接到二面通知,过了二面接着来补充面经~
二面凉经~,技术主管面每个人30min左右 自我介绍
大学里最让你印象深刻的事
工作地点选择的杭州,问我为什么想留在杭州
毕业两三年内的工作打算和生活打算
聊了些日常的东西,就不详细罗列了,
我建议大家找工作,尽量不要暴露自己有对象这件事,我是被迫暴露的,微信登录的腾讯会议头像被面
试主管发现是情头,上来就问我说跟上午面过的一个小伙子你俩是什么关系,然后那会我脑子也是蒙的,想都没想就说了实话,然后俩人一起凉凉。。。。。。
最后给我发了感谢信,再见!
资源分享 下方这份完整的软件测试视频学习教程已经上传CSDN官方认证的二维码,朋友们如果需要可以自行免费领取 【保证100%免费】
原链表图:
方法一:头插法链表逆置
1.断开头节点与其他节点的连接(提前存好head->next的地址)
Node* p = head->next;
Node* q = p->next;
head->next = NULL;
2. 头插法在head后面插入p后链表的各个节点
p->next = head->next;
head->next = p;
p、q指针往后移
p = q;
if (q != NULL)
q = q->next;
3. 依此类推直到全部插入,链表逆置完成
完整代码:
void R_head(List head) { assert(head != NULL); if (head == NULL) return; if (GetLength(head) <= 1) return; Node* p = head->next; Node* q = p->next; head->next = NULL; while (p != NULL) { p->next = head->next; head->next = p; p = q; if (q !
Maven高级 目标
理解并实现分模块开发能够使用聚合工程快速构建项目能够使用继承简化项目配置能够根据需求配置生成、开发、测试环境,并在各个环境间切换运行了解Maven的私服 1,分模块开发 1.1 分模块开发设计 (1)按照功能拆分
我们现在的项目都是在一个模块中,比如前面的SSM整合开发。虽然这样做功能也都实现了,但是也存在了一些问题,我们拿银行的项目为例来聊聊这个事。
网络没有那么发达的时候,我们需要到银行柜台或者取款机进行业务操作随着互联网的发展,我们有了电脑以后,就可以在网页上登录银行网站使用U盾进行业务操作再来就是随着智能手机的普及,我们只需要用手机登录APP就可以进行业务操作 上面三个场景出现的时间是不相同的,如果非要把三个场景的模块代码放入到一个项目,那么当其中某一个模块代码出现问题,就会导致整个项目无法正常启动,从而导致银行的多个业务都无法正常班理。所以我们会按照功能将项目进行拆分。
(2)按照模块拆分
比如电商的项目中,有订单和商品两个模块,订单中需要包含商品的详细信息,所以需要商品的模型类,商品模块也会用到商品的模型类,这个时候如果两个模块中都写模型类,就会出现重复代码,后期的维护成本就比较高。我们就想能不能将它们公共的部分抽取成一个独立的模块,其他模块要想使用可以像添加第三方jar包依赖一样来使用我们自己抽取的模块,这样就解决了代码重复的问题,这种拆分方式就说我们所说的按照模块拆分。
经过两个案例的分析,我们就知道:
将原始模块按照功能拆分成若干个子模块,方便模块间的相互调用,接口共享。 刚刚我们说了可以将domain层进行拆分,除了domain层,我们也可以将其他的层也拆成一个个对立的模块,如:
这样的话,项目中的每一层都可以单独维护,也可以很方便的被别人使用。关于分模块开发的意义,我们就说完了,说了这么多好处,那么该如何实现呢?
1.2 分模块开发实现 前面我们已经完成了SSM整合,接下来,咱们就基于SSM整合的项目来实现对项目的拆分。
1.2.1 环境准备 部署到IDEA中,将环境快速准备好,部署成功后,项目的格式如下:
1.2.2 抽取domain层 步骤1:创建新模块 创建一个名称为maven_03_pojo的jar项目,为什么项目名是从02到03这样创建,原因后面我们会提到,这块的名称可以任意。
步骤2:项目中创建domain包 在maven_03_pojo项目中创建com.itheima.domain包,并将maven_02_ssm中Book类拷贝到该包中
步骤3:删除原项目中的domain包 删除后,maven_02_ssm项目中用到Book的类中都会有红色提示,如下:
**说明:**出错的原因是maven_02_ssm中已经将Book类删除,所以该项目找不到Book类,所以报错
要想解决上述问题,我们需要在maven_02_ssm中添加maven_03_pojo的依赖。
步骤4:建立依赖关系 在maven_02_ssm项目的pom.xml添加maven_03_pojo的依赖
<dependency> <groupId>com.itheima</groupId> <artifactId>maven_03_pojo</artifactId> <version>1.0-SNAPSHOT</version> </dependency> 因为添加了依赖,所以在maven_02_ssm中就已经能找到Book类,所以刚才的报红提示就会消失。
步骤5:编译maven_02_ssm项目 编译maven_02_ssm你会在控制台看到如下错误
错误信息为:不能解决maven_02_ssm项目的依赖问题,找不到maven_03_pojo这个jar包。
为什么找不到呢?
原因是Maven会从本地仓库找对应的jar包,但是本地仓库又不存在该jar包所以会报错。
在IDEA中是有maven_03_pojo这个项目,所以我们只需要将maven_03_pojo项目安装到本地仓库即可。
步骤6:将项目安装本地仓库 将需要被依赖的项目maven_03_pojo,使用maven的install命令,把其安装到Maven的本地仓库中。
安装成功后,在对应的路径下就看到安装好的jar包
**说明:**具体安装在哪里,和你们自己电脑上Maven的本地仓库配置的位置有关。
当再次执行maven_02_ssm的compile的命令后,就已经能够成功编译。
1.2.3 抽取Dao层 步骤1:创建新模块 创建一个名称为maven_04_dao的jar项目
步骤2:项目中创建dao包 在maven_04_dao项目中创建com.itheima.dao包,并将maven_02_ssm中BookDao类拷贝到该包中
在maven_04_dao中会有如下几个问题需要解决下:
项目maven_04_dao的BookDao接口中Book类找不到报错
解决方案在maven_04_dao项目的pom.xml中添加maven_03_pojo项目
<dependencies> <dependency> <groupId>com.itheima</groupId> <artifactId>maven_03_pojo</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> 项目maven_04_dao的BookDao接口中,Mybatis的增删改查注解报错
解决方案在maven_04_dao项目的pom.xml中添加mybatis的相关依赖
拖控件 listView 控件到新建form中,并添加相应的button,lable和textbox,如下图:
1、点击表格右上角的三角形,添加表头信息
2、Name: 程序里调用的名称,Text:表格里显示的信息,其它可以设置大小等信息
3、显示网格线 属性 GridLines --- True
这样,一个listView就画出来了。
4、往表格里填写数据,跟着来就可以了。
private void button1_Click(object sender, EventArgs e) { string time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); //数据更新,UI暂时挂起,直到EndUpdate绘制控件,可以有效避免闪烁并大大提高加载速度 listView1.BeginUpdate(); if (txtNameBox.Text != null && txtPasswordBox.Text != null) { //实例化创建对象item ListViewItem item = new ListViewItem(); //向listView控件的项中添加第一个元素ID item = listView1.Items.Add(txtIDNum.Text.Trim()); //个人认为这句类似于数据库的添加主键元素,为了标明到底是哪一行,为后续操作做铺垫 //在子项中继续添加第二个元素User item.SubItems.Add(txtName.Text.Trim()); //这句操作会跟随上句类似添加主键操作后面,作为主键那行的第二个元素 //同理添加第三个元素 item.SubItems.Add(txtPassword.Text.Trim()); //原理同上,后面可以继续添加元素,如果你有需求且在winform中已设计好属性列个数 item.SubItems.Add(time); //item.BackColor = Color.Red; //清空上次添加的数据,方便这次添加新数据 txtIDNum.Text = ""; txtName.Text = ""; txtPassword.Text = ""; //结束数据处理,UI界面一次性绘制。 listView1.EndUpdate(); } } 5、改变背景颜色,和字体颜色
https://blog.csdn.net/qq_39512532/article/details/127577952
1、导出数据 # 先往测试库插入一条测试语句 clickhouse-client --password ps123 -d default -q "insert into student values('小王', '18', '1', 'XXX小区')" # 下面是导出数据 # 导出带表头的txt文件 clickhouse-client --password ps123 -d default -q "select * from student FORMAT CSVWithNames" --format_csv_delimiter='|' > /data/student.txt # 导出不带表头的txt文件 clickhouse-client --password ps123 -d default -q "select * from student FORMAT CSV" --format_csv_delimiter='|' > /data/student.txt # 导出带表头的csv文件 带表头即有标题的:name、age clickhouse-client --password ps123 -d default -q "select * from student FORMAT CSVWithNames" --format_csv_delimiter='|' > /data/student.
偶尔用sql文件导入数据库,但是因为生成脚本时没有勾选结构和数据,导出了只是结构的sql文件,这样再次导入数据的时候就需要把原来的表删了,当表格过多了时就很麻烦,这里记录一个非sql语句执行的方法。
打开SQL Management 管理工具,展开数据库,点击数据库里的“表”
然后按F7,右边会打开所有的表,按住ctrl或者shit可以选择多张表,右键可以选择删除。感觉是比SQL语句方便。
一、ListView 定义:ListView控件: 以垂直列表的方式显示数据内容,用户用上下滑动的方式查看数据,并且能够根据数据的长度自适应屏幕显示
数据源----绑定----> 适配器adpater----传递view--->listview(相当于很多组的view)
ListView 项目框架:
实现效果:
MainActivity
//省略import public class MainActivity extends AppCompatActivity { private ListView lv; private String[]names = {"iu1","iu2","iu3","iu4","iu5","iu6"}; private int[] imageids = {R.drawable.iu1,R.drawable.iu2,R.drawable.iu3,R.drawable.iu4,R.drawable.iu5,R.drawable.iu6}; // R.drawable.iu1 这个返回的是一个数字 所以这是一个 整形数组 private List<Animal> ls; //创建一个 animals数组 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initialdata(); //初始化上面的 ls数组 lv=findViewById(R.id.lv1); //先给 listview这个整体找到对应的layout文件 再用适配器填充数据 lv.setAdapter(new AnimalAdapter()); //适配器是我们自己定义的适配器 lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { Toast.
最近研究pygame游戏制作板块,本次对于简单的俄罗斯方块进行介绍。
1.首先引入我们需要用到的pygame库和random库(pygame库基础知识请移步首页)
import pygame import random 2.对pygame库进行初始化(一般来说,使用pygame库时先进行初始化,保证pygame的代码块可以正常运行)
pygame.init() 3.设置一些初始数据(比如俄罗斯方块的每一个正方形边长box_size、行列数、rgb颜色块)
box_size = 30 #小方格 box_width = 15 #小方格列数 box_height = 20 #小方格行数 width = box_size * box_width #游戏区域宽度 height = box_size * box_height #游戏区域高度 side_width = 200 #旁白区域宽度 screen_width = width + side_width #屏幕总宽度 white = (245,245,245) #rgb表白色 black = (0, 0, 0) #黑色 line_color= (139,125,107) #边线颜色 暗灰色 cube_colors = [(255,245,40),(175,175,20),(185,185,185),(155,0,0),(175,20,20),(0, 155,0),(20,175,20),(0,0,155),(20,20,175)] #俄罗斯方块颜色组,在后续随机生成俄罗斯方块时会进行调用 4.设置屏幕(此处我们规定的屏幕为(650,600),规定标题栏,屏幕刷新频率)
pygame.display.set_mode() 创建窗口
pygame.display.set_caption() 标题栏
screen = pygame.
使用layui框架,对table表格中超长文字隐藏成…,放鼠标在上面自动显示文字,移开关闭提示 效果如下
话不多说,上代码
1、在需要隐藏多余文字的table加上,重点是fix-table的样式操作: .fix-table{table-layout: fixed;} .fix-table td {white-space: nowrap; /* 自适应宽度*/overflow:hidden;text-overflow:ellipsis;/*省略号显示*/} 2、在页面初始化隐藏和显示文字的方法,如下: 3、showAndHideMsg()方法具体代码如下: var tip_index; /** * 页面表格内容超出宽度显示... * 鼠标放上去之后回显具体内容 * 移开鼠标内容消失 */ function showAndHideMsg(){ $(document).on("mouseenter","td",function(){ if (this.offsetWidth < this.scrollWidth) { let that = this; let text = $(this).text(); let wid; if(text.length>1000){ wid = '900px'; }else if(text.length>600){ wid = '700px'; }else if(text.length>150){ wid = '500px'; }else if(text.length>100){ wid = '250px'; }else if(text.length>50){ wid = '150px'; } layui.use('layer', function(layer) { tip_index = layer.
使用yum -install nginx 命令安装nginx。然后通过dnf list nginx命令查询了安装结果。第一次通过sytemctl status nginx 命令进行查看服务启动状态时,结果显示dead,并未成功启动,通过sytemctl start nginx命令启动并再次查看启动状态,启动成功。通过ps -ef | grep nginx命令查询nginx进程。通过ip addr查看nginx服务所在系统的ip地址。第一次在远端计算机上的浏览器中访问失败,进行了防火墙设置,通过sudo firewall-cmd --zone=public --add-part=80/tcp --permanent命令打开TCP协议的80端口,再次在远端计算机浏览器中访问http://localhost(你自己的ip地址)访问成功。 至此,http访问完毕。
查阅知:https协议默认的端口号是443,http协议默认端口号是80。http协议是明文传输协议,无法防止中间人盗取、篡改信息等,所以http网站存在众多安全风险隐患。而https存在不同于http的默认端口及一个SSL加密/身份验证层(在http与tcp之间),将能有效地进行身份验证和加密传输,保护网站安全。
通过sudo firewall-cmd --add-port=443/tcp --permanent命令使防火墙开放https的默认端口443。然后配置nginx.conf文件。用vi /etc/nginx/nginx.conf 命令进入nginx.conf文件,按 i 转为插入模式,要root权限,发现nginx默认并没有配置https,因此请将文件中58-81行的注释去掉,并保存。修改完毕后,建议用sudo nginx -t 测试下配置文件中是否存在错误。上面测试结果提示server.crt文件没找到,就是所谓的证书。可以创建一个自签名证书。正常流程应该是要到专门的部门申请。通过sudo mv server.key private/调整server.key配置文件的位置。通过sudo systemctl reload nginx重载配置信息后重新访问https://localhost(你自己的ip地址)成功。 至此,https访问完毕。
问题描述: 在我刚安装完vue脚手架后,初次使用时发现无法使用快捷生成文件结构模板
原因分析: 可能是vue.json没有配置模板
解决方案: 在vscode中配置vue.json
注意:这里输入vue后回车,会自动弹出vue.json界面。之后直接输入下面代码!!!
{ "Print to console": { "prefix": "vue", "body": [ "<template>", " <div class=\"\">\n", " </div>", "</template>\n", "<script>", "export default {", " name: '',", " data() {", " return {}", " },", " components: {", " ", " },", " computed: {", " ", " },", " mounted: {", " ", " },", " methods: {", " ", " },", "}", "</script>\n", "<style scoped>"
今天copy下来一份公司以前的老项目,跑起来的时候报的错误,
按照官方文档进行更改后还是不行最后找到了一个方案
在androidstudio的终端上输入taskkill /f /im java.exe杀死java的进程就可以了
以剑指offerⅡ 068 查找插入位置为例:
给定一个排序的整数数组 nums 和一个整数目标值 target ,请在数组中找到 target ,并返回其下标。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
示例 1:
输入: nums = [1,3,5,6], target = 5
输出: 2
示例 2:
输入: nums = [1,3,5,6], target = 2
输出: 1
示例 3:
输入: nums = [1,3,5,6], target = 7
输出: 4
示例 4:
输入: nums = [1,3,5,6], target = 0
输出: 0
示例 5:
输入: nums = [1], target = 0
输出: 0
数列排序 题目描述 给定一个数列 a a a,这个数列满足 a i ≠ a j a_i \not =a_j ai=aj( i ≠ j i\not=j i=j),现在要求你把这个数列从小到大排序,每次允许你交换其中任意一对数,请问最少需要几次交换?
输入格式 第一行是一个整数,代表数字个数 n n n。
第二行有 n n n 个整数用空格分隔开,表示数列 a a a。
输出格式 只有一行,包含一个数,表示最少的交换次数。
样例 #1 样例输入 #1 8 8 23 4 16 77 -5 53 100 样例输出 #1 5 提示 数据规模与约定 对于 100 % 100\% 100% 的数据,保证 1 ≤ n ≤ 1 0 5 1\le n\le10^5 1≤n≤105, − 2 31 < a i < 2 31 − 1 -2^{31}\lt a_i\lt2^{31}-1 −231<ai<231−1。
我们有一些二维坐标,如 “(1, 3)” 或 “(2, 0.5)”,然后我们移除所有逗号,小数点和空格,得到一个字符串S。返回所有可能的原始字符串到一个列表中。
原始的坐标表示法不会存在多余的零,所以不会出现类似于"00", “0.0”, “0.00”, “1.0”, “001”, "00.01"或一些其他更小的数来表示坐标。此外,一个小数点前至少存在一个数,所以也不会出现“.1”形式的数字。
最后返回的列表可以是任意顺序的。而且注意返回的两个数字中间(逗号之后)都有一个空格。
示例 1:
输入: “(123)”
输出: [“(1, 23)”, “(12, 3)”, “(1.2, 3)”, “(1, 2.3)”]
示例 2:
输入: “(00011)”
输出: [“(0.001, 1)”, “(0, 0.011)”]
解释:
0.0, 00, 0001 或 00.01 是不被允许的。
示例 3:
输入: “(0123)”
输出: [“(0, 123)”, “(0, 12.3)”, “(0, 1.23)”, “(0.1, 23)”, “(0.1, 2.3)”, “(0.12, 3)”]
示例 4:
输入: “(100)”
输出: [(10, 0)]
解释:
1.0 是不被允许的。
静态链表是数据结构线性表中的一种,因为其每一个结点只有一个直接前驱和直接后继,对于开头结点和末尾结点只有一个直接前驱或直接后继。 本人听老师讲课,看老师关于静态链表PPT时有些许不懂,看了CSDN其他关于静态链表的帖子后也还存在许多疑惑,现在自己明白之后试着把它的逻辑写出来。 我们说链表是一种链式存储结构,是因为它每一个结构体节点中存放着下一个结构体节点的地址,通过指针与地址使得链表被称作链。那么在一些语言中,因为封装较完备,我们无法对地址直接进行操作,例如java。所以静态链表可以在某种意义上替代链表。
我们知道但凡一种语言,可能没有指针,但是数组这种基本的数据类型一定会有,静态链表就是利用数组来模拟实现链表的功能。
静态链表有两种形式,第一种是以结构体为基本单元,一个结构体对应一个节点,结构体中有两个元素,一个是该节点存放的数据data,另一个是该节点存放的游标cur(注意cur中存放的是下一个节点的下标,等同于链表中的指针域,都是表示下一个节点的位置信息的);一种是构建两个同步的数组,一个数组存放data,一个数组同步存放该下标对应的cur。其实这俩差不多,第一种更加好理解一点,我们用第一种来举例:
其实我们能将静态链表这一个数组拆成两个链表来看,因为一开始创建数组没有元素存储,所以一开始待存储链表很长,已存储链表为空。我们需要存储数据的时候,就把带存储链表的第一个节点取下,用来存放数据,并把它接到已存储链表上,这样带存储链表越来越短,已存储链表越来越长。
基本思路是:第一个节点(下标index=0)的data不存放数据,cur存放待存储链表的第一个节点下标(注意,是还没有利用过的节点下标)最后一个节点的(下标为length-1)的data不存放数据,cur存放已存储链表的第一个节点的下标。
如图可看大概存储原理↑
下面展示具体代码:
构建静态链表 struct L { int data; int cur; }arr[100];//创建一百个节点大小的静态链表,并定义标签为L的结构体数据类型 #include<stdio.h> struct L* initlist(struct L* arr,int n)//返回这个结构体数组的首地址 { for(int i=1;i<99;i++) { arr[i].cur=i+1; } arr[0].cur=2; arr[99].cur=1; arr[1].data=n; arr[1].cur=0; return arr; } 插入操作 插入操作涉及到几部
第一,一定会更改arr[0].cur的值,因为待存储数组的首元素被拿来存储数据,所以值会变更。
第二,可能会更改最后一个节点的cur值(即arr[99].cur),如果插入的元素存储在链表的第一个位置,则会更改。
第三,a->b –> a->c->b,更改指针指向,需要两步操作
struct L* listInsert(struct L* arr,int n,int i) { if(i<=0) { printf("错误"); return arr; } int k=99; for(int j=1;j<=i-1;j++) { k=arr[k].cur; if(arr[k].cur==0) { break; } } int temp=arr[0].
枚举与联合
先来看看两者的形式
枚举:
#include<stdio.h> enum Day { Mon, Tues, Wed, Thu, Fri, Sat, Sun }; int main() { return 0; } 联合体(也叫共用体):
#include<stdio.h> union Un { char c; int i; }; int main() { return 0; } 下面分别解析这两种自定义变量类型:
枚举:
由关键字enum 和标签组成(类似于结构体)
{}里的内容是枚举类型的可能取值
枚举类型的初始化:
枚举类型大括号里代表这种类型的可能取值,一个成员代表一个值,例如现在未进行初始化,则第一个Mon 代表0,第二个Tues 代表1…以此类推
,分别代表一个初始值
当然我们也可以手动赋予这些变量以初始值,格式如下:
#include<stdio.h> enum day { mon = 1, tues = 2, wed = 5, thur = 10 }; int main() { return 0; } 这样也是一种赋予初始值的方法,和上一种系统自动赋值相比,这一种更自由