尽管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

尽管regex模式是正确的,而且字符串也是正确的,但Why返回的值为false

我认为您的循环中有一个小错误:

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;
}