尽管正则表达式模式正确,并且字符串也是正确的,为什么返回false值

时间:2014-06-04 21:27:43

标签: c# regex

所以我有一个函数决定输入(这是第三种类型的语法)是正确的还是不正确的。虽然组件很好,但每次都会返回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

等字符串匹配的模式

2 个答案:

答案 0 :(得分:1)

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

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不匹配。对于Universe中的任何字符串,这两个字符串中至少有一个不匹配!

我很确定您确实想要检查两者是否不匹配,只有然后find设置为false,正确?

最后但并非最不重要

实际上您的代码可以使用一些进一步的改进:

  • 也许使用一个匹配所有有效字符串的正则表达式而不是两个你总是检查的正则字符串
  • 我希望您不要使用rule!=temp[0]检查这是否是循环的第一次迭代......危险! (忽略这一点,如果这确实是你想要的行为,那么你可以拥有像&#34;♥→♥| a&#34;)
  • 这样的字符串。
  • 控制流程:使用return false安装一个额外的变量突破循​​环

答案 1 :(得分:0)

这里有多个问题......

if条件

if (rule != temp[0] && (!rgx.IsMatch(rule) || !rgx2.IsMatch(rule)))
{
    find = false;
}

忽略第一位,这只是确保您只在之后检查零件......

!rgx.IsMatch(rule) || !rgx2.IsMatch(rule)

...表示如果规则无法匹配任一正则表达式,您将返回false。换句话说,要返回true,它必须匹配 both

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