ファイルが読み込めない?

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
sub

ファイルが読み込めない?

#1

投稿記事 by sub » 18年前

いつもお世話になっています。
今回も質問させていただきたいと思います。よろしくお願いします。

ファイルをrで読み込む、qなら終了、dでそれを表示して、sで名前などの順番にソートするプログラムなのですがrで読み込む段階でエラーがでてきてしまいます。

コマンドsを新しく作る前まではちゃんとできていたのでsの部分が悪いと思うのですがどこかわかりません。

ソースは
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int cmp_name(const void *a,const void *b);
int cmp_eng(const void *a,const void *b);
int cmp_mat(const void *a,const void *b);
int cmp_sci(const void *a,const void *b);



typedef struct score{ 
char   name[40]; 
int    eng; 
int    mat; 
int    sci; 
} Score; 

Score *data;

int main(void) 
{ 
FILE *fp; 
char cmd[20], fname[20], rank, member[6]; 
int j=1,number; 

while (rank!='q'){ 
       printf("CMD>"); 
       fflush(stdout); 
       fgets(cmd, 20, stdin); 
       sscanf(cmd, "%c %s", &rank, fname); 
     
     
     switch(rank){ 
        	
        	
     case 'r':  
            if ((fp = fopen(fname, "r")) == NULL){ 
            printf("Cannot open the File!\n"); 
            return (-1); 
        } 
        
        for(j=1;j<=number;j++){ 
     	fscanf(fp, "%s %d %d %d", data[j].name, &data[j].eng, &data[j].mat, &data[j].sci);
        }
        
        break; 
        
        
     case 'd':          
     
     fgets(member, 6, fp);
     sscanf(member,"%d",&number);
     data=(Score*)malloc(sizeof(Score)*number);
     
     
     
     for(j=1;j<=number;j++){ 
     	fscanf(fp, "%s %d %d %d", data[j].name, &data[j].eng, &data[j].mat, &data[j].sci);
           printf("名前:%s\n",data[j].name); 
           printf("英語:%d\n",data[j].eng); 
           printf("数学:%d\n",data[j].mat); 
           printf("理科:%d\n\n",data[j].sci);
           }          
           break; 
     
     
     case 'q': 
        fclose(fp); 
        printf("File close!\n"); 
        break; 
     
     case 's':
     
     
        if(!strcmp(fname,"name")){
        	qsort(data,number,sizeof(Score),cmp_name);
        }else if(!strcmp(fname,"eng")){
        	qsort(data,number,sizeof(Score),cmp_eng);
        }else if(!strcmp(fname,"mat")){
        	qsort(data,number,sizeof(Score),cmp_mat);
        }else if(!strcmp(fname,"sci")){
        	qsort(data,number,sizeof(Score),cmp_sci);
        }
        
        
        
        
        break;
        
     
     default: 
        printf("コマンドを正しく入力してください\n"); 
    } 
} 
    return (0); 
} 

int cmp_name(const void *a,const void *b)
{
	Score *va,*vb;
	va=(Score*)a;vb=(Score*)b;
	
	return(strcmp(va->name,vb->name));
}
	
int cmp_eng(const void *a,const void *b)
{
	Score *va,*vb;
	va=(Score*)a;vb=(Score*)b;
	
	return(va->eng - vb->eng);
}

int cmp_mat(const void *a,const void *b)
{
	Score *va,*vb;
	va=(Score*)a;vb=(Score*)b;
	
	return(va->mat - vb->mat);
}

int cmp_sci(const void *a,const void *b)
{
	Score *va,*vb;
	va=(Score*)a;vb=(Score*)b;
	
	return(va->sci - vb->sci);
}
でファイルは

3
a 10 20 30
b 40 10 20
c 30 30 10

エラーメッセージ

CMD>r data1.txt
4 [main] ex04 972 _cygtls::handle_exceptions: Exception: STATUS_ACCESS_VIOLATION
1038 [main] ex04 972 open_stackdumpfile: Dumping stack trace to ex04.exe.stackdump

というふうにでます。

間違っている点を教えていただけるとうれしいです。

box

Re:ファイルが読み込めない?

#2

投稿記事 by box » 18年前

ロジックに無理があるようです。

'r'コマンドでファイルポインタfpを取得して、
1番目~number番目のデータを読んでいます。

一方、'd'コマンドでは、取得済みのファイルポインタfpから、
numberの値を取得し、さらにここでも1番目~number番目のデータを読んでいます。

'r'→'d'の順に実行すると、まだnumberの値が確定していないのに
1番目~number番目のデータを読もうとします。

逆に、'd'→'r'の順に実行すると、まだファイルポインタfpの値が確定していないのに
そこから読もうとしています。

また、1番目~number番目のデータを2度読む必要はないはずです。
さらに、'd'でnumberの分だけ領域を確保して、配列のように扱う際、
アクセスできる添字は1~numberではなく0~(number-1)です。
C言語の配列はゼロ始まりです。

sub

Re:ファイルが読み込めない?

#3

投稿記事 by sub » 18年前

ここが間違っていたんですね・・・どうもありがとうございます。

やり直してみるとエラーはでないのですが思うように表示できません・・・
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int cmp_name(const void *a,const void *b);
int cmp_eng(const void *a,const void *b);
int cmp_mat(const void *a,const void *b);
int cmp_sci(const void *a,const void *b);



typedef struct score{ 
char   name[40]; 
int    eng; 
int    mat; 
int    sci; 
} Score; 

Score *data;

int main(void) 
{ 
FILE *fp; 
char cmd[20], fname[20], rank, member[6]; 
int j=1,number; 

while (rank!='q'){ 
       printf("CMD>"); 
       fflush(stdout); 
       fgets(cmd, 20, stdin); 
       sscanf(cmd, "%c %s", &rank, fname); 
     
     
     switch(rank){ 
        	
        	
     case 'r':  
            if ((fp = fopen(fname, "r")) == NULL){ 
            printf("Cannot open the File!\n"); 
            return (-1); 
        } 
        
        fgets(member, 6, fp);
        sscanf(member,"%d",&number);
        data=(Score*)malloc(sizeof(Score)*number);
     
     
        
        for(j=1;j<=number;j++){ 
     	fscanf(fp, "%s %d %d %d", data[j].name, &data[j].eng, &data[j].mat, &data[j].sci);
        }
        
        break; 
        
        
     case 'd':         
     
     
     
     for(j=1;j<=number;j++){ 
           printf("名前:%s\n",data[j].name); 
           printf("英語:%d\n",data[j].eng); 
           printf("数学:%d\n",data[j].mat); 
           printf("理科:%d\n\n",data[j].sci);
           }          
           break; 
     
     
     case 'q': 
        fclose(fp); 
        printf("File close!\n"); 
        break; 
     
     case 's':
     
     
        if(!strcmp(fname,"name")){
        	qsort(data,number,sizeof(Score),cmp_name);
        }else if(!strcmp(fname,"eng")){
        	qsort(data,number,sizeof(Score),cmp_eng);
        }else if(!strcmp(fname,"mat")){
        	qsort(data,number,sizeof(Score),cmp_mat);
        }else if(!strcmp(fname,"sci")){
        	qsort(data,number,sizeof(Score),cmp_sci);
        }
        
        
        
        
        break;
        
     
     default: 
        printf("コマンドを正しく入力してください\n"); 
    } 
} 
    return (0); 
} 

int cmp_name(const void *a,const void *b)
{
	Score *va,*vb;
	va=(Score *)a;
	vb=(Score *)b;
	
	return(strcmp(va->name,vb->name));
}
	
int cmp_eng(const void *a,const void *b)
{
	Score *va,*vb;
	va=(Score *)a;
	vb=(Score *)b;
	
	return((va->eng) - (vb->eng));
}

int cmp_mat(const void *a,const void *b)
{
	Score *va,*vb;
	va=(Score*)a;
	vb=(Score*)b;
	
	return(va->mat - vb->mat);
}

int cmp_sci(const void *a,const void *b)
{
	Score *va,*vb;
	va=(Score*)a;
	vb=(Score*)b;
	
	return(va->sci - vb->sci);
}
このようにしたのですがコマンドsの時にnameのソートはやってくれるのですがeng,mat,sciのソートをしてくれてないようです。プログラムが間違っているのでしょうか?

ファイルが

3
b 10 20 30
a 40 10 20
c 30 3 10




CMD>r data2.txt
CMD>s name
CMD>d
名前:a
英語:40
数学:10
理科:20

名前:b
英語:10
数学:20
理科:30

名前:c
英語:30
数学:3
理科:10

CMD>s mat
CMD>d
名前:a
英語:40
数学:10
理科:20

名前:b
英語:10
数学:20
理科:30

名前:c
英語:30
数学:3
理科:10

CMD>

こういう結果になってしまいます。s matのコマンドでもs nameが使われているような感じなのですがデバッグしてみるとちゃんとint cmp_mat(const void *a,const void *b)が使われているみたいなんです。

どこが間違っているのか教えていただけますでしょうか。

box

Re:ファイルが読み込めない?

#4

投稿記事 by box » 18年前

>         for(j=1;j<=number;j++){ 
>      for(j=1;j<=number;j++){ 

この2行を修正してください。
1からnumberではなく、0から(number-1)です。
前の回答で書きました。

それから、
・コンパイル時に出る警告をなくしてください
・プログラムを終了する前に、動的に確保していた領域をfreeしてください

sub

Re:ファイルが読み込めない?

#5

投稿記事 by sub » 18年前

できましたー^^;

どうもありがとうございました!

でも
・プログラムを終了する前に、動的に確保していた領域をfreeしてください
ができません・・・

最期にfcloseするだけではだめなのでしょうか?

box

Re:ファイルが読み込めない?

#6

投稿記事 by box » 18年前

使っていたファイルのクローズと
プログラム実行中にmalloc()系の関数で動的に確保した領域の開放とは、
別々のことを意味します。

今回のプログラムでは、'q'コマンドを入力して
プログラムを終了するところに
free(data);
を書いておけばよいでしょう。

実際には、プログラムを終了するときに
 ・開いていたファイルは自動的にクローズする
 ・動的に確保していた領域は自動的に開放する
らしいのです。しかし、プログラムのお作法として
 ・自分が開いたものは自分で閉じる
 ・自分が確保した領域は自分で明け渡す
というやり方がよいと思います。

sub

Re:ファイルが読み込めない?

#7

投稿記事 by sub » 18年前

そうなのですか・・・どうもありがとうございます。

プログラム初めて半年ちょっとになるのですが同級生についていけてないように感じます・・・

少しずつでも覚えていけばいつかわかるようになると思って頑張ります。

閉鎖

“C言語何でも質問掲示板” へ戻る