微醺的博客


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 日程表

  • 站点地图

vim - 插入模式技巧

发表于 2019-09-05 | 分类于 vim技巧

插入模式只专注于做一件事, 那就是输入文字.

1 插入模式中及时更正错误

如果在插入模式下输入错误时,正常可以用退格键删除错误文本.它会如我们所愿的删除光标前的字符.另外我们还可以使用下面一些组合键:

按键操作 用途
<C-h> 删除前一个字符
<C-w> 删除前一个单词
<C-u> 删除至行首

这些命令不是插入模式所独有的,甚至也不是 Vim 所独有的,在 Vim 的命令行模式中,以及在 bash shell 中,也可以使用它们。

2 返回普通模式

切换回普通模式的经典方式是使用 键, 但在许多键盘上这个键的距离可能有点远。作为替代,我们也可以用 <C-[> ,它的效果与 完全相同.
详情可参见: h i_CTRL-[

图:

按键操作 用途
<Esc> 返回普通模式
<C-[> 删除前一个单词
<C-o> 切换到插入-普通模式

刚开始使用 vim 时可能会觉得不断地切换模式比较烦, 但是使用一段时间后就会慢慢上手了.

2.1 插入 - 普通模式

插入-普通模式是普通模式的一个特例,它能让我们执行一次普遍模式命令。在此模式中,我们可以执行一个普通模式命令,执行完后,马上就又返回到插入模式。要从插入模式切换到插入-普通模式,可以按 <C-o>
参见: i_CTRL-O

例如, 当我们正在窗口的顶行或是底行时, 想看到更多的上下文, 在普通模式我们可以 zz 重绘窗口并把当前行显示在窗口的正中间. 所以我们可以使用命令: <C-o>zz 这样可以不受中断的继续打字.

3 不离开插入模式, 粘贴寄存器中的文本

Vim 的复制和粘贴操作一般都在普通模式中执行,不过有时我们也许想不离开插入模式,就能往文档里粘贴文本。

在插入模式中, 按<C-r>{register}把寄存器中的内容插入到文件中. 其中register是我们想要插入的寄存器的名字. (参见: h i_CTRL-R). 在插入模式中,可以用{register} 命令很方便地粘贴几个单词。可是如果寄存器中包含了大量的文本, 你也许会发现屏幕的更新有些轻微的延时。 这是因为 Vim在插入寄存器内的文本时,其插入方式就如同这些文本是由键盘上一个个输进来的。因此,如果 ‘textwidth’ 或者‘autoindent’ 选项被激活了的话,那么最终就可能会出现不必要的换行或额外的缩进。<C-r><C-p>{register} 命令则会更智能一些,它会按原义插入寄存器内的文本.

1
2
重新映射大小写转换键(Caps Lock)
------------------------------------------

4 使用表达式寄存器做运算

表达式寄存器允许我们做一些运算,并把运算结果直接插入到文档中。

大部分的 Vim寄存器中保存的都是文本, 不过表达式寄存器则是个另类, 它可以用来执行一段 Vim 脚本, 并返回其结果.

我们可以用 = 符号指明使用表达式寄存器。在插入模式中,输入 <C-r>= 就可以访问这一寄存器。这条命令会在屏幕的下方显示一个提示符,我们可以在其后输入要执行的表达式。输入表达式后敲一下 <CR>, Vim 就会把执行的结果插入到文档的当前位置了。
示例文本:

1
6 chairs, each costing $35, totals $

当光标处于当前行时, 可以输入:

1
2
A  
<C-r>=6*35<CR>

||–>> A 将光标移到行尾并进入插入模式
||–>> 调用表达式寄存器, 并返回6*35的计算结果到光标当前位置.

当然, 表达式寄存器不仅仅可以用来做运算, 还有其他更高级的应用.

5 用字符编码插入非常用字符

6 用二和字母插入非常用字符

7 用替换模式替换已有文本

vim 的拼写检查器

发表于 2019-08-30 | 分类于 vim技巧

人们需要一些时间把锯子磨锋利.

利用vim的拼写检查器,查找并更正拼写错误

开启和关闭拼写检查

1.开启

1
: set spell

2.关闭

1
: set nospell

阅读全文 »

Linux-线程同步和互斥

发表于 2019-08-18 | 分类于 Linux多线程编程

Linux线程基础—-线程同步与互斥

1.同步的概念

1.1 同步概念

所谓同步,即同时起步,协调一致.不同的对象,对”同步”的理解方式不同. 如: 设备同步是指两个设备之间规定一个共同的时间参考; 数据库同步,是指让两个或多个数据库保持一致,或者按需要部分保持一致; 文件同步,是指让两个或多个文件夹里的文件保持一致等等.而编程中,通信中所说的同步与生活中大家印象中的同步略有差异.”同”是指协同,协助,互助配合.主旨在协同步调,按预定顺序先后次序运行.

1.2 数据混乱的原因

1) 资源共享(独享资源不存在此问题)
2) 调度随机, 即意味着数据访问会出现竞争
3) 线程间缺乏必要的同步机制.

