• 締切済み

更新記録CGIで「前へ」「次へ」の記事を出す方法

更新記録CGI(perl)を利用して、それを改造したいと思っています。 記事は1つだけ表示して、記事下に「←次へ」「前へ→」のようなリンクを作って前後に移動したいです。 素人考えで以下のようにしました。 $no =5; (現在の記事NO。数字が入ります) $new_no = $no--; $old_no = $no++; print "<a href=\"news.cgi?vno=$new_no\">「←次へ」</a>\n"; print "<a href=\"news.cgi?vno=$old_no\">「前へ→」</a>\n"; しかしこれだと、2つの問題が発生します。 1.最新記事・最古の記事の次または前ページが存在しないのに行ってしまう。 2.何らかの理由で記事を消した場合でもそこに行ってしまう。 この2点を回避するにはどうしたら良いでしょうか? $no =5; open(IN,"$logfile") || &error("Open Error : $logfile"); while (<IN>) { ($no,$year1,$month1,$day1,$name,$tail1,$W1,$H1,$item1,$item2,$item3,$item4,$item5,$host) = split(/<>/); <<<--- どうにかして、この記事の次記事があるかを判別する --->>> if($new_no){ print "<a href=\"news.cgi?vno=$new_no\">「←次へ」</a>\n"; }else{ print "<font color=#aaaaaa>「←次へ」</font>\n"; } <<<--- どうにかして、この記事の前記事があるかを判別する --->>> if($old_no){ print "<a href=\"news.cgi?vno=$old_no\">「前へ→」</a>\n"; }else{ print "<font color=#aaaaaa>「前へ→」</font>\n"; } このようにしたいのですが、方法を教えてください。

  • Perl
  • 回答数4
  • ありがとう数10

みんなの回答

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.4

> これをしたいのですが、どのように記述したら良いかがわからないほどの初心者です それなら、まずは、このやり方に見当がつくくらいの勉強をしてからの方がよいのでは? ・テキストファイルを全部リストに入れる方法 ・リストの並び換えの方法(sort関数のちょっと高度な使い方) などは、初級の入門書にも載っていると思います。 ※ 他にも 「3行だけ記録して、真ん中が該当行だったら前後の記事番号を使う」 「注目記事番号未満のうちの最大値と、注目記事番号超のうちの最小値を求める」 等の手法もあります。 それから、++ / -- はちゃんと理解してください。 単に「1減らした数」ということにはなりません。 変数の前に書いたときと後に書いたときとの違いも重要です。 理解できていないのなら、使わない方がいいくらいです。 $new_no=$no++;#新しい記事だから現記事より+1 とありますが、 後に置いた場合の ++ は ・まず、元の値を使用する ・使った後でその変数自体を+1する という効果があります。つまり、この文は { $new_no=$no; $no=$no + 1 ; } とほぼ同じことになります。同様に $old_no=$no--;#古い記事だから現記事より-1 は { $old_no=$no ; $no = $no - 1 ; } です。 では、最初に$no=5として $new_no=$no; #=> $new_no = ? $no=$no + 1 ; #=> $no = ? $old_no=$no ; #=> $old_no = ? $no = $no - 1 ; #=> $no =? としたら、それぞれどうなりますか? 上の?をそれぞれ埋めてみてください。

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.3

> ログファイル開く→現ページを確認→それに+1と-1した数字を作る→whileでヒットしたところを表示 考えていけば、いくらでも方法はありますが、とりあえずは、その方針でいいのでは? あとは、ちょっとしたアイディアだけです。 例えば: ○「数字を作る」のではなくて、-1番目、+1番目を探す。 全行を記事番号順にソートして、 @l に保存 $l[$i] が$noの記事なら、 $l[$i-1] と $l[$i+1]が目的の「前後の記事」。 $i==0なら「前の記事」は無いし、$i+1と@lの長さを比較すれば「後の記事」が存在するかどうか判定できる 他にも: 前の記事番号 = $noより小さい記事番号の最大値 後の記事番号 = $noより大きな記事番号の最小値 であることに注目する それ以前の問題として、no++/no--では期待する番号になっていない、というのは、既に指摘のある通りです。

master-3rd
質問者

補足

返答ありがとうございます。 >全行を記事番号順にソートして、 @l に保存 >$l[$i] が$noの記事なら、 $l[$i-1] と $l[$i+1]が目的の「前後の記事」。 これです!これをしたいのですが、どのように記述したら良いかがわからないほどの初心者です。 出来れば具体的にどうしたら良いかを教えていただけるととてもうれしいです!

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

「プログラムがあるからデータ構造もわかるだろ」ってのは, 質問としては乱暴だなぁ. 現実的な問題として どうもきちんとデータか読めないと思ったら, 実はプログラムが間違ってました ってこともあるわけなので, データ構造はデータ構造として書いておくべきだと思うよ. さておき, 大事なことを聞き忘れていました. ・「削除」すると, データとしてはどうなるんですか? 当該行が消えるのか, それともどこかに「削除したよ」って情報が記録されるのか, あるいはそのどちらでもない別の方法で管理する? ・(こっちはさほど重要じゃないけど) 順番はどうなっていますか? いずれにしても方向性としては「適切なデータ構造を作る」ことになるわけだけど, その「適切なデータ構造」が条件によって変化する可能性はある. あと余談だけど, $vno が 5 のとき $new_no = $vno--; $old_no = $vno++; によって $vno, $new_no, $old_no の値がどうなるか答えられますか?

master-3rd
質問者

補足

返答ありがとうございます。 >データ構造はデータ構造として書いておくべきだと思うよ. すみません。そういう事以前に、何をどう記入したら良いかさえ分かっていない初心者なので、あのような書き込みになっていまいました。 細かく指示をもらえるととてもありがたいです。 >「削除」すると, データとしてはどうなるんですか? その行が消えます。 ログに、 5<>2014<>1<>1<>新着題名5<>~ 4<>2014<>1<>1<>新着題名4<>~ 3<>2014<>1<>1<>新着題名3<>~ 2<>2014<>1<>1<>新着題名2<>~ 1<>2014<>1<>1<>新着題名1<>~ とあって、4番目の記事を削除すると 5<>2014<>1<>1<>新着題名5<>~ 3<>2014<>1<>1<>新着題名3<>~ 2<>2014<>1<>1<>新着題名2<>~ 1<>2014<>1<>1<>新着題名1<>~ となります。 こういうログで、該当する記事を表示させたい場合、「~news.cgi?vno=5」のようにして、内部では、 while (<IN>) { ($no,$year1,$month1,$day1,$name,$tail1,$W1,$H1,$item1,$item2,$item3,$item4,$item5,$host) = split(/<>/); if ($in{'vno'} == $no) { print"$name<br>~\n"; } } で記事を探します。 この方式だと、$noに1をプラスマイナスした場合、消された記事に行ってしまうことになりますよね… >あと余談だけど, $vno が 5 のとき すみません、これも書き間違えですよね while (<IN>) { ($no,$year1,$month1,$day1,$name,$tail1,$W1,$H1,$item1,$item2,$item3,$item4,$item5,$host) = split(/<>/); if ($in{'vno'} == $no) { print"~\n"; $new_no=$no++;#新しい記事だから現記事より+1 $old_no=$no--;#古い記事だから現記事より-1 #↑この位置なら$in{'vno'}は使う必要なしですよね? } } で、 $vnoを5としたら $new_noは6、$old_noは4と思ってますが、間違ってないでしょうか? 今これを記入しながら少し考えたのですが、該当する記事番号が無ければさらに+1(-1)すると言うのはどうでしょう? 次・前のリンクをそれぞれ ~news.cgi?vno=$new_no&move=new ~news.cgi?vno=$old_no&move=old とし、 while (<IN>) { ($no,$year1,$month1,$day1,$name,$tail1,$W1,$H1,$item1,$item2,$item3,$item4,$item5,$host) = split(/<>/); if ($in{'vno'} == $no) { print"~\n"; $new_no=$no++;#新しい記事だから現記事より+1 $old_no=$no--;#古い記事だから現記事より-1 #↑この位置なら$in{'vno'}は使う必要なしですよね? #この位置に前後へのリンク }else{#該当記事が無ければ if($in{'move'} eq $new){ $vno++; &view; #この表示をするサブルーチンに戻る exit; } if($in{'move'} eq $old){ $vno--; &view; #この表示をするサブルーチンに戻る exit; } } … すごく回りくどいことをしているようにも思いますが… でも、これだと、最初の記事・最後の記事にたどり着いた際、おかしな挙動になりますよね… すみません、私の知識ではこの程度しか考えられません。 なんとなくレベルがわかっていただけるとうれしいです。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

まずもって ・各記事をどう保存しているのか を書いてくれないことには話にならない. あと, 「何らかの理由で記事を消した場合」にどうするのか (記事NO が 4 の記事を消した場合, 記事NO 3 の記事の「前」と「次」はそれぞれ何になるのか) も明確にしておく必要がある. ついでに: $no =5; (現在の記事NO。数字が入ります) $new_no = $no--; $old_no = $no++; で $no, $new_no と $old_no の値がそれぞれ何になるかわかりますか? $no =5; open(IN,"$logfile") || &error("Open Error : $logfile"); while (<IN>) { ($no,$year1,$month1,$day1,$name,$tail1,$W1,$H1,$item1,$item2,$item3,$item4,$item5,$host) = split(/<>/); # 以下略 } とやると最初の $no =5; の意味がなくなってしまうことは理解できていますよね?

master-3rd
質問者

補足

すみません色々抜けてました。 >各記事をどう保存しているのか datファイルに$no,$year1,$month1,$day1,$name,~ の順で、"<>"で区切って保存しています。 (open~while~の部分で理解していただけると思ったので記入したのですが、書き方が間違っていたでしょうか…) >記事NO が 4 の記事を消した場合, 記事NO 3 の記事の「前」と「次」はそれぞれ何になるのか 4を消した場合、3の記事の場合は5と2の記事に行くようにしたいです。 >no =5;の意味がなくなってしまう すみません書き間違えです。 ページを表示するのはvnoですね。 ~news.cgi?vno=5 で5記事目を表示します。 またそれぞれ $new_no = $vno--; $old_no = $vno++; です。 私のスキルでは、 ログファイル開く→現ページを確認→それに+1と-1した数字を作る→whileでヒットしたところを表示、としかできません。 それをどうにかして「ログの前後の記事を表示させる」としたいです。 引き続きよろしくお願いします。

関連するQ&A

  • 次のcgiファイルを開くには?

    すみません。初心者です。 001.cgi というファイルで フォーム に 正解を入力して Enterキー を 押したら 次の 002.cgi を 開く(実行する)ようにするには どうしたらよいでしょうか? 今は↓このようにして 「次のファイルへ」をクリックしてもらっています。 Enterキーを押すだけで 次の002.cgi (=$num2.cgi)へ行きたいのです。よろしく、お願いいたします。 #-------- if (param('answer') eq $ans){ print ('正解'); print ("<a href=$num2.cgi accesskey=]>次のcgiファイルへ (Alt+])</a> "); #--------

    • ベストアンサー
    • Perl
  • 記事の最後の次のページ、前のページ

    HTML5でHPを作ってるのですが、 1つ目の記事に関する内容を1つのページとして作成しました。 その作成した記事の最後に、前後のページのリンクを張りたいと考えています。 <考えている内容> 前のページへ    トップへ   次のページへ といったものを作成したいと考えているのですが、 どのように作るのが一般的なのでしょうか? <footer id="navi_footer"> <a href="リンク先">前のページへ</a> <a href="リンク先">トップへ</a> <a href="リンク先">次のページへ</a> </footer> では芸がないかな・・・。と思っています。 何か言い作り方等を知っている方がおられましたが ご教授よろしくお願いします。

    • ベストアンサー
    • CSS
  • URLに#を表示するには?

    初めまして。無料のCGI(掲示板)をDLして自分のHPで使用しているのですが「Res」ボタンをクリックするとスレッドの一番上に来てしまい、返信フォームが一番下にある為に使いづらいので改造を試みています。 とは言っても初心者なのでやり方自体が間違っているかもしれませんが。 返信フォーム付近に<a name=jump>タグを入力してあります、URLに「#jump」と手入力すれば思った事が出来るのですが以下のCGIにどの様に記述すれば良いのか教えてください。 print "<form action=\"$script\" method=GET>\n"; if($up_down){ print "<a href=\"#$mm[$x-1]\">▲前</a> <a href=\"#$mm[$x+1]\" class=\"ud\">▼次</a>"; $x++; } print "<input type=hidden name=mode value=new_html>\n"; print "<input type=hidden name=no value=$no>\n"; print "<input type=submit value='Res'> &nbsp; </td></form>\n"; 下から2行目の「=$no」の後に「#jump」と記述すると「#」が「%23」になってURLが出てきます。 これをURLで「#jump」と表示されるようにしたいのです。 下手くそな説明で申し訳ありませんがよろしくお願いします。

    • ベストアンサー
    • Perl
  • 掲示板(kentさんの所のsunbbs)に1分おきにリフレッシュする方法

    kentさんの所の掲示板のsunbbsについてです。 自動で掲示板を1分おきとか2分おきに自動更新する方法を 探しています。 リフレッシュの文を入れればいいのかもしれませんが どこにどのようにいれればいいのか分かりません。 よろしくお願いします。 下に関係のありそうなところをコピーいたします。 違うかもしれませんが。 #------------------------------------------------- # HTML生成処理 #------------------------------------------------- sub html_regist { local($i,$next,$back,$data); local($file,$page) = @_; open(WR,">$file") || &error("Write Error: $file"); print WR &header('HTML'); # リンク部 print WR "<B><font color=\"$p_color\">$point2</font>"; print WR "<a href=\"$home\" target=\"_top\">Home</a>\n"; if (!$whatsnew) { print WR "<font color=\"$p_color\">$point</font>"; print WR "<a href=\"$script?mode=form\">Post</a>\n"; } print WR "<font color=\"$p_color\">$point</font>"; print WR "<a href=\"$script?mode=find\">Search</a>\n"; # 過去ログ if ($pastkey) { print WR "<font color=\"$p_color\">$point</font>"; print WR "<a href=\"$script?mode=past\">Log</a>\n"; } print WR "<font color=\"$p_color\">$point</font>"; print WR "<a href=\"$script?mode=admin\">Admin</a></B>\n<div align=center>\n"; # タイトル部 if ($t_gif eq '') { print WR "<font color=\"$t_color\" size=6><b style=\"font-size:$t_size\">$title</b></font>\n"; } else { print WR "<img src=\"$t_gif\" width=$tg_w height=$tg_h alt=\"$title\">\n"; } # ひとことメッセージを表示 $message =~ s/\r\n/<br>/g; $message =~ s/\r/<br>/g; $message =~ s/\n/<br>/g; print WR "<P>$message</div><hr>\n"; # 記事を展開 if ($page == 2) { $next = $pagelog+1; $last = $max; } else { $next = 0; $last = $pagelog; } $i=0; open(IN,"$logfile") || &error("Open Error: $logfile"); while ($data = <IN>) { $i++; if ($i < $next) { next; } if ($i > $last) { last; } print WR &log_view($data, $page); } close(IN); if (!$whatsnew) { print WR "<table align=left><tr>\n"; } # 次/前ページのリンクを生成 if (@lines > $pagelog && $page == 1) { print WR "<td><form action=\"$htm_url$nexthtm\">"; print WR "<input type=submit value=\"次ページ\"></td></form>\n"; } elsif (@lines > $pagelog && $page == 2) { print WR "<td><form action=\"$htm_url$htmfile\">"; print WR "<input type=submit value=\"前ページ\"></Td></form>\n"; } print WR "</table>\n"; # 削除フォーム if (!$whatsnew) { print WR "<table align=right><tr><td>\n"; print WR "<form action=\"$script\" method=\"POST\">\n"; print WR "記事No <input type=text name=no size=4>\n"; print WR "削除キー <input type=password name=pwd size=4>\n"; print WR "<input type=hidden name=mode value=userdel>\n"; print WR "<input type=submit value='記事削除'></td></form></table><br clear=all>\n"; } # 著作権を表示(削除不可) print WR "<div align=center style='font-size:10px;font-family:Verdana,Helvetica,Arial'><!-- $ver -->\n"; print WR "- <a href='http://www.kent-web.com/' target='_top'>SunBoard</a> -\n"; print WR "</div>\n</body>\n</html>\n"; close(WR); }

    • ベストアンサー
    • CGI
  • テキストファイルを読んで次のcgiファイルを動かすには?

    お願いします。初心者です。 0001.cgi で 正解 Einstein を Send すると  file.txt に -1 と書き込むようにしました。 さらに  0002.cgi へのリンクが出て、これをクリックすると 0002.cgi が動くようにしました。  そして、 file.txt に -1 が ない場合に 0002.cgi が動き始めないようにしようとしています。 0001.cgi の問題に正解しないと、0002.cgi へ行けない ようにしようとしています。どうしたらよいのでしょうか? どうか、お教えください。 よろしく、お願いいたします。 0001.cgi は、こんなふうになっています。 ↓ ---------------------------------------- print header; # -------------------------------------- print start_html('0001'); #ここに問題を入れました 答は Einstein です。 print startform( -method => 'POST', -action => '0001.cgi' ); print blockquote( textarea( -name => 'die Antwort', -rows => '3', -columns => '40' ) ); print br; print submit(-value => 'Send'); print reset; print endform; # -------------------------------------- if (param('die Antwort') eq 'Einstein'){ print h2('Einstein'); print h2('<a href="0002.cgi">next page</a>'); open(FILE, '>>file.txt') or die "$!"; print FILE ("-1"); close(FILE) } else{ print h3('false'); } # -------------------------------------- print end_html; # --------------------------------------

    • ベストアンサー
    • CGI
  • a.cgi → b.cgiへデータの受渡し方法

    a.cgi → b.cgiへデータの受渡しを行いたいのですが i-modeのHPで,画面入力させた内容を a.cgi → b.cgiに受け渡す方法を教えて下さい。 例?:a.cgiに下記のコーディングでは無理ですよね・・・ $aa=$FORM{'aa'}; print "Location: http:・・・・・i/b.cgi?a=$aa\n\n";

    • ベストアンサー
    • Perl
  • 次のページ・前のページにタイトルを表示させたい

    よろしくお願いします。 無料のFC2ブログを独学で始めたばかりです。 共有テンプレートを使わせて頂いて、HTMLを少し変更したりしましたが、基本的なことはわかりません。 ブログの記事の外に、 「前のページ  HOME  次のページ」 というのがありますが、 「(前の記事のタイトル)  HOME  (次の記事のタイトル)」 というように、記事のタイトルを表示したいのですが、 HTMLで「前の記事」の所をどのように変えたら良いのか教えて頂けないでしょうか。 以下のようになっています。 <!--─────────■次のページ・前のページ ────────────────────────────--> <div class="page_navi"> <!--permanent_area--> <!--preventry--> <a href="<%preventry_url>"> &laquo; <%preventry_title></a> <!--/preventry--> <a href="<%url>">&nbsp;<%template_home>&nbsp;</a> <!--nextentry--> <a href="<%nextentry_url>"><%nextentry_title> &raquo; </a> <!--/nextentry--> <!--/permanent_area--> <!--not_permanent_area--> <!--prevpage--><a href="<%prevpage_url>"><!--/prevpage-->&laquo;-次のページ-<!--prevpage--></a><!--/prevpage--> <a href="<%url>">&nbsp;-HOME-&nbsp;</a> <!--nextpage--><a href="<%nextpage_url>"><!--/nextpage-->-前のページ-&raquo;<!--nextpage--></a><!--/nextpage--> <!--/not_permanent_area--> </div><!--──────■次のページ・前のページここまで-->

  • PHPでパスの作成方法に関して

    教えて下さい。 あるファイルを開こうと考えていますが、ファイル名をその都度変更したい為、 変数に格納してあり、その変数を使ってパスを作成しようと考えています。 以下のような記述をしましたが、正しくパスを生成してくれません。 どのような記述をすれば良いでしょうか? 初歩的な質問で申し訳ありませんが、教えて下さい。 <?php print("<TABLE BORDER='0'>\n"); print("<TR>\n"); print("<td width='100' height='20'><font size='2'><A Href='//192.999.999.999/doc/'.'$tmp_no'.'.pdf' Target='_blank'>AAAAA</A></font></td>\n"); print("</TR>\n"); print("</TABLE>\n"); ?> ※ $tmp_noに値が格納されています。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • CGIにおいて、エンコード・文字化けの対処方法

    以下のようにCGIを記述しております。(本日勉強したてで間違いだらけでしたら申し訳ございません。) ============= #!/usr/local/bin/perl print "Content-type: text/html; charset=EUC-JP\n"; print "\n"; print "<html>\n"; print "<title>Hello CGI</title>\n"; print "<body>\n"; print "<h1>Hello CGI!</h1>\n"; print "<hr>\n"; print qq( 上記のCGIファイルのメッセージは、次のように記述しました。<br><br> #!/usr/local/bin/perl<br><br> print "Content-type: text/html\\n";<br> print "\\n";<br> print "&lt;html&gt;\\n";<br> print "&lt;title&gt;Hello CGI&lt;/title&gt;\\n";<br> print "&lt;body&gt;\\n";<br> print "&lt;h1&gt;Hello CGI!&lt;/h1&gt;\\n";<br> print "&lt;/body&gt;";<br> print "&lt;/html&gt;";<br><br> ); print "</body>"; print "</html>"; =========== 以上をIE7で表示しますと、エンコードが西ヨーロッパ言語になって文字化けを起こしてしまいます。 何か記述の仕方が間違っているのでしょうか。 よろしくお願いいたします。

    • ベストアンサー
    • CGI
  • CGIのカスタマイズについて

    ネットレスキューさんの簡易データベースについて search.cgiの表示部分でテーブルを一つずつ生成させようと思ったのですがエラーが出ます。 どこが悪いのでしょうか? ----------ここから------- foreach $data (@NEW) { ($d,$DATE,$PREF,$NAME,$EMAIL,$HURL,$AGE,$HANDLE,$REM) = split(/\,/,$data); print "<table width="450" border="0" cellspacing="0" cellpadding="0" class="p12_16">\n"; print "<tr>\n"; print "<td colspan="2" bgcolor="#CC0033" height="14"><font color="#FFFFFF">● $NAME</font></td>\n"; print "</tr>\n"; print "<tr>\n"; print "<td width="70">地域</td>\n"; print "<td width="380">$PREF</td>\n"; print "</tr>\n"; print "<tr>\n"; print "<td height="14">Eメール</td>\n"; print "<td><a href=\"mailto:$EMAIL\">$EMAIL</a></td>\n"; print "</tr>\n"; ---中略---- print "<td height="14">内容</td>\n"; print "<td>$REM</td>\n"; print "</tr>\n"; print "</table>\n"; if ($next_num ne '') { while (($key,$val) = each %FORM2) { if ($key ne 'FF') { $buf = "$buf&$key=$val"; } } print "<h3>↓<a href=\"search.cgi?$buf&FF=$next_num\">次の$page件</a></h3>\n"; } } print "</body></html>\n\n"; exit; --------------ここまで----- splitの扱い方が良く分っていません。 御存知の方御指導下さいませ。

    • ベストアンサー
    • CGI

専門家に質問してみよう