• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:2つ質問があり、まず1つ目なのですが・・)

プログラム1行ずつみていったところ、何をしているか分からないところがけっこうありまして。。。[Perl初心者]

このQ&Aのポイント
  • プログラム1行ずつみていったところ、何をしているか分からないところがけっこうありまして。
  • Perl初心者で困惑しております(><)以下の文でコメントがないところ分かりません。 コメントあるところも怪しいかもしれません。
  • プログラムの詳細な内容を把握するのは難しいですが、ループと条件分岐が使われていることがわかります。

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

  • ベストアンサー
  • Werner
  • ベストアンサー率53% (395/735)
回答No.2

> $a =~ s/\n$//; で$aの末尾の末尾の改行文字(\n)を捨て、 > @b = split(/,/,$a); で$aを'を区切り文字として分割し、分割した各要素を配列@bに入れています。 ここの動作はsplit関数について調べて、実際に使ってみればすぐに分かります。 http://www.rfs.jp/sb/perl/05/split.html 残りは#1で説明した内容とほとんど同じです。 なお、こういう処理(セパレータで文字列を分割)をする場合はsplitを使うのが普通です。 最初のプログラムの方はどちらかというと変わった書き方ですね。

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

その他の回答 (1)

  • Werner
  • ベストアンサー率53% (395/735)
回答No.1

まずこのプログラムは1つのプログラムではありませんね? 私が見た限りでは > while( $a = <> ) 以降は別のプログラムであるのが自然だと思いましたが。 また、それぞれのプログラムがそもそもどんな処理をするためのものかは分かっているのですか? (こういう情報は、分かっているのなら回答者の理解を助けるためにも質問時に書いておくべきです。) ソースコードを読んでみましたが、 1つめのプログラムは CSV(Comma Separated Values)を出力するプログラムのようです。 CSVは名前の通り各値を,(カンマ)で区切って並べたものです。 2つめのプログラムは 1つめのプログラムで生成されたCSVを読み込んで 行と列それぞれの平均値を出力するようです。 私なりにコメントを追加・変更したコードを下に示します。 コメントで書ききれなかった分は一番下に書きました。 --------<1つめのプログラム>-------- #79行21列のCSVを出力 #ただし一列目は行の名前 #各値は20以上100未満の整数、または空である for($i=1; $i<80; $i++) {    #$iが80未満の間ループ、$iは初期値1で1ずつ増える。ループ回数79回   printf("a2006%03d",$i);  #a2006001から2006079まで出力。   for($k=0; $k<20; $k++) { #20回ループ     $pnt=int(rand(100)); #0以上100未満の整数乱数をpntに代入。     print ",";       #,を出力。     if( $pnt >=20 ) {   #pntが20以上ならpntを出力。       print $pnt;     }   }   print "\n";        #改行を出力。 } --------<2つめのプログラム>-------- #標準入力からCSVを読み込み #各行や各列の値の平均値を求める #ただし平均値を求めるに当たって空の値は無視する while( $a = <> ) {         #標準入力から1行ずつ読み込んで$aに代入   $a =~ s/\n$//;        #$aの末尾の改行コード(\n)を捨てる。   @b = $a =~ /^([^,]*)(,*.*)$/; #$aの最初の,(カンマ)より前を$b[0]に、残りを$b[1]にいれる   $name = $b[0];   $seq =0;   $isum = 0;   $icnt =0;   while( $b[1] ne "" ) {         #処理中の行を全部処理し終わるまでループ     @b = $b[1] =~ /^,([^,]*)(,*.*)$/; #$b[1]の最初の,は捨て、次の,より手前の部分を$b[0]に移す     if( $b[0] ne "" ) {         #空の値は無視する       $isum += $b[0];         #行の合計値を求めるために値を加算       $sum[$seq] += $b[0];     #列の合計値を求めるために値を加算       $icnt++;             #行中の空でない値(数値)の数をカウント       $cnt[$seq]++;         #列中の空でない値(数値)の数をカウント     }     $seq++;              #,(カンマ)の数、すなわち空も含んだ要素の数をカウント   }   printf("%s:%.2f\n", $name, $isum/$icnt); #行の名前とその平均値を出力 } for($i=0; $i<=$#sum; $i++) { #配列@sumの配列要素数分(=列数)ループ   #各列の平均値を出力   printf(" %.2f", $sum[$i]/$cnt[$i]); } print "\n"; --------<End>-------- > $a = <> この部分は厳密には「標準入力から入力が与えられた場合はそちらを読み込み、 ファイル名が引数として与えられた場合はファイルから読み込み」ます。 http://infosys.gsid.nagoya-u.ac.jp/~ohna/perl_lesson/perl04.html > @b = $a =~ /^([^,]*)(,*.*)$/; この部分では、 $a =~ /^([^,]*)(,*.*)$/ でマッチングが行われ、 パターンの中のカッコで括られた部分に対応した要素を 配列として@bに代入しています。 例えば、$a="1,2,3,4,5,6"だったなら、 /[^,]*/は"1"にマッチし、/,*.*/は",2,3,4,5,6"にマッチするので、 この処理の結果@b=("1", ",2,3,4,5,6")となります。 http://www.rfs.jp/sb/perl/02/09.html 詳しくはこのページの 「リストコンテキストでのパターンマッチ」を参照してください。 (正規表現やパターンマッチ自体を知らないなら全部に目を通した方がよいでしょう。) #余談 質問者さんの元のコメントを見て、 forループの挙動がよく分かっていない、 パターンマッチについて知らないという印象を受けました。 Perl初心者ということですが、 分からないところの方が多いような状態なら 先にPerlの基本的なところを一通り勉強をしておくことを勧めます。

saranpopo
質問者

お礼

丁寧に教えていただき本当に有り難うございました。じつはお礼を載せたつもりでしたが、コンピュータが重かったので載らなかったようです。お礼が遅れてしまい申し訳ありません。。(><) ちなみに以下のプログラムでも同じ結果がでるようですが、この場合はどういった感じに見ていけばいいのでしょうか。。。 while( $a = <> ) { $a =~ s/\n$//; @b = split(/,/,$a); $isum=0; $icnt=0; for($i=1; $i<=$#b; $i++) { if( $b[$i] ne "" ) { $isum += $b[$i]; $sum[$i] += $b[$i]; $icnt++; $cnt[$i]++; } } printf("%s:%.2f\n", $b[0], $isum/$icnt); } for($i=1; $i<=$#sum; $i++) { printf(" %.2f", $sum[$i]/$cnt[$i]); } print "\n";

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

関連するQ&A

  • プログラミングで質問があります。

    プログラミングで質問があります。 実数値を入力して、その平均を出すプログラミングを作ったのですが、うまく行きません。 どこが間違っているのか教えてほしいです #include <stdio.h> int main (void) { float a=1,sum=0; int b=0,i; while(a!=0) { printf("整数値を一つ入力してください。"); scanf("%f",&a); if(a!=0) { b=b+1; } for(i=0;i<=b;i=i++) { sum=sum+a; } } printf("平均値は%fです\n",sum/b); } 実行して、10、10、10と入力すると、90になってしまいます(..;)

  • 次のプログラムは、n個の中からr個とる組み合わせが何通りあるか求め出力

    次のプログラムは、n個の中からr個とる組み合わせが何通りあるか求め出力するものである。 ただしこの組み合わせは次のようにけいさんするものである nCr=n!/r!×(n-r)! ○の中にあてはまる数値や文字を教えてください C言語です #include<stdio.h> void main(void) { int a,b,n,r,cnt; int kumiawase; a=○; b=1; printf("n=10"); scanf("%d",&n); printf("r=3"); scanf("%d",&r); for(cnt=n;cnt>1;cnt--){ a=○; } for(cnt=r;cnt>1;cnt--){ b=b*cnt; } for(cnt=○;cnt>1;cnt--){ b=b*cnt; } kumiawase=○/○ printf("%d個から%d個とる組み合わせ=%d\n",n,r,kumiawase); }

  • C言語で、「自然数nを入力し、nの約数をすべて求めて出力後、その個数と

    C言語で、「自然数nを入力し、nの約数をすべて求めて出力後、その個数と合計を出力をする。尚、nとして0(ゼロ)以下が入力されるまで、何度も繰り返す」という問題をやっています。 出力例は、(3を入力したとして) 「3の約数は 1  3 約数の個数は2個 約数の和は4」というものです。 そこで、コーディングをしたのですが、先生が開発したコンパイラで運用したところ、フリーズが起きて強制終了してしまいました。先生は、「そんなことはない。フリーズが起きるときはそのプログラムにバグがあるときだ」と言ってました。 そこでコーディングしたプログラムは以下の通りです。 #include <stdio.h> main() {int i,j,n,cnt,sum; printf("自然数=");scanf("%d",&n); while(n>=0){ printf("%dの約数は",n); for(i=1;i<=n;i++){ if(n/i>=0){ j=n/i; printf(" %d",j); sum=sum+j; cnt++; j=0;} } printf("\n"); printf("約数の個数は%d個",cnt); printf("約数の和は%d",sum); }} どこかに間違いがありますか? IF文の中でいちいちめんどくさいことをしていますが、気にしないでください。

  • 質問ですが

    教えていただきたいのですが、C言語で名前と点数を入力して合計と平均を求めるというプログラムを作ったのですが、 main関数の中で情報入力、合計と平均の計算をしているのでそれぞれ入力関数、合計を求める関数、平均を求める関数というものを作ってmain関数をすっきりとさせたいのですがどうすればいいですか? #include <stdio.h> typedef struct{ char name[15]; int jpn; int eng; int math; int sum; } stdent; typedef struct{ double sum; double jpn; double eng; double math; } Score; void maxmin(stdent *, int); main() { int i, n; n = 5; stdent person[n]; Score average; average.jpn = 0; average.eng = 0; average.math = 0; average.sum = 0; for(i = 0; i < n; i++) { printf("Student No.%d \n",i + 1); printf("Name? "); scanf("%s", person[i].name); printf("Japanese? "); scanf("%d", &(person[i].jpn)); printf("English? "); scanf("%d", &(person[i].eng)); printf("Math? "); scanf("%d", &(person[i].math)); printf("\n"); person[i].sum = person[i].jpn + person[i].eng + person[i].math; average.jpn += person[i].jpn; average.eng += person[i].eng; average.math += person[i].math; average.sum += person[i].sum; } average.jpn /= n; average.eng /= n; average.math /= n; average.sum /= n; printf(" 名前 国語 英語 数学 \n"); printf("------------------------------------\n"); for(i = 0; i < n; i++) { printf("%8s %3d %3d %3d %3d\n", person[i].name, person[i].jpn, person[i].eng, person[i].math, person[i].sum); } printf("------------------------------------\n"); printf("平均 %.1lf %.1lf %.1lf %.1lf\n\n", average.jpn,average.eng,average.math,average.sum); return 0; }

  • ネイピア数(e)のプログラム

    テイラー展開によってネイピア数の近似値を求める プログラミングが全くわかりません。 e = 2.71828 18284 59045 23536 02874 71352 … を計算したいのですが。 #include <stdio.h> #include <math.h> int kaijou(int p) { int cnt; int val=1; for(cnt=1 ; cnt<=p ; cnt++){ val=val*cnt; } return(val); } double napier(int p) { printf("eを計算します。E = (1+(1/k))^k\n"); printf("k=いくつまで計算しますか ?\n"); scanf("%d", &n); double E[n]; E[1] = 1; for (j = 1; j <= n; j++){ E[j] = E[j] + 1; } for (k = 1; k <= n; k++) { K = K + 1; A = 1 / K; // printf("A = %e, ",A); B = 1 + A; // printf("B = %e\n",B); for ( i = 1; i<=k; i++){ E[k] = E[k] * B; // printf("E[%3d]= %e\n",k,E[k]); } void main(void) { int n; int cnt; double answer; printf("計算する最大の項nを入力してください:"); scanf("%d",&n); for(cnt=1 ; cnt<=n ; cnt++){ answer=napier(cnt); printf("第%d項までの近似値:%f 真値:%f 差:%f\n",cnt,answer,exp(1),answer-exp(1)); } }

  • 問題です。

    #include <stdio.h> short X1(char *,char *,char *); void X2(char *,short,short); void X3(char *,short,char *); void main(void) { char Str[][30]={"CDECDEGEDCDEC","CDE","AB"}; short Ret; Ret=X1(Str[0],Str[1],Str[2]); printf("Str[0] : %s\n", Str[0]); printf("Str[1] : %s\n", Str[1]); printf("Str[2] : %s\n", Str[2]); printf("Ret : %d\n", Ret); } short X1(char *pStr1,char *pStr2,char *pStr3) { short Len1,Len2,Len3; short Cnt1,Cnt2; short Ret = 0; for (Len1= 0;pStr1[Len1]!=0;Len1++); for (Len2= 0;pStr2[Len2]!=0;Len2++); for (Len3= 0;pStr3[Len3]!=0;Len3++); if (Len1<Len2 || Len2==0) return Ret; for (Cnt1=0; Cnt1<=Len1-Len2; Cnt1++){ for (Cnt2=0; Cnt2<Len2; Cnt2++){ if (pStr1[Cnt1+Cnt2]!=pStr2[Cnt2]) break; } if (Cnt2==Len2){ X2(pStr1,Cnt1+1,Len2); X3(pStr1,Cnt1+1,pStr3); Len1 += Len3-Len2; Cnt1 += Len3-1; Ret++; } } return Ret; } void X2(char *pStr, short Pnt, short Num) { short Cnt, Len; for (Len = 0; pStr[Len]!=0; Len++); for (Cnt = Pnt+Num-1; Cnt<=Len; Cnt++){ pStr[Cnt-Num] = pStr[Cnt]; } } void X3(char *pDst, short Pnt; char *pSrc) { short SrcLen, DstLen; short Cnt; for (SrcLen=0; pSrc[SrcLen]!=0; SrcLen++); for (DstLen=0; pDst[DstLen]!=0; DstLen++); for (Cnt=DstLen-1; Cnt>=Pnt-1; Cnt--){ pDst[Cnt+SrcLen]=pDst[Cnt]; } for (Cnt=0; Cnt<SrcLen; Cnt++){ pDst[Pnt+Cnt-1]=pSrc[Cnt]; } pDst[DstLen+SrcLen]=0; } というようなプログラムの出力結果はどうなるか?という問題ですが、Str[0]:ABABGEDABC, Str[1]:CDE, Str[2]:AB, Ret:3となるんですが、どうしてそうなるかが、全然分かりません。どなたか説明してもらえないでしょうか?お願いします。

  • 課題なんですが・・・

    プログラムが書いてあるため非常に長文です。 お許しください。 いま、C++でのプログラミング課題が出ているのですが、 正方形の中抜きは出来たのですが、三角形・逆三角形の中抜きが作れません・・・。 もちろん、宿題・課題の丸投げは禁止されているのは分かっています。 しかし、一向に進まないのでなにかヒントだけでも(できたら答えも・・・というのは冗談です)教えていただけないでしょうか。 ちなみに問題は、入力数分の縦×横の図形を描くプログラムを組む。 というものです。 #include <stdio.h> void main (void) { /*変数の宣言*/ int cnt1, cnt2,n; /*数字の入力*/ do { printf("数字2~19を入力してください:"); scanf("%d",&n); if(n<2 || n>19) { printf("入力エラーです!!\nもう一度"); } }while(n<2 || n>19); /*正方形の作成*/ printf("\n正方形\n"); for(cnt1=0;cnt1<n;cnt1++) { for(cnt2=1;cnt2<=n;cnt2++) { printf("*"); } printf("\n"); }   printf("\n三角形\n"); for(cnt1=1;cnt1<=n;cnt1++) { for(cnt2=0;cnt2<cnt1;cnt2++) { printf("*"); } printf("\n"); } printf("\n逆三角形\n"); for(cnt1=1;cnt1<=n;cnt1++) { for(cnt2=n;cnt2>=cnt1;cnt2--) { printf("*"); } printf("\n"); } printf("\n三角旗\n"); for(cnt1=1;cnt1<=n;cnt1++) { for(cnt2=0;cnt2<cnt1;cnt2++) { printf("*"); } printf("\n"); } for(cnt1=n-1;cnt1>=0;cnt1--) { for(cnt2=0;cnt2<cnt1;cnt2++) { printf("*"); } printf("\n"); } printf("\nダイヤ形\n"); for(cnt1=1;cnt1<=n;cnt1++) { for(cnt2=1;cnt2<=n*2;cnt2++) { if(cnt2<=n-cnt1 || cnt2>=n+cnt1) { printf(" "); } else { printf("*"); } } printf("\n"); } for(cnt1=n-1;cnt1>0;cnt1--) { for(cnt2=1;cnt2<=n*2;cnt2++) { if(cnt2<=n-cnt1 || cnt2>=n+cnt1) { printf(" "); } else { printf("*"); } } printf("\n"); } printf("\n中抜き正方形\n"); for(cnt1=1;cnt1<=n;cnt1++) { if(cnt1==1 || cnt1==n) { for(cnt2=1;cnt2<=n;cnt2++) { printf("*"); } } else for(cnt2=1;cnt2<=n;cnt2++) { if(cnt2==1 || cnt2==n) { printf("*"); } else { printf(" "); } } printf("\n"); } rewind(stdin); getchar(); }

  • c++について

    以下のプログラムをコンパイルしてみたのですが、うまく作動しません。 どこかに欠陥があるのでしょうか? 分かる方、よろしくお願いします。 #include <stdio.h> #include <stdlib.h> #include <math.h> #pragma warning(disable : 4996) #define N 3 typedef struct Shop { char name[10]; int sale; } Shop; void pp(Shop*a) { int i; printf("\n"); for(i=0; i<N; i++,a++) printf("Name , Sale = %s ,\t%d\n",a->name,a->sale); printf("\n"); } int main(void) { double sum; //売上高合計 double ave; //売上高平均 double hensa1; /* double hensa2; */ /* double sd; //標準偏差 */ Shop*data,*t; int i,j; data=t=malloc(sizeof(Shop)*N); for(i=0; i<N; i++,t++) { printf("店舗名を入力してください\n"); scanf("%s", &t->name); printf("売上高を入力してください。\n"); scanf("%d", &t->sale); sum += t->sale; } ave = sum/N; for(i=0; i<N; i++,t++) hensa1 += (pow(ave-t->sale, 2)); t=malloc(sizeof(Shop)); for(i=0; i<N-1; i++) { for(j=i+1; j<N; j++) { if(data[i].sale > data[j].sale) { t[0]=data[i]; data[i]=data[j]; data[j]=t[0]; } } } printf("\n"); printf("%g\t:Sum\n%g\t:Average\n%g\t:Standard deviation\n", sum,ave,sqrt(hensa1)/N); pp(data); return 0; }

  • C言語の関数の定義について質問します

    struct monster{ int type; /* タイプ */ char trick[25]; /* 技 */ char trick2[25]; /* 技2 */ int tricktype; /* 技1のタイプ */ int tricktype2; /* 技2のタイプ */ int trickeffect; /* 技1の威力 */ int trickeffect2; /* 技2の威力 */ char name[10]; /* 名前 */ int power; /* 攻撃力 */ int diffence; /* 防御力 */ int speed; /* 素早さ */ int HP; /* 体力 */ /* 1,fire 2,water 3,nature 4,thunder 5,wind */ }; main(){ int a[2][3]; struct monster monster[5] = { { 1, "a", "b", 1, 2, 120, 80, "v", 60, 60, 60, 100}, { 2, "a", "b", 2, 3, 120, 80, "w", 60, 60, 60, 100}, { 3, "a", "b", 3, 4, 120, 80, "x", 60, 60, 60, 100}, { 4, "a", "b", 4, 5, 120, 80, "y", 60, 60, 60, 100}, { 5, "a", "b", 5, 1, 120, 80, "z", 60, 60, 60, 100}, }; struct monster monster2[5] = { { 1, "a", "b", 1, 2, 120, 80, "v", 60, 60, 60, 100}, { 2, "a", "b", 2, 3, 120, 80, "w", 60, 60, 60, 100}, { 3, "a", "b", 3, 4, 120, 80, "x", 60, 60, 60, 100}, { 4, "a", "b", 4, 5, 120, 80, "y", 60, 60, 60, 100}, { 5, "a", "b", 5, 1, 120, 80, "z", 60, 60, 60, 100}, }; inputmonster(a, monster); printf("これからバトルを開始します\n\n"); printf("player1は%sをくりだした。\n", monster[a[0][0]-1].name); printf("player2は%sをくりだした。\n", monster2[a[1][0]-1].name); battle(a); return 0; } void inputmonster(int x[][3], struct monster monster) { int i, s, t, m, n; for(t = 0; t < 2; t++){ s = 0; while (s < 1){ printf("player%dは好きなモンスターを3つ選んでください\n\n", t+1); for (i = 0; i<3; i++){ printf("%d体目を選んでください。\n\n", i+1); for(m = 0; m < 5; m++) printf("%d, %s\n", m+1, monster[m].name); scanf("%d", &x[t][i]); printf("%d体目 : %s\n\n", i+1, monster[x[t][i]-1].name); } printf("これでよろしいですか?\n"); for(i = 0; i<3; i++) printf("%d体目 : %s ", i+1, monster[x[t][i]-1].name); printf("1、はい 2、いいえ\n"); scanf("%d", &n); if(n == 1) s = 1; else s = 0; } } } 上記のようにプログラムをコンパイルしたところ、 monsterbattle.c: 関数 ‘inputmonster’ 内: monsterbattle.c:497:63: エラー: 添字が付けられた値が、配列、ポインタまたはベクト ルではありません for(m = 0; m < 5; m++) printf("%d, %s\n", m+1, monster[m].name); ^ monsterbattle.c:499:45: エラー: 添字が付けられた値が、配列、ポインタまたはベクト ルではありません printf("%d体目 : %s\n\n", i+1, monster[x[t][i]-1].name); ^ monsterbattle.c:503:68: エラー: 添字が付けられた値が、配列、ポインタまたはベクト ルではありません for(i = 0; i<3; i++) printf("%d体目 : %s ", i+1, monster[x[t][i]-1].na me); というような結果が返ってきました。 どうやら定義がうまくなっていないようなのですが、どこを改善すればうまく動くようになるのでしょうか? お手数ですが、よろしくお願いいたします。

  • printfで・・

    ループの途中でカウンタのモニタ表示を したいのですが、改行したりせずに、プロンプト上に 上書きして表示させるにはどのようにしたら良いのでしょうか?ご存知の方教えてください<(_ _)> たとえば、以下のようにしてしまうと 1000行書き出されてしまいますよね。 %dのところだけ上書きして表示したいのですが可能でしょうか? int i,cnt; cnt =0; for(i=0;i<1000;i++){ printf("cnt = %d\n",cnt); }