尽管regex模式是正确的,而且字符串也是正确的,但Why返回的值为false
本文关键字:返回 Why false 模式 regex 尽管 字符串 | 更新日期: 2023-09-27 18:06:59
所以我有一个函数来决定输入(这是第三种类型的语法(是否正确。尽管组件是好的,但每次都会返回false。
这是代码:
public bool isCorrectGram(List<string> rules)
{
bool find=false;
Regex rgx=new Regex("[a-z]{1}[A-Z]{1}");
Regex rgx2 = new Regex("[a-z]{1}");
foreach(string line in rules)
{
List<string> temp = line.Split('|', '→').ToList<string>();
foreach(string rule in temp)
{
System.Windows.Forms.MessageBox.Show(rule);
if (rule!=temp[0]&&(!rgx.IsMatch(rule) || !rgx2.IsMatch(rule)))
{
find = false;
}
else find= true;
if (!find)
break;
}
if (!find)
break;
}
return find;
}
正确的样本输入是:
S→aA
A→a
(所以每个规则都是正确的,其中包含一个小字母和一个大写字母,或者只有一个小(
[编辑]问题出在正则表达式上。我有一个只与字符串匹配的模式,如a或aB
我认为您的循环中有一个小错误:
if语句中的表达式
if (rule!=temp[0]&&(!rgx.IsMatch(rule) || !rgx2.IsMatch(rule)))
应该是类似的东西
if (rule!=temp[0]&&(!rgx.IsMatch(rule) && !rgx2.IsMatch(rule)))
或
if (rule!=temp[0]&& !(rgx.IsMatch(rule) || rgx2.IsMatch(rule)))
为什么
表达式的第二部分总是计算为true
!您正在测试rgx
是否不匹配或rgx2
是否不匹配。对于宇宙中的任何字符串,这两个字符串中至少有一个不匹配!
我敢肯定,您实际上想检查是否两个都不匹配,并且只有,然后将find
设置为false
,对吧?
最后但并非最不重要
实际上,您的代码还需要进一步改进:
- 也许使用一个匹配所有有效字符串的正则表达式,而不是两个都检查的正则表达式
- 我希望您不要使用
rule!=temp[0]
来检查这是否是循环的第一次迭代。。。危险的(不过,忽略这一点,如果这真的是你想要的行为,那么你可以使用类似"♥→♥|a"( - 控制流:使用
return false
设置一个额外的变量来中断循环
此处存在多个问题。。。
if条件
if (rule != temp[0] && (!rgx.IsMatch(rule) || !rgx2.IsMatch(rule)))
{
find = false;
}
忽略第一位,这只是确保您只检查→
之后的零件。。。
!rgx.IsMatch(rule) || !rgx2.IsMatch(rule)
意味着如果规则与任一正则表达式不匹配,则返回false
。换句话说,要返回true,它必须匹配和。
哪个a
显然不匹配——它与第一个正则表达式不匹配。你想要的条件是:
!(rgx.IsMatch(rule) || rgx2.IsMatch(rule))
也就是说,如果规则未能匹配两个正则表达式,则返回false
。
正则表达式
现在,对于aA
,它显然将匹配第一个正则表达式,但它也将匹配第二个,因为[a-z]{1}
只是意味着字符串必须包含一个字符a-z
。要只匹配由该单个字符组成的字符串而不匹配其他字符,您需要例如^[a-z]{1}$
-或简单的^[a-z]$
。
您也可以将两个正则表达式合并为一个来简化:^[a-z][A-Z]?$
^ = assert start of string
[a-z] = match 1 lowercase character
[A-Z]? = match 0 or 1 uppercase characters
$ = assert end of string.
可读性
顺便说一下,在我看来,这是"单一退出"思维方式(即避免在方法中间使用返回(对任何人都没有帮助的情况之一。通过忽略"单一出口"的思维方式进行上述修复和简化:
public bool isCorrectGram(List<string> rules)
{
Regex rgx = new Regex("^[a-z][A-Z]?$");
foreach(string line in rules)
{
// The compiler can infer the generic type (<string>) for `ToList()`.
List<string> temp = line.Split('|', '→').ToList();
foreach (string rule in temp)
{
if (rule != temp[0] && !rgx.IsMatch(rule))
{
return false;
}
}
}
return true;
}