码海拾遗
前言:完整的总结总是劳神耗时的,已经熟稔的或者易于得到的部分也没有总结下来的必要。然遨游码海,总归有一些需要记忆的小点,好记性不如烂笔头,单开一篇又没必要,索性全归为一篇,作为手册。
Linux
常用命令
软件安装
直接:sudo apt install
tldr
:too long dont read,一个简单版本的man手册,记得先-u更新一下fzf
:对输出列表进行模糊查询colordiff
:彩色版diff,可以alias为difffd-find
:更快的find命令,命令为fdfind
,alias为fd,功能非常多,-h
查看htop
:更易于阅读的top命令ncdu
:更易于阅读的du命令,可以直接排序,查看文件夹大小ripgrep
:更强大的grep命令,命令为rg
bat
:能高亮的cat命令,命令为batcat
,alias为batdiff-so-fancy
:下载后添加到PATH,chown和chgrp一下就好了,用法是git diff --color | diff-so-fancy
,可以alias为gitd。能够让git diff显示的清晰一些,看情况用
shell编程
- 变量都是字符串,即
"%s"
输出 ((var=var + 1)), var=$(expr "var" + 1)
- $RANDOM 生成随机数
ctrl-a/e
:行首/行尾;Alt-b/f
:左/右一个单词
crtl-w
:往左删一个词;Alt-d
:往右删一个词
ctrl-u/k
:删除光标左/右所有字符
ctrl-y
:粘贴刚才删除的内容
ctrl shift '-'
:撤销操作^xxx
:删除上一条命令中的 xxx
^foo^bar
:把上一条命令中的 foo 替换为 bar
三剑客 grep awk sed
例子(1)
用awk和sed迁移阿里云上的图片:
-
找到阿里云oss仓库,选择批量导出url,导出后是一个.csv文件,格式为obj,url
-
找一个文件夹下载所有url
cat export_urls.csv | awk -F, '{print $2}' | xargs wget
-
把下载的这些文件上传到新的oss上,得到新的链接。这会导致原来的笔记里面的图片链接全部失效,因此要更改链接。链接的区别只在前面的bucket地址,后面的图片名是完全一样的。因此只需要找到所有的笔记文件,把其中图片url中前面的bucket链接改成新的连接前缀即可
-
此处用到的fd命令要先下载,即fd-find。可以对文件夹进行递归正则查询。至此,就完成了对所有图片的迁移、更改链接操作。
fd ".*\.md$" | xargs sed -i 's/https:\/\/xxx.xxx/https:\/\/yyy.yyy/g'
vim
零碎
- 定义宏:
q + [a-zA-Z] + your_operation + q
,使用时@ + [a-zA-Z]
Ctrl + a
光标第一个数字加一,Ctrl + x
光标第一个数字减一- 行内移动:
f w b e
- 自动补全:
Ctrl + p
- 查询man手册:
K
- #:自动查找井号后面的单词
ctrl w ←↑↓→
切换窗口,ctrl w HJKL
移动窗口:vertical resize +-n
:调整当前窗口宽度,去掉vertical
调整高度- 默认的
map
是递归的,比如a映射b,b映射c,那么就等于是a映射了c。可以根据使用模式,做非递归的映射,即nnoremap/inoremap/vnoremap/cnoremap
(normal/insert/visual/comandline) - doc/help.md · chenxuan/vim-fast - 码云 - 开源中国 (gitee.com)
myvimrc
快速配置:vimfast || 基于vimplus || vim快捷键help.md || 内置快捷键key.md
# 无插件快速配置 √
wget https://gitee.com/mirrorvim/vim-fast/raw/master/vimrc-no-plug -O ~/.vimrc
"//"开头的不用添加到vimrc中,只是表说明作用
通用设置
let mapleader = "," " 定义<leader>键为逗号[,]
打开窗口
"分屏与竖直分屏
// :split [file]
// :vsplit [file]
"vim中调试
// Termdebug [bug_file] " 打开源代码、gdb、IO三个窗口
nnoremap <leader><leader>d Termdebug<space> " 用[,,d]直接打开此模式
"vim中打开新的终端
// :vert term " vert,即打开竖直方向终端,去掉即水平方向分窗口
nnoremap <leader><leader>t :vert term " 打开竖直终端
nnoremap <leader><leader>t :bo term ++rows=6 "六行水平终端
窗口调整
"改变窗口大小
nnoremap <c-up> :resize+1<cr>
nnoremap <c-down> :resize-1<cr>
nnoremap <c-left> :vertical resize+1<cr>
nnoremap <c-right> :vertical resize-1<cr>
"改变当前窗口
nnoremap <s-up> <c-w>k
nnoremap <s-down> <c-w>j
nnoremap <s-left> <c-w>h
nnoremap <s-right> <c-w>l
"改变窗口位置
nnoremap <c-s-up> <c-w>K
nnoremap <c-s-down> <c-w>J
nnoremap <c-s-left> <c-w>H
nnoremap <c-s-right> <c-w>L
其他便捷操作
" 自动括号
inoremap ( ()<left> "插入模式
inoremap [ []<left>
inoremap { {}<left>
cnoremap ( ()<left> "命令行模式
cnoremap [ []<left>
cnoremap { {}<left>
" 快捷编辑文件
nnoremap e :edit<space><c-r>=getcwd()<cr>/
mybash_aliases
# default
alias gdb='gdb -q'
alias ll='ls -alhF --color=auto'
alias python='python3'
# git
alias gita='git add'
alias gitb='git branch'
alias gitc='git checkout'
alias gitl='git log'
alias gitlg='git log --graph'
alias gitlo='git log --oneline'
alias gitlog='git log --oneline --graph'
alias gitr='git reset'
alias gitrh='git reset --hard'
alias gitrs='git reset --soft'
alias gits='git status'
alias gitd='git diff --color | diff-so-fancy'
# some tools
alias bat='batcat'
alias diff='colordiff'
alias fd='fdfind'
alias grep='rg'
alias top='htop'
# for convinence
alias PATH='echo $PATH | xargs -d: -n1'
alias sb='source ~/.bashrc'
alias sv='source ~/.vimrc'
alias vimb='vim ~/.bashrc'
alias vimv='vim ~/.vimrc'
# windows
# alias jupyter='jupyter notebook'
# alias make='mingw32-make.exe'
# wsl
# alias wincodes='cd /mnt/d/codes'
# alias windesk='cd /mnt/c/Users/wddjwk/Desktop'
# alias windownload='cd /mnt/c/Users/wddjwk/Downloads'
# alias wintest='cd /mnt/d/test'
# alias win~='cd /mnt/c/Users/wddjwk'
git
零碎
git config --global init.defaultBranch main
- 找机会修改一下github用户名
--global
:~/.gitconfig
--system
:/etc/gitconfig
快捷git
可以直接创建一个
.bash_aliases
文件也可以
git global comfig alias.st status
,配置别名
makefile
模板1
# 一个适合中小规模的makefile模版,基本上自己按照实际情况指定一下 源文件,目标文件,头文件目录,以及源文件后缀就行了。
# ---------------------------------------------------------------------------
# commands
# ---------------------------------------------------------------------------
CC := gcc
LINK := gcc
RM := rm -rf
MV := mv
TAR := tar
MKDIR := mkdir
# ---------------------------------------------------------------------------
# settings
# ---------------------------------------------------------------------------
SRC_SUFFIX := .c
OBJ_SUFFIX := .o
LIB_SUFFIX := .a
BIN_SUFFIX := .exe
DLL_SUFFIX := .so
INC_PREFIX := -I
LIB_PREFIX := -L
OPT_C := -c
OPT_OUT := -o
OPT_LINKOUT := -o
CFLAGS := $(OPT_C)
LIBFLAGS := -Debug
# ---------------------------------------------------------------------------
# directories
# ---------------------------------------------------------------------------
SRC_DIR := ./src
OBJ_DIR := ./obj
INC_DIR := ./inc
LIB_DIR := ./lib /usr/local/lib /lib /usr/lib
# ---------------------------------------------------------------------------
# common settings
# ---------------------------------------------------------------------------
SRCS := $(wildcard $(SRC_DIR)/*$(SRC_SUFFIX))
OBJS := $(patsubst $(SRC_DIR)/%$(SRC_SUFFIX),$(OBJ_DIR)/%$(OBJ_SUFFIX),$(SRCS))
INCS := $(addprefix $(INC_PREFIX), $(INC_DIR))
LIBS := $(addprefix $(LIB_PREFIX), $(LIB_DIR)) $(LIBFLAGS)
TEMPFILES := core core.* *$(OBJ_SUFFIX) temp.* *.out typescript*
# ---------------------------------------------------------------------------
# make rule
# ---------------------------------------------------------------------------
TARGET := loader
.PHONY: all clean
all: $(TARGET)
clean:
$(RM) $(TARGET)$(BIN_SUFFIX) $(OBJS)
$(TARGET):$(OBJS)
$(LINK) $(OPT_LINKOUT)$(TARGET)$(BIN_SUFFIX) $(LIBS) $(OBJS)
$(OBJS):$(OBJ_DIR)/%$(OBJ_SUFFIX):$(SRC_DIR)/%$(SRC_SUFFIX)
$(CC) $(CFLAGS) $(INCS) $(OPT_OUT)$@ $<
模板2
CXX := g++
SRC_DIR := ./src
OBJ_DIR := ./build
BIN_DIR := ./bin
INC_DIR := ./include
VPATH = $(INC_DIR) $(OBJ_DIR) $(SRC_DIR)
vpath %.h $(INC_DIR)
# 一种搜索源文件的方式
# SRC_DIRS = $(shell find $(SRC_DIR) -maxdepth 3 -type d)
# SRCS = $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)/*.cpp))
# TODO: 这样子出来的目标文件,在jing'tai时就找不到依赖了
# OBJS := $(OBJ_DIR)/$(notdir $(patsubst %.cpp, %.o, $(SRCS)))
SRCS := $(wildcard $(SRC_DIR)/*.cpp)
OBJS := $(patsubst $(SRC_DIR)/%.cpp, $(OBJ_DIR)/%.o, $(SRCS))
INCS := $(addprefix -I, $(INC_DIR))
BUILDING_DIRS := $(OBJ_DIR) $(BIN_DIR)
TARGET := adb_lab2.exe
RUN := run.sh
$(TARGET) : $(BUILDING_DIRS) $(OBJS)
$(CXX) -o $(BIN_DIR)/$(TARGET) $(OBJS)
@touch $(RUN)
@echo "$(BIN_DIR)/$(TARGET)" > $(RUN)
# 这里的前缀不能少。makefile不会自动去VPATH里面找这几个目标,而是直接当成新的目标来对待
$(OBJ_DIR)/BufferPoolManager.o : BufferPoolManager.h LRUReplacer.h
$(OBJ_DIR)/DataStorageManager.o : DataStorageManager.h
$(OBJ_DIR)/LRUReplacer.o : LRUReplacer.h
$(OBJ_DIR)/main.o : BufferPoolManager.h
# 一个创建运行时依赖文件夹的方法
$(BUILDING_DIRS) :
@mkdir $@
# 这叫 静态模式
$(OBJS) : $(OBJ_DIR)/%.o : $(SRC_DIR)/%.cpp
$(CXX) -o $@ -c $< $(INCS)
.PHONY: all clean output
all : $(TARGET)
clean:
-rm -rf $(BUILDING_DIRS) test.dbf $(RUN)
output:
@echo $(SRCS)
@echo --------------
@echo $(OBJS)
模板3
CC := gcc
CC_INCLUDE_FLAGS := -I ./include/
CC_FLAGS := $(CC_INCLUDE_FLAGS) -g
# 程序执行的参数
ARGS := ~/codes
DIR_SRC := ./src
DIR_OBJ := ./build
DIR_EXE := ./bin
SRCS := $(shell find $(DIR_SRC) -name "*.c")
OBJS := $(patsubst $(DIR_SRC)/%.c, $(DIR_OBJ)/%.o, $(SRCS))
DPTS := $(patsubst %.c, %.d, $(SRCS))
DIRS := $(DIR_OBJ) $(DIR_EXE)
target := $(DIR_EXE)/my_ls_pro
$(target): $(DIRS) $(OBJS)
$(CC) $(OBJS) -o $@
$(DIRS):
@mkdir $@
$(DIR_OBJ)/%.o: $(DIR_SRC)/%.c
$(CC) $(CC_FLAGS) -c $< -o $@
%.d: %.c
@set -e; \
rm -f $@; \
$(CC) -MM $(CC_FLAGS) $< $(CC_INCLUDE_FLAGS) > $@.$$$$.dtmp; \
sed 's,\(.*\)\.o\:,$*\.o $*\.d\:,g' < $@.$$$$.dtmp > $@;\
rm -f $@.$$$$.dtmp
-include $(DPTS)
clean:
rm -f $(OBJS)
rm -f $(DPTS)
run:
make
$(target) $(ARGS)
教程
REF1:makefile简明教程, REF2:如何输出到指定文件夹 ,REF3:关于自动生成依赖.d文件
模式替换
$(patsubst <pattern>,<replacement>,<text> )
查找
这里,可以包括通配符“%”,表示任意长度的字串。如果中也包含“%”,那么,中的这个“%”将是中的那个“%”所代表的字串。(可以用“\”来转义,以“%”来表示真实含义的“%”字符)
$(patsubst %.c,%.o, a.c b.c)
# 把字串 “a.c b.c” 符合模式[%.c]的单词替换成[%.o],返回结果是 “a.o b.o”
变量替换引用
对于一个已经定义的变量,可以使用“替换引用”将其值中的后缀字符(串)使用指定的字符(字符串)替换。格式为$(VAR:A=B)
或者${VAR:A=B}
意思是,替换变量“VAR”中所有“A”字符结尾的字为“B”结尾的字。“结尾”的含义是空格之前(变量值多个字之间使用空格分开)。而对于变量其它部分的“A”字符不进行替换。
foo := a.o b.o c.o
bar := $(foo:.o=.c)
# 注意变量不要带 $
SRCS_NODIR := $(notdir $(wildcard $(SRC_DIR)/*$(SRC_SUFFIX)))
OBJS_NODIR := $(SRCS_NODIR:$(SRC_SUFFIX)=$(OBJ_SUFFIX))
编码风格
命名
普通变量
推荐使用下划线隔开单词(Google开源风格指南),也可以使用驼峰命名法,但是不要使用无意义的字母!
成员变量
以下内容准确性待考究。但首尾下划线一般都表示“私有”之意
-
__foo__: 定义的是特殊方法,一般是系统定义名字,类似__init__()之类
-
_foo:以单划线开头的表示的是protected类型的变量或函数,即保护类型,只允许本身和子类访问。也有在后面加下划线的,同理。都是表达"私有"之意。
-
__foo:以双下划线开头的表示的是private类型的变量或函数,即私有类型,只允许本身访问。
-
C语言中,单下划线开头表示是标准库的变量,双下划线表示是编译器的变量
注释
文件注释
/**
* @file 文件名
* @brief 简介
* @details 细节
* @author 作者
* @version 版本号
* @date 年-月-日
* @copyright 版权
* @todo 待办
* @throw 异常描述
* @bugs 漏洞
* @pre 前提条件
* @see [参考]
*/
函数注释
/**
* @brief 函数描述
* @param 参数描述
* @return 返回描述
* @retval 返回值描述
*/
结构体注释
/**
* @brief 类的详细描述
*/
常变量注释
//定义一个整型变量a
int a
int a; /*!< 定义一个整型变量a */
int a; /**< 定义一个整型变量a */
int a; //!< 定义一个整型变量a
int a; ///< 定义一个整型变量a
HTML
markdown
表格的使用
并排插入图片,需要用到表格才能实现。插入图片不需要用到<a herf></a>
,不然点一下就跳转也有些烦人。html
标签不写在代码块内即生效。
图片大小可以用<td style="width:50%"></td>
来调整,各占50%就好了
<table style="border:none;text-align:center;">
<tr>
<td style="width:50%"><img src="" alt="" border="0" /></td>
<td style="width:50%"><img src="" alt="" border="0" /></td>
</tr>
<!--可以排图,也可以图文混排,也可以用来添加注释-->
<tr>
<td style="width:50%"><strong>图1 </strong></td>
<td style="width:50%"><strong>图2 </strong></td>
</tr>
</table>
音视频
<audio controls>
<source src="https://www.runoob.com/try/demo_source/horse.mp3" >
您的浏览器不支持 audio 元素。
</audio>
<video width="320" height="240" controls>
<source src="https://www.runoob.com/try/demo_source/movie.mp4" type="video/mp4">
您的浏览器不支持 HTML5 video 标签。
</video>
markdown to slide
C
函数速查
(可以参考本地文件[C函数速查](file://D:/books/C/C函数速查.pdf))
printf
-
打印颜色
颜色控制码-cnblogs// 一般格式为 printf("\033[控制码1;控制码2;控制码3...m %s \033[控制码m\n", str); // 例如下面将输出一个黄色的str printf("\033[32m %s \033[0m \n", str);
-
打印数据类型
a A
:以十六进制形式输出浮点数(C99)
字符串处理
⭐️autof()
// 字符串转浮点数
double atof(const char *s);
// 字符转转int
int atoi(const char *s);
C++
语法&特性
关键字和上下文关键字
// delete
void func(int)=delete;
// override, final
void f() override final;
类模板与友元函数
// 模板类中声明友元函数共有四种:
template <typename T>
class A{
public:
friend void f1(); // 1.不需要模板参数的,非模板函数
friend void f2(A<T>& a); // 2.需要模板参数的,非模板函数
friend void f3<T>(A<T>& a); // 3.需要模板参数的,模板函数
template <typename U> // 4.需要模板参数且自带参数的模板函数
friend void f4(A<U>& a);
private:
T v;
};
不要在类内声明的是第二种,在类外定义的却是第三种了。
库与函数速查
输入输出
⭐️getline()
-
有两个getline()函数,一个在<istream>里面,通过(输入流)成员调用的方式指出输入流,一个在<string>里面,为顶层函数,在参数列表中指出输入流
-
getline()实际读取的为==(n - 1)个字符,且会把终止符从流中删除==
-
读到文件尾返回eofbit
// # include<istream> // 注意是char*,同时要指出读入的size
istream& getline (char* s, streamsize n, char delim );
// # include<string>
istream& getline (istream& is, string& str, char delim);
⭐️get()
-
与getline()区别在于,读到delim字符后,会中止并将其保留在流中,这就会被下一个用户读到
-
只有<istream>版本
// 依次为:single character (1),c-string (2),stream buffer (3)
int get(); istream& get (char& c);
istream& get (char* s, streamsize n, char delim);
istream& get (streambuf& sb, char delim);
正则表达式
<regex>库是C11中新增的特性,下面给出一些使用的例子
regex
:定义一个正则表达式类,如regex rx("^[0-9]");
match_result
:
标准库STL
算法
贪心算法
最优子结构的证明1
最优子结构:问题 S i j S_{ij} Sij的最优解 A i j A_{ij} Aij必然包含子问题 S i k S_{ik} Sik和 S k j S_{kj} Skj的最优解 A i k A_{ik} Aik和 A k j A_{kj} Akj
证明(cust-and-paste)法:如果不包含,则子问题有一个更好的解,粘贴进来比原来的最优解要好,则原来的不是最优,推出矛盾
贪心选择性质:做出局部的最优解可以得到全局的最优解
命题:做出当前最优选择{x},则存在一个问题S的最优解A,包含{x}
证明:如果最优解B不包含{x},则对任意B中元素y,均有 w ( y ) < w ( x ) w(y) < w(x) w(y)<w(x)。从A={x}开始构建,不断从B中选择元素加入A中,直至|A|=|B|,此时A与B的不同就在于,A有{x},B有{ y i y_i yi}。由于 w ( y i ) < w ( x ) w(y_i) < w(x) w(yi)<w(x),故 w ( B ) < w ( A ) w(B) < w(A) w(B)<w(A),B不是最优解,推出矛盾。
因此最优解一定包含这一局部最优解,下面的任务就是找出这个包含x的最优解A。又由于问题S具有最优子结构,因此这一问题又转换为,求出问题 A − { x } A-\{x\} A−{x}的最优解,对其继续运用贪心选择性质,然后不断迭代即可。
references
参见[《算法导论》](D:\books\数据结构与算法\算法导论 第3版.pdf)关于霍夫曼编码和拟阵贪心选择性质的证明 ↩︎