Scintilla教程(2): 文本检索与修改
整体介绍
Scintilla主要用于对文本的编辑,因此该部分的功能是Scintilla的核心所在。Scintilla以字节为基础单元处理整个文本。对于不同的编码格式,每个字符所占的字节个数并不相同。
比如常用的UTF-8编码,一个中文等于三个字节,中文标点占三个字节。一个英文字符等于一个字节,英文标点占一个字节。而对于Unicode编码,一个英文等于两个字节,一个中文(含繁体)等于两个字节。
在实际开发中,选择UTF-8编码,对于文本"abc",调用Scintilla获取文档字节总长的方法(SCI_GETLENGTH),返回值为3;对于文本"测试",调用Scintilla获取文档字节总长的方法(SCI_GETLENGTH),返回值为6。
SCI_GETTEXT
SCI_GETTEXT(position length, char *text NUL-terminated) → position
该消息可获取从文档开头获取length-1长度的字节,所获取字节存入形参text内,因此text的空间应至少分配length的字节(最后一个字节为\0)。该消息返回值position为所获取字节的长度(注:改返回值通常等于length-1)。如果需要获取文档中的全部字节,可以先调用消息SCI_GETLENGTH,获取文档字节总长lenTotal,然后再调用方法:
SCI_GETTEXT(lenTotal+1, *text)
以UTF-8编码,如下文本内容为例:
如果对该文本发送如下消息:
SCI_GETTEXT(3, *text)
则返回的position=2,text所获取的文本内容为“Sc”。
如果对该文本发送如下消息:
SCI_GETTEXT(15, *text)
则返回的position=14,text所获取的文本内容为“Scintilla是��”。此处最后的乱码是由于UTF-8中文占三个字节,而传入的length=15,实际获取字节数为length-1=14,刚好少了一个字节。如果发送如下消息:
SCI_GETTEXT(16, *text)
则返回的position=15,text所获取的文本内容为“Scintilla是一”。
SCI_SETTEXT
SCI_SETTEXT(<unused>, const char *text)
该消息可替换当前编辑器中的所有文本内容(即先清空后载入text的内容),text最后必须以\0作为结尾。
以UTF-8编码,如下文本内容为例:
如果对该文本发送如下消息:
SCI_SETTEXT(0,"Scintilla完全开放源代码,并且提供一个license允许用户自由地将它用在开源软件或是商业软件中")
则文本内容为如下:
注:本消息(SCI_SETTEXT)经常用来载入并显示文本文件。而对于打开文本文件的操作,正常而言是不允许有回退(undo)操作的,因此在完成本消息调用后,通常会调用消息SCI_EMPTYUNDOBUFFER,用来清空回退(undo)操作历史序列。
SCI_SETSAVEPOINT
SCI_SETSAVEPOINT()
该消息用于设置控件内文本内容的保存标记。通常本消息与外部保存操作联动(Ctrl+S)。当文本内容变化后,回退(undo)操作历史序列会有相应变化,此时如果调用SCI_GETMODIFY消息:
bool dirtyFlag = SCI_GETMODIFY()
返回的当前文本修改状态dirtyFlag = true。
该消息使用场景:
打开文本文件后,执行SCI_SETSAVEPOINT()
保存文本文件后,执行SCI_SETSAVEPOINT()
SCI_SETSAVEPOINT消息与如下两个事件相关:
SCN_SAVEPOINTREACHED :执行SCI_SETSAVEPOINT后,该事件触发。
SCN_SAVEPOINTLEFT :当文本内容有更改后,该事件触发。(此时外部容器可以做对应处理,比如可以将文件标题最后增加*号,表示需要保存)
SCI_GETLINE
SCI_GETLINE(line line, char *text) → position
该消息用于获取某一行(如果有换行情况,则换行符也会被获取)的文本内容。形参line的起始为序号0,所获取的文本内容被存入在形参text中。text的大小可以通过调用消息获取:
SCI_LINELENGTH(line line)
对于消息SCI_GETLINE而言,如果其形参line的值大于文本的行数,则text存入的字节为空。
以UTF-8编码,如下文本内容为例(注意第一行最后有换行):
如果对该文本执行如下代码:
int line = 0; int len = SCI_LINELENGTH(line); //伪代码 char* textLine = new char[len+1]; memset(textLine, 0, len + 1); SCI_GETLINE(line, textLine) //伪代码
执行过程中的变量值为(注意最后的\r\n):
len = 59; textLine = "Scintilla是一个强大和稳定的源代码编辑控件\r\n"
SCI_REPLACESEL
SCI_REPLACESEL(<unused>, const char *text)
该消息用于替换选中的文本内容,其中形参text为待替入的字符串,以\0结尾。如果当前没有任何选中的内容,则该消息实际上执行的是插入操作(插入点为光标所在位置)。
完成本消息的调用后,光标位置位于插入字符串的末端。
以UTF-8编码,如下文本内容为例(注意选中的文本):
如果对该文本发送如下消息:
SCI_REPLACESEL(0,"123abc")
则结果为:
注意:执行该消息后,光标位置为所插入字符串"123abc"的末端。
SCI_SETREADONLY,SCI_GETREADONLY
SCI_SETREADONLY(bool readOnly), SCI_GETREADONLY → bool
SCI_SETREADONLY与SCI_GETREADONLY 用于设置与读取文本的只读属性。当发送如下消息:
SCI_SETREADONLY(true)
则文本内容不可编辑。
在Scintilla的源码中,与编辑相关的处理,都会判断当前文本的只读属性,如Document.cxx中的插入字符串操作,有如下判断:
Sci::Position Document::InsertString(Sci::Position position, const char *s, Sci::Position insertLength) {if (insertLength <= 0) {return 0;}CheckReadOnly(); // 判断当前文本的只读属性if (cb.IsReadOnly()) {return 0;}...... }
SCI_GETTEXTRANGE
SCI_GETTEXTRANGE(<unused>, Sci_TextRange *tr) → position
该消息类似SCI_GETTEXT消息,用于获得文档中的文本内容。区别在于SCI_GETTEXT是从文档头部开始获取,而本消息SCI_GETTEXTRANGE可以设定获取范围。
Sci_TextRange 是Scintilla定义的一个用于存储文本范围的数据结构,如下为其定义:
typedef long Sci_PositionCR; struct Sci_CharacterRange {Sci_PositionCR cpMin;Sci_PositionCR cpMax; }; struct Sci_TextRange {struct Sci_CharacterRange chrg; //文本范围: 起始点与结束点char *lpstrText; //保存所选文本范围内的内容 };
以UTF-8编码,如下文本内容为例:
如果对该文本执行如下代码:
char text[10000] = { 0 }; Sci_TextRange textRange; textRange.chrg.cpMin = 1; textRange.chrg.cpMax = 5; textRange.lpstrText = text; SCI_GETTEXTRANGE(&textRange); //伪代码
执行过程中的变量值为:
text = "cint"
如果对该文本执行如下代码:
char text[10000] = { 0 }; Sci_TextRange textRange; textRange.chrg.cpMin = 9; textRange.chrg.cpMax = 15; textRange.lpstrText = text; SCI_GETTEXTRANGE(&textRange); //伪代码
执行过程中的变量值为(注意textRange设定的范围包含字节数为6,是3的整倍数,刚好包含两个UTF-8中文字符。如果不是3的整倍数,则获取的文本末尾会是乱码):
text = "是一"
SCI_GETSTYLEDTEXT
SCI_GETSTYLEDTEXT(<unused>, Sci_TextRange *tr) → position
该消息用于获取每个字节的值以及其当前样式,具体所返回数据详见下面的样例。在Scintilla中,文本内容的样式控制(如设置字体、下划线等)是通过设定不同的样式类型完成的。如下为Scintilla预先定义好的样式类型:
#define STYLE_DEFAULT 32 //默认样式 #define STYLE_LINENUMBER 33 #define STYLE_BRACELIGHT 34 #define STYLE_BRACEBAD 35 #define STYLE_CONTROLCHAR 36 #define STYLE_INDENTGUIDE 37 #define STYLE_CALLTIP 38 #define STYLE_FOLDDISPLAYTEXT 39 #define STYLE_LASTPREDEFINED 39 #define STYLE_MAX 255 //最多可以设置255个样式
在Scintilla文本中的每一个字节都有其对应的样式,因此在显示文本时,Scintilla便可以根据每一个字节的样式,来进行特性化显示。具体样式的设定方法,在后面Styling相关说明时有详细展示。
本消息中的结构体Sci_TextRange在介绍SCI_GETTEXTRANGE时已经做过详细说明。
以UTF-8编码,如下文本内容为例(其中字符串"Sci"的样式做了单独定义,其样式值设定为STYLE_TEST=50):
如果对该文本执行如下代码:
#define STYLE_TEST 50 //自定义样式类型 STYLE_TEST=50 SCI_GETSTYLEDTEXT(SCI_STARTSTYLING,0); //伪代码,样式起始字节 SCI_GETSTYLEDTEXT(SCI_SETSTYLING, 3, STYLE_TEST); //伪代码,样式结束字节 char styledText[10000] = { 0 }; Sci_TextRange textRange; textRange.chrg.cpMin = 0; textRange.chrg.cpMax = 15; textRange.lpstrText = styledText; SCI_GETSTYLEDTEXT(&textRange); //伪代码
执行过程中的变量值styledText为:
- styledText,100 0x00000005a46fa950 <字符串中的字符无效。> char[100][0] 83 'S' char[1] 50 '2' char[2] 99 'c' char[3] 50 '2' char[4] 105 'i' char[5] 50 '2' char[6] 110 'n' char[7] 0 '\0' char[8] 116 't' char[9] 0 '\0' char[10] 105 'i' char[11] 0 '\0' char[12] 108 'l' char[13] 0 '\0' char[14] 108 'l' char[15] 0 '\0' char[16] 97 'a' char[17] 0 '\0' char
如上可见,变量styledText的第0、2、4位是文本字节的值“Sci”,第1、3、5位是定义的样式类型50,后面没有定义,则样式类型为0。
SCI_ALLOCATE
SCI_ALLOCATE(position bytes)
本消息用于分配一个足够大的文档缓冲区,从而避免了在文本内容修改时所造成的频繁文本内存扩容以及拷贝。
Scintilla的文本内容存放在CellBuffer的成员变量substance中:
class CellBuffer { private:bool hasStyles;bool largeDocument;SplitVector<char> substance; //存放Scintilla的文本内容SplitVector<char> style;bool readOnly;bool utf8Substance;Scintilla::LineEndType utf8LineEnds;...... }
在对Scintilla的文本做增加字符串的动作时(比如输入一些字符串),会调用到CellBuffer的插入字符串方法:
void CellBuffer::BasicInsertString(Sci::Position position, const char *s, Sci::Position insertLength)
在该方法内部,成员变量substance会根据当前空间大小进行动态扩容:
void RoomFor(ptrdiff_t insertionLength) {if (gapLength <= insertionLength) {while (growSize < static_cast<ptrdiff_t>(body.size() / 6))growSize *= 2;ReAllocate(body.size() + insertionLength + growSize);} }
因此,提前给Scintilla设置一个缓存空间,可以提高性能。
SCI_ADDTEXT
SCI_ADDTEXT(position length, const char *text)
该消息用于在光标所在位置插入一定长度的字符串(形参const char *text),插入长度为(形参position length)。如果text="123abc",length=4,则插入字符串为“123a”。
以UTF-8编码,如下文本内容为例:
如果对该文本发送如下消息(注意当前光标在文字“是”后面):
SCI_ADDTEXT(4,"123abc")
则结果为:
注意当前光标在新增加的字符串“123a”后面。
SCI_ADDSTYLEDTEXT
SCI_ADDSTYLEDTEXT(position length, cell *c)
该消息类似于SCI_ADDTEXT,用于在光标所在位置插入一定长度的字符串,所不同的是,插入字符串带有样式信息。
如预定义样式如下(具体样式的设定方法,在后面Styling相关说明时有详细展示):
#define STYLE_TEST 50 //自定义样式类型 STYLE_TEST=50,字体大小:12,颜色:蓝色,带下划线
以UTF-8编码,如下文本内容为例:
如果对该文本执行如下代码:
#define STYLE_TEST 50 //自定义样式类型 STYLE_TEST=50 char textWithStyle[1000] = {0}; textWithStyle[0] = '1'; textWithStyle[1] = STYLE_SEL; textWithStyle[2] = '2'; textWithStyle[3] = STYLE_SEL; textWithStyle[4] = '3'; textWithStyle[5] = STYLE_SEL; textWithStyle[6] = 'a'; textWithStyle[7] = STYLE_SEL; textWithStyle[8] = 'b'; textWithStyle[9] = STYLE_SEL; textWithStyle[10] = 'c'; textWithStyle[11] = STYLE_SEL; SCI_GETSTYLEDTEXT(12,textWithStyle); //伪代码
则结果为:
SCI_APPENDTEXT
SCI_APPENDTEXT(position length, const char *text)
该消息类似于SCI_ADDTEXT,区别在于本消息用于在文档结尾位置插入一定长度的字符串,而SCI_ADDTEXT则是在光标所在位置插入。
以UTF-8编码,如下文本内容为例:
如果对该文本发送如下消息(注意当前光标在文字“是”后面):
SCI_APPENDTEXT(4,"123abc")
则结果为:
注意当前新增加的字符串位于文档末尾处,光标位置不变,仍然在文字“是”后面,另外,当前文档如果有选中字符串,其选中状态不变。
SCI_INSERTTEXT
SCI_INSERTTEXT(position pos, const char *text)
该消息类似于SCI_ADDTEXT,区别在于本消息用于在文档指定位置处插入全部长度的字符串,入参position pos 即为指定插入位置处。
以UTF-8编码,如下文本内容为例:
如果对该文本发送如下消息:
SCI_INSERTTEXT(12,"123abc")
则结果为:
SCI_CHANGEINSERTION
SCI_CHANGEINSERTION(position length, const char *text)
当准备在文本内容中增加或插入字符串时(比如调用SCI_SETTEXT、SCI_ADDTEXT以及SCI_INSERTTEXT等消息),Scintilla会发送通知事件:SCN_MODIFIED,发送同时会携带通知数据:Scintilla::NotificationData。
当有增加或插入字符串的动作时,Scintilla::NotificationData数据中的成员变量modificationType的值被设为SC_MOD_INSERTCHECK。
此时,用户可以通过该消息SCI_CHANGEINSERTION对即将增加或插入字符串做修改。
对Scintilla的通知事件的处理可以通过继承Editor类的纯虚函数实现:
virtual void NotifyParent(Scintilla::NotificationData scn) = 0;
实现方法为(QT程序会采用信号与槽的实现方式,原理一样):
//MyTextEdit继承ScintillaBase类,而ScintillaBase类又继承Editor类,从而可以处理Scintilla的通知事件 void MyTextEdit::NotifyParent(Scintilla::NotificationData *scn) {int snCode = (int)scn->nmhdr.code;switch (snCode) {case SCN_MODIFIED:{int modificationType = (int)scn->modificationType;switch (modificationType){case SC_MOD_INSERTCHECK:{//TODO: 此处就可以发送SCI_CHANGEINSERTION消息对即将增加或插入字符串做修改break;}default:break;}break;}} }
以UTF-8编码,如下文本内容为例:
对该文本内容的通知事件做如下处理(如果插入的字符串为"123abc",则将其修改为字符串"change",之后再插入):
//MyTextEdit继承ScintillaBase类,而ScintillaBase类又继承Editor类,从而可以处理Scintilla的通知事件 void MyTextEdit::NotifyParent(Scintilla::NotificationData *scn) {int snCode = (int)scn->nmhdr.code;switch (snCode) {case SCN_MODIFIED:{int modificationType = (int)scn->modificationType;switch (modificationType){case SC_MOD_INSERTCHECK:{//如果插入的字符串为"123abc",则将其修改为字符串"change",之后再插入。if (strcmp(scn->text, "123abc")==0){m_sciEditor->SendScintilla(SCI_CHANGEINSERTION, 6, "change");}break;}default:break;}break;}} }
此时对该文本发送如下消息:
SCI_INSERTTEXT(12,"123abc")
则结果为:
SCI_CLEARALL
SCI_CLEARALL()
该消息用于清空全部文本内容。注:当前文本处于非只读状态
以UTF-8编码,如下文本内容为例:
此时对该文本发送如下消息:
SCI_CLEARALL()
则结果为:
SCI_DELETERANGE
SCI_DELETERANGE(position start, position lengthDelete)
该消息用于清空设定起始位置与长度的文本内容。注:当前文本处于非只读状态
以UTF-8编码,如下文本内容为例:
此时对该文本发送如下消息:
SCI_DELETERANGE(1,8)
则结果为:
SCI_CLEARDOCUMENTSTYLE
SCI_CLEARDOCUMENTSTYLE()
该消息用于清除当前文本内容的所有样式以及重置当前的折叠状态(取消全部折叠)。
以UTF-8编码,如下文本内容为例(其中字符串"Sci"有独特样式):
此时对该文本发送如下消息:
SCI_CLEARDOCUMENTSTYLE()
则结果为:
SCI_GETCHARAT
SCI_GETCHARAT(position pos) → int
该消息用于获取所选位置的字节(注意不是字符,特别是对于中文,如“中”,该字符的UTF-8编码为“E4B8AD”,因此如果此时发送消息SCI_GETCHARAT(0),则返回值为0xE4)。
以UTF-8编码,如下文本内容为例:
此时对该文本发送如下消息:
int res = SCI_GETCHARAT(9);
则结果res值为:0xffffffe6。
SCI_GETSTYLEAT(position pos)
SCI_GETSTYLEAT(position pos) → int
该消息用于清除当前文本内容的所有样式以及重置当前的折叠状态(取消全部折叠)。
以UTF-8编码,如下文本内容为例(其中字符串"Sci"的样式值设定为50。具体样式的设定方法,在后面Styling相关说明时有详细展示):
此时对该文本发送如下消息:
int res = SCI_GETSTYLEAT(0);
则结果res值为:50。
SCI_RELEASEALLEXTENDEDSTYLES,SCI_ALLOCATEEXTENDEDSTYLES
SCI_RELEASEALLEXTENDEDSTYLES()
SCI_ALLOCATEEXTENDEDSTYLES(int numberStyles) → int
这两个消息应用于扩展样式。在Scintilla中,文本内容的样式控制(如设置字体、下划线等)是通过设定不同的样式类型完成的。如下为Scintilla预先定义好的样式类型:
#define STYLE_DEFAULT 32 //默认样式 #define STYLE_LINENUMBER 33 #define STYLE_BRACELIGHT 34 #define STYLE_BRACEBAD 35 #define STYLE_CONTROLCHAR 36 #define STYLE_INDENTGUIDE 37 #define STYLE_CALLTIP 38 #define STYLE_FOLDDISPLAYTEXT 39 #define STYLE_LASTPREDEFINED 39 #define STYLE_MAX 255 //最多可以设置255个样式
由上可见,样式的定义值最多到255。但是针对页边(通常位于编辑器左侧,可以设置断点、页码等)以及注解功能,各自也需要样式定义,因此就需要扩充样式值。在Scintilla中,这两种消息分别对应如下两个函数:
void ViewStyle::ReleaseAllExtendedStyles() noexcept {nextExtendedStyle = 256; //从256开始 } int ViewStyle::AllocateExtendedStyles(int numberStyles) {//numberStyles是扩充的数量const int startRange = nextExtendedStyle;nextExtendedStyle += numberStyles;EnsureStyle(nextExtendedStyle);for (int i=startRange; i<nextExtendedStyle; i++) {styles[i].ClearTo(styles[StyleDefault]);}return startRange; }
后续针对页边以及注解的样式扩充消息:SCI_MARGINSETSTYLEOFFSET(页边样式偏移) 以及 SCI_ANNOTATIONSETSTYLEOFFSET(注解样式偏移)。其调用之前需要应用消息SCI_ALLOCATEEXTENDEDSTYLES。
SCI_TARGETASUTF8
SCI_TARGETASUTF8(<unused>, char *s) → position
目前这个消息在Scintilla的源码中没有做实现,Scintilla的API文档对其描述主要是用于检索编码为UTF-8的目标值。
SCI_ENCODEDFROMUTF8,SCI_SETLENGTHFORENCODE
SCI_ENCODEDFROMUTF8(const char *utf8, char *encoded) → position
SCI_SETLENGTHFORENCODE(position bytes)
上述两个消息作用在于将UTF8字符串转换成当前文档的编码格式,在ScintillaQt.cpp中有如下处理过程:
std::string ScintillaQt::EncodedFromUTF8(std::string_view utf8) const {if (IsUnicodeMode()) {return std::string(utf8);} else {QString text = QString::fromUtf8(utf8.data(), static_cast<int>(utf8.length()));QTextCodec *codec = QTextCodec::codecForName(CharacterSetID(CharacterSetOfDocument()));QByteArray ba = codec->fromUnicode(text);return std::string(ba.data(), ba.length());} }
但是该函数并没有实际被调用,因此上述两消息暂时也无法应用。
Scintilla教程(2): 文本检索与修改相关推荐
- ps如何修改图片大小尺寸_PS新手入门教程:学习如何修改画布的大小
PS新手入门教程:学习如何修改画布的大小.在photoshop中,可以把画布理解为一张白纸,而我们要处理的图像可以理解为这张白纸表面上的画.我们修改画布的大小时,图像并不会随着画布的大小而整体变大或缩 ...
- Magento教程 25:如何修改系统发送的通知信件?
欢迎使用Magento购物车系统 ,上次和大家介绍的是限制会员留言的产品评论设定 :Astral Web这次要介绍如何修改通知信件的内文. 所谓的通知信件就是当客户注册成功.订单完成.出货通知等系统自 ...
- Magento教程 10:如何修改网站文字?
你知道知名运动品牌NIKE.休闲鞋品牌TOMS都在使用Magento吗? Magento是一种多商店购物网站系统,其便利性佳.扩充性高,且功能强大,因此广受商家青睐. 此外,Magento在后台.前台 ...
- SAP UI5 应用开发教程之一百 - 如何修改 SAP UI5 框架的源代码实现,以及使用本地部署的 SAP UI5 SDK 试读版
一套适合 SAP UI5 初学者循序渐进的学习教程 作者简介 Jerry Wang,2007 年从电子科技大学计算机专业硕士毕业后加入 SAP 成都研究院工作至今.Jerry 是 SAP 社区导师,S ...
- mysql修改游戏元宝_页游源码【武斗乾坤】自带安装启动教程+元宝游戏数据修改教程+自由一键游戏启动服务端...
页游源码[武斗乾坤]自带安装启动教程+元宝游戏数据修改教程+自由一键游戏启动服务端_站长下载 资源说明: 1.本资源为一键启动服务端,只需要安装好所需组件一键启动即可运行. 2.资源默认为单机架设,无 ...
- zblog首页模板修改php,【zblog】zblogphp主题模板修改教程 zblogphp模板怎么修改?
zblogphp主题模板修改教程 zblogphp模板怎么修改? 这一篇主要是介绍"zblogphp"的模板修改教程,zblogasp的模板修改教程请看本站之前发的一篇教程&quo ...
- 视频消重教程视频教程 视频md5修改app
视频消重教程视频教程 视频md5修改app 在印尼不太平,在印度也不好过.近日有印度立法者表示Tik Tok中出现了.网络欺凌等内容,认为Tik Tok导致了青少年 ...
- BLE-NRF51822教程11-手机动态修改设备名
该教程讲解如何实现用手机来动态修改设备名,达到手机连接设备后修改设备名称,然后断开连接再扫描能够看到新的设备名. 教程基于sdk9.0 下的uartdemo,如下目录中xxx\Keil_v5\ARM\ ...
- 反编译android 状态栏沉浸,教程:反编译修改实现状态栏时间居左,去除锁屏运营商...
本帖最后由 Gleam 于 2017-7-30 21:15 编辑 重要的事情说三遍: 操作不当会有风险,如不能开机,systemui无限错误等,修改之前确定是否备份system分区. 操作不当会有风险 ...
- InDesign 教程如何创建和修改和使用母版页
欢迎观看indesign教程,小编带大家学习 InDesign 的基本工具和使用技巧,了解InDesign如何创建和修改母版页,以及如何将母版页应用至文档页面. 母版页对于在整个文档中实现一致性非常有 ...
最新文章
- [嵌入式]Bootloader的作用
- 【漫画解读银行业务】
- x390更换开机_ThinkPad X390怎么装win10系统|ThinkPad X390用u盘重装win10系统教程-系统城...
- 如何从过滤器中排除URL
- OutOfMemoryError:Java堆空间–分析和解决方法
- OpenStack Weekly Rank 2015.08.24
- 实战篇—关于某产品的切分细则
- C++模版 (一) ----- 函数模版
- HelloDjango 第 10 篇:小细节 Markdown 文章自动生成目录,提升阅读体验
- vue引入bootstrap.min.css报错:Cannot find module ./assets/css/bootstrap.min.css
- 为什么root下不能使用passwd命令_Linux:CentOS 7中常用的基础命令
- storm中分组策略Field Grouping简单总结笔记
- Azure School女神相邀,把每分钟都过的更充实
- CCPC 合肥站 打铁记
- Latex 插入大括号分类情况
- 67、INGeo:利用占用网格先验加速/减少迭代次数
- Eclipse配置Python的IDE
- 测试有没有说梦话的软件,抖音上记录梦话的软件是什么 记录梦话的软件介绍...
- 现实迷途 第三十二章 阴晴反复(下)
- numpy——.npy和.npz文件