概述
在工业应用的终端软件中,常会包含类似"运行参数"设置的功能,通常,它们是有输入限制的,以保证控制器设备安全稳定运行;在嵌入式移动终端中,该种输入限制通常配合着自定义软件盘进行作用,既有输入过程检查,又有输入完成后的输入检查。该文涉及的输入接收者,主要是Qt下的QLineEdit控件;主要从Qt正则表达式及校验器的配置与使用,正则表达式失效异常处理,Etc,展开…
输入限制的方案
现阶段使用正则表达式的场景主要有:运行参数设置、Lua可视化编辑输入限制…
在进入正题前,先来探讨下马后炮的限制输入方法:在lineEdit中完成输入后,通过其editingFinished信号,或textChanged信号,或直接取text()内容来判断输入过程或输入结果。举两个例子:
-
限制某LineEdit输入浮点数据,但不能输入0,不能为空,不能单负号
第一个限制要求很容易用正则表达式实现,但是第二三四要求,却不能用正则表达式限制住(只是到现在没找到)。 -
限制某LineEdit可以输入(\\\")(作为Lua字符串变量的赋值内容,但不允许输入(")(\")(\\"),原因吗,参考如下代码区。这种情况,要求"前必须有3条反斜杠,正则表达似乎不能实现这种限制要求。
-
限制某LineEdit可以输入负号-,但是不允许输入Lua注释符 - -(#两个负号中间无空格),Here限制点#第二个-负号是后输入字符的检查,所以理论上是可能实现正则表达式限制的,具体表达式可以向后阅读。
正则表达式语法
元字符在正则表达式上下文中的行为-参考1,基本涵盖了正则表达式描述字符的含义。进行如下几点补充。
a(?!b) //匹配后面没有 b 的 a
^Help 如果Help出现在字符串的开头,就匹配它
[^Help] 这里的^ 与元字符^的意思不一样,其表示排除的意思
正则表达式的作用,不止是限制编辑框的输入,还可用以字符串的查找检查等,可去看看QRegExp的接口函数列表,加深下理解。
PS转义字符
转义字符串-百科,其实所有编程语言,拥有转义字符的原因基本上是两点:一、使用转义字符来表示字符集中定义的字符,比如ASCll里面的控制字符及回车换行等字符,这些字符都没有现成的文字代号。所以只能用转义字符来表示 。二、某一些特定的字符在编辑语言中被定义为特殊用途的字符。这些字符由于被定义为特殊用途,它们失去了原有的意义。比如说Html中,<被HTML定义为标签的开始,所以当我们转入<时,HTML就会把它当作为开始,而不是当作一个<来看待。再如PHP 的双引号("),被PHP定义为字符串的外围标签,所以如果你在一对双引号里面,还想要使用双引号,只能使用转义字符了。不然PHP就会报错了。
在当前用的QtCreator集成环境,字符串中的"等字符必须输转义字符\,否则将会编译错误。:
//编译失败 因\作为原本的含义出现在""中时 也要转义 不光"需要
lua_str = " ni hao \\"qugx0528\\", chi fan ba! "; //lua、c++..
//正确的代码写法为
lua_str = " ni hao \\\"qugx0528\\\", chi fan ba! "; //lua、c++..
//简单测试
ui->lineEdit_1->setText(" nihao" "); //编译失败
ui->lineEdit_1->setText(" nihao\" "); //编译成功
QString strInput(" nihao\\\" ");
ui->lineEdit_1->setText(strInput); //其运行效果与setText(" nihao\" ")一致
//定义一个QString对象str_yinhao
str_yinhao.append("\""); //编译要求
/**
转义字符反斜杠\,可猜测其纯粹的是一个编译器或解释器的需求产物,只有在书写字符串常量(双引号内)时才会有实际使用意义。当我们直接用键盘在lineEdit中输入时,或传字符串参数时均无转义的概念,因为他们是运行赋值过程,与编译无关。
**/
//画lineEdit_1、 lineEdit_2 然后使用键盘 在lineEdit_1 输入字符(\")
QString str1 = ui->lineEdit_1->text();
ui->lineEdit_2->setText(str1); //显示\" 没有直接的字符串编译 故也与转义八竿子打不着
直接法与排除法
嘿,这可能是我自己造的名词。“直接法” 限制能输入哪些字符;“排除法” 限制哪些字符不能输入。
//浮点数输入范围为[-180,180] 含小数4位
QRegExp rx("^-?(180|1?[0-7]?\\d(\\.\\d{1,4})?)$");
//除了H、e、l、p之外的任一字符
[^Help]
//尝试限制输入连续字符qugx
特殊限制输入
举例:限制输入(- - Lua注释符#两个负号中间无空格)、限制输入(\单反斜杠)
//限制输入单反斜杠
QString strExp = "^([^\\\\]*)$";
//Ps:在正则表达式中写字符串 对于那些需要转义的字符 如"双引号 '单引号 \反斜杠自身等 其语法与C、C++、Lua等一致
//其效果是不能输入任何字符
QString strExp = "^([^\\]*)$"; //感觉有些奇葩
//限制输入双引号
QString strExp = "^([^\"]*)$";
//限制输入短线/负号
QString strExp = "^([^--]*)$";
基本分析:
符号(反斜杠\)、(负号-),在正则表达式自身语法中有使用(如 [a-g] 匹配a到g中的任一字符),要限制它们的输入,必须要输入两遍该字符才能生效。但是像左右大括号 } { 等自身语法中具有的符号,却不需要这样,也不需要加反斜杠转义(若加上\将会存在编译告警unknow escaape sequence 但是运行可生效)。
//实现一种限制输入连续负号 - lua注释符的方案
QString strExp = "^([^--]*-[^--])*$";
//Ps:该表达式的缺陷是不太好限制总输入个数
//注意不能写成
QString strExp = "^([^--]*-[^--]*)$"; //其限制了只能输入一个在其他字符间的负号
动态-输入个数限制
//除(") (') (\) (?) ({}) (space) (:) 之外的count个字符(一个汉字算一个字符)
#define File_Name_Limit(count) \
QString("^(([^\"\'\\\\?{} :]){0,%1})$").arg(count) \
QRegExp regExp(File_Name_Limit(20));
QValidator *pValidator = new QRegExpValidator(regExp, this);
ui->lineEdit->setValidator(pValidator);
setText影响限制
如若为pLineEdit设置了正则表达式strExp,然后setText一个不符合它的串,则限制失效。
//set一个不符合其正则表达式的串
pLineEdit->setText(string_nomatch);
/** @brief
* 在上述不符合已设正则的串的基础上的后续输入,将不受限制. 除非:
* 那些个不符合strExp的字符被删除、或者直接被clear过,则正则限制恢复正常
**/
...
QRegExp regExp(File_Name_Limit(20));
QValidator *pValidator = new QRegExpValidator(regExp, this);
ui->lineEdit->setValidator(pValidator);
//直接的设置不受正则表达式限制
ui->lineEdit->setText("abcdef\"ghijk");
//界面显示后,只需将lineEdite中的"删除,则pValidator恢复功效
//有时,需要在键盘输入前先判断显示字符串
if (!QRegExp(strExp).exactMatch(pLineEdit->text()))
{
pLineEdit->clear(); //使得正则表达式重新生效
}
Qt的输入限制
在Qt4.8.6中,QValidator Inherited by: QDoubleValidator, QIntValidator, and QRegExpValidator. 其中QDoubleValidator在使用上存在bug,对于QIntValidator的使用还是很方便的。