什么是正则表达式验证字符串是否为pandigital(包含1到9的所有数字一次)?
例如:
123456789
891364572
但不是:
11234556789
25896471
我知道如何在没有正则表达式的情况下执行此操作,但我无法为其创建正则表达式。
感谢。
这不是作业。
答案 0 :(得分:15)
简短而甜蜜,使用负向前瞻:
/^(?!.*([1-9]).*\1)[1-9]{9}$/
[1-9]
是非零数字的字符类 - 相当于[123456789]
.*
匹配任何长度的任何字符串。.*([1-9]).*\1.*
匹配任何包含至少两次相同非零数字的字符串
([1-9])
\1
匹配,反向引用与第一次捕获的匹配相匹配。.*
匹配之前的任意填充,以及非零数字与其重复之间的匹配。(?!<pattern>)
匹配包含的模式不匹配的任何位置。这是一个否定前瞻,因为它只匹配字符串中的位置,并且不会消耗任何一个 - 只是向前看以将其与包含的模式进行比较。 [1-9]{9}
匹配九个nonzeo数字。
<pattern>{9}
表示匹配前面的模式9次。^<pattern>$
匹配与包含的模式完全匹配的任何字符串(而不是包含与模式匹配的子字符串)
^
匹配字符串开头的位置或行的开头$
匹配字符串末尾的位置或行的结尾如此组合,我们检查以确保它不重复任何数字,然后我们检查它只是数字。因为它长9位,没有重复,所以必须只显示一次。那就是pigeonhole principle正在发挥作用!
特定正则表达式引擎的语法可能有所不同。以上是PCRE(Perl,Ruby和一堆不同的其他语言支持)。 Posix regular expressions语法略有不同。并非所有引擎都支持负向前瞻,但大多数都支持反向引用。它们都不是正式理论正则表达式定义的一部分,但非常方便。
答案 1 :(得分:4)
正则表达式并不是这里工作的最佳工具,但是你去了:
^(?=[^1]*1[^1]*$)(?=[^2]*2[^2]*$)(?=[^3]*3[^3]*$)(?=[^4]*4[^4]*$)(?=[^5]*5[^5]*$)(?=[^6]*6[^6]*$)(?=[^7]*7[^7]*$)(?=[^8]*8[^8]*$)(?=[^9]*9[^9]*$)[1-9]+$
(?= )
是一个先见之明。它实际上并不适合正则表达式的描述,因为它没有描述常规语言。
答案 2 :(得分:2)
如果不是作业,则不应使用RE。以下C代码应该是一个良好的开端。
#include <stdio.h>
int isPandigital (char *inputStr) {
/* Initial used states of false. */
char used[] = {0,0,0,0,0,0,0,0,0,0};
int count = 0;
char ch;
/* Process each character in string. */
while ((ch = *inputStr++) != '\0') {
/* Non-numeric, bad. */
if ((ch < '0') || (ch > '9')) {
return 0;
}
/* Too many, bad. */
if (++count > 9) {
return 0;
}
/* Multiples, bad. */
if (used[ch - '0']) {
return 0;
}
/* Store fact that this one's been used. */
used[ch - '0'] = 1;
}
/* Good or bad depending on how many we've had. */
return (count == 9);
}
int main (int argCount, char *argVar[]) {
int i;
for (i = 1; i < argCount; i++) {
if (isPandigital (argVar[i])) {
printf ("'%s' is pandigital\n", argVar[i]);
} else {
printf ("'%s' is NOT pandigital\n", argVar[i]);
}
}
return 0;
}
使用您的测试数据:
$ pandigital 123456789 891364572 11234556789 25896471
我们得到以下结果:
'123456789' is pandigital
'891364572' is pandigital
'11234556789' is NOT pandigital
'25896471' is NOT pandigital
答案 3 :(得分:1)
这在程序代码中更容易做,循环遍历每个字符并在数组中标记它们......或者这是一些功课?
答案 4 :(得分:0)
bool chk(string s, int idx, set sofar) {
return index == s.length ? true : isdigit(s[idx]) && !sofar.count(s[idx]) && chk(s,++idx,sofar.insert(s[idx]));
}