• ベストアンサー

行の操作

ファイルから行を読み込み、それに順じて行をソートするプログラムを作りたいのですが、ちょっと混乱しています。ファイルは、以下のようになっています。 abcedf 0.53343 efghij 0.09473 klmnop 0.23453 . . . これをスコアとして行ごとに並べ替えようと思っています。以下のようなプログラムを考えたのですが、まず配列の格納がうまくいきません。よろしくお願いします。 main(){ int i, j; char line[50], name[50]; double *sor,tmp; FILE *qqq; sor=(double*)malloc(sizeof(int*)*Y); qqq = fopen("score_sort.txt","r"); //行単位の操作 while (fgets(line ,15, qqq) != NULL) { sscanf(line,"%s %f",name ,sor); } for(i=0;i<Y;i++) printf("sor[%d]=%f\n",i,sor[i]); return 0; fclose(qqq); }

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

  • ベストアンサー
回答No.6

こんばんは。yasuyuki007と申します。 C言語において、「ポインタと配列は自由に混同しても問題無い」という格言?があります。 これを使用すると、yuji221さんの質問に対する回答としては、以下の通りです。 //行単位の操作 j = 0; while (fgets(line, sizeof(line), qqq) != NULL) {  sscanf(line, "%s %lf", name, &sor[j]);  j++; } 以下は、yuji221さんのプログラムを読んでいて、ちょっと気になった点についてアドバイスしておきます。 (仕事でプログラムを作成している、現役プログラマ(10年戦士)の視点から見てです) ・fgetsにおいて、バッファサイズを直接記述するのはよろしくない。(後々の保守において、バッファサイズが変更になった際に、修正箇所が増えてしまう) ⇒修正箇所が増えるに従って、バグ(プログラムミス)を作り込む可能性が高くなる。 ・mallocで確保したメモリを開放していない。 (OS側で自動開放してくれていればいいが、そうでないとメモリ不足となる可能性がある) ・オープンしたファイルがクローズされない。 (fclose(qqq);がreturn 0;の後に記述されているので、実行されない) 以上の注意点を理解した上で、立派なプログラム屋さんとして成長していって下さい。

yuji221
質問者

お礼

ようやくできました。ありがとうございます。やはりメモリはfreeで解放すべきだと思います。

その他の回答 (5)

  • kokorone
  • ベストアンサー率38% (417/1093)
回答No.5

すみません。#1です。先ほどの発言は、 #1です。#2さん、失礼しました。

  • kokorone
  • ベストアンサー率38% (417/1093)
回答No.4

#1,#2です。失礼しました。 sor++としてしまっては、sorの位置がずれて いってしまいますよね。 そこで、sor[i];とやっても、更新されたsor が基準になってしまいますね。 やはり、 j=0; while (fgets(line ,15, qqq) != NULL) { sscanf(line,"%s %f",name ,(sor+j)); j++; } としてみてください。 sorのポインタは、更新しないようにしてください。

yuji221
質問者

お礼

ありがとうございました。

  • buihyaku
  • ベストアンサー率29% (97/326)
回答No.3

よく考えたら、sorポインタを進めてしまってはあとで困りますね。それからsscanfはdouble値で受けるのなら %fではなく%lfが正解のようです。 double *sorptr = sor; /* 最初の位置を覚える */ while (fgets(line ,50, qqq) != NULL) { sscanf(line,"%s %lf",name ,sorptr++); } これでどうでしょうか?

yuji221
質問者

お礼

ありがとうございました。lfにすべきでした。

  • buihyaku
  • ベストアンサー率29% (97/326)
回答No.2

読んでもいまひとつよくわからないのですが、Yは全行数なのでしょうか?sorはdouble値の配列ですか? だとすると sor=(double*)malloc(sizeof(int*)*Y); は sor=(double*)malloc(sizeof(double)*Y); すべきでは? ポインタとdoubleではサイズが違いますのでこのままではメモリを壊します。 あとせっかく50文字バッファがとってあるのだからここはどかんと50でいきたいですね。 while (fgets(line ,50, qqq) != NULL) { sscanf(line,"%s %f",name ,sor++); } しかしsorは取れてもnameは捨てられてしまってますがよいのでしょうか。。

yuji221
質問者

お礼

ご指摘ありがとうございます。確かにnameもmallocして格納すべきだと思います。sorはdoubleの値を格納するための配列です。また、Yは全行数です。未だに0が格納されてしまいます・・・。

  • kokorone
  • ベストアンサー率38% (417/1093)
回答No.1

sscanf(); ですが、sorを使っていますが、whileループ 内でポインタの更新がされていないため、 毎回、sorの先頭に書き込んでしまいます。 また、Yも定義されていませんね。 int Y; -------------------- Y=0; while (fgets(line ,15, qqq) != NULL) { sscanf(line,"%s %f",name ,sor++); Y++; } としてください。

yuji221
質問者

お礼

ありがとうございます。Yはdefineで定義していて、全行数です。一応プログラムは回るようになったのですが、全て0になってしまいます・・・。

関連するQ&A

  • C言語 ファイル処理に関する事

    テキストエディタで打ち込んだファイル 【hw.dat】 Akiba 160 59.3 Kurata 162 51.6 Masaki 182 76.5 Tanaka 170 60.7 Tsuji 175 83.9 Washio 175 72.5 名前・身長・体重のデータです。 <問>   「hw.dat」から読み込んだデータを身長順にソートした上で   表示するプログラムを作成せよ。 下記のプログラムでは実行結果が何も出てきません。 入門レベルのスキルしかありません。何処が良くないのでしょうか。 教えて下さい。 [プログラム]   #include <stdio.h>   #include <string.h>   void swap_double(double *x, double *y)   {   int temp = *x;   *x = *y;   *y = temp;   }   void swap_name(char *sx, char *sy)   {   char *temp;    strcpy(temp, sx);   strcpy(sx, sy);   strcpy(sy, temp);   }   void sort(double *he, double *we, int n)   {   int i, j;    for(i = 0; i < n - 1; i++){   if(*(he - 1) > *he ){ swap_double((he - 1), he); swap_double((we - 1), we); } } }   void sort_name(double *he, char *na, int n)   {    int i, j;    for(i = 0; i < n - 1; i++){   if(*(he - 1) > *he ){ swap_name((na - 1), na); } } }  int main(void)   {    FILE *fp;    int ninzu = 0;    char *name[100];    double height, weight;    double hsum = 0.0;    double wsum = 0.0;    int i;    char *na[i];    double he[6];    double we[6];    if ((fp = fopen("hw.dat", "r")) == NULL)    printf("\aファイルをオープンできません。\n");    else{   for(i = 0; i < 6; i++){   while (fscanf(fp, "%s%lf%lf", name , &height , &weight) != EOF ){ *na = *name; he[i] = height; we[i] = weight; ninzu++; hsum += he[i]; wsum += we[i];   printf("%-10s %5.1f %5.1f\n", na, height, weight);   }   }   printf("------------------------\n");   printf("平均 %5.1f %5.1f\n", hsum / ninzu, wsum / ninzu);   }   puts("\n身長順にソートしました。");   for(i = 0; i < 6; i++){ *na = *name; he[i] = height; we[i] = weight; ninzu++; hsum += he[i]; wsum += we[i]; }   for(i = 0; i < 6; i++){   sort(he, we, 6);   sort_name(he, *na, 6);   printf("%-10s %5.1f %5.1f\n", *(na + i) , *(he + i), *(we + i));   }   printf("------------------------\n");   printf("平均 %5.1f %5.1f\n", hsum / ninzu, wsum / ninzu);  fclose(fp);   return 0;  }   

  • プログラムのことについてご質問します。

    プログラムのことについてご質問します。 先日から以下のプログラムのことについて悩んでいます。 #include<stdio.h> #include<math.h> int main(int argc,char *argv[]){ FILE *rfp; FILE *wfp; int nline = 0; double score[100]; double sum_score = 0; char name[100][256]; int i; double heikinn; double hensati[100]; double ga[100]; double g[100]; double gg=0; double d=0; if (argc != 3){ fprintf(stderr,"使い方:%s 入力ファイル 出力ファイル\n",argv[0]); return -1; } if ((rfp=fopen(argv[1],"r")) ==NULL){ fprintf(stderr,"%sが開けません\n",argv[1]); return -1; } if ((wfp=fopen(argv[1],"w")) ==NULL){ fprintf(stderr,"%sが開けません\n",argv[2]); return -1; } while(fscanf(rfp,"%[^,],%lf\n", name[nline], &score[nline]) >0){ sum_score += score[nline]; nline ++; } heikinn=sum_score/nline; for (i=0; i<=nline; i++){ ga[i]=(score[i]-heikinn); g[i] = ga[i]*ga[i]; gg += g[i]; } for (i=0; i<=nline; i++){ d= gg/(nline-1); hensati[i]=10*ga[i]/sqrt(d)+50; } for(i=0; i<=nline; i++){ fprintf(wfp,"Average score is %s, %5.2lf,%5.2lf.\n",name[i],&score[i],hensati[i]); } fclose(wfp); fclose(rfp); return 0; } エラーは、出ないのですがプログラムが完了できません。 皆様のお力をおかりできないでしょうか? よろしくお願いします。

  • プログラムのことについてご質問します。

    プログラムのことについてご質問します。 先日から以下のプログラムのことについて悩んでいます。 このプログラムは、テキストファイル(内容は「名前,成績」)を読み込んで、テキストファイル(内容は「名前,成績,偏差値」)を書きだすというものなのです。てか、そのつもりで作りました。 コンパイルの時は、エラーが出ないのですが、いざ起動してみると、プログラムが終了せず、書き出しも行われません。 #include<stdio.h> #include<math.h> int main(int argc,char *argv[]){ FILE *rfp; FILE *wfp; int nline = 0; double score[100]; double sum_score = 0; char name[100][256]; int i; double heikinn; double hensati[100]; double ga[100]; double g[100]; double gg=0; double d=0; if (argc != 3){ fprintf(stderr,"使い方:%s 入力ファイル 出力ファイル\n",argv[0]); return -1; } if ((rfp=fopen(argv[1],"r")) ==NULL){ fprintf(stderr,"%sが開けません\n",argv[1]); return -1; } if ((wfp=fopen(argv[1],"w")) ==NULL){ fprintf(stderr,"%sが開けません\n",argv[2]); return -1; } while(fscanf(rfp,"%[^,],%lf\n", name[nline], &score[nline]) >0){ sum_score += score[nline]; nline ++; } heikinn=sum_score/nline; for (i=0; i<=nline; i++){ ga[i]=(score[i]-heikinn); g[i] = ga[i]*ga[i]; gg += g[i]; } for (i=0; i<=nline; i++){ d= gg/(nline-1); hensati[i]=10*ga[i]/sqrt(d)+50; } for(i=0; i<=nline; i++){ fprintf(wfp,"Average score is %s, %5.2lf,%5.2lf.\n",name[i],&score[i],hensati[i]); } fclose(wfp); fclose(rfp); return 0; } 皆様のお力をおかりできないでしょうか? よろしくお願いします。

  • ポインタと構造体の利用について

    samplefile.txtの中身 c03888 工大八郎 90 a03111 工大一郎 100 a03222 工大二郎 30 b03666 工大六郎 70 b03555 工大五郎 60 a03333 工大三郎 80 c03777 工大七郎 40 c03999 工大九郎 20 b03444 工大四郎 50 このデータをfscanfで取り込んで構造体に代入 typedef struct { char code[7]; char name[21]; int score; }REC; そしてこのデータを昇順にソートして結果を出力したいのですが 問題はここから work52.cというファイルとbubble.cというファイルとmy_sort.hというファイルがあり、work52.cからmy_sortという関数(バブルソート)を使いたい。 work52.cの中身 #include <stdio.h> #include "my_sort.h" #define MAX_NUM 500 int main(int argc, char *argv[]){ FILE *fp; REC rec[MAX_NUM]; int i, sum , min, max , n; if (argc != 2) { printf("ファイル名を指定してください\n"); return(-1); } if ((fp = fopen(argv[1], "r")) == NULL) { printf("ファイルを開けませんでした\n"); return(-1); } i = 0; while (fscanf(fp, "%s %s %d", rec[i].code, rec[i].name, &rec[i].score) != EOF){ i++; } fclose(fp); n = i; /* 初期値の設定 */ min = rec[0].score; max = rec[0].score; sum = rec[0].score; for (i = 1; i < n; i++){ sum += rec[i].score; if (rec[i].score < min) { min = rec[i].score; } if (rec[i].score > max) { max = rec[i].score; } } my_sort(rec, n); printf("最高点:%3d\n", max); printf("最低点:%3d\n", min); printf("平均点:%5.1f\n", (double) sum / n); for (i = 0; i < n; i++){ printf("%3d\t%s\t%s\n", rec[i].score, rec[i].code, rec[i].name); } return(0); } my_sort.hの中身 typedef struct { char code[7]; char name[21]; int score; }REC; void my_sort(REC *rec,int n); バブルソートで整列 #include <stdio.h> #include "my_sort.h" #define MAX 50 void my_sort(REC *rec, int n){ for(i = 0;i < n - 1; i++){ for(j = n - 1;j > i;j--){ /*この中身が問題----1*/ } } } 1の部分でchar codeとchar nameとint scoreの値を交換するときにどうすればいけるでしょうか?ご教授ください。

  • 整数型配列と2次元文字型配列の入れ替え方

    以下のプログラムを実行結果のように作りたいのですがexchange_numberの中身の書き方(配列の入れ替え方)が分らないので教えて下さい。 #include<stdio.h> #define M 10 #define N 5 void sort_score(int score_cpy[M]); int linear_search(int score_cpy[M],int key); void exchange_number(int order[M],char number[M][N]); int no; int main(void) { int i,number[M][N],score[M],score_cpy[M],order[M]; printf("人数を入力して下さい:"); scanf("%d",no); ("学生番号と平均点を入力して下さい。"); for(i=0;i<M;i++){ printf("学生番号:"); scanf("%s",&number[i][N]); printf("得点:"); scanf("%d",&score[i]); } for(i=0;i<=M;i++) score_cpy[i]=score[i]; sort_score(score_cpy); for(i=0;i<M;i++){ order[i]=linear_search(score_cpy,score[i]); } exchange_number(order,number); printf("\n\n得点の高い順に並び替えて表示します\n\n"); for(i=0;i<no;i++) printf("学生番号 :%s %d点\n",number[i],score_cpy[i]); return 0; } void sort_score(int score_cpy[M]) { int i,j,score; for(j=0;j<no-1;j++){ for(i=no-1;i>0;i--){ if(score_cpy[i-1]<score_cpy[i]){ score=score_cpy[i-1]; score_cpy[i-1]=score_cpy[i]; score_cpy[i]=score; } } } } int linear_search(int score_cpy[M],int key) { int i; for(i=0;i<no;i++){ if(score_cpy[i]==key){ return i; } } return -1; } void exchange_number(int order[M],char number[M][N]) {?} ちなみに実行結果は以下の通りです。 人数を入力して下さい:10 学生番号と平均点を入力して下さい。 学生番号:y3051 得点:85 学生番号:y3052 得点:65 学生番号:y3053 得点:75 学生番号:y3054 得点:63 学生番号:y3055 得点:95 学生番号:y3056 得点:68 学生番号:y3057 得点:80 学生番号:y3058 得点:90 学生番号:y3059 得点:83 学生番号:y3060 得点:70 得点の高い順に並び替えて表示します 学生番号:y3055 95 点 学生番号:y3058 90 点 学生番号:y3051 85 点 学生番号:y3059 83 点 学生番号:y3057 80 点 学生番号:y3053 75 点 学生番号:y3060 70 点 学生番号:y3056 68 点 学生番号:y3052 65 点 学生番号:y3054 63 点 プログラム中で間違えがありましたら指摘して頂けると幸いです。それで良いお待ちしております。

  • 学生番号が正常に出力されていません

    この質問と同じ質問が他に1つありますが、何分急いでいますのでご了承下さい。以下のプログラムで実行結果が、入力された得点に対応する学生番号を得点の高い順に並び替えて出力したいのです。得点の方は正常に出力されているのですが学生番号がおかしな出力になっています。しかし、どこをどう直せば良いか分かりません。なので分かりやすく説明お願い致します。 #include<stdio.h> #define M 10 #define N 5 void sort_score(int score_cpy[M]); int linear_search(int score_cpy[M],int key); void exchange_number(int order[M],char number[M][N]); int no; int main(void) { int i,score[M],score_cpy[M],order[M]; char number[M][N]; printf("人数を入力して下さい:"); scanf("%d",&no); ("学生番号と平均点を入力して下さい。"); for(i=0;i<no;i++){ printf("学生番号:"); scanf("%s",&number[i][N]); printf("得点:"); scanf("%d",&score[i]); } for(i=0;i<=M;i++){ score_cpy[i]=score[i]; } sort_score(score_cpy); for(i=0;i<M;i++){ order[i]=linear_search(score_cpy,score[i]); } exchange_number(order,number); printf("\n\n得点の高い順に並び替えて表示します\n\n"); for(i=0;i<no;i++){ printf("学生番号 :%s %d点\n",number[i],score_cpy[i]); } return 0; } void sort_score(int score_cpy[M]) { int i,j,score; for(j=0;j<no-1;j++){ for(i=no-1;i>0;i--){ if(score_cpy[i-1]<score_cpy[i]){ score=score_cpy[i-1]; score_cpy[i-1]=score_cpy[i]; score_cpy[i]=score; } } } } int linear_search(int score_cpy[M],int key) { int i; for(i=0;i<no;i++){ if(score_cpy[i]==key){ return i; } } return -1; } void exchange_number(int order[M],char number[M][N]) { int i,temp[M]; for(i=0;i<M;i++){ if(order[i]==-1)break; temp[i]=number[i][N]; } for(i=0;i<M;i++){ if(order[i]==-1)break; number[order[i]][N]=temp[i]; } } 人数を入力して下さい:10 学生番号:y3051 得点:85 学生番号:y3052 得点:65 学生番号:y3053 得点:75 学生番号:y3054 得点:63 学生番号:y3055 得点:95 学生番号:y3056 得点:68 学生番号:y3057 得点:80 学生番号:y3058 得点:90 学生番号:y3059 得点:83 学生番号:y3060 得点:70 得点の高い順に並び替えて表示します 学生番号 : 95点 学生番号 :y3051y3052y3053y3054y3055y3056y3057y3058y3059y3060 90点 学生番号 :y3052y3053y3054y3055y3056y3057y3058y3059y3060 85点 学生番号 :y3053y3054y3055y3056y3057y3058y3059y3060 83点 学生番号 :y3054y3055y3056y3057y3058y3059y3060 80点 学生番号 :y3055y3056y3057y3058y3059y3060 75点 学生番号 :y3056y3057y3058y3059y3060 70点 学生番号 :y3057y3058y3059y3060 68点 学生番号 :y3058y3059y3060 65点 学生番号 :y3059y3060 63点

  • Linuxの並び替えで特定の行を一番最後の行に配置

    Linux において sort などを使ったテキストファイルの中身の並び替えにおいて 特定の(なるべく複数の)行、ここでは仮に target line 1 target line 2 という内容の行だとします(ご覧の通り空白が入っています)。 これを一番最後の行に配置されるようにしたい、などということは可能でしょうか? また、 sort -u と組み合わせるには sort -u input.txt | sort > output.txt の後半部分をこのケースのコマンドに書き換えるだけで問題ないでしょうか? どうぞよろしくお願いいたします。

  • ルンゲクッタのプロクラム実行できません

    プログラムの実行ができません。 どこを直したらよいのか教えて下さい。 よろしくお願いします。 #include <stdio.h> #include <stdlib.h> #include <math.h> double *dvector(long i,long j); void free_dvector(double *a,long i); double func(double x,double y); double *rk4(double y0,double a,double b, int n,double(*f)()); int main(void) { double *y,h,a=0.0, b=1.0, y0=1.0; int i,n; printf("分割数を入力して下さい------->"); scanf("%d",&n); y=dvector(0,n); y=rk4(y0,a,b,n,func); h=(b-a)/n; for(i=0;i<=n;i++) { printf("x=%f \t y=%f \n",a+i*h,y[i]); } return 0; } double *rk4(double y0,double a, double b,int n,double (*f)()) { double k1,k2,k3,k4,h,*y,x; int i; y=dvector(0,n); h=(b-a)/n; y[0]=y0; x=a; for(i=0;i<n;i++) { k1=f(x,y[i]); k2=f(x+h/2.0,y[i]+h*k1/2.0); k3=f(x+h/2.0,y[i]+h*k2/2.0); k4=f(x+h,y[i]+h*k3); y[i+1]=y[i]+h/6.0*(k1+2.0*k2+2.0*k3+k4); x +=h; } return y; free_dvector(y,0); }

  • 座標をランダムに表示させてx座標順にソートするプログラムを考えています

    座標をランダムに表示させてx座標順にソートするプログラムを考えています とりあえず、以下の様に決まった数の座標でソートすることはできたのですが、ランダムにするとなるとどうすればいいのかわかりません。 ------------------------------------------------- #include <stdio.h> int makepoints(int * pn, double * x, double * y){ double xp,yp; int k; int i,j; int n; n = 7; *pn = n; xp = 1; for(k=0;k<n;k++) { xp = xp/2; yp = xp*xp; x[k] = xp; y[k] = yp; } printf("初期座標列:\n"); for(k=0;k<n;k++) { printf("%f_%f\n",x[k],y[k]); } for(j=1;j<n;j++) { for(i=0;i<j;i++) { if(x[i]>x[j]){ xp=x[i];x[i]=x[j];x[j]=xp; yp=y[i];y[i]=y[j];y[j]=yp; } } } printf("整列後の座標列:\n"); for(k=0;k<n;k++) { printf("%d %f %f\n",k ,x[k],y[k]); } return 0; } ------------------------------------------------- なんとなくrand関数を使えばいいのかな、というのはわかるのですが、プログラミングに弱く困っています。 この後のプログラミング教えてくださる方いればよろしくお願いします。

  • 関数宣言

    3次元で領域を確保するプログラムをmalloc関数を用いて書きました。しかし、プログラムが長いので関数宣言をしなさいといわれたために、以下のプログラムを書きました。しかし、途中でつまづいてしまい、どのように関数を用いたり、関数を定義すれば良いのか混乱しています。初心者ですが、どうかお願いします。 /*ソース*/ #include<stdio.h> #include<stdlib.h> int main(){ double ***C; f3Malloc(C,.,.); //数値を代入(関数の使い方?) f3Free(C,.,.); } /*3次元配列(返し方?)*/ double*** f3Malloc(C,,){ int i,j,x,y,z; x = 2; y = 3; z = 4; C=(double***)malloc(sizeof(double**)*x*y*z); for(i=0;i<y;i++){ C[i]=(double**)malloc(sizeof(double*)*y*z); for(j=0;j<z;j++){ C[i][j]=(double*)malloc(sizeof(double)*z); } } } /*メモリの解放(返し方?)*/ void f3Free(C,.,.){ int i,j,x,y; x = 2; y = 3; for(i=0;i<x;i++){ for(j=0;j<y;j++){ free(C[i][j]); } free(C[i]); } free(C); }

専門家に質問してみよう