JavaScript双操作数计算器输入的正则验证优化问询
修复双操作数计算器的实时输入验证逻辑
我开发了一款支持+、-、*、/运算的双操作数计算器,原本用内联正则做实时输入验证,但现有逻辑允许2.+.1这类不符合预期的输入。需要调整验证规则,满足:
- 输入
.后必须跟数字(或自动补0) - 输入
+-*/运算符后必须跟数字(或自动补0) - 逐字符实时校验,而非输入完成后统一检查
现有验证代码:
//check if operator is present if(/[+\-*\/]/.test(display1.textContent)){ //validate the string each time a new character is added if(!/^\d+\.?\d*[+\-*\/]?\d*\.?\d*$/.test(display1.textContent)){ console.log('invalid') return false } //validate the string character by character before operator } else { if(!/^\d+\.?\d*$/.test(display1.textContent)){ console.log('invalid') return false } }
解决方案:分步校验+前置拦截+自动补全
由于单一正则难以覆盖所有实时输入的边界场景,改用分步校验逻辑,结合前置字符检查和自动补全,既拦截非法输入,又将不规范输入转化为合法格式。
1. 核心验证函数
先实现一个基础的验证函数,确保输入的整体格式合法:
function validateInput(currentDisplayText) { if (!currentDisplayText) return true; const hasOperator = /[+\-*\/]/.test(currentDisplayText); const operatorIndex = currentDisplayText.search(/[+\-*\/]/); if (!hasOperator) { // 第一个操作数:只能是整数或合法小数(不能有多个小数点,不能仅为小数点) return /^\d+(\.\d*)?$/.test(currentDisplayText); } else { const firstOperand = currentDisplayText.slice(0, operatorIndex); const secondOperand = currentDisplayText.slice(operatorIndex + 1); // 验证第一个操作数合法性 if (!/^\d+(\.\d*)?$/.test(firstOperand)) return false; // 第二个操作数为空时暂时允许(刚输入运算符还没输数字) if (!secondOperand) return true; // 验证第二个操作数合法性 return /^\d+(\.\d*)?$/.test(secondOperand); } }
2. 前置字符拦截
在用户输入新字符前,预判是否允许添加,避免出现.+、+.这类非法序列:
function canAddCharacter(currentText, newChar) { // 只允许数字、小数点、运算符 if (!/[\d\.+\-*\/]/.test(newChar)) return false; // 输入小数点的规则:当前操作数不能已有小数点,不能单独作为第一个字符 if (newChar === '.') { const currentSegment = /[+\-*\/]/.test(currentText) ? currentText.slice(currentText.search(/[+\-*\/]/) + 1) : currentText; if (currentSegment.includes('.') || currentText === '') return false; } // 输入运算符的规则:不能已有运算符,前面必须是合法操作数 if (/[+\-*\/]/.test(newChar)) { if (/[+\-*\/]/.test(currentText) || !/^\d+(\.\d*)?$/.test(currentText)) { return false; } } // 最后做整体验证 return validateInput(currentText + newChar); }
3. 自动补全逻辑
将用户的不规范输入转化为合法格式,比如把2.+补成2.0+,把+.1补成+0.1:
function handleUserInput(newChar) { let currentText = display1.textContent; // 操作数以小数点结尾时,输入运算符前自动补0 if (/[+\-*\/]/.test(newChar) && currentText.endsWith('.')) { currentText += '0'; } // 运算符后直接输入小数点时,自动补0 if (newChar === '.' && /[+\-*\/]/.test(currentText)) { currentText += '0'; } // 验证通过则更新显示,否则拦截 if (canAddCharacter(currentText, newChar)) { display1.textContent = currentText + newChar; } else { console.log('无效输入'); } }
逻辑说明
- 拆分了单操作数和双操作数阶段的验证,避免单一正则的模糊匹配
- 前置拦截确保不会出现非法字符序列,比如连续的非数字符号
- 自动补全让用户的不规范输入自动转化为合法格式,提升体验
内容的提问来源于stack exchange,提问作者James Dineley
相关产品推荐
相关产品推荐

