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