前面两点不能改变,欲提高效率,传递数据资源必须共享.只要共享资源就一定会出现竞争.只要存在竞争关系,数据就很容易出现混乱。所以只能从第三点着手解决。使多个线程在访问共享资源的时候,出现互斥。

3.线程同步

是一个宏观概念,在微观上包含线程的相互排斥和线程先后执行的约束问题.
同步即协同步调,按预定的先后次序运行.
线程同步指一个线程发出某一功能调用时, 在没有得到结果前,该调用不返回. 同时其他线程为保证数据一致性,不能调用该功能. 如: A任务的运行依赖于B任务产生的数据.
目的: 是为了避免数据混乱,解决与时间有关的错误.实际上,不仅线程间需要同步,进程间,信号间等都需要同步. 因此, 所有"多个控制流,共同操作一个共享资源"的情况,都需要同步.

解决同步办法: 条件变量, 线程信号量

2.线程同步手段

线程互斥

线程执行的相互排斥.
散步在不同任务之间的若干程序片断,当某个任务运行其中一个程序片段时,其它任务就不能运行它们之中的任一程序片段,只能等到该任务运行完这个程序片段后才可以运行。最基本的场景就是:一个公共资源同一时刻只能被一个进程或线程使用,多个进程或线程不能同时使用公共资源。
解决互斥方式: 互斥锁,读写锁,线程信号量

互斥锁创建和销毁

#include <pthread.h>
//创建快速互斥锁.
pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;
//创建递归互斥锁.
pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
//创建检错互斥锁.
pthread_mutex_t errchkmutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;

//创建并初始化一个互斥锁
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
//功能:上锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
//功能:尝试上锁,拿不到锁返回出错信息
int pthread_mutex_trylock(pthread_mutex_t *mutex);
//功能:释放锁
int pthread_mutex_unlock(pthread_mutex_t *mutex); ///成功返回0,出错返回出错码

//销毁互斥锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);

参数: 
mutex: 互斥锁.
mutexattr: 互斥锁创建方式.

互斥锁属性创建和销毁

#include <pthread.h>
int pthread_mutexattr_init(pthread_mutexattr_t *attr);    
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);

互斥锁类型操纵
[mutex_lock_type.c]
int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind);
int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind);
attr: 互斥锁属性;
type: 互斥锁类型: 
    1)标准互斥锁: PTHREAD_MUTEX_NORMAL, 第一次上锁成功,第二次上锁会阻塞.
    2)递归互斥锁: PTHREAD_MUTEX_RECURSIVE, 第一次上锁成功,第二次上锁还是成功,内部计数.
    3)检错互斥锁: PTHREAD_MUTEX_ERRORCHECK, 第一次上锁成功,第二次上锁出错.
    4)默认互斥锁: PTHREAD_MUTEX_DEFAULT, 同标准互斥锁.

互斥锁进程共享属性操作
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restric attr, int *restrict pshared);
int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared);
返回: 成功返回0, 出错返回错误编号.
线程共享属性:
    PTHREAD_PROCESS_PRIVATE, 默认情况, 锁只能用于一个进程内部的两个线程进行互斥.
    PTHREAD_PROCESS_SHARED, 锁可以用于两个不同进程中的线程进行互斥.
缺点: 线程使用互斥锁缺乏读并发性.

线程互斥 - 读写锁

当读操作较多,写操作较少时,可使用读写锁提高线程读并发性.
(1) 创建和销毁
#include <pthread.h> 
int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *restrict attr);   
int pthread_rwlock_destroy(pthrad_rwlock_t *rwlock);
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;

(2) 读写锁加锁和解锁
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); //加读锁
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); //写加锁
int pthread_rwlock_unlock(phtread_rwlock_t *rwlock); //释放锁
成功返回0, 失败返回错误编号.

Linux 线程属性初始化,销毁,设置和获得分离属性

发表于 2019-08-12 | 分类于 Linux多线程编程

线程属性初始化和销毁

#include <pthread.h>
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);

在pthread_create函数的第二个参数就是线程属性.

