编码学习笔记
编码是最繁琐的问题之一了,尤其对于 C++这种 string
还只是char *简易封装的底层语言来说,对于非 ASCII
的字符串需要考虑各个环节的编码,只要错了一项最终就是乱码。对于一些更高级的语言比如
Python3,全部使用 utf8 就少了很多乱七八糟的乱码问题。
ASCII 码
首先从 ASCII 码开始,在早期的计算机中,使用一个字节(8 比特,实际上是
7
比特)来表示所有英文字母和常见的标点符号,以及回车,制表符等控制字符,如下表。
这里 4 比特用一个十六进制数来表示,实际上没有用完\(2^8=256\)个,只用了一半 128
个,具体而言就是只用了 7 比特,最高位始终为 0。
一些控制字符比如著名的换行符:CR/LF,制表符 HT(tab),剩下的 128
个字符,其实对于绝大多数欧美的拼音文字都是足够的,因此基于 ASCII
码也产生了很多表示西欧文字的编码方案。但是对于成千上万的汉字编码,一个字节显然是不可能完成的任务,典型的中日韩三国的编码问题,通常这被称为
CJK 编码,针对这些语言必须设计多字节编码方案。
多字节编码
仅仅使用 ASCII
字符显然是 ...
Burgers方程转换公式
作为典型的守恒律方程,Burgers
方程可以完成时间导和空间导的彻底转换,这里记录一下,后面肯定会用到。
\[
u_t + u u_x = 0
\]
一阶导信息
1u_t -> u_x
一阶导还是显然的:
\[
u_x = -\frac{u_t}{u}
\]
二阶导信息
1u_tt -> u_xt -> u_xx
做一下准备,对原始方程进行如下的求导
\[
\begin{aligned}
u_t + u u_x &= 0\\
u_{tt} + u_t u_x + u u_{xt} &=0, (\partial_t)\\
u_{tx} + u_x u_x + u u_{xx} &=0, (\partial_x)
\end{aligned}
\]
得到
\[
u_{xt} = -\frac{1}{u}\left(u_{tt} + u_t u_x\right)
\]
还有
\[
u_{xx} = -\frac{1}{u}\left(u_{tx} + u_x u_x\right)
\]
三阶导信息
1u_ttt -> u_xtt -> u ...
文本文件的常见问题
关于文件的处理,在实际应用尤其是跨平台时会遇到各种各样的问题,主要包括如下几个问题:
非 ASCII
字符的编码问题:UTF-8?(这个问题太大了,因此放在另一篇专门的笔记中)
换行符的问题:LF or CRLF?
制表符问题:tab or space?
二进制数据的大小端问题
本文将主要对这些问题进行简要整理。
换行符问题
不同平台上文本文件的换行符是不一样的,具体来说:
Windows:CRLF \r\n
Linux:LF \n
macOS:早期是 CR \r,现在已经改成 LF
\n
现在只有 Windows 的 CRLF
是个异类了。其实严格来说\r的含义是回车,回到行首;\n的含义是换行,换到下一行。
换行符不一致会带来很多问题:例如 Linux 的文本文件在 Windows
上,可能出现无法换行,连续显示一大段的效果;例如 Windows 的文本在 Linux
上可能出现大量的^M,这就是\r并没有被理解为换行符的一部分。
原生的一些文本处理程序,可能无法兼容其它系统上的换行符,例如 Windows
自带的记事本只支持 CRLF,bash 脚本只支持 LF。
现代的 ...
Everything查询语法整理
学习整理一下 everything 的高级用法吧,感觉这对于提高 Windows
上的生产力很有帮助。(不砍柴,光想着磨刀 ing)
everything 的基本工作流程:
输入一个指令或多个指令的组合
everything
对输入指令进行解析,获取具体要求(解析规则受到筛选器以及设置中的选项影响)
everything
在数据库中进行检索,检索的项可能是:文件或文件夹的直接名称,或含有绝对路径的完整名称,这与具体情况和开启的选项有关。
检索是否与指令的具体要求相符,返回满足要求的所有项(不区分文件/文件夹)
注:Windows
在文件名和文件夹名称当中不能包含如下特殊字符,允许出现空格
1\ / : * ? " < > |
这些特殊字符可能在 everything 中有特殊的语法作用。
1. 搜索选项
我们首先关注菜单栏->搜索的部分选项:
解释一下:(如图即是默认的状态)
区分大小写
全字匹配:
不开启全字匹配:我们输入txt可能匹配到a.txt或者txt2.zip,即txt可能不是作为一个完整单词
开启全字匹配:确保txt只会作为一个完整单词 ...
Nginx基本使用与建站配置
记录一下 Nginx 的基本使用与建站配置,免得改的时候又忘记了。
(这里不涉及 hexo 博客还有 cloudreve
网盘的具体配置细节,这两个内容有专门的笔记)
Nginx 基本使用
基本命令
常见操作要求在 root 用户下进行:
第一类操作
启动:systemctl nginx start
关闭:systemctl nginx stop
重启:systemctl nginx restart
第二类操作
测试:nginx -t,显示配置文件目录,检查
nginx.conf 是否有语法错误,并进行测试。
重新加载配置:nginx -s reload,reload
命令会重新加载配置文件,此时 nginx
服务不会中断,服务启动,文件即加载成功。
平稳地关闭:nginx -s quit,迅速地关闭:nginx -s stop。
配置逻辑
首先记录一下 Nginx 的配置逻辑:(root
用户直接apt-get安装,而非源码编译)nginx
配置文件全部位于/etc/nginx/目录,其中值得关注的包括:
nginx.conf 主配置文件
sites-availab ...
Visual Studio 简单使用记录
之前的 C++编程都是在 Linux 或者 VScode+MinGW
进行的,但有时难免需要使用宇宙第一 IDE,简单记录一些 VS
的基本使用吧,尤其了解一下分布在各个菜单栏各个按钮下的常用配置。(直接命令行参数多省事,省的到处找配置目录)
本文全部在 VS2019 完成,并且不考虑 MSVC 的纯命令行使用。
1. 解决方案与项目
项目是 VS
中的基本概念,例如某个库的开发就是一个项目,解决方案是项目的上层概念,一个解决方案可以包含多个项目。简单情况下一个项目会对应一个同名的解决方案。
解决方案在文件系统中直接对应一个xxx.sln解决方案文件,它记录了解决方案层面的配置信息。(可以直接点击.sln文件在
VS 中启动解决方案)
项目在文件系统中会对应.vcxproj以及.vcxproj.*文件,它们记录了项目层面的配置信息。如果点击.vcxproj文件,似乎还是启动对应的整个解决方案。例如.vcxproj.filters记录了一个虚拟的目录结构,.vcxproj.user记录了用户的
IDE 设置(包括 IDE
布局,工具栏等设置,通常不影响项目编译,可以删除)
在创建新项目界 ...
Cpp Most vexing parse
学习整理一下关于 C++ Most vexing parse 的内容,主要参考wiki。
Most vexing parse(最令人烦恼的解析)指的是
C/C++编译器在处理某些特殊语句时,既可以理解为函数声明,也可以理解为对象初始化的情况,这两种情况都满足
C/C++的语法标准,但是编译器无法区分,导致的解析困难。
C++编译器对此的做法是:遇到歧义时倾向于视作函数声明,并且在 C++11
之后为对象初始化提供了新的花括号初始化语法。花括号初始化语法同时又带来了更多的语法困难,进一步加剧了语法的复杂度。
C 语言
这个问题的来源是 C 语言在声明函数时接受比较宽松的语法,而
C++也兼容了这部分语法。
例一
第一个例子,下面的几个函数声明是一样的
12345int f(double); // (1.1)int f(double t); // (1.2)int f(double (t)); // (1.3)
它们都表示f是一个接收一个double参数,返回值类型为int的函数,这里允许对参数t加上括号。
注意到(1.3)在语法上是有歧义的:
解释一:声明f是一个接收一个double参 ...
常用编程语言
本文列举并简要介绍了常用的编程语言,顺序参考TIOBE
排行榜,但是删除了作者从未使用过的部分语言。
本文主要包括通用编程语言(GPL,general-purpose
language),不包括大部分领域特定语言(DSL,domain-specific
language),例如在 bash,powershell 使用的语言,或者 CMake
语言。当然,本文列举的数值计算领域的 MATLAB,Mathematica 也应该被归类为
DSL。
Python
Python
是一种著名的胶水语言,脚本语言,学习门槛低,代码可读性很高。
Python
的运算效率较低,尤其是原生数组的运算和循环等。通常科学计算为了达到高效率,都会调用
numpy 等库进行操作,这些库主要基于 C/C++/Fortran。
Python 是机器学习,人工智能时代的宠儿,深度学习主要都是使用 Python
来搭建神经网络。(在投入实际生产,对速度有要求时可能会使用 C++重写)
1print("hello,world!")
C
C
是最经典的语言,主要用于系统开发工作,特别是组成操作系统的程 ...
Cpp 单例模式
单例模式作为最简单但最常用的设计模式,整理一下 C++的相关语法吧。
单例模式简介
单例模式(Singleton
Pattern),使用最广泛的设计模式之一。其意图是保证一个类仅有一个实例被构造,并提供一个访问它的全局访问接口,该实例被程序的所有模块共享。
大致的做法为:
定义一个单例类;
私有化构造函数,防止外界直接创建单例类的对象;
禁用拷贝构造,移动赋值等函数,可以私有化,也可以直接使用=delete;
使用一个公有的静态方法获取该实例;
确保在第一次调用之前该实例被构造。
在 C++中我们需要考虑:
在什么时机构造?程序一开始,第一次调用前?
如何构造这个实例?在堆上构造,还是通过静态变量?如果单例在堆上构造,是否存在内存泄漏?
实例构造失败会如何?抛异常?返回空指针?
通过接口返回指针还是引用?
线程安全?多线程下会不会重复构造?加锁?
我们暂时不考虑类的继承问题,以及需要给单例的构造传参数的问题。
关于构造时机的不同,有以下两种习惯的称呼:
饿汉模式(Eager Singleton),在程序启动后立刻构造单例;
懒汉模式(Lazy Singleton),在第一次调 ...
Cpp 基本数据类型
C/C++很烦人的一点在于,它最基本的数据类型都是不确定的,为了兼容某些奇怪的设备,C++标准并没有强制规定基本数据类型的位数,这可能导致很多
bug。
我们只考虑 64 位系统,考虑 x86-64 的 Windows/Linux 平台(32
位系统可能字节数更少,但是已经很少用了,本文不考虑)。
非常不建议使用整数类型long,以及浮点数类型long double,因为它们在不同的平台很可能位数不同。
整数类型
基本的整数类型大概有如下几种:(有符号类型,还有对应的无符号类型)
char
short (int)
int
long (int)
long long (int)
注意:标准并没有严格规定它们的字节数大小,但是规定了字节数的大小关系(即表示范围的大小关系),以及它们至少需要的字节数。
1short <= int <= long <= long long
主要参考 cpp reference 和 wiki,下图取自cpp
reference
上图中的 64 位数据模型包括 LP64(主要对应 Unix-like 平台)和
LLP64(主要对应 Win ...