CODE Polyglot / 入門 / 第7回

入力チェック — 郵便番号の形を確かめる

受け取った文字列が郵便番号の形(半角の数字3桁・ハイフン・4桁、またはハイフンなし7桁)かを確かめます。全角の「123」を数字として通してしまう言語があります。

画面にこう出れば正解

どの言語で書いても、同じ入力なら画面に出る文字は1文字も違わない、というのが正解の決め方です(例は Python で動かしたときのコマンドです)。

ハイフンあり

$ python3 zipcode.py 123-4567
OK: 123-4567

ハイフンなし

$ python3 zipcode.py 1234567
OK: 123-4567

桁が足りない

$ python3 zipcode.py 123-456
NG: 郵便番号は半角の数字7桁で入力してください(例 123-4567)

全角の数字

$ python3 zipcode.py 123-4567
NG: 郵便番号は半角の数字7桁で入力してください(例 123-4567)

全角の数字(ハイフンなし)

$ python3 zipcode.py 1234567
NG: 郵便番号は半角の数字7桁で入力してください(例 123-4567)

文字が混ざる

$ python3 zipcode.py 12a-4567
NG: 郵便番号は半角の数字7桁で入力してください(例 123-4567)

前後に空白

$ python3 zipcode.py "123-4567 "
NG: 郵便番号は半角の数字7桁で入力してください(例 123-4567)

10言語のプログラム

どれもそのまま保存して動かせます。毎朝、上の正解の例をすべて実際に動かして確かめています。

zipcode.php8.4.26 で 7 / 7 件の出力が正解と一致

<?php
// 郵便番号の形(数字3桁・ハイフン・4桁、またはハイフンなし7桁)かを確かめる
$s = $argv[1];
// 半角の数字だけを受け付けるように、\d ではなく [0-9] と書く。\z は「本当の終わり」($ は末尾の改行の前にも合う)
if (preg_match('/\A[0-9]{3}-?[0-9]{4}\z/', $s)) {
    $digits = str_replace('-', '', $s);
    echo "OK: " . substr($digits, 0, 3) . "-" . substr($digits, 3) . "\n";
} else {
    echo "NG: 郵便番号は半角の数字7桁で入力してください(例 123-4567)\n";
}

動かし方(ファイルを保存したフォルダで) ・ PHP を入れる

$ php zipcode.php 123-4567

言語でつまずきやすいところ

初心者がよく書く形(各言語で最初に習う書き方をそのまま使ったもの)を、同じ正解表で動かした結果です。言語を出した答えごとにまとめ、赤い字はその言語が実際に出した間違った行です。

入力初心者がよく書く形の答え(10言語)
ハイフンあり123-4567

✓10言語すべて正解

ハイフンなし1234567

✓10言語すべて正解

桁が足りない123-456

✓10言語すべて正解

全角の数字123-4567

✓10言語すべて正解

全角の数字(ハイフンなし)1234567
  • Python・C#・Rust・SwiftOK: 123-4567
  • PHP・Go・JavaScript・Java・Ruby・Kotlin✓ 正解
文字が混ざる12a-4567

✓10言語すべて正解

前後に空白"123-4567 "

✓10言語すべて正解

この回でやること

  • 文字列が決まった形に合うかを、正規表現で確かめる
  • 合っていれば形をそろえて出し、合っていなければ理由を出す

解説

正規表現

^[0-9]{3}-?[0-9]{4}$ は「先頭から、0〜9 の数字3つ、ハイフンは有っても無くてもよい、数字4つで終わる」という意味です。問い合わせフォームの入力チェックでよく使います。

\d は全角の数字にも合うことがある

数字を表す \d は、言語によって合う文字が違います。

言語\d が全角の「1」に合うか
Python・C#・Swift合う(あらゆる言語の数字に合う)
JavaScript・Java・Kotlin・Go・Ruby・PHP合わない(半角の 0〜9 だけ)

Rust には標準の正規表現がありません。1文字ずつ確かめるときに is_numeric() を使うと全角の数字も通るので、is_ascii_digit() を使います。

全角の数字を通してしまうと、そのあとの処理(数としての計算や、データベースへの保存)で困ることがあります。この回では \d ではなく [0-9] と書いて、半角だけを受け付けています。

前後の空白

コピーして貼り付けた値には、最後に空白が入ることがあります。この回では空白も「形が違う」として NG にしています。実際のフォームでは、確かめる前に空白を取り除く(trim)のが親切です。

練習

  1. 全角の数字を半角に直してから確かめるようにしてみましょう
  2. 電話番号(例 03-1234-5678)を確かめるプログラムを書いてみましょう