阅读全文 »

Linux 线程清理和控制函数

发表于 2019-08-12 | 分类于 Linux多线程编程

简介

清理函数和控制函数

这一对一般是成对出现的

#include <pthread.h>
void pthread_cleanup_push(void (routine)(void ),void *arg);
参数:
routine: 清理函数指针
arg: 调用清理函数传递的参数
void pthread_cleanup_pop(int execute);
参数:
execute:值1时执行清理函数,值0时不执行线程清理函数.

触发线程调用清理函数的动作

1)调用pthread_exit
2)相应取消请求
3)用非零execute参数调用pthread_cleanup_pop时
阅读全文 »

doxygen 安装与使用

发表于 2019-08-08

安装

安装方式1:
下载源码: http://www.doxygen.nl/download.html
doxygen-1.8.15.linux.bin.tar.gz
tar xf doxygen-1.8.15.src.tar.gz
cd doxygen-1.8.15

使用stow安装管理
./configure –prefix /usr/local/stow/doxygen
编译与安装doxygen到stow
sudo make install
至此,doxygen 程序已安装在/usr/local/stow/doxygen/中
cd /usr/local/stow
sudo stow doxygen
doxygen包中包含的所有文件和目录已经符号链接到目录/usr/local/
验证, doxygen -v 出现如下信息,说明已经成功.

1
2
hhs@ubuntu:doxygen-1.8.15$ doxygen -v
1.8.15

当你想移除doxygen时,可以在/usr/local/stow目录下执行, stow –delete doxygen进行移除.

安装方式2:
git clone https://github.com/doxygen/doxygen.git
cd doxygen
mkdir build
cd build
cmake -G “Unix Makefiles” ..
make && make install

在安装方式1和方式2中, 方式2为官方安装方法, 安装方式1为个人喜欢使用的安装方式,使用stow管理安装的第三方工具,方便移除.

使用

Docker 入门简介

发表于 2019-08-03

什么是Docker?

1)Docker 是世界领先的软件容器平台。
2)Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核 的cgroup,namespace,以及AUFS类的UnionFS等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术。 由于隔离的进程独立于宿主和其它的隔离的进 程,因此也称其为容器。Docke最初实现是基于 LXC.
3)Docker 能够自动执行重复性任务,例如搭建和配置开发环境,从而解放了开发人员以便他们专注在真正重要的事情上:构建杰出的软件。
4)用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。

目前最新docker分为 docker-ce和docker-ee两个版本,其中ce为社区版免费的,ee为商业版商用的,目前测试用ce版本。

安装

sudo apt-get install -y docker.io
把用户加入到docker组,避免运行docker需要sudo权限.
sudo usermod -aG docker hhs

测试是否运行成功

1
sudo docker run hello-world

如果出现:

1
2
3
Unable to find image 'hello-world:latest' locally
docker: Error response from daemon: Get https://registry-1.docker.io/v2/library/hello-world/manifests/latest: Get https://auth.docker.io/token?scope=repository%3Alibrary%2Fhello-world%3Apull&service=registry.docker.io: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers).
See 'docker run --help'.

这是因为docker在本地没有找到hello-world镜像,也没有从docker仓库中拉取镜像,出现这个问题的原因:是应为docker服务器在国外,我们在国内无法正常拉取镜像,所以就需要我们为docker设置国内阿里云的镜像加速器;所以需要增加/etc/docker/daemon.json配置文件设置为阿里云镜像.

1
2
3
{ 
"registry-mirrors": ["https://alzgoonw.mirror.aliyuncs.com"]
}

如果出现如下打印,说明成功.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/

For more examples and ideas, visit:
https://docs.docker.com/get-started/

基本使用

未命名

发表于 2019-07-28

Python是一种面向对象的解释性高级编程语言, 具有动态语义。

除法运算的结果为浮点数,1/2 得到0.5, 如果想舍弃小数只留整数,则用双斜杠1//2,向下取整。
对于整除运算, 需要明白的一个重点是它向下圆整结果。 因此在结果为负数的情况下, 圆整后将离0更远。 这意味着对于-10 // 3, 将向下圆整到-4, 而不是向上圆整到-3。

乘方运算符的优先级比求负(单目减) 高, 因此-32等价于-(32)。 如果你要计算的是(-3)**2, 必须明确指出。

1.6 获取用户输入

input函数,

1
2
3
4
5
6
7
>>> x = input("x: ")
x: 4
>>> y = input("y: ")
y: 10
>>> print(int(x) * int(y))
40
>>>

1.7 乘方运算

pow(x, y)函数,
abs()求绝对值, round()函数将浮点数圆整为最接近的整数。floor()向下圆整.

1.8 模块

import命令来导入模块,如: import math, 然后可以使用模块内的函数math.floor(-4.5)
ceil()函数返回大于或者等于给定数的最小整数。

通过使用命令import的变种from module import function, 可在调用函数时不指定模块前缀。
如,from math import sqrt 调用sqrt()函数时,可以免输入模块名。
事实上, 可使用变量来引用函数(以及其他大部分Python元素) 。 执行赋值语句foo = math.sqrt后,就可使用foo来计算平方根
但是这种方式容易引起命名冲突,很隐晦,建议使用import完整导入模块。

python本身提供了对复数的支持

1
2
>>> (1 + 3j) * (9 + 4j)
(-3+31j)

2.2 通用的序列操作

索引、 切片、 相加、 相乘和成员资格检查, Pyhton还提供了一些内置函数,可用于确定序列的长度以及找出序列中最大和最小的元素.

  1. remove, 用于删除第一个为指定值的元素.
  2. reverse, 按相反的顺序排列列表中的元素, 修改但是不返回任何值.reversed按相反的顺序返回迭代序列,可以用list将返回的对象转换为列表.
  3. sort, 用于对列表就地排序,即对原来的列表进行修改,不返回排序后的列表副本.sorted可以返回排序后的列表副本.

2.4 元组: 不可修改的序列

元组通常用圆括号括起来.
tuple函数(其实的一个类型, 不是函数)将一个序列作为参数,并将其转换为元组.

3使用字符串

字符串格式设置

1
2
3
4
5
6
7
8
9
10
11
12
>>> "The number is {num}".format(num=42)
'The number is 42'
>>> "The number is {num:f}".format(num=42)
'The number is 42.000000'
>>> "The number is {num:.2f}".format(num=42)
'The number is 42.00'
>>> "The number is {num:b}".format(num=42)
'The number is 101010'
>>> "The number is {num:c}".format(num=42)
'The number is *'
>>> "The number is {num:e}".format(num=42)
'The number is 4.200000e+01'

类型 含义
b 将整数表示为二进制数
c 将整数解读为Unicode码点
d 将整数视为十进制数进行处理, 这是整数默认使用的说明符
e 使用科学表示法来表示小数(用e来表示指数)
E 与e相同, 但使用E来表示指数
f 将小数表示为定点数
F 与f相同, 但对于特殊值(nan和inf) , 使用大写表示
g 自动在定点表示法和科学表示法之间做出选择。 这是默认用于小数的说明符,但在默认情况下至少有1位小数
G 与g相同, 但使用大写来表示指数和特殊值
n 与g相同, 但插入随区域而异的数字分隔符
o 将整数表示为八进制数
s 保持字符串的格式不变, 这是默认用于字符串的说明符
x 将整数表示为十六进制数并使用小写字母
X 与x相同, 但使用大写字母
% 将数表示为百分比值(乘以100, 按说明符f设置格式, 再在后面加上%)

3.4字符串方法

center, 在两边添加填充字符(默认空格)让字符串居中
find, 在字符串中查找子串,如果找到返回第一个字符的索引,否则返回-1.

Linux 命令 -- ls cd pwd

发表于 2019-07-18 | 分类于 Linux 命令

1 Linux pwd —— 打印当前工作目录名

pwd - print name of current/working directory
Linux pwd命令用于显示工作目录。
执行pwd指令可立刻得知目前所在的工作目录的绝对路径名称。

阅读全文 »

C++ 类和对象的定义

发表于 2019-07-14 | 分类于 C++基础

类是面向对象程序设计的核心,它实际上是一种新的数据类型,也是实现抽象类型的工具,因为类是通过抽象数据类型的方法来实现一种数据类型。类是对某一类对象的抽象,而对象是某一种类的一个实例。

1 类的定义

类的定义一般分为声明和实现部分。声明部分用来声明该类中的成员,包含数据成员的声明和成员函数的声明。成员函数是用来对数据成员进行操作的,又称“方法”。实现部分用来对成员函数进行定义。
概括的说,声明部分是用来告诉使用者“干什么”,而实现部分是告诉使用者“怎么干”。

阅读全文 »

123

微醺

科技浪潮中的一个小兵

25 日志
13 分类
20 标签
RSS
GitHub E-Mail Google FB Page StackOverflow YouTube
© 2019 微醺
由 Hexo 强力驱动
|
主题 — NexT.Gemini v5.1.4