ショッピングモール  ポータブルCD  ヘッドホンステレオ  ICレコーダー  アクティブスピーカー


【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※マルチポスト(多重投稿)は謹んで!

 詳しくはこちら



 本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール   掲示板1こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧

No.3350

関数化について
投稿者---練習生(2005/01/25 21:10:56)


ありがとうございます。おかげでエラーがなくなりました。

でも関数化の成績処理がしっかり動作していないみたいです。

#include<stdio.h>
#include <stdlib.h>
int sample(int N, int data[50], int max, int min, double avg);
int main(void){
  int N, i, data1[50], data2[50], data3[50], max1, max2, max3, min1,min2,min3;
  double sum,sum2,sum3, sum1, sum4, sum5;
  char fname01[30]="sugaku.dat";
  char fname02[30]="eigo.dat";
  char fname03[30]="kokugo.dat";
  char hyou1[50], hyou2[50], hyou3[50];
  FILE *fp, *fp1, *fp2, *fp3;
  
      if((fp1=fopen(fname01,"r"))==NULL){
        printf("File open error! 0");
        exit(1);
      }
      N=0;
      while(fscanf(fp1,"%d",&data1[N])!=-1){
            N++;
      }
      fclose(fp1);

  
   max1=data1[0];
   min1=data1[0];
   for(i=0; i<N; i++){
      if(max1<data1[i]){
        max1=data1[i];
      }
      if(min1>data1[i]){
        min1=data1[i];
      }
   }
    i = 0;
    sum = 0;
    while (i < N) { 
        sum += data1[i];
        i++;
    }
    sum1=sum/N;
    printf("数学(max=%2d min=%2d sum1=%2.1lf)\n",max1,min1,sum1);

   
      if((fp2=fopen(fname02,"r"))==NULL){
        printf("File open error! 1");
        exit(1);
      }
      N=0;
      while(fscanf(fp2,"%d",&data2[N])!=-1){
            N++;
      }
      fclose(fp2);


   max2=data2[0];
   min2=data2[0];
   for(i=0; i<N; i++){
      if(max2<data2[i]){
        max2=data2[i];
      }
      if(min2>data2[i]){
        min2=data2[i];
      }
   }
    i = 0;
    sum2 = 0;
    while (i < N) { 
        sum2 += data2[i];
        i++;
    }
    sum4=sum2/N;
    printf("英語(max=%2d min=%2d sum1=%2.1lf)\n",max2,min2,sum4);


      if((fp3=fopen(fname03,"r"))==NULL){
        printf("File open error! 2");
        exit(1);
      }
      N=0;
      while(fscanf(fp3,"%d",&data3[N])!=-1){
            N++;
      }
      fclose(fp3);
  

   max3=data3[0];
   min3=data3[0];
   for(i=0; i<N; i++){
      if(max3<data3[i]){
        max3=data3[i];
      }
      if(min3>data3[i]){
        min3=data3[i];
      }
   }
    i = 0;
    sum3 = 0;
    while (i < N) { 
        sum3 += data3[i];
        i++;
    }
    sum5=sum3/N;
    printf("国語(max=%2d min=%2d sum1=%2.1lf)\n",max3,min3,sum5);


  if((fp=fopen("111.dat","w"))==NULL){
      printf("File open error! 3");
      exit(1);
  }
  
  i=0; 
  for(i=0; i<N; i++){  

 hyou1[i]=sample(N, data1, max1, min1, sum1);
 hyou2[i]=sample(N, data2, max2, min2, sum4);
 hyou3[i]=sample(N, data3, max3, min3, sum5);

 fprintf(fp,"%2d %d:%c %d:%c %d:%c \n", i+1, data1[i], hyou1[i], data2[i], hyou2[i], data3[i], hyou3[i]);
  }
  fclose(fp);
  
  return 0;
}

int sample(int N, int data[50], int max, int min, double avg){
int i;
char hyou[50];

i=0;
 for(i=0; i<N; i++){  
if(data[i]>=(avg + 1.0 *(max - avg)/3.0)){
hyou[i]='A';
}else if(data[i]>=(avg - 1.0 *(avg - min)/3.0)){
hyou[i]='B';
}else if(data[i]>=(avg + 2.0 *(avg - min)/3.0)){
hyou[i]='C';
}else{ 
hyou[i]='D';
}
}
return hyou[i];
}





先ほどの疑問ですが、
data1[N]→data1ってデータが送り込まれるわけで、配列になってるんですか?
N値がなくても、指定数字までデータが入るんですか?


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:関数化について 3351 HALLS 2005/01/25 22:38:03
<子記事> Re:関数化について 3354 RiSK 2005/01/25 23:08:51


No.3351

Re:関数化について
投稿者---HALLS(2005/01/25 22:38:03)


>data1[N]→data1ってデータが送り込まれるわけで、配列になってるんですか?
>N値がなくても、指定数字までデータが入るんですか?

関数の引数としてdata1[N]と書いたとき、それは配列中の1個の要素だけを
渡しているにすぎません。
今回は配列全体を渡す必要があるはずですので、配列の先頭要素への
ポインタ(配列名と同じ)を表わすdata1と書きます。

なお、呼び出される関数の中で、int data1[50]のように要素数を書くことは
ほとんど意味がありません。int data1[]やint *data1と書く方が
一般的ではないかと思います。
呼び出される関数には、配列の先頭要素へのポインタを渡しているだけです。
したがって、要素数すらわかりません。
必要に応じて、要素数を明示的に渡すことになります。今回はそうしていますね。


この投稿にコメントする

削除パスワード

No.3354

Re:関数化について
投稿者---RiSK(2005/01/25 23:08:51)


練習生さんが成長することを願って,苦言を呈します。


>でも関数化の成績処理がしっかり動作していないみたいです。

で,どうして欲しいのでしょうか?


以下,ソースを指摘。

# 初めは言わないでおこうと思っていましたが,
# コードを読む人(練習生さん,私を含む)のために
# 細かいことも指摘します。
# めげないでね。
## 大丈夫だとは思うけど。


> data1[50], data2[50], data3[50], ...

hoge1, hoge2... というネーミングはよくないです。
どの教科と対応しているのでしょうか?
名前で分かるようにするべき。
# 数が少ないならまだしも,ちょっと氾濫状態です。sum にいたってはもう…

また,教科一つに必要な情報は構造体にまとめるなどするとスッキリします。
例:
typedef struct {
    char name[30];
    int data[50];
    int max;
    FILE * fp;
} SUBJECT;


>      while(fscanf(fp1,"%d",&data1[N])!=-1){

fscanf で -1 と比較するのはおかしいと私言いませんでしたっけ?
→No.3335

こういうの見るとガッカリしちゃうんで,気を付けてねん。


    if((fp1=fopen(fname01,"r"))==NULL){
        printf("File open error! 0");
    (...snip...)
    sum1=sum/N;
    printf("数学(max=%2d min=%2d sum1=%2.1lf)\n",max1,min1,sum1);

同じ処理が3回もありますね。
コピペしました?
これはコピペファーストといって嫌がられます。

同じ処理は関数化するのが鉄則。
必要な情報を構造体にまとめていれば,それを関数に渡せば良いだけです。


sample 関数について

これまた,名前が変ですが関数の呼び出し方(ループで呼んでる)から見て
「個人のランクを出す」関数ですよね?

だったら個人の情報と max, min, avg を渡すだけで良いでしょう。

> int sample(int N, int data[50], int max, int min, double avg){

これは全員の情報を渡していませんか?

// main
// :
    for (i = 0; i < N; ++i) {
        char math_rank = sample(data1[i], max1, min1, avg1);
        char eng_rank = sample(data2[i], max2, min2, avg2);
        char jpn_rank = sample(data3[i], max3, min3, avg3);
        fprintf(fp,"%2d %d:%c %d:%c %d:%c \n", i+1, data1[i], math_rank, data2[i], eng_rank, data3[i], jpn_rank);
    }
// :
}
int sample(int data, int max, int min, double avg)
{
    int rank;
    if (data >= (avg + 1.0 *(max - avg)/3.0)) {
        rank = 'A';
    } else if (data >= (avg - 1.0 *(avg - min)/3.0)) {
        rank = 'B';
    } else if (data >= (avg + 2.0 *(avg - min)/3.0)) {
        rank = 'C';
    } else {
        rank = 'D';
    }
    return rank;
}

こうなってくると
    char hyou1[50], hyou2[50], hyou3[50];
も不要。

評価をその場で出すので配列は不要だと言ったはずなんだけどなぁ…



この投稿にコメントする

削除パスワード

No.3356

Re:関数化について
投稿者---練習生(2005/01/26 00:39:42)


RiSKさん 申し訳ありませんでした。

評価処理のあたりでは、配列は、使わないほうがいい。と指摘を頂きました。
どうして使ってしまったかというと、
大学講義での指導では、

このようなソースを頂いて、参考にということで

int i, N, max, min;
int data1[50];
double avg;
char hyou1[50];

if(data1[i]>=(sum1 + 1.0 *(max1 - sum1)/3.0)){
   hyou1[i]='A';
}else if(data1[i]>=(sum1 - 1.0 *(sum1 - min1)/3.0)){
   hyou1[i]='B';
}else if(data1[i]>=(sum1 + 2.0 *(sum1 - min1)/3.0)){
   hyou1[i]='C';
}else{ 
   hyou1[i]='D';
}



配列中心にやっていこうと思ってました。

そして色々とソースを作って、コンパイルしたりして、わかったことが沢山得られました。配列は、いらないほうがいいですね。

関数化で、配列を使うと文字化けすることがある。
     評価を入れる配列は、入力する場所(出すところ)がなく、そのままゴミがたまってしまう。(こんな感じかな?)
     等・・

色々学びました。 ありがとうございます。


この投稿にコメントする

削除パスワード

No.3357

Re:関数化について
投稿者---RiSK(2005/01/26 01:00:29)


>関数化で、配列を使うと文字化けすることがある。
>     評価を入れる配列は、入力する場所(出すところ)がなく、そのままゴミがたまってしまう。(こんな感じかな?)
>     等・・

関数に配列(の先頭要素へのポインタ)を渡すと文字化けするのではありません。
配列を初期化も代入もせずに使っていることが問題です。

きちんと初期化/代入していれば,関数に渡したって大丈夫。
配列のすべての要素に値を代入するだけ関数だったら,
初期化/代入していない配列を渡しても良いと思いますよ。

「関数に渡すときに配列名は配列の先頭要素へのポインタを表す」事を
理解していないのでは?


修正版のソースは見せてくれないのかなぁ…


この投稿にコメントする

削除パスワード

No.3358

Re:関数化について
投稿者---練習生(2005/01/26 21:18:05)


こんなものでよろしいでしょうか?
最高値、最小値、平均値を求めるところは、関数化してません。
字下げなどをしてみました。

#include<stdio.h>
#include <stdlib.h>
int sample(int data, int max, int min, double avg);
int main(void){
  
  int i, N;
  int data1[50], data2[50];
  int max1, max2, min1, min2;
  double sum, sum1, sum2, sum3;
  
  char fname01[30]="sugaku.dat";
  char fname02[30]="eigo.dat";
  char hyou1[50], hyou2[50];

  FILE *fp, *fp1, *fp2;
  
         if((fp1=fopen(fname01,"r"))==NULL){
            printf("File open error! 0");
            exit(1);
         }
         N=0;
         while(fscanf(fp1,"%d",&data1[N])!==1){
                N++;
         }
         fclose(fp1);

  
   max1=data1[0];
   min1=data1[0];
   for(i=0; i<N; i++){
      if(max1<data1[i]){
        max1=data1[i];
      }
      if(min1>data1[i]){
        min1=data1[i];
      }
   }
    i = 0;
    sum = 0;
    while (i < N) { 
        sum += data1[i];
        i++;
    }
    sum1=sum/N;
    printf("sugaku: max=%2d min=%2d avg=%2.1lf \n",max1,min1,sum1);

   
         if((fp2=fopen(fname02,"r"))==NULL){
            printf("File open error! 1");
            exit(1);
         }
         N=0;
         while(fscanf(fp2,"%d",&data2[N])!==1){
                N++;
         }
         fclose(fp2);


   max2=data2[0];
   min2=data2[0];
   for(i=0; i<N; i++){
      if(max2<data2[i]){
        max2=data2[i];
      }
      if(min2>data2[i]){
        min2=data2[i];
      }
   }
    i = 0;
    sum2 = 0;
    while (i < N) { 
        sum2 += data2[i];
        i++;
    }
    sum3=sum2/N;
    printf("eigo: max=%2d min=%2d avg=%2.1lf \n",max2,min2,sum3);


         

         if((fp=fopen("000.dat","w"))==NULL){
             printf("File open error! 3");
             exit(1);
         }
  
   
         i=0; 
         for(i=0; i<N; i++){ 

           char rank1 = sample(data1[i], max1, min1, sum1);
           char rank2 = sample(data2[i], max2, min2, sum3);
           char rank3 = sample(data3[i], max3, min3, sum5);
  
         fprintf(fp,"%2d %d:%c %d:%c %d:%c \n", i+1, data1[i], rank1, data2[i], rank2);
         }
         fclose(fp);
  
     return 0;
}


int sample(int data, int max, int min, double avg){

    int rank;

    if(data>=(avg + 1.0 *(max - avg)/3.0)){
              rank='A';
    }else if(data>=(avg - 1.0 *(avg - min)/3.0)){
              rank='B';
    }else if(data>=(avg + 2.0 *(avg - min)/3.0)){
              rank='C';
    }else{ 
              rank='D';
    }

    return rank;
}





この投稿にコメントする

削除パスワード

No.3359

Re:関数化について
投稿者---練習生(2005/01/26 21:20:27)


 char rank3 = sample(data3[i], max3, min3, sum5);


消すの忘れてました。2教科分にして、短めにしておきましたので。


この投稿にコメントする

削除パスワード

No.3360

Re:関数化について
投稿者---HALLS(2005/01/26 22:20:48)


>消すの忘れてました。2教科分にして、短めにしておきましたので。

コンパイル時にエラーや警告が出ないソースを
見せていただけないでしょうか。

投稿前に、動作を確認なさっていないのでしょうか。


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧




掲示板提供:Real Integrity