• ベストアンサー

perlのプログラミングについて

perlのプログラミングについて詳しい解説をお願いいたします。 sub list_reverce{ my $old=shift; my&new=undef; while (my $cur=$old){ $old=$old‐>[NEXT]; $cur‐>[NEXT]=$new; } return $new } 全くの初心者です。連結リストに対してのreverseなのですが、わかりません。 ご回答お願いいたします。

質問者が選んだベストアンサー

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

このプログラムは、おそらく期待通りの動きをしません。 ここに書かれた通りならプログラムが間違っています。あなたが入力したのなら、入力間違いしていると思われます。 使われている命令自体は、Perlの基礎です。 なので、個々の命令については理解はできているものとして、解説はしません。 「連結リスト」という、データ構造は理解できてますか? それを、このプログラムではどうやって実現させてますか?ハッシュ?クラス?リスト(データ構造としての連結リストではなく、Perlの機能としての)? $old = A→B→C→D→undef(終端判別用) となっているリストを $new = D→C→B→A→undef にして、$newを返す、というのが期待される動作だと思われます。 ここで「→」は A->NEXT = B となっていることを表現しています。 my&new=undef; は my $new=undef; の間違いでは。 連結リストにハッシュが使われているなら {'NEXT'} 等と{}を使います。 リストが使われているなら、どこかで use constant NEXT=>1 などとNEXTに値を設定しているはずです。 どちらが正しいか、あるいは、これ以外なのか、確認してください。 動作がわからないなら、コンピュータになったつもりで、自分で実際に実行してみましょう。 ・初期状態 undef($new) A($old)→B→C→D→undef ・whileループ A($cur,$old)→B→C→D→undef ・$oldを次の位置へ A($cur)→B($old)→C→D→undef ・$curの矢印を$newへ変更 undef($new)←A($cur) / B($old)→C→D→undef ・$newを変更: これが提示されてるプログラムに抜けている undef←A($cur, $new) / B($old)→C→D→undef ・whileの次のループ undef←A($new) / B($cur, $old)→C→D→undef ・$oldを次の位置へ undef←A($new) / B($cur)→C($old)→D→undef ・$curの矢印を$newへ変更 undef←A($new) ← B($cur) / C($old)→D→undef ・$newを変更 undef←A ← B($cur, $new) / C($old)→D→undef 以下同様。最終的に undef←A ← B← C ←D($new) / undef($cur, $new) でwhileの条件が偽→終了

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (1)

回答No.2

## 私も初心者でここでお世話になっていますので恩返しです。 ## 私のわかる範囲で書いてみました。参考になれば幸いです。 sub list_reverce{ ##サブルーチンの名称は list_reverce だよ、と言う意味 my $old=shift; ## 変数$oldをmy で宣言するとともに 引数からshift関数で代入している my&new=undef; ## なぞ? my $new=undef;のタイプミス(typoという)か?ならば変数$newを宣言し未定義値undefを代入し明示的に未定義にしている while (my $cur=$old){ ## $curが$oldの間処理を繰り返す $old=$old‐>[NEXT]; ## 先ほどのshiftした引数はリファレンスなのですね、そのリファレンスをデリファレンスした配列のNEXT番目を$oldに代入 $cur‐>[NEXT]=$new; ## $newを$curをデリファレンスした配列のNEXT番目に$newを代入 } return $new ## $newが戻り値 } ## 全体を見ないと[NEXT]と言うのがよくわかりません。 ## 以上私のわかる範囲で書いてみました。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • perlのクラスについて

    perlでクラスを作成しています。その際、コンストラクタnewで無名配列を定義して、funcメソッドで、この無名配列に値をいれるにはどうすればよいでしょうか? sub new { my $class = shift; my $self->array = []; bless($self, $class); return $self; } sub func { my $self = shift; $self->arrayに配列のデータを入れる。 }

    • ベストアンサー
    • Perl
  • オブジェクト指向プログラミング

    Perlのクラス定義の例題なんですが、わからないところがあります。 ファイルCapFile.pm package CapFile; sub new{ my $class = shift; my $path = shift; return(bless { ':path' => $path }, $class); } sub read { my $obj = shift; my $path = $obj->{':path'}; ..... ファイルcap-test #!/usr/bin/perl use CapFile; $cap = new CapFile ('/etc/termcap'); $cap->read(); ... サブルーチンreadにある my $path = $obj->{':path'}; なんですが、呼び出し側では引数がないのですが、$objには何が入っているんでしょうか。 そして$pathには何が入るんでしょうか。

    • ベストアンサー
    • Perl
  • Perl 強制終了の回避について

    Attempt to free unreferenced scalar とは? http://oshiete1.goo.ne.jp/qa4237453.html の続きです。 とりあえず、下に現状で分かる最小限の再現性があるスクリプトを 書いておきます。 print &opentmpl("body"); print &opentmpl('footer'); # これがない場合はエラーにならない sub opentmpl { my $fn = shift; my $VAR = shift || {}; my $file = &{$fn}(); &regex(\$file, $VAR, '__([A-Z_\d]+?(\[\d+?\])?)__', ['$VAR->{"%s"}', '$1']); &regex(\$file, $VAR, '&{(.+?)}&', ['%s', '$1']); return $file; return undef; } sub regex { my $str = shift; my $VAR = shift; my $pattern = shift; my $replace = shift; $$str =~ s/((([^\n]*?)$pattern(?=.*))+(\n?))/&func($1, $VAR, $pattern, @$replace)/egs; return; } sub func { my $str = shift; my $VAR = shift; my $pattern = shift; my $buf = shift; $str =~ s/$pattern/$@ = ''; $_ = eval(sprintf($buf, map { eval($_); } @_)); $@ ? $@ : $_/egs; if($str =~ /^\s*\n?$/s) { return; } return $str; } sub body { print "Content-type: text/plain; charset=shift_jis\n\n"; return <<'HTML'; &{ return &opentmpl('table', {'TEST' => 'test'}); }& HTML } sub table { return <<'HTML'; __TEST__ HTML } sub footer { return <<'HTML'; test HTML } 調べてみた限りではActivePerl for Win32以外のPerlでも同様のよう です。 (Linux上でも同様のようです) 5.8.8ではエラーになりますが、5.10.xではエラーにならないようです。 (同じ環境において5.8.8では再現し、5.10.0にバージョンアップすると 再現しなくなり、再度5.8.8にバージョンダウンすると再現します) 本番機の環境が5.8.8で勝手にバージョンアップなどができないため、 5.8.8で正常に動作するようにするにはどうしたらよいでしょうか。 結構、無駄も多いと思いますので全く同じ動作をしながらより効率の いい書き方ができたらいいなと思います。 (なお、実際には使用しているけど上記では使用していない部分が 含まれていてその部分がない場合もエラーにならないようです)

    • ベストアンサー
    • Perl
  • データ構造のプログラム

    #include <stdio.h> struct node{ char no; struct node *next; }; struct node head; int main(void) { struct node *new, *cur; char n; while(1){ scanf("%s", &n); if(n=='-'){ break; } new=(struct node*)malloc(sizeof(struct node)); if(new==NULL){ printf("error\n"); return(0); } new->no=n; new->next=head,next; head.next=new; } cur=head.next; while(cur!=NULL); printf("%s",cur); putchar('\n'); cur=cur->next; } free(new); new=free; return(0); } 上のプログラムを書き換えて (1),’-’が入力されたとき文字の入力を終了しそれまでに格納された文字を出力せよ。 ただし、リストに格納する際リストの最後に格納するようにせよ。 例 a(入力) b(入力) c(入力) -(入力) a(出力) b(出力) c(出力) (2),’-’が入力された後,次に入力された文字を持つ要素をリストから削除し、 最後にリスト中の全て文字を出力するようにせよ 例 a(入力) b(入力) c(入力) -(入力) b(入力) c(出力) a(出力) このような問題なのですが、分かりません。 どなたか教えてください。

  • リスト構造のプログラミング

    #include<stdio.h> #include<stdlib.h> typedef struct number{ float x; struct number *next; }Num; void append_list(Num **, float); int main(void) { Num *start,*p; float i,d; start=NULL; for(i=0.0;i<10.0;i++){ append_list(&start,i); } p=start; while(p!=NULL){ printf("%f\n",p->x); p=p->next; } p=start; while(p !=NULL){ Num *q; q=p; p=p->next; free(q); } return 0; } void append_list(Num **s, float n) { Num *end, *new; if(*s==NULL){ *s=(Num *)malloc(sizeof(Num)*1); (*s)->x=n; (*s)->next=NULL; return; }end=(*s); while(end->next !=NULL){ end=end->next; } new=(Num *)malloc(sizeof(Num)*1); new->x=n; new->next=NULL; end->next=new; } 0~9までの数値を順番に追加してリスト構造のデータ構造で 保存するプログラミングを作ったのですが、これにキーボード から入力した1つの実数(0~9)を数値の順序を乱さないよう にその数値を持つ要素を追加するにはどうすればよいのでしょうか?

  • 構造体について

    typedef struct num{ char rv[1000]; struct number *next; struct number *prev; }Num; このような双方向のリスト構造に void aplist(Num **s,char ns[]){ Num *old, *new; if(*s==NULL){ *s = (Num *)malloc(sizeof(Num)*1); strcpy((*s)->rv,ns); (*s)->next = NULL; (*s)->ago = NULL; return;} old= (*s); while(old->next != NULL){ old = old->next;} new = (Num *)malloc(sizeof(Num)*1); strcpy(new->rv,ns); new->next = NULL; old->next = new; new->prev = old; 関数の中でこのようにnext,oldを指定していったのですが、これでよいでしょうか?また、このリストを逆方向(prevの方向)に表示していきたいのですがどのように書けばよいでしょうか?nsは1行の文字列で、各構造体に1行ずつ入れていっています。

  • オブジェクト? perlをオーバーライドする方法?

    perl 5.6を使っております。 Perl5.8では PerlIOが入出力の際に文字コードを自動変換しているのですが この機能を5.6でもスクリプト互換で使いたい(スクリプトを5.6と5.8を同じにする)のですが、 既存のprint, getc, read, write関数をオーバーライド?することは可能でしょうか? 一々、if(5.8 <= $])としたくないためです。 例えば、外部がeucでperl処理がutf8の場合 sub getc{ return Jcode->new(...)->utf8; } sub print{ return Jcode->new(...)->euc; } sub read{ return Jcode->new(...)->utf8; } sub write{ return Jcode->new(...)->euc; }

    • ベストアンサー
    • Perl
  • Perlでのselfの書き方

    お世話になっています。 今他人が作ったPerlのプログラムを見ているのですが、 その中で、 パラメータを受け取る部分が、、、 sub hogehoge { my $self = shift; my ($one, $two) = @_; .. bra bra bra } と言う感じになっています。 またPerl初心者ですが、私の調べたところでは、 この二つの行は同等の意味なので、 sub hogehoge { my ($self, $one, $two) = @_; ... bra bra bra } と一行でかけてしまうと思うのですが、 $selfと$one, $twoを2行に分けている理由とか あるのでしょうか。 $selfだけ2行目の方法ではかけないとか? それともただ単に、 my $self = shift; と1行目に書くのがならわしだからでしょうか。 詳しい方が居ましたらよろしくお願いします。

    • ベストアンサー
    • Perl
  • 「Learning Perl」(第4章、問3)

    Perl初心者です。 「Learning Perl」(オライリー社、第5版)を勉強中なのですが、4章の練習問題3でつまずいています。 #!/usr/bin/perl use strict; sub total { my $sum; foreach (@_) { $sum += $_; } $sum; } sub average { if(@_ == 0) {return} my $count = @_; my $sum = total(@_); $sum/$count; } sub above_average { my $average = average(@_); my @list; foreach my $element (@_) { if($element > $average) { push @list, $element; } } @list; } my $average = average(100, 1..10); print "\$average = $average\n"; my $barney = above_average(100, 1..10); print "\$barney = $barney\n"; とやったのですが、結果が $average = 14.0909090909091 $barney = 1 となってしまいます。 ($averageの値は正しいのですが、$barneyの値が100となってほしいのに、1になってしまっています。) すみませんが、識者の方、どこが悪いのか、ご教授お願いします。

    • ベストアンサー
    • Perl
  • Perlの正規表現に関する質問です。

    Perlの正規表現に関する質問です。 下記を実行した場合、$1~・・・には下記のどの正規表現に該当する値が入るの でしょうか? sub test{ my $text = shift; pos($$text) = undef; while ( $$text =~ m{ (\s*<) ( !-+ | !-+\s*(/|//)?\s*(.*?)\s*(/|//)?\s*-+ | (/)?([!a-z0-9\-]+)\s*((?:[a-z0-9\-]+\s*=\s*[\w\-/]+|[a-z0-9\-]+\s*=\s*".*?"|[a-z0-9\-]+\s*=\s*'.*?'|\s+[^<>]{2,})*)?\s*(/)? ) (>\s*) (.*?(?=(?:<!-+ | </?[a-z0-9\-!]+\s*(?:[a-z-]+\s*=\s*[\w\-/]+|[a-z0-9\-]+\s*=\s*".*?"|[a-z0-9\-]+\s*=\s*'.*?'|\s+[^>]{2,})*)\s*(/)?>?))? }sxgi ) { ・・・ }

    • ベストアンサー
    • Perl