当内部有空格时,加拿大邮政编码的验证失败
Validation of Canadian postal code fails when whitespace inside
我正在尝试编写一个程序来验证加拿大邮政编码。
给定两种格式
A1A1A1
A1A 1A1
问题
我的代码无法识别第二种格式的 white space。
当我验证第二种格式时,它会打印 "Invalid"
两次,即使它是合法的邮政编码。
代码
public class validatePostalCodeTest {
public static void main(String[] args) {
Scanner kb = new Scanner(System.in);
System.out.println("Please enter postalcode:");
while (kb.hasNext()){
String posCode = kb.next();
if (posCode.length() > 7)
System.out.println("\nInvalid");
if (posCode.length() < 6)
System.out.println("\nInvalid");
if (posCode.length()== 7){
boolean valid = true;
for (int i = 0; i < posCode.length(); i++){
char a = posCode.charAt(0);
char b = posCode.charAt(2);
char c = posCode.charAt(4);
char d = posCode.charAt(1);
char e = posCode.charAt(5);
char f = posCode.charAt(6);
char g = posCode.charAt(3);
if(! Character.isLetter(a))
valid = false;
else if (! Character.isLetter(b))
valid = false;
else if (! Character.isDigit(c))
valid = false;
else if (! Character.isDigit(d))
valid = false;
else if (! Character.isLetter(e))
valid = false;
else if (! Character.isDigit(f))
valid = false;
else if (! Character.isWhitespace(g))
valid = false;
break;
}
if (valid) System.out.println("\nValid");
else System.out.println("\nInvalid");
}
if (posCode.length()== 6){
boolean valid = true;
for (int i = 0; i < posCode.length(); i++){
char a = posCode.charAt(0);
char b = posCode.charAt(2);
char c = posCode.charAt(4);
char d = posCode.charAt(1);
char e = posCode.charAt(3);
char f = posCode.charAt(5);
if(! Character.isLetter(a))
valid = false;
else if (! Character.isLetter(b))
valid = false;
else if (! Character.isLetter(c))
valid = false;
else if (! Character.isDigit(d))
valid = false;
else if (! Character.isDigit(e))
valid = false;
else if (! Character.isDigit(f))
valid = false;
break;
}
if (valid) System.out.println("\nValid");
else System.out.println("\nInvalid");
}
System.out.println("\nPlease enter a postalcode:");
}
System.out.println("Program ending due to end-of-file");
}
}
我会在这里使用正则表达式:
boolean isPostalCodeValid (String postalcode) {
return postalcode.matches("^\w\d\w\d\w\d|\w\d\w\s\d\w\d$"));
}
此处演示:
public class validatePostalCodeTest {
public static void main(String[] args) {
Scanner kb = new Scanner(System.in);
System.out.println("Please enter a Postcode:");
while (kb.hasNext()){
String posCode = kb.next();
if (posCode.length()== 7){
boolean valid = true;
char a = posCode.charAt(0);
char b = posCode.charAt(2);
char c = posCode.charAt(4);
char d = posCode.charAt(1);
char e = posCode.charAt(5);
char f = posCode.charAt(6);
char g = posCode.charAt(3);
if(! Character.isLetter(a))
valid = false;
else if (! Character.isLetter(b))
valid = false;
else if (! Character.isLetter(c))
valid = false;
else if (! Character.isDigit(d))
valid = false;
else if (! Character.isDigit(e))
valid = false;
else if (! Character.isDigit(f))
valid = false;
else if (! Character.isWhitespace(g))
valid = false;
if (valid) System.out.println("\nValid");
else System.out.println("\nInvalid");
}
else if (posCode.length()== 6){
boolean valid = true;
char a = posCode.charAt(0);
char b = posCode.charAt(2);
char c = posCode.charAt(4);
char d = posCode.charAt(1);
char e = posCode.charAt(3);
char f = posCode.charAt(5);
if(! Character.isLetter(a))
valid = false;
else if (! Character.isLetter(b))
valid = false;
else if (! Character.isLetter(c))
valid = false;
else if (! Character.isDigit(d))
valid = false;
else if (! Character.isDigit(e))
valid = false;
else if (! Character.isDigit(f))
valid = false;
if (valid) System.out.println("\nValid");
else System.out.println("\nInvalid");
}
else{
System.out.println("\nInvalid Length");
}
System.out.println("\nPlease enter a Postcode:");
}
System.out.println("Program ending due to end-of-file");
}
}
请尝试上面logic.I已经优化了
您使用了kb.next()
,它将以space分隔读取数据,
因此,当您将邮政编码输入为 A1A 1A1
时,它将花费 2 次,第一个是 A1A
,第二个是 1A1
,因此您将获得 2 次无效输出,因为它需要 2时间数据有一个 space,所以你需要使用 nextLine() 它会帮助你解决你的问题,
检查下面已解决的答案
public class validatePostalCodeTest
{
public static void main (String[] args) throws java.lang.Exception
{
Scanner kb = new Scanner(System.in);
System.out.println("Please enter postalcode:");
String posCode = kb.nextLine();
if (posCode.length() > 7)
System.out.println("\nInvalid");
if (posCode.length() < 6)
System.out.println("\nInvalid");
if (posCode.length()== 7){
boolean valid = true;
char a = posCode.charAt(0);
char b = posCode.charAt(2);
char c = posCode.charAt(4);
char d = posCode.charAt(1);
char e = posCode.charAt(5);
char f = posCode.charAt(6);
char g = posCode.charAt(3);
if(! Character.isLetter(a))
valid = false;
else if (! Character.isLetter(b))
valid = false;
else if (! Character.isDigit(c))
valid = false;
else if (! Character.isDigit(d))
valid = false;
else if (! Character.isLetter(e))
valid = false;
else if (! Character.isDigit(f))
valid = false;
else if (! Character.isWhitespace(g))
valid = false;
if (valid) System.out.println("\nValid");
else System.out.println("\nInvalid");
}
if (posCode.length()== 6){
boolean valid = true;
char a = posCode.charAt(0);
char b = posCode.charAt(2);
char c = posCode.charAt(4);
char d = posCode.charAt(1);
char e = posCode.charAt(3);
char f = posCode.charAt(5);
if(! Character.isLetter(a))
valid = false;
else if (! Character.isLetter(b))
valid = false;
else if (! Character.isLetter(c))
valid = false;
else if (! Character.isDigit(d))
valid = false;
else if (! Character.isDigit(e))
valid = false;
else if (! Character.isDigit(f))
valid = false;
if (valid) System.out.println("\nValid");
else System.out.println("\nInvalid");
}
System.out.println("Program ending due to end-of-file");
}
}
让我们从简化代码开始。
你的循环最多只执行一次一次,因为你在它们的末尾有一个break
,这确实提出了一个问题,为什么要费心有循环吗?
您描述的加拿大邮政编码格式,一般形式为:
/[A-Z]\d[A-Z]\d[A-Z]\d/
没有 space,并且
/[A-Z]\d[A-Z]\s\d[A-Z]\d/
...其中[A-Z]
表示大写字符类A到Z,\d
表示0到9的数字,\s
表示a白色space字符。我知道您没有使用正则表达式,但这就是我计划表示您需要解决的数据的方式。
让我们从简化没有 space 的案例开始。那是你的整个第二个循环。我们从 next
切换到 nextLine()
开始,以便在我们的扫描仪中使用。
String posCode = kb.nextLine();
现在,我们只想读入整行并检查其长度。如果等于 6,我们继续 - 您的代码已经这样做了。
if(posCode.length() == 6) {
// validation logic
}
现在是棘手的部分。你还记得我上面提到的正则表达式吗?碰巧他们有一个模式:
- 偶数位字符必须是从 A 到 Z 的字符。
- 奇数位字符必须是 0 到 9 之间的数字。
这样,我们就可以构造一个循环,根据这个逻辑为我们检查一些东西。注意 Character.isLetter
和 Character.isDigit
.
的否定
for(int i = 0; i < posCode.length(); i++) {
if(i % 2 == 0) { // even digits
if(!Character.isLetter(posCode.charAt(i))) {
// reject!
System.out.println("Invalid!");
break;
}
} else { // odd digits
if(!Character.isDigit(posCode.charAt(i))) {
// reject!
System.out.println("Invalid!");
break;
}
}
}
实际上,这就是您需要做的全部。 whitespace字符是特例,跳过即可轻松忽略
int spaceLocation = posCode.indexOf(" ");
if(spaceLocation != -1) {
// carve the space out and concatenate
posCode = posCode.substring(0, spaceLocation) + posCode.substring(spaceLocation + 1, posCode.length());
}
通过上述操作,您只需要一种方法,就可以成功验证两种情况。
您可以减少很多 if-else
语句并减少代码行数。
以下代码与您的逻辑相同,它会按照您的意愿检查邮政编码:
public class validatePostalCodeTest {
public static void main(String[] args) throws java.lang.Exception {
Scanner kb = new Scanner(System.in);
System.out.println("Please enter postalcode:");
char charPC[] = kb.nextLine().toCharArray();
boolean valid = false;
if (charPC.length == 7) {
if (Character.isLetter(charPC[0]) && Character.isLetter(charPC[2]) && Character.isLetter(charPC[5])
&& Character.isDigit(charPC[4]) && Character.isDigit(charPC[1]) && Character.isDigit(charPC[6])
&& Character.isWhitespace(charPC[3])) {
valid = true;
}
}
else if (charPC.length == 6) {
if (Character.isLetter(charPC[0]) && Character.isLetter(charPC[2]) && Character.isLetter(charPC[4])
&& Character.isDigit(charPC[1]) && Character.isDigit(charPC[3]) && Character.isDigit(charPC[5])) {
valid = true;
}
}
if (valid)
System.out.println("\nValid");
else
System.out.println("\nInvalid");
System.out.println("Program ending due to end-of-file");
}
}
为什么不使用正则表达式?
加拿大邮政编码作为正则表达式
你给定的两种加拿大邮政编码格式都有一个模式。这可以表示为 regular expression (regex):
regex
example match
variant
[A-Z]\d[A-Z]\d[A-Z]\d
A1A1A1
without spaces
[A-Z]\d[A-Z]\s\d[A-Z]\d
A1A1 A1
with a space between parts
其中:
[A-Z]
表示大写字母A到Z
\d
表示0到9的数字
\s
表示一个空白字符
改进正则表达式,测试demo on regex101:
^[A-Z]\d[A-Z]\d\s?[A-Z]\d$
- 用
^
和 $
包围正则表达式以匹配从开始 (^
) 到结束 ($
) 的完整行
- 在
\s
上添加的 qunatifier 表示 零或一个 空格 (\s?
)。
也可以通过使用贪婪量词 *
来替换零或多个(任意)。
将此正则表达式与 String.matches(regex)
一起使用,您可以轻松验证:
public static boolean isValidCanadianPostcode(String input) {
return input.matches("^[A-Z]\d[A-Z]\d\s?[A-Z]\d$");
}
注意:对于 Java 字符串中的正确正则表达式,我们需要用另一个反斜杠转义每个反斜杠(例如 \s
变为 \s
)。
我正在尝试编写一个程序来验证加拿大邮政编码。
给定两种格式
A1A1A1
A1A 1A1
问题
我的代码无法识别第二种格式的 white space。
当我验证第二种格式时,它会打印 "Invalid"
两次,即使它是合法的邮政编码。
代码
public class validatePostalCodeTest {
public static void main(String[] args) {
Scanner kb = new Scanner(System.in);
System.out.println("Please enter postalcode:");
while (kb.hasNext()){
String posCode = kb.next();
if (posCode.length() > 7)
System.out.println("\nInvalid");
if (posCode.length() < 6)
System.out.println("\nInvalid");
if (posCode.length()== 7){
boolean valid = true;
for (int i = 0; i < posCode.length(); i++){
char a = posCode.charAt(0);
char b = posCode.charAt(2);
char c = posCode.charAt(4);
char d = posCode.charAt(1);
char e = posCode.charAt(5);
char f = posCode.charAt(6);
char g = posCode.charAt(3);
if(! Character.isLetter(a))
valid = false;
else if (! Character.isLetter(b))
valid = false;
else if (! Character.isDigit(c))
valid = false;
else if (! Character.isDigit(d))
valid = false;
else if (! Character.isLetter(e))
valid = false;
else if (! Character.isDigit(f))
valid = false;
else if (! Character.isWhitespace(g))
valid = false;
break;
}
if (valid) System.out.println("\nValid");
else System.out.println("\nInvalid");
}
if (posCode.length()== 6){
boolean valid = true;
for (int i = 0; i < posCode.length(); i++){
char a = posCode.charAt(0);
char b = posCode.charAt(2);
char c = posCode.charAt(4);
char d = posCode.charAt(1);
char e = posCode.charAt(3);
char f = posCode.charAt(5);
if(! Character.isLetter(a))
valid = false;
else if (! Character.isLetter(b))
valid = false;
else if (! Character.isLetter(c))
valid = false;
else if (! Character.isDigit(d))
valid = false;
else if (! Character.isDigit(e))
valid = false;
else if (! Character.isDigit(f))
valid = false;
break;
}
if (valid) System.out.println("\nValid");
else System.out.println("\nInvalid");
}
System.out.println("\nPlease enter a postalcode:");
}
System.out.println("Program ending due to end-of-file");
}
}
我会在这里使用正则表达式:
boolean isPostalCodeValid (String postalcode) {
return postalcode.matches("^\w\d\w\d\w\d|\w\d\w\s\d\w\d$"));
}
此处演示:
public class validatePostalCodeTest {
public static void main(String[] args) {
Scanner kb = new Scanner(System.in);
System.out.println("Please enter a Postcode:");
while (kb.hasNext()){
String posCode = kb.next();
if (posCode.length()== 7){
boolean valid = true;
char a = posCode.charAt(0);
char b = posCode.charAt(2);
char c = posCode.charAt(4);
char d = posCode.charAt(1);
char e = posCode.charAt(5);
char f = posCode.charAt(6);
char g = posCode.charAt(3);
if(! Character.isLetter(a))
valid = false;
else if (! Character.isLetter(b))
valid = false;
else if (! Character.isLetter(c))
valid = false;
else if (! Character.isDigit(d))
valid = false;
else if (! Character.isDigit(e))
valid = false;
else if (! Character.isDigit(f))
valid = false;
else if (! Character.isWhitespace(g))
valid = false;
if (valid) System.out.println("\nValid");
else System.out.println("\nInvalid");
}
else if (posCode.length()== 6){
boolean valid = true;
char a = posCode.charAt(0);
char b = posCode.charAt(2);
char c = posCode.charAt(4);
char d = posCode.charAt(1);
char e = posCode.charAt(3);
char f = posCode.charAt(5);
if(! Character.isLetter(a))
valid = false;
else if (! Character.isLetter(b))
valid = false;
else if (! Character.isLetter(c))
valid = false;
else if (! Character.isDigit(d))
valid = false;
else if (! Character.isDigit(e))
valid = false;
else if (! Character.isDigit(f))
valid = false;
if (valid) System.out.println("\nValid");
else System.out.println("\nInvalid");
}
else{
System.out.println("\nInvalid Length");
}
System.out.println("\nPlease enter a Postcode:");
}
System.out.println("Program ending due to end-of-file");
}
}
请尝试上面logic.I已经优化了
您使用了kb.next()
,它将以space分隔读取数据,
因此,当您将邮政编码输入为 A1A 1A1
时,它将花费 2 次,第一个是 A1A
,第二个是 1A1
,因此您将获得 2 次无效输出,因为它需要 2时间数据有一个 space,所以你需要使用 nextLine() 它会帮助你解决你的问题,
检查下面已解决的答案
public class validatePostalCodeTest
{
public static void main (String[] args) throws java.lang.Exception
{
Scanner kb = new Scanner(System.in);
System.out.println("Please enter postalcode:");
String posCode = kb.nextLine();
if (posCode.length() > 7)
System.out.println("\nInvalid");
if (posCode.length() < 6)
System.out.println("\nInvalid");
if (posCode.length()== 7){
boolean valid = true;
char a = posCode.charAt(0);
char b = posCode.charAt(2);
char c = posCode.charAt(4);
char d = posCode.charAt(1);
char e = posCode.charAt(5);
char f = posCode.charAt(6);
char g = posCode.charAt(3);
if(! Character.isLetter(a))
valid = false;
else if (! Character.isLetter(b))
valid = false;
else if (! Character.isDigit(c))
valid = false;
else if (! Character.isDigit(d))
valid = false;
else if (! Character.isLetter(e))
valid = false;
else if (! Character.isDigit(f))
valid = false;
else if (! Character.isWhitespace(g))
valid = false;
if (valid) System.out.println("\nValid");
else System.out.println("\nInvalid");
}
if (posCode.length()== 6){
boolean valid = true;
char a = posCode.charAt(0);
char b = posCode.charAt(2);
char c = posCode.charAt(4);
char d = posCode.charAt(1);
char e = posCode.charAt(3);
char f = posCode.charAt(5);
if(! Character.isLetter(a))
valid = false;
else if (! Character.isLetter(b))
valid = false;
else if (! Character.isLetter(c))
valid = false;
else if (! Character.isDigit(d))
valid = false;
else if (! Character.isDigit(e))
valid = false;
else if (! Character.isDigit(f))
valid = false;
if (valid) System.out.println("\nValid");
else System.out.println("\nInvalid");
}
System.out.println("Program ending due to end-of-file");
}
}
让我们从简化代码开始。
你的循环最多只执行一次一次,因为你在它们的末尾有一个break
,这确实提出了一个问题,为什么要费心有循环吗?
您描述的加拿大邮政编码格式,一般形式为:
/[A-Z]\d[A-Z]\d[A-Z]\d/
没有 space,并且
/[A-Z]\d[A-Z]\s\d[A-Z]\d/
...其中[A-Z]
表示大写字符类A到Z,\d
表示0到9的数字,\s
表示a白色space字符。我知道您没有使用正则表达式,但这就是我计划表示您需要解决的数据的方式。
让我们从简化没有 space 的案例开始。那是你的整个第二个循环。我们从 next
切换到 nextLine()
开始,以便在我们的扫描仪中使用。
String posCode = kb.nextLine();
现在,我们只想读入整行并检查其长度。如果等于 6,我们继续 - 您的代码已经这样做了。
if(posCode.length() == 6) {
// validation logic
}
现在是棘手的部分。你还记得我上面提到的正则表达式吗?碰巧他们有一个模式:
- 偶数位字符必须是从 A 到 Z 的字符。
- 奇数位字符必须是 0 到 9 之间的数字。
这样,我们就可以构造一个循环,根据这个逻辑为我们检查一些东西。注意 Character.isLetter
和 Character.isDigit
.
for(int i = 0; i < posCode.length(); i++) {
if(i % 2 == 0) { // even digits
if(!Character.isLetter(posCode.charAt(i))) {
// reject!
System.out.println("Invalid!");
break;
}
} else { // odd digits
if(!Character.isDigit(posCode.charAt(i))) {
// reject!
System.out.println("Invalid!");
break;
}
}
}
实际上,这就是您需要做的全部。 whitespace字符是特例,跳过即可轻松忽略
int spaceLocation = posCode.indexOf(" ");
if(spaceLocation != -1) {
// carve the space out and concatenate
posCode = posCode.substring(0, spaceLocation) + posCode.substring(spaceLocation + 1, posCode.length());
}
通过上述操作,您只需要一种方法,就可以成功验证两种情况。
您可以减少很多 if-else
语句并减少代码行数。
以下代码与您的逻辑相同,它会按照您的意愿检查邮政编码:
public class validatePostalCodeTest {
public static void main(String[] args) throws java.lang.Exception {
Scanner kb = new Scanner(System.in);
System.out.println("Please enter postalcode:");
char charPC[] = kb.nextLine().toCharArray();
boolean valid = false;
if (charPC.length == 7) {
if (Character.isLetter(charPC[0]) && Character.isLetter(charPC[2]) && Character.isLetter(charPC[5])
&& Character.isDigit(charPC[4]) && Character.isDigit(charPC[1]) && Character.isDigit(charPC[6])
&& Character.isWhitespace(charPC[3])) {
valid = true;
}
}
else if (charPC.length == 6) {
if (Character.isLetter(charPC[0]) && Character.isLetter(charPC[2]) && Character.isLetter(charPC[4])
&& Character.isDigit(charPC[1]) && Character.isDigit(charPC[3]) && Character.isDigit(charPC[5])) {
valid = true;
}
}
if (valid)
System.out.println("\nValid");
else
System.out.println("\nInvalid");
System.out.println("Program ending due to end-of-file");
}
}
为什么不使用正则表达式?
加拿大邮政编码作为正则表达式
你给定的两种加拿大邮政编码格式都有一个模式。这可以表示为 regular expression (regex):
regex | example match | variant |
---|---|---|
[A-Z]\d[A-Z]\d[A-Z]\d |
A1A1A1 |
without spaces |
[A-Z]\d[A-Z]\s\d[A-Z]\d |
A1A1 A1 |
with a space between parts |
其中:
[A-Z]
表示大写字母A到Z\d
表示0到9的数字\s
表示一个空白字符
改进正则表达式,测试demo on regex101:
^[A-Z]\d[A-Z]\d\s?[A-Z]\d$
- 用
^
和$
包围正则表达式以匹配从开始 (^
) 到结束 ($
) 的完整行
- 在
\s
上添加的 qunatifier 表示 零或一个 空格 (\s?
)。 也可以通过使用贪婪量词*
来替换零或多个(任意)。
将此正则表达式与 String.matches(regex)
一起使用,您可以轻松验证:
public static boolean isValidCanadianPostcode(String input) {
return input.matches("^[A-Z]\d[A-Z]\d\s?[A-Z]\d$");
}
注意:对于 Java 字符串中的正确正则表达式,我们需要用另一个反斜杠转义每个反斜杠(例如 \s
变为 \s
)。