メールアドレスを登録してもらったり削除してもらったりするプログラムです。
.datファイルに登録されたメールアドレスが1行づつ入ってます(改行付き)
重複チェックをする部分がよくわかりません。
チェックしたいメールアドレスを$mailに入れてます。
登録時、重複してないかチェックする時に
.datファイルを@allbodyに読み込んで
foreach $line (@allbody){
if ($line =~ /$email/){
&error("そのメールアドレスは登録済みです");
}
とすると出来てるようです。
これが削除時の場合
foreach $line (@allbody){
if (!($line =~ /$email/)){
&error("そのメールアドレスは登録されてません");
}
とすると出来ません。
登録されてようがされてなかろうが、登録されてません、と表示されます。
そもそも登録時の時できてると思ってるのが間違いなんでしょうか?
どうすればうまくいくか教えて下さい。
No.4ベストアンサー
- 回答日時:
> よくわからないのが「@allbodyの全要素と比較すれば一致しないことがあるのは当たり前」という事です。
なんでなんでしょう??
説明がちょっと簡潔過ぎましたね。
ある値が配列に「含まれていない」ことを確認するには、その値を配列の全要素と比較し、どの要素とも一致しないことを調べる必要があります。しかし、質問で書かれた方法は、ある要素と一致しなかった時点で「含まれていない」と判断してしまっているのです。
例えば、登録済みのアドレスが「abc@example.com」と「def@example.com」の2件あったとしましょう(この2件が @allbody に入ります)。また、そのうちの abc@ の方を削除するものとしましょう(abc@ のアドレスが $email に入ります)。
まず、foreach $line (@allbody){ によって $line に abc@example.com が入ります。次に if (!($line =~ /$email/)){ で比較しますが、$line と $email は同じ値なのでエラーにはなりません。
しかし、ループの2回目では $line に def@example.com が入ります。もちろん、$email とは一致しないので、&error が実行されてしまいます。
せっかくループの1回目で「含まれていること」を確認できたのに、これでは元も子もありません。また、削除したいのが def@ の方だったなら1回目でエラーとなってしまうので、含まれていることすら確認できません。
このように、ループ内の条件判断だけで「含まれていないこと」を調べることはできないのです。しかし、逆の「含まれていること」を調べるにはそれで十分なので、No.2 で示した方法ではそれを利用し、含まれていないこと(!含まれている)を調べたのです。
ちなみに、No.3 で BLUEPIXY さんが書かれている「ハッシュ」を使うと、No.2 の is_registered は次の用に書き換えられます。
sub is_registered {
my $test = shift;
my %entry = map {$_=>1} @_;
return $entry{$test};
}
アルゴリズムに関する質問だと思ったので敢えて書きはしなかったのですが、確かにこの方法の方が簡単ですね。
再度の回答ありがとうございます。
何度も何度も読んでやっと良く理解できました。
どうも私はforeachの動きをよく理解してなかったようです。(ってかforeachの中にif(‥を入れた場合の動きを理解してなかったのかな)
foreach $line (@allbody){
print "$line"
}
とすれば@allbody全てプリントしてくれるって本に書いてあったので、そこで脳がストップしてたみたいです。
私の脳に足りないのはフラグです。以前にもご教授いただいたんですがフラグ。もっとうまくフラグを使えるよう(思いつけるよう)頑張ります。
わかりやすい説明をありがとうございました。%まで‥‥。
お時間をさいていだたいた分、頑張りたいと思います。
No.3
- 回答日時:
このような処理をする場合は、ハッシュを使うのが簡単だと思います。
%ですか‥‥
実は苦手で一度も使った事ないんです‥‥難しそうでしょう。
でも苦手とか言ってる場合じゃないですよねぇ。
アドバイスをもらって、私程度がやりたい事でも%を使えば簡単にできるという事がわかったので、これを機に勉強してみよう(かなぁ‥‥)と思ってみました。
アドバイスありがとうございました。
No.2
- 回答日時:
まず、メールアドレスのような完全形のチェックが必要なものに、パターンマッチを使うのはやめましょう。
例えば、「hoge@example.com」というアドレスで登録しようとした時、それを「含む」アドレス(例えば「fuga-hoge@example.com」など)が既に登録されていると、登録済みと判断されてしまいます。もちろん、そのようなことがないように正規表現を書けば済むのですが、Perl には文字列の一致、不一致を調べる eq や ne があるので、普通はそちらを使います。
本題ですが、削除時のチェックがうまく行かないのは、全てのアドレスと比較してしまっているからです。もし、$email がちゃんと登録されているアドレスだったとしても、@allbody の全要素と比較すれば「一致しないことがある」のは当たり前です。
このような場合はループの途中で判断しようとせず、ループとフラグを使って「登録されていること」を調べるようにします。
$registered = 0;
foreach $line (@allbody) {
if ($line eq $email) {
$registered = 1;
last; # 登録されているのが分かったので、これ以上調べなくてもよい。
}
}
if (!$registered) {
error("そのメールアドレスは登録されてません");
}
また、登録時にも同じことを調べているので、これを 「$registered を返す関数」として定義し、両方で使い回すとよいでしょう。
sub is_registered {
my ($test, @entry) = @_;
foreach my $item (@entry) {
if ($test eq $item) {
return 1;
}
}
return 0;
}
# 登録時の重複チェック
if (is_registered($email, @allbody)) {
error("そのメールアドレスは登録済みです");
}
# 削除時の登録チェック
if (! is_registered($email, @allbody)) {
error("そのメールアドレスは登録されてません");
}
※インデントに全角空白を使っているので、コピーする場合はタブなどに置換して下さい。
さっそくの回答ありがとうございます。
とてもわかりやすい説明うれしく思います。
パターンマッチを使ってはいけない理由など、とても納得しました。
よくわからないのが「@allbodyの全要素と比較すれば一致しないことがあるのは当たり前」という事です。
なんでなんでしょう??
一致した時点で一度ループを抜ければ良いのかなぁ、というのはわかりました。でもその理由がわからないのです。
よろしければ、もう一度そのあたり教えていただけませんか。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Gmail チャットGPTの登録ができない 1 2023/03/07 02:43
- その他(IT・Webサービス) クレカの認証ワンタイムパスワードが送られてこない 1 2022/10/18 20:29
- PHP PHP MySql 画像を取得 1 2022/06/04 14:05
- 病院・検査 木下グループ新型コロナPCR検査キットを購入して月曜日にポスト投函しました ですが、その際に会員登録 1 2023/01/20 21:36
- メルカリ メルカリ新規登録 1 2023/07/07 18:21
- ハッキング・フィッシング詐欺 OKWAVEのログインと会員登録と新規登録 1 2023/04/10 17:09
- LINE 還暦過ぎの爺さんに分かりやすく教えて欲しいんじゃが。LINEを始めるのにスマホが必要なのかのぅ? 2 2023/01/07 11:44
- LINE LINE登録で相手に知られる個人情報は何ですか? 3 2023/03/17 16:59
- その他(スマートフォン・携帯電話・VR) 某信用金庫の通帳アプリ 4 2023/04/09 11:01
- 電子マネー・電子決済 Visa LINE Pay P+を作りました。 カードレスで、すぐに作れました。 vpassに登録し 1 2023/08/19 23:12
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
1コールだけ鳴るけど切れる電話...
-
相手側の携帯が電源切れてる時...
-
ラインナップとラインアップは...
-
Windowsのバッチファイルで正規...
-
生産ラインの品質を表す直行率...
-
いきなりラインのトークに「新...
-
face book で女性の方からline ...
-
LINE追加で「該当するユーザー...
-
ある男子から、ライン追加され...
-
よく05(04)lineって見かけるん...
-
既婚女性にラインを聞くことに...
-
遠くにいる友達とLINE交換する...
-
python2.6で「cv2」のNameerror...
-
グループラインから個人宛に
-
半年付き合ってきた彼女をブロ...
-
「一点鎖線」を英語でいうと?
-
lineのワン切り、なぜ?
-
まだそんなに親しくない相手と...
-
あの噂の世界三大チェーンメー...
-
「一番上、真ん中、下」を示す英語
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
1コールだけ鳴るけど切れる電話...
-
相手側の携帯が電源切れてる時...
-
LINE追加で「該当するユーザー...
-
よく05(04)lineって見かけるん...
-
いきなりラインのトークに「新...
-
face book で女性の方からline ...
-
ラインナップとラインアップは...
-
Windowsのバッチファイルで正規...
-
遠くにいる友達とLINE交換する...
-
ある男子から、ライン追加され...
-
生産ラインの品質を表す直行率...
-
質問です。 先日クラスの女子に...
-
既婚女性にラインを聞くことに...
-
lineのワン切り、なぜ?
-
「一番上、真ん中、下」を示す英語
-
python flask から fastapiへの...
-
LINEで好きな人が「笑」を全然つ...
-
まだそんなに親しくない相手と...
-
先輩のライン(男性)を追加した...
-
スマホに外国の電話番号を登録...
おすすめ情報