24不苟论第四

不苟论第四

不苟#

【题解】

本篇论臣下应持的操守。所谓“不苟”有两个含义:一是笃行礼义,即“必中理然后动,必当义然后举”。五人之佐不肯为武王系、蹇叔不肯为穆公出不义之谋、赵衰辞赏三例都是说明这一点的。二是谨守分职。公孙枝请见客而受罚,说明不得越职而行。前者是儒家“非礼勿言,非礼勿动”的翻版,后者则是法家“治不逾官”思想的体现。

一曰:

贤者之事也,虽贵不苟为,虽听不自阿(1),必中理然后动,必当义然后举。此忠臣之行也,贤主之所说,而不肖主之所不说。非恶其声也。人主虽不肖,其说忠臣之声与贤主同,行其实则与贤主有异。异,故其功名祸福亦异。异,故子胥见说于阖闾,而恶乎夫差;比干生而恶于商,死而见说乎周(2)。

【注释】

(1)阿:私。

(2)死而见说(yuè)乎周:武王灭商后,曾封比干表彰他的忠义。

【译文】

第一:

贤明的人做事,即使地位尊贵也不随意而行,即使为君主所听信也不借以谋私,一定要合于事理然后才行动,符合道义然后才去做。这是忠臣的德行,是贤明的君主所赏识的,不肖的君主所厌恶的。不肖的君主并不是厌恶忠臣的声音。他们虽然不肖,喜欢忠臣的声音跟贤明的君主还是相同的,但实际做起来却跟贤明的君主不同。实际行动不同,所以他们的功名祸福也就不同。正因为不同,所以伍子胥被阖闾赏识,却被夫差厌恶;比干活着时被商纣厌恶,死后却被周朝赞赏。

武王至殷郊,系堕(1)。五人御于前(2),莫肯之为,曰:“吾所以事君者,非系也。”武王左释白羽(3),右释黄钺(4),勉而自为系。孔子闻之曰:“此五人者之所以为王者佐也,不肖主之所弗安也。”故天子有不胜细民者,天下有不胜千乘者。

【注释】

(1)系:带子,这里指袜带。

(2)五人:指周武王的五个辅臣,即周公旦、召公奭、太公望、毕公高、苏公忿生。御:侍。

(3)白羽:用白色羽毛装饰的旗帜。

(4)黄钺:用黄金作装饰的大斧。白羽、黄钺都是古代的仪仗。

【译文】

周武王率大军伐纣,到了殷都郊外,袜带掉了下来。当时他的五个辅臣都在身边陪侍,没有一个人肯替他把带子系上,他们说:“我们来侍奉君主,并不是替他系带子的。”武王左手放下白羽,右手放下黄钺,自己费力地把带子系上了。孔子听到这件事后说:“这正是五个人之所以成为王者辅臣的原因,也正是不肖的君主所不能容忍的。”所以天子有时不能胜过小民,占有天下者有时不能胜过只有千辆兵车的诸侯国。

秦缪公见戎由余(1),说而欲留之,由余不肯。缪公以告蹇叔。蹇叔曰:“君以告内史廖(2)。”内史廖对曰:“戎人不达于五音与五味(3),君不若遗之(4)。”缪公以女乐二八人与良宰遗之(5)。戎王喜,迷惑大乱,饮酒昼夜不休。由余骤谏而不听(6),因怒而归缪公也。蹇叔非不能为内史廖之所为也,其义不行也(7)。缪公能令人臣时立其正义,故雪殽之耻(8),而西至河雍也(9)。

【注释】

(1)由余:祖先为晋人,亡入西戎,后归附秦穆公,辅佐穆公霸西戏。

(2)内史廖:名字叫廖的内史。内史,官名,周代开始设置,掌管爵禄赏罚。

(3)达:通晓。

(4)遗(wèi):赠送,送给。

(5)二八人:“人”字为衍文。

(6)骤:屡次。

(7)其义不行:遗女乐良宰使戎王迷乱,并使其君臣不和,这是不义的事,所以蹇叔不做。

(8)雪殽之耻:秦穆公三十六年(前624,秦晋殽之战后三年),秦伐晋,取晋地,并埋葬死于殽的秦军尸骨,起土为坟。“雪殽之耻”即指这件事。雪,洗刷。

(9)河雍:指古雍州,包括今陕西、甘肃两省大部及青海省一部分地区。

【译文】

秦穆公见到戎国的由余,很赏识他,想把他留下。由余不答应。穆公将此事告诉了蹇叔。蹇叔说:“您可以把此事告诉给内史廖。”内史廖听了,回答说:“戎人不懂得音乐和美味,您不如把这些东西送给他们。”穆公就把两队女乐和技艺高超的厨师送给了戎人。戎王十分高兴,神魂颠倒,饮酒昼夜不止。由余多次劝谏,戎王不听,因而一怒之下归附了秦穆公。蹇叔并不是不能做内史廖做的事,而是他所遵守的道义不允许这样做。秦穆公能让臣下时时坚持自己的道义,所以能洗刷殽之战的耻辱,把疆土向西开拓到雍州。

秦缪公相百里奚。晋使叔虎、齐使东郭蹇如秦(1),公孙枝请见之(2)。公曰:“请见客,子之事欤?”对曰:“非也。”“相国使子乎?”对曰:“不也。”公曰:“然则子事非子之事也(3)。秦国僻陋戎夷(4),事服其任(5),人事其事,犹惧为诸侯笑,今子为非子之事!退!将论而罪(6)。”公孙枝出,自敷于百里氏(7)。百里奚请之。公曰:“此所闻于相国欤?枝无罪,奚请?有罪,奚请焉?”百里奚归,辞公孙枝。公孙枝徙(8),自敷于街。百里奚令吏行其罪。定分官(9),此古人之所以为法也。今缪公乡之矣(10)。其霸西戎,岂不宜哉?

【注释】

(1)叔虎:晋大夫,即下文的郤子虎。姓郤,名豹,字叔虎。东郭蹇:齐大夫,姓东郭,名蹇。

(2)公孙枝:秦大夫,字子桑。

(3)子事非子之事:第一个“事”字为动词,做。第二个“事”字为名词,指按职分应做的事。

(4)僻陋戎夷:指处于戎夷所居的僻陋之地。

(5)服:任用。

(6)而:你。

(7)敷:陈说。

(8)徙:指离开百里奚处。

(9)分(fèn)官:名分职守。

(10)乡(xiàng):向,趋向。

【译文】

秦穆公任命百里奚为相国。这时,晋派叔虎、齐派东郭蹇出使秦国,公孙枝请求会见他们。穆公说:“请求会见客人,这是你职分内的事吗?”公孙枝回答说:“不是。”穆公又问:“是相国委派你了吗?”回答说:“没有。”秦穆公说:“既然这样,你是要做不该你做的事。秦国偏僻荒远,处于戎夷之地,即使是事事都有专职,人人各守其责,仍然怕被诸侯耻笑,而现在你竟然要做不该你做的事!下去吧!将审理惩治你的罪过!”公孙枝出来,到百里奚那里陈述事情的原委。百里奚替他向穆公求情。穆公说:“这样的事是相国该过问的吗?公孙枝没有罪的话,有什么必要求情?要是有罪的话,求情又有什么用?”百里奚回来,回绝了公孙枝。公孙枝转而又到闹市中去陈诉。百里奚命令官吏对公孙枝论罪行罚。确定官员的名分职守,这是古人实行法治的方法。如今秦穆公已朝这个方向努力了。他称霸西戎,难道不是情理之中的吗?

晋文公将伐邺(1),赵衰言所以胜邺之术(2)。文公用之,果胜。还,将行赏。衰曰:“君将赏其本乎?赏其末乎?赏其末,则骑乘者存(3);赏其本,则臣闻之郤子虎。”文公召郤子虎曰:“衰言所以胜邺,邺既胜,将赏之,曰:‘盖闻之于子虎,请赏子虎。’”子虎曰:“言之易,行之难,臣言之者也。”公曰:“子无辞。”郤子虎不敢固辞,乃受矣。凡行赏欲其博也,博则多助。今虎非亲言者也,而赏犹及之,此疏远者之所以尽能竭智者也。晋文公亡久矣,归而因大乱之余(4),犹能以霸,其由此欤?

【注释】

(1)邺:春秋卫地,在今河北临漳。

(2)赵衰:晋大夫,曾从晋文公出亡,谥成子。

(3)骑乘者:泛指将士。

(4)因:承袭。

【译文】

晋文公将要伐邺,赵衰提出了胜邺的方法。文公采纳了他的建议,果然获得胜利。伐邺归来,文公将要赏赐他。赵衰说:“您是要赏赐根本呢,还是要赏赐末节呢?如果赏赐末节,那么有参战的将士在;如果赏赐根本,那么我的建议是从郤子虎那里听来的。”文公召见郤子虎,说:“赵衰提出了胜邺的方法,现在伐邺已经获胜,我要赏赐他,他说:‘我是从子虎那里听来的,请赏赐子虎。’”郤子虎说:“事情谈起来容易,做起来难,我只是个谈了几句的人。”文公说:“你就不要推辞了。”郤子虎不敢坚决推辞,才接受了赏赐。凡是奖赏,赏赐的范围应该越大越好,范围大,得到的帮助就多。如今郤子虎并不是直接进言的人,而奖赏仍然赏赐到他,这是关系疏远的人之所以能为君主竭尽才智的原因。晋文公流亡在外很久了,回国后继承的又是大乱以后的残破局面,但仍能凭这种条件成就霸业,大概就是这个原因吧!

赞能#

【题解】

“赞能”即举任贤能。本篇以鲍叔牙和沈尹茎举贤为例,从举荐人才的角度阐述任贤的思想。文章指出“功无大乎进贤”,“得地千里,不若得一圣人”,旨在倡导为臣者当以举贤为己任,并强调了得贤对于成就王霸之业的决定性作用。

二曰:

贤者善人以人(1),中人以事,不肖者以财。得十良马,不若得一伯乐;得十良剑,不若得一欧冶(2);得地千里,不若得一圣人。舜得皋陶而舜授之,汤得伊尹而有夏民,文王得吕望而服殷商。夫得圣人,岂有里数哉(3)?

【注释】

(1)善:亲善。以人:指根据这个人的仁德。人,通“仁”。

(2)欧冶:春秋时冶工,善铸剑。

(3)岂有里数哉:得圣人即可得天下,而天下土地不止千里,所以说“岂有里数哉”。

【译文】

第二:

贤明的人同人亲善是根据这个人的仁德,一般的人同人亲善是根据这个人的功业,不肖的人同人亲善是根据这个人的财富。得到十匹好马,不如得到一个善于相马的伯乐;得到十口宝剑,不如得到一个善于铸剑的欧冶;得到千里土地,不如得到一个圣人。舜得到皋陶就用他治好了天下,汤得到伊尹就拥有了夏的民众,周文王得到吕望就征服了殷商。得到圣人,所能得到的土地哪能以里数计量呢!

管子束缚在鲁,桓公欲相鲍叔。鲍叔曰:“吾君欲霸王,则管夷吾在彼。臣弗若也。”桓公曰:“夷吾,寡人之贼也(1),射我者也,不可。”鲍叔曰:“夷吾,为其君射人者也。君若得而臣之,则彼亦将为君射人。”桓公不听,强相鲍叔。固辞让,而相桓公果听之(2)。于是乎使人告鲁曰:“管夷吾,寡人之雠也,愿得之而亲加手焉。”鲁君许诺(3),乃使吏鞹其拳(4),胶其目,盛之以鸱夷(5),置之车中。至齐境,桓公使人以朝车迎之(6)。祓以爟火(7),衅以牺猳焉(8),生与之如国。命有司除庙筵几(9),而荐之曰(10):“自孤之闻夷吾之言也,目益明,耳益聪,孤弗敢专,敢以告于先君。”因顾而命管子曰:“夷吾佐予!”管仲还走(11),再拜稽首,受令而出。管子治齐国,举事有功,桓公必先赏鲍叔,曰:“使齐国得管子者,鲍叔也。”桓公可谓知行赏矣。凡行赏欲其本也,本则过无由生矣。

【注释】

(1)贼:杀人者。

将epub文件转换为md文件

这是后续记录,好几个月前处理的,因此步骤可能有漏,尽量回忆

下载epub格式书籍#

https://zh.z-lib.fm/ ,网址时不时失效,需要到https://yinghezhinan.com/site/z-library/找到最新网址。注册后下载软件默认是不需要钱的,但是非会员一天只能下载10本(可以多注册几个号,只要求邮箱注册即可),正常情况下够用我这里用《吕氏春秋》这本书举例

epub编辑器#

我这里用的calibre便捷版7.19,具体谷哥一搜便有,不详细讲了(主要是太久了,怕有些细节忘了,不如不说)

编辑目录#

处理前需要先把epub文件备份一下,这里会修改源文件。

编辑书籍#

编辑处理#

一开始的目录长这样

我习惯把前面几章和后面几章都各自归为一章(下面的处理逻辑,会把每一章处理成单独的一个md文件)
随便找一个,右键编辑目录即可
然后在第一个前新建一个书名-版权-前言-目录,之后把其他二三次五级目录都删掉即可,如图:

小技巧:先全选,然后同时按住ctrl+大标题(依次取消大标题选择,然后全部删除小标题)

完毕后点击确定,然后ctrl+s保存,关闭编辑窗口

epub拆分#

现在需要把epub文件进行拆分

注意这几个地方,现在先看一下目前目录结构,点击书籍文件,然后查看他的上级目录,目前只有一本

回到calibre软件,选中书籍,点击Epub拆分功能,ctrl+a全选章节,然后点击每个章节一本书,这里就会多出27本
现在我们再查看刚才的D:\software\calibre\Calibre Portable\Calibre Library\Lu Jiu目录除了一本书原书,其他都是新拆分出来的

拆分后的epub转换成txtZ格式#

选中拆分后的27个文件

转换书籍–>输出格式txtZ(其他设置默认)
随便点一本书的文件夹进去看,会发现多了一个txtZ文件
可以复制一份.txtZ文件,之后改成.zip,会发现就是txt文件+image图片的文件堆了(为了不影响脚本功能,记得删除这里的.zip文件)

shell-批量将txtZ转换成md#

我写了个shell脚本处理epub转md文件,由于个人使用,没有太过讲究,所以有一些限制,建议在linux环境下运行,当然,我是在windows10+cmder下运行该脚本的。脚本内容如下:

脚本#

n=$#
if [ $n -ne 2 ] ; then
   echo -e "Please set the dir(source)(book目录) dir(dest)(md目录). "
   exit 0
fi

#待处理的txtz文件目录
bookDir=$1;
dirMd=$2; 

initDirMd(){
fileName="$1/_index.md" 
cat >> $fileName <<-_EOF_
---
bookCollapseSection: true
title:
---
_EOF_
# echo "创建$fileName成功"
}
initContentMd(){
fileName="$1/index.md"
time=`date '+%Y-%m-%dT%H:%M:%S%:z'`
cat >> $fileName <<-_EOF_
---
title: 
description: 
categories:
  - 学习
tags: 
  - MySQL
  - MySQL是怎样运行的
cssAttach: 
  - book01
cssclasses: 
  - book01
date: $time
lastmod: $time
---
_EOF_
# echo "创建$fileName成功"
}

#遍历books目录并在相应位置创建目录
iterateBooks(){

	local dirBook=$1;
	local dirMd=$2;
	local files=$(ls "$dirBook")
	#echo "$files"
	#临时修改SHELL中的分隔符
	oldIFS=$IFS
	IFS=$'\n'
	initDirMd "$dirMd"
	for file in $files; do
		local fullPathFile="$dirBook/$file";
		if [[ -d $fullPathFile ]]; then
			# echo $file 
			#如果是目录则在目录创建对应的目录
			mkdir -p "$dirMd/$file" 
			initContentMd "$dirMd/$file" 
			#处理目录下文件
			handleDir "$fullPathFile" "$dirMd/$file"
		fi
	done
	IFS=$oldIFS
}

#处理目录下的文件
handleDir(){ 
	local dirBook=$1;
	local dirMd=$2;
	local files=$(ls "$dirBook")
	#echo "$files"
	#临时修改SHELL中的分隔符
	oldIFS=$IFS
	IFS=$'\n'
	for file in $files; do
		#如果是.txtz结尾
		if [[ $(expr "$file" : ".\+\.txtz$") > 0 ]]; then
			local fullPathFile="$dirBook/$file";
			cp -r "$fullPathFile" "$fullPathFile.zip"
		    echo "$fullPathFile"
			unzip -qo  "$fullPathFile" -d $dirBook
			rm "$fullPathFile.zip"

			#处理解压后的文件
			#sed -Ei "s/^##(.*?\s)/\1/g" index.txt 
			# sed不支持PCRE
			# \\\\\[用来取 \[ 
			#sed -Ei "s/\\\\\[([0-9]+)\\\\\]/[\1]/g"  index.txt 

			#替换图片地址
			# 这里-i -pe 一个不能去掉,且顺序不能改。且p去掉没效果,不知道原因
			# perl命令行加上"-e"选项,就能在perl命令行中直接写perl表达式
			# -i:对输入的每一行执行一次代码,并进行原地编辑(覆盖原文件)
			# -p:对输入的每一行执行一次Perl代码,并打印输出结果。 
			# g是全局,p:保存匹配的字符串到${^PREMATCH} ${^MATCH} ${^POSTMATCH}中,它们在结果上对应$` $& $'
			perl -i -pe 's/(\!\[.*?\])\(images/$1\(img/gp' "$dirBook/index.txt"
			#perl中$&表示整个字符串
			# perl -i -pe 's/(\!\[.*?\])\(img.*?\)/$&  \n/gp' "$dirBook/index.txt"
			#替换\(\) \[\]之类的默认转义(不需要)
			perl -i -pe 's/\\\[(.*?)\\\]/\[$1\]/gp' "$dirBook/index.txt"
			perl -i -pe 's/\\\((.*?)\\\)/\($1\)/gp' "$dirBook/index.txt"
			# 反引号`,星号*,下划线_
			perl -i -pe 's/\\`/`/gp' "$dirBook/index.txt"
			perl -i -pe 's/\\\*/\*/gp' "$dirBook/index.txt"
			perl -i -pe 's/\\_/_/gp' "$dirBook/index.txt"
			#标题降1级(#\s+)\*{2}(.*?)\*{4}
			perl -i -pe 's/^#(.*?\s)/$1/gp' "$dirBook/index.txt" 

			#去除#号后面4个星号(#\s+)(.*?)\s*\n\*{4}\s*\n\*{2}(.*)
			#perl -i -0 -pe 's/(#\s+)\*{2}(.*?)\*{4}.*\n\*{4}.*\n\*{2}(.*)\n.*\n/$1$2 $3/gp' "$dirBook/index.txt" 
			


			#去除#后面连续的4个星号
			#perl -i -pe 's/^(#.*?\s)\*{4}/$1/gp' "$dirBook/index.txt" 
			#去除#号后面4个星号(#\s+)\*{2}(.*?)\*{4}
			#perl -i -pe 's/(#\s+)\*{2}(.*?)\*{4}/$1$2/gp' "$dirBook/index.txt"
			#处理img图片
			# sed -Ei "s/(\!\[\.*?\])\(images/\1\(img/g"  "$dirBook/index.txt"
			#替换\(\) \[\]之类的默认转义(不需要)
			# sed -Ei "s/\\\\\[/[/g"  "$dirBook/index.txt"
			# sed -Ei "s/\\\\\]/]/g"  "$dirBook/index.txt"
			# sed -Ei "s/\\\\\(/(/g"  "$dirBook/index.txt"
			# sed -Ei "s/\\\\\)/)/g"  "$dirBook/index.txt"			
			#去除#后面连续的4个星号
			# sed -Ei "s/\*{4}//g"  "$dirBook/index.txt"
			# sed -Ei "s/\\\\\[(.*?)\\\\\]/[\1]/g"  "$dirBook/index.txt"
			# sed -Ei "s/\\\\\((.*?)\\\\\)/(\1)/g"  "$dirBook/index.txt"			
			#标题降1级
			# sed -Ei  "s/^#(.*?\s)/\1/g"  "$dirBook/index.txt"
			mkdir -p "$dirMd/img" 
			cp -r "$dirBook"/images/* "$dirMd/img"
			rm -rf "$dirBook"/images
			echo -ne "\n" >>  "$dirMd/index.md"
			# echo "23" >>  "$dirMd/index.md"
			cat "$dirBook/index.txt" >>  "$dirMd/index.md"
			rm -rf "$dirBook"/index.txt
		fi
	done
	IFS=$oldIFS

}
iterateBooks "$bookDir" "$dirMd"
# handleDir "$bookDir" "$dirMd"

将脚本放在某个目录下(随意)

01-04设置cpp

WelcomeToCpp#

  • 使用c++可以控制CPU应该执行的每条指令
  • C++的代码编译后可以在任何平台运行,前提是有一个为对应平台生成机器代码的编译器
  • 与C++不同,C#或JAVA,他们在虚拟机中运行,运行时将代码从“中间语言”转换为机器代码
  • 学习新事物的关键就是对事物进行实验
  • 将讨论如何利用C++库
  • C++实际上如何工作
  • 关于内存和指针:内存区域,智能指针,移动语义,模板
  • 宏,以及为多个平台编程
  • 编写自己的数据结构,学习如何使他们比C++标准库中的结构更快
  • 低级优化,与编译器和汇编相关

设置C++#

windows平台#

  1. 需要文本编辑器,将C++代码编写为文本文件,传递给编译器以生成某种可执行二进制文件,以便可以运行

  2. 或者跳过1,直接用IDE,即有一套帮助你编写和调试代码的工具。(Visual Studio,视频用的2017,我这里下载的 Visual Studio Community 2022)

  3. 安装勾选:

  4. 新建项目

    不要勾选 Place solution and project in the same directory

    解决方案,solution,是一组相互关联的项目,他们有各种项目类型,解决方案就像工作台,每个项目本质上是一组文件,会编译成目标二进制文件(无论是库还是实际的可执行文件)

  5. 添加新项

  6. 代码文件(Main.cpp)

#include <iostream>
int main() {
	std::cout << "hello world!" << std::endl;
	std::cin.get();
}

配置文件修改#

下载ChernoVS.vssettings文件,并放到下面的位置
C:\Users\ly\AppData\Local\Microsoft\VisualStudio\17.0_f89cedea\Settings

在vs工具栏中-tools-ImportAndExportSettings-

ImportSelectedEnvironmentSettings

选择no,just Import new,选择 ChernoVS.vssetings即可

运行#

  1. 右键,构建(项目)


    文件系统查看:

  2. 双击.exe文件,结果:


    按任意键终止


或者单机本地的Windows调试器来运行它

154【杂项】算竞常用_C++_STL_用法

C++ 标准模板库 (STL, Standard Template Library):包含一些常用数据结构与算法的模板的 C++ 软件库。其包含四个组件——算法 (Algorithms)、容器 (Containers)、仿函数 (Functors)、迭代器 (Iterators).

示例:

  • 算法:sort(a.begin(), a.end())
  • 容器:priority_queue<int> pque
  • 仿函数:greater<int>()
  • 迭代器:vector<int>::iterator it = a.begin()

1 前言#

STL 作为一个封装良好,性能合格的 C++ 标准库,在算法竞赛中运用极其常见。灵活且正确使用 STL 可以节省非常多解题时间,这一点不仅是由于可以直接调用,还是因为它封装良好,可以让代码的可读性变高,解题思路更清晰,调试过程 往往 更顺利。

不过 STL 毕竟使用了很多复杂的结构来实现丰富的功能,它的效率往往是比不上自己手搓针对特定题目的数据结构与算法的。因此,STL 的使用相当于使用更长的运行时间换取更高的编程效率。因此,在实际比赛中要权衡 STL 的利弊,不过这一点就得靠经验了。

接下来,我会分享在算法竞赛中常用的 STL 容器和算法,对于函数和迭代器,就不着重展开讲了。

2 常用容器#

2.1 内容总览#

打勾的是本次将会详细讲解的,加粗的是算法竞赛中有必要学习的。

  • 顺序容器

    • array

    • vector

    • deque

    • forward_list

    • list

  • 关联容器

    • set
    • map
    • multiset
    • multimap
  • 无序关联容器

    • unordered_set
    • unordered_map
    • unordered_multiset
    • unordered_multimap
  • 容器适配器

qt学习

建议版本#

  • Qt 4.8.7 官方推荐的 MinGW 版本为 4.4.x,但是MinGW4.4没法编译,MinGW4.5才行,然后找不到MinGW4.5,这里使用了MinGW4.8。qtCreator配套推荐3.0.1(也可以用3.5.0)

下载(视频所用版本)#

- perl-->  https://strawberryperl.com/download/5.16.3.1/strawberry-perl-5.16.3.1-32bit-portable.zip
- MinGW(4.8.1): https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/4.8.1/threads-posix/sjlj/i686-4.8.1-release-posix-sjlj-rt_v3-rev2.7z/download (兼容windowsXP)
- (推荐)https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/4.8.2/threads-posix/dwarf/ (新版win7以上)
=====qt 4.8.7========
- qt库(带MinGW和qtCreator) :https://download.qt.io/new_archive/qt/4.8/4.8.7/qt-opensource-windows-x86-mingw482-4.8.7.exe
- qt库(源码): https://download.qt.io/new_archive/qt/4.8/4.8.7/qt-everywhere-opensource-src-4.8.7.zip
- qtCreator: https://qt.mirror.constant.com/archive/qtcreator/3.0/3.0.1/qt-creator-opensource-windows-x86-3.0.1.exe
===弃用===
- MinGW(4.4): https://www.123912.com/s/u5pSjv-32uAH?提取码:M27Z  
	- 要记得设置环境变量
- qt库: https://download.qt.io/archive/qt/4.7/qt-win-opensource-4.7.0-mingw.exe  
- Qt Creator: https://download.qt.io/archive/qtcreator/2.0/qt-creator-win-opensource-2.0.1.exe  
====使用5.0.2====
qt+mingw--> https://download.qt.io/archive/qt/5.0/5.0.2/qt-windows-opensource-5.0.2-mingw47_32-x86-offline.exe
源码-->  https://download.qt.io/archive/qt/5.0/5.0.2/single/qt-everywhere-opensource-src-5.0.2.zip
=====在线版5.15======
https://mirrors.tuna.tsinghua.edu.cn/qt/official_releases/online_installers/qt-online-installer-windows-x64-online.exe
- .\qt-online-installer-windows-x64-online.exe  --mirror https://mirrors.ustc.edu.cn/qtproject 
- Archive中选择5.15及6.8
- 安装内容:MinGW,Android,QtCharts,QtMultimedia,QtQuich3D,QtShaderTools
=====其他=======
- qt库(带MinGW和qtCreator): https://download.qt.io/new_archive/qt/5.2/5.2.1/qt-opensource-windows-x86-mingw48_opengl-5.2.1.exe

编译静态编译的qmake#

  • 下载源码
  • 路径不能有奇奇怪怪的符号(.-_ 之类)
  • (弃)修改 E:\Qt\qtSrc\qtbase\mkspecs\win32-g++\qmake.conf,修改QMAKE_LFLAGS = -static -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc(仅添加-static)

目录结构#

#mkdir "E:\Qt\qtCustom487\buildQtStatic" #/p
mkdir "E:\Qt\qtCustom\buildQtStatic" #/p
#mkdir "E:\Qt\qtCustom487\qtStatic" #/p
mkdir "E:\Qt\qtCustom\qtStatic" 
#mkdir "E:\Qt\qtCustom487\qtSrc" #/p
mkdir "E:\Qt\qtCustom\qtSrc"  
#E:\Qt\qtCustom下
				- buildQtStatic #(新建的)编译时切换到这个目录
				- qtSrc #源码
				- qtStatic #(新建的)install目录

静态编译#

我用的是视频0087集的办法,也可以用 https://www.cnblogs.com/atggg/p/16878575.html试试

平板安装linuxDeploy的问题简记

关于系统服务#

ly@tabs8:~$ ls -l /etc/systemd/system/sshd.service
lrwxrwxrwx. 1 root root 31 Apr  3 14:16 /etc/systemd/system/sshd.service(用户自定义service存放地址) -> /lib/systemd/system/ssh.service(系统安装软件后的service存放地址)

但是sudo service hello status,chroot容器中查找的只是/etc/init.d/这个路径下的hello(不查找/etc/systemd和lib/systemd中的),但是如果使用systemctl disable hello,则/etc/init.d中的hello服务不会被运行,并且会删除/etc/systemd/system/multi-user.target.wants文件夹下的软连接。如果systemctl enable hello,则会在/etc/systemd/system/multi-user.target.wants文件夹下生成一个软连接。
执行完/etc/init.d/hello就不会再操作其他东西了(hello.service没有用)

建议linuxdeploy的自动化开启Sysv模式,然后在/etc/init.d/里头编写脚本就可以了,如果要开机启动,使用systemctl enable xxx即可。

问题1#

chroot容器中,sudo systemctl enable hello.service后,开机启动时并没有执行。但是如果服务名hello在/etc/init.d/文件中存在对应名的SysV Init 脚本,就会执行,这是为什么呢

在普通 chroot 中,SysV Init 脚本能执行是因为其不依赖 PID 1 管理器,而 systemd 服务需要完整的初始化环境。若需 systemd 功能,应优先使用 systemd-nspawn。

问题2 ★#

chroot容器中,默认情况下,系统启动时会执行/etc/init.d/hello脚本(SysV Init 脚本),但是如果sudo systemctl disable hello.service后,开机启动时就不会执行了,这是为什么呢

 Debian 12(即使使用 systemd)默认保留了 SysV Init 兼容性,通过systemd-sysv-generator 工具动态生成 .service 文件来管理 /etc/init.d/ 中的脚本。当执行 systemctl disable hello.service 时:①删除符号链接:会移除 /etc/systemd/system/<target>.wants/ 中指向自动生成的 hello.service 的符号链接(如 multi-user.target.wants/hello.service)。②禁用服务:即使 /etc/init.d/hello 存在,systemd 也不会在开机时触发其执行,因为兼容层已被禁用。

systemctl enable#

ly@tabs8:~$ sudo systemctl disable ssh
Synchronizing state of ssh.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install disable ssh
Removed "/etc/systemd/system/multi-user.target.wants/ssh.service".
Removed "/etc/systemd/system/sshd.service".
#=================================
ly@tabs8:~$ ls -l /etc/systemd/system/multi-user.target.wants | grep ssh
ly@tabs8:~$ ls -l /etc/systemd/system/ | grep ssh
#================开机自启动========
ly@tabs8:~$ sudo systemctl enable ssh
Synchronizing state of ssh.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable ssh
#创建了两个符号链接
#保证兼容性,十几年前一直是用sshd
Created symlink /etc/systemd/system/sshd.service → /lib/systemd/system/ssh.service.
#multi-user.target.wants下: 开机自启动
Created symlink /etc/systemd/system/multi-user.target.wants/ssh.service → /lib/systemd/system/ssh.service.
#开机自启动其实是直接链接到系统(软件)自己的service
ly@tabs8:~$ ls -l /etc/systemd/system/multi-user.target.wants | grep ssh
lrwxrwxrwx. 1 root root 31 Apr  3 15:05 ssh.service -> /lib/systemd/system/ssh.service
ly@tabs8:~$ ls -l /etc/systemd/system/ | grep ssh
lrwxrwxrwx. 1 root root   31 Apr  3 15:05 sshd.service -> /lib/systemd/system/ssh.service

#====总的来说,我只要在/etc/systemd/system/下创建自己的服务S,然后systemctl enable S即可

service编写(这里没用上)#

vim /etc/systemd/system/vncser

[Unit]
Description=TigerVncService  # 服务描述
After=network.target          # 定义启动顺序(在网络就绪后启动)

[Service]
Type=simple                  # 服务类型(simple/forking/oneshot等)
ExecStart=/usr/local/bin/tigervnc.sh    # 启动命令(绝对路径)
Restart=on-failure           # 失败时自动重启
User=ly                  # 运行用户(可选)
#Group=nogroup                # 运行组(可选)
#WorkingDirectory=/path/to    # 工作目录(可选)

[Install]
WantedBy=multi-user.target   # 定义服务所属的“目标”(开机自启)

一些命令暂记#

#镜像下载 https://mirrors-i.tuna.tsinghua.edu.cn/lxc-images/images/debian/bookworm/arm64/
#发行版 [rootfs.tar]
#源地址 ${EXTERNAL_STORAGE}/linuxdeploy/bookworm.tar.xz

#=====!!!!安装类型[ 目录]会有一些问题,比如ssh提示权限过高,不太懂..=======
#安装路径[ ${ENV_DIR}/rootfs/bookworm ] --> [ /data/data/ru.meefik.linuxdeploy/files/rootfs/bookworm ]----安装类型[ 目录]
#安装路径[ /data/media/0/linuxdeploy/bookworm ]----安装类型[ 目录] 
#建议放镜像
#安装路径{EXTERNAL_STORAGE}/linuxdeploy/bookworm.img----安装类型[ 镜像文件]

#用户名--用户密码--特权用户--本地化--DNS--networktrigger--powertrigger--随便弃用
#(弃用)初始化-启用-run-parts--路径/etc/rc.local--初始用户root
#!!!!初始化我这里使用sysv,通过systemctl enable ssh可以让ssh开机自启动,但是systemctl start ssh不能使用,需要用service ssh start替代
#挂载目录--挂载点--source使用/data/media/0 (data开头的,android14中其他的好像都不行不知道为什么,给ly加了 aid_media_rw  这个组权限) sudo usermod -aG  aid_media_rw username
#其他都不需要

#设置 telnet守护模式打开

挂载目录说明#

为了统一,可以用/mnt/pass_through/0/emulated/0/(内置存储卡) 以及/mnt/pass_through/0/822C-9525/(外置存储卡)

05日志

undolog#

作用#

  1. 恢复某条记录原始状态
  2. 记录修改过程,MVCC的原理,结合事务id知道哪些数据可见 undo log的修改本身会被记录到redo log中。即使undo log未刷盘,崩溃恢复时也可以通过redo log重建undo log。

redolog#

  1. 数据持久性–事务提交后,buffer pool一些脏页没有写入数据库磁盘文件。重启时,利用redolog恢复(表空间、页号、偏移量、数值)的数据(磁盘数据)
  2. 由于redolog有几种策略时机刷入磁盘。另有额外线程每隔1s不断刷入redolog buffer pool数据到redolog磁盘日志文件中,如果事务未提交但是刷入了redolog日志文件也无妨。可以根据一些标识,找到哪个事务是未提交的,然后再用undolog恢复原始状态。
root@db211:/var/lib/mysql# ls
auto.cnf	 ibdata1	     public_key.pem
ca-key.pem	 ib_logfile0 (redolog)	     server-cert.pem
ca.pem		 ib_logfile1 (redolog)		 server-key.pem
client-cert.pem  ibtmp1		     sys
client-key.pem	 mysql		     test
db211-slow.log	 performance_schema  xx
ib_buffer_pool 	 private_key.pem

update语句执行流程#

流程#

  1. 事务开始
    1. 写Undo Log到Undo Log Buffer(记录旧值)
    2. 修改Buffer Pool中的数据页(生成脏页)
    3. 写Redo Log到Redo Log Buffer(记录物理变更) 修改BufferPool后,还会MySQL还会生成对应的Binlog 事件逻辑操作记录),先写入线程的私有内存缓冲区(Binlog Cache
  2. 事务提交
    1. Redo Log 标记为 Prepare
    2. 写Binlog并刷盘
    3. Redo Log Commit阶段(标记提交)

redolog的刷盘策略#

  1. Redo Log Buffer 空间不足:当 Redo Log Buffer 的写入速度超过刷盘速度时,InnoDB 会强制刷盘以释放空间。
  2. 后台线程定期刷盘:InnoDB 的后台线程(如 log_writer 和 log_flusher)会周期性刷盘(默认每秒一次,由 innodb_flush_log_at_timeout 控制)。
  3. 参数配置触发
    1. 0:设置为 0 的时候,表示每次事务提交时不进行刷盘操作。这种方式性能最高,但是也最不安全,因为如果 MySQL 挂了或宕机了,可能会丢失最近 1 秒内的事务。
    2. 1:设置为 1 的时候,表示每次事务提交时都将进行刷盘操作。这种方式性能最低,但是也最安全,因为只要事务提交成功,redo log 记录就一定在磁盘里,不会有任何数据丢失。
    3. 2:设置为 2 的时候,表示每次事务提交时都只把 log buffer 里的 redo log 内容写入 page cache(文件系统缓存)。page cache 是专门用来缓存文件的,这里被缓存的文件就是 redo log 文件。这种方式的性能和安全性都介于前两者中间。

这里其实有个疑问,就是redolog并不是事务提交后才刷盘的,而是很有可能事务提交前就刷盘了。如果提交前刷盘了,之后系统宕机了,那么redolog磁盘文件就多出了一些未提交事务的日志。解决办法:可以通过一些属性,在undolog中找到未提交事务的id,然后通过undolog回滚未提交事务。

04事务

关闭自动提交#

在MySQL命令行的默认设置下,事务都是自动提交的,即执行SQL语句后就会马上执行COMMIT操作。因此开始一个事务,必须使用BEGIN、START TRANSACTION,(显示开启事务)或者执行SET AUTOCOMMIT=0,以禁用当前会话的自动提交。

  1. select语句一般用来输出用户变量,比如select @变量名,用于输出数据源不是表格的数据。
  2. 系统变量在变量名前面有两个@
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.00 sec)

mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+
1 row in set (0.00 sec)
# 修改变量
set autocommit=0;

本文中autocommit=0,开始事务需要使用begin显式开启

事务并发存在的问题#

没有脏读问题,如果两个事务同时修改一条数据,那么另一个事务的修改操作会被阻塞
【隔离性】脏读(读到了还没有提交的数据)

【隔离性】不可重复读(同一事务中,第1次读的数据和第2次读的数据不一样。读到了事务操作过程中其他事务提交的数据,也不应该,这个没法保证一致性。比如我第一次根据某个事务做了一个操作,第二次想同样的逻辑做一个判断操作,但是数据变了,导致同一个事务中对同一个(其实不是了)数据做的操作居然不一致

【隔离性】虚读、幻读(同一事务中:我第一次读到某一条数据,但是第二次没读到;或者第一次没读到,第二次居然读到了。条数问题)

事务的隔离级别#

READ_UNCOMMITTED 读未提交
READ_COMMITTED 读已提交
REPEATABLE_READ 重复读 SERIALIZABLE 串行化(行锁) 修改事务隔离级别:

set tx_isolation='SERIALIZABLE'; (可以加global,让新开的session也使用该事务隔离级别)

经测试,如果有三个session(mysql客户端),其中一个(a)是SERIALIZABLE,而其他两个(b,c)是READ_UNCOMMITTED,那么客户端b,c之间不会因为锁挂起,而ab或ac会导致(行)锁挂起

REPEATABLE_READ重复读#

REPEATABLE_READ重复读的隔离级别只能在一定程度上防止幻读 如果事务a(插入一条新数据,或者删除一条数据)后提交。那么变动的数据不会在事务b被查出来。但是如果插入的这条数据(在事务b,注意 不是事务a)被修改了,那么之后它会在事务b被查出来

新增后修改#

事务a新增数据后提交,在事务b执行中修改了该数据,则该数据会显示出来(影响了)

#=======事务b=======
mysql> begin;
mysql> select * from user;
+----+-----+
| id | age |
+----+-----+
|  1 |  10 |
|  2 |  20 |
|  3 |  33 |
+----+-----+
#=======事务a=======
mysql> insert into user(age) values(44);
#=======事务b=======
mysql> select * from user;
+----+-----+
| id | age |
+----+-----+
|  1 |  10 |
|  2 |  20 |
|  3 |  33 |
+----+-----+
#=======事务a=======
mysql> update user set age=55 where id = 4;
#=======事务b=======
mysql> select * from user;
+----+-----+
| id | age |
+----+-----+
|  1 |  10 |
|  2 |  20 |
|  3 |  33 |
+----+-----+
#=======事务b=======
mysql> update user set age=55 where id = 4;
mysql> select * from user;
+----+-----+
| id | age |
+----+-----+
|  1 |  10 |
|  2 |  20 |
|  3 |  33 |
|  4 |  55 |
+----+-----+
##此时如果事务a进行 delete from user where id = 4; 那么事务a会阻塞,直到事务b commit

删除后修改#

事务a删除数据后提交,在事务b执行中修改了该数据,该数据也照样存在(不影响)

03存储引擎

表结构、数据、索引

文件目录#

 root@db211:/var/lib/mysql/mysql# ls | tail -16
tables_priv.frm
tables_priv.MYD
tables_priv.MYI
time_zone.frm
time_zone.ibd
time_zone_leap_second.frm
time_zone_leap_second.ibd
time_zone_name.frm
time_zone_name.ibd
time_zone_transition.frm
time_zone_transition.ibd
time_zone_transition_type.frm   #INNODB存储引擎-表结构
time_zone_transition_type.ibd   #INNODB存储引擎-表数据+表索引(包括所有索引)
user.frm   #MyISAM存储引擎-表结构
user.MYD   #MyISAM存储引擎-表数据
user.MYI   #MyISAM存储引擎-表索引

INNODE存储引擎的表主键聚簇索引和数据在同一个文件(所以即使没有设置主键,innodb也会为每一行自动生成一个默认的隐藏主键列,用来形成B+树)

索引#

索引创建#

建表时创建#

create table index1( id int, name varchar(20), index idx_id_name (id,name));

后续添加#

create index idx_name on bank_bill (name);

B树#

m阶B树 ,m个分支(或者说m个区间)
x个元素就会有x+1个区间

B+树和B树区别#

从B树考虑#

log2 2000万≈24.3 log500 2000万≈3 (m阶平衡树) 如果是500阶B树,那么2000万个节点最多只需要3层

从B+树考虑#

MySQL中,一个节点1页,也就是16KB(可以改),而一个节点可以放(主键bigint(8字节)+页号地址 6字节)单元1170个,假设是1000,那两层可以放100 0000万个节点。由于1个节点16KB,如果一条数据用1KB的话,那么最底层每个叶子节点就是放16条数据。那就是3层可以放1600万条数据。这是估算,细算的话应该是2000万左右

其他#

操作系统内存管理按页面4K为单位。MySQL默认使用InnoDB存储引擎,其数据块大小(block size)一般默认为16KB

using index#

mysql> explain select name from student where name = 'liuxiang' \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: student
   partitions: NULL
         type: ref
possible_keys: idx_name
          key: idx_name
      key_len: 152
          ref: const
         rows: 1
     filtered: 100.00
        Extra: Using index (直接在二级索引搜索就结束了)

下面这个还需要回表

02增删改查

分类#

  • DDL 数据定义语言(create,drop,alter)
  • DML 数据操纵语言(insert,delete,update,select)
  • DCL 数据控制语言(grant,revoke)

删除#

mysql> select * from user;
+----+----------+-----+-----+
| id | name     | age | sex |
+----+----------+-----+-----+
|  1 | zhangsan |  20 | M   |
|  2 | wuqi     |  34 | M   |
|  5 | baobaoi  |  45 | W   |
|  6 | lalal    |  44 | W   |
+----+----------+-----+-----+
4 rows in set (0.00 sec)
mysql> delete from user where id = 6
#如果之后重启了mysql(且id最大为5,则再插入的数据id为6),(如果id最大为10,则插入的数据id为11);如果没有重启,则再插入的数据id为7
mysql> nsert into user(name,age,sex) values('hah',35,'W');

新增#

一次新增多条数据和多次新增单条数据区别

搜索#

limit可以优化sql语句,不过要看数据的位置

mysql> select * from t_user  limit 1999999 ,1;
+---------+------------------+------------+
| id      | email            | password   |
+---------+------------------+------------+
| 2000000 | cwng78@yahoo.com | h4HcxZKBNQ |
+---------+------------------+------------+
1 row in set (0.52 sec)
#这条数据在最后一条,所以优化效果不怎么样
mysql> select * from t_user where email='cwng78@yahoo.com';
+---------+------------------+------------+
| id      | email            | password   |
+---------+------------------+------------+
| 2000000 | cwng78@yahoo.com | h4HcxZKBNQ |
+---------+------------------+------------+
1 row in set (0.47 sec)

在第一条或者前面,则优化效果显著