No.17236![]() |
次のプログラムを関数を使って簡略化したいのですが・・・ 投稿者---新米(2004/10/12 15:55:35) |
||
次のプログラムを関数を使って簡略化したいのですが、うまくいきません。コンパイルは通るのですが、強制終了されてしまいます。私の考えでは、式のプログラムの中でリソースファイルとデータファイルの所を関数化しようと思っています。で、アドレスを渡さないといけないのでポインタを使っているつもりなのですが・・・ OSはWindowsXPでK2エディタにソースを書きコマンドプロンプトで実行しています。↓のソースの後に私が書いたソースを載せています。どうかご教授お願いします。 /* データファイルとリソースファイルを読み込みリソースファイルの型に合った形で出力する */ #include<stdio.h> #include<string.h> #include<stdlib.h> typedef struct DATA{ char name[100]; /* リソースファイルのデータの種類を入れる */ int size; /* リソースファイルのバイト数を入れる */ char kata[100]; /* リソースファイルのそれぞれの型を入れる */ }DATA; void main(){ FILE *d_fp, *r_fp; struct DATA data[20]; char inbuf[100]; int i,j=0; /* i,jはfor文で使う。sizeはリソースファイルのsizeの合計を入れる */ char temp[100],temp1[100]; /* 代わりに入れとく入れ物 */ int nRead; int num; int stop; /* リソースファイルオープン */ if((r_fp = fopen("resorcsfile4.txt","r"))==NULL){ printf("リソースファイルオープンエラー\n"); } /* データファイルオープン */ if((d_fp = fopen("TEST4.DAT","rb"))==NULL){ printf("データファイルオープンエラー\n"); } for(i=0;;i++){ fscanf(r_fp,"%s ",&temp); if(temp[0] == temp1[0]){ /* 新しい読み込みなしでfor文終了 */ break; } strcpy(temp1 ,temp); /* リソースファイルが no = d name = 6s addr = 8s だった場合に 読み込んだ順に 1 2 3 4 5 6 7 8 9 となるので以下のようにした */ if((i+2+1)%3==0){ /* ↑でいう1,4,7番目(データ項目)を取得 */ strcpy(data[j].name ,temp); } if((i+1)%3==0){ /* ↑でいう3,6,9番目(バイト数)を取得 */ strcpy(data[j].kata ,temp); if(temp[0] == 'd'){ /* dの場合int型(4バイト)取得 */ data[j].size = 4; strcpy(data[j].kata ,"int"); }else if(strcmp(&temp[0], "s" )==0){ printf("リソースファイルのchar型にサイズを指定してください。\n"); break; }else{ /* sの場合それぞれのbit取得 */ data[j].size = atoi(data[j].kata); strcpy(data[j].kata ,"char"); } j++; } } /* 名前・サイズ・型名をそれぞれ表示 */ for(i=0;i<j;i++){ printf("data[%d].mame = %s \n",i,data[i].name); printf("data[%d].size = %d \n",i,data[i].size); printf("data[%d].kata = %s \n",i,data[i].kata); } stop = j-1; inbuf[0] = 0x00; /****************ここからデータファイル表示********************/ for(i=0;;i++){ /* 型がint型の場合 */ if(strcmp(data[i].kata ,"int")==0){ nRead = fread(&num,sizeof(char), sizeof(int),d_fp); if(nRead != sizeof(int)) { break; } printf(" %s: %d \n",data[i].name,num); /* 型がchar型の場合 */ }else{ /* 指定された文字でバッファを初期化 */ memset(inbuf, 0x00, sizeof(inbuf)); nRead = fread(&inbuf,sizeof(char),data[i].size,d_fp); if(nRead != data[i].size) { break; } printf(" %s: %s \n",data[i].name,inbuf); } if(i==stop){ i = -1; } } /* リソースファイル・データファイルを閉じる */ fclose(d_fp); fclose(r_fp); } 私の書いたプログラム文字数オーバーのためはこれの次に乗せます。 |
No.17237![]() |
Re:次のプログラムを関数を使って簡略化したいのですが・・・ 投稿者---新米(2004/10/12 15:59:17) |
||
私の書いたプログラムです。追記ですが、もし他に良い方法があれば教えてください。よろしくお願いします。 /* データファイルとリソースファイルを読み込みリソースファイルの型に合った形で出力する */ #include<stdio.h> #include<string.h> #include<stdlib.h> typedef struct DATA{ char name[100]; /* リソースファイルのデータの種類を入れる */ int size; /* リソースファイルのバイト数を入れる */ char kata[100]; /* リソースファイルのそれぞれの型を入れる */ }DATA; //int resorce_k(void); int resorce_k(char namebox[100], int sizebox[100], char katabox[100]){ FILE *r_fp; struct DATA data[20]; int i,j=0; char temp[100],temp1[100]; /* 代わりに入れとく入れ物 */ /* リソースファイルオープン */ if((r_fp = fopen("resorcsfile4.txt","r"))==NULL){ printf("リソースファイルオープンエラー\n"); } for(i=0;;i++){ fscanf(r_fp,"%s ",&temp); printf("%s \n",temp); if(temp[0] == temp1[0]){ /* 新しい読み込みなしでfor文終了 */ break; } strcpy(temp1 ,temp); /* リソースファイルが no = d name = 6s addr = 8s だった場合に 読み込んだ順に 1 2 3 4 5 6 7 8 9 となるので以下のようにした */ if((i+2+1)%3==0){ /* ↑でいう1,4,7番目(データ項目)を取得 */ strcpy(data[j].name ,temp); } if((i+1)%3==0){ /* ↑でいう3,6,9番目(バイト数)を取得 */ strcpy(data[j].kata ,temp); if(temp[0] == 'd'){ /* dの場合int型(4バイト)取得 */ data[j].size = 4; strcpy(data[j].kata ,"int"); }else if(strcmp(&temp[0], "s" )==0){ printf("リソースファイルのchar型にサイズを指定してください。\n"); break; }else{ /* sの場合それぞれのbit取得 */ data[j].size = atoi(data[j].kata); strcpy(data[j].kata ,"char"); } j++; } } /* 名前・サイズ・型名をそれぞれ表示 */ for(i=0;i<j;i++){ printf("data[%d].name = %s \n",i,data[i].name); printf("data[%d].size = %d \n",i,data[i].size); printf("data[%d].kata = %s \n",i,data[i].kata); } *namebox = *data[0].name; *sizebox = data[0].size; *katabox = *data[0].kata; printf("name = %s \n",*namebox); printf("size = %d \n",&sizebox[0]); printf("kata = %s \n",katabox); fclose(r_fp); return(j-1); } int data_k(int stop){ FILE *d_fp; struct DATA data[20]; char inbuf[100]; int nRead; int num; int i; inbuf[0] = 0x00; /* データファイルオープン */ if((d_fp = fopen("TEST4.DAT","rb"))==NULL){ printf("データファイルオープンエラー\n"); } printf("@\n"); /****************ここからデータファイル表示********************/ for(i=0;;i++){ /* 型がint型の場合 */ if(strcmp(data[i].kata ,"int")==0){ nRead = fread(&num,sizeof(char), sizeof(int),d_fp); if(nRead != sizeof(int)) { break; } printf(" %s: %d \n",data[i].name,num); /* 型がchar型の場合 */ }else{ /* 指定された文字でバッファを初期化 */ memset(inbuf, 0x00, sizeof(inbuf)); nRead = fread(&inbuf,sizeof(char),data[i].size,d_fp); if(nRead != data[i].size) { break; } printf(" %s: %s \n",data[i].name,inbuf); } if(i==stop){ i = -1; } } /* リソースファイル・データファイルを閉じる */ fclose(d_fp); return 10; } void main(){ struct DATA data[20]; char namebox[100],katabox[100]; int sizebox[100]; int stop; int gool; stop = resorce_k(&namebox[0], &sizebox[0], &katabox[0]); // stop = resorce_k(namebox[100], sizebox[100], katabox[100]); gool = data_k(stop); printf("完了合図:%d\n",gool); } |
No.17252![]() |
Re:次のプログラムを関数を使って簡略化したいのですが・・・ 投稿者---ぽこ(2004/10/12 20:47:31) |
||
>次のプログラムを関数を使って簡略化したいのですが、うまくいきません。コンパイルは通るのですが、強制終了されてしまいます。私の考えでは、式のプログラムの中でリソースファイルとデータファイルの所を関数化しようと思っています。 まずは、プログラムを正常動作させることを考えませんか? ファイル開けない時に処理を継続したり、初期化も代入もされていない temp1[0]と比較したり、まずそうな箇所は多々あります。 |
No.17271![]() |
Re:次のプログラムを関数を使って簡略化 投稿者---新米(2004/10/13 11:35:08) |
||
>まずは、プログラムを正常動作させることを考えませんか? ですね。すみません。 >ファイル開けない時に処理を継続したり、初期化も代入もされていない >temp1[0]と比較したり、まずそうな箇所は多々あります。 一応少し訂正しました。 新しい質問なんですが、今ここまでプログラムが出来ています。で、 resoce_kの関数の所で最後に作られた構造体の中身をdata_kの方の関数に持って行きたいのですが、どうすればいいでしょうか?なんとなくポインタと思いやっているのですが、コンパイルが通りません。うまくいっているところまでのプログラムを載せています。 /* データファイルとリソースファイルを読み込みリソースファイルの型に合った形で出力する */ #include<stdio.h> #include<string.h> #include<stdlib.h> typedef struct DATA{ char name[100]; /* リソースファイルのデータの種類を入れる */ int size; /* リソースファイルのバイト数を入れる */ char kata[100]; /* リソースファイルのそれぞれの型を入れる */ }DATA; int resorce_k(int i,int j, char temp[100], int end){ struct DATA data[20]; // char temp[100],temp1[100]; /* 代わりに入れとく入れ物 */ // int j = 0; /* リソースファイルが no = d name = 6s addr = 8s だった場合に 読み込んだ順に 1 2 3 4 5 6 7 8 9 となるので以下のようにした */ // printf("temp = %s \n",temp); // printf("i = %d\n",i); if(end != 1){ if((i+2+1)%3==0){ /* ↑でいう1,4,7番目(データ項目)を取得 */ strcpy(data[j].name ,temp); } if((i+1)%3==0){ /* ↑でいう3,6,9番目(バイト数)を取得 */ strcpy(data[j].kata ,temp); if(temp[0] == 'd'){ /* dの場合int型(4バイト)取得 */ data[j].size = 4; strcpy(data[j].kata ,"int"); }else if(strcmp(&temp[0], "s" )==0){ printf("リソースファイルのchar型にサイズを指定してください。\n"); // break; }else{ /* sの場合それぞれのbit取得 */ data[j].size = atoi(data[j].kata); strcpy(data[j].kata ,"char"); } j++; } /* 名前・サイズ・型名をそれぞれ表示 */ }else{ for(i=0;i<j;i++){ printf("data[%d].name = %s \n",i,data[i].name); printf("data[%d].size = %d \n",i,data[i].size); printf("data[%d].kata = %s \n",i,data[i].kata); } } return j; // stop = j-1; } int data_k(){ } void main(){ FILE *d_fp, *r_fp; struct DATA data[20]; char temp[100],temp1[100]; char inbuf[100]; int i,j=0,end=0; /* i,jはfor文で使う。sizeはリソースファイルのsizeの合計を入れる */ int nRead; int num; int stop; /* リソースファイルオープン */ if((r_fp = fopen("resorcsfile4.txt","r"))==NULL){ printf("リソースファイルオープンエラー\n"); exit(1); } /* データファイルオープン */ if((d_fp = fopen("TEST4.DAT","rb"))==NULL){ printf("データファイルオープンエラー\n"); exit(1); } for(i=0;;i++){ fscanf(r_fp,"%s ",&temp[0]); if(temp[0] == temp1[0]){ /* 新しい読み込みなしでfor文終了 */ end = 1; i--; resorce_k(i,j,&temp[0],end); break; } strcpy(temp1 ,temp); j = resorce_k(i,j,&temp[0],end); } data_k(); /* リソースファイル・データファイルを閉じる */ fclose(d_fp); fclose(r_fp); } |
No.17276![]() |
Re:次のプログラムを関数を使って簡略化 投稿者---かずま(2004/10/13 11:59:35) |
||
> resoce_kの関数の所で最後に作られた構造体の中身をdata_kの方の > 関数に持って行きたいのですが、どうすればいいでしょうか? 関数 resource_kの局所データは resource_kを抜けるとなくなってしまいます。 関数 resource_k と関数 data_k で共通のデータを使いたかったら そのデータの格納場所(変数)は、main で用意したほうがよいでしょう。 int resource_k(struct DATA *data, int i, int j, int end) { ... } int data_k(struct DATA *data, int n) { ... } int main(void) { struct DATA data[20]; ... n = resource_k(data, i, j, end); data_k(data, n); return 0; } ところで、元のプログラムの main の temp1[0] の値は何ですか? |
No.17278![]() |
Re:次のプログラムを関数を使って簡略化 投稿者---新米(2004/10/13 12:54:16) |
||
>> resoce_kの関数の所で最後に作られた構造体の中身をdata_kの方の >> 関数に持って行きたいのですが、どうすればいいでしょうか? > >関数 resource_kの局所データは resource_kを抜けるとなくなってしまいます。 >関数 resource_k と関数 data_k で共通のデータを使いたかったら >そのデータの格納場所(変数)は、main で用意したほうがよいでしょう。 > やはりそれしかないですか・・・ご指摘ありがとうございます。 int resource_k(struct DATA *data, int i, int j, int end) { ... } int data_k(struct DATA *data, int n) { ... } int main(void) { struct DATA data[20]; ... n = resource_k(data, i, j, end); data_k(data, n); return 0; } >ところで、元のプログラムの main の temp1[0] の値は何ですか? temp1[0]にはアドレスが入っています。(と思います^^; リソースファイルを入れています。リソースファイルの中身は ADDR = 3s NO = d NAME = 4s FROM = 5s で temp1[0]を%dで表記すると 65 61 51 78 61 100 78 61 52 70 61 53 53 となっています。 53 53 と同じものがきた時にfor文を抜けるようにしています。 かずまさんの書いてくれたものでもう一度考えてみます。ありがとうございます。また書くと思うのでその時はお願いしますm(__)m |
No.17279![]() |
Re:次のプログラムを関数を使って簡略化(追記) 投稿者---新米(2004/10/13 13:07:15) |
||
int resource_k(struct DATA *data, int i, int j, int end) { ... } int data_k(struct DATA *data, int n) { ... } int main(void) { struct DATA data[20]; ... n = resource_k(data, i, j, end); data_k(data, n); return 0; } </pre> この場合なんですが、ファイルを開くところもmainでした方いいのでしょうか?色々試したのですが、関数の中でファイルを開くと、関数が呼び出されるたびに、ファイルを開くので同じものばかり呼び出してしまいます。 それで今回さっきほどのようなプログラムになってしまったのですが、かずまさんのおっしゃるとうりmainに構造体のデータをもってこれませんでした。それとも関数の呼び出しを一回で(関数の中でファイルを開いて)、ファイルの読み込みをするべきなのでしょうか? よかったらご指導よろしくお願いします。 |
No.17280![]() |
Re:次のプログラムを関数を使って簡略化(追記) 投稿者---ぽこ(2004/10/13 14:27:48) |
||
>この場合なんですが、ファイルを開くところもmainでした方いいのでしょうか?色々試したのですが、関数の中でファイルを開くと、関数が呼び出されるたびに、ファイルを開くので同じものばかり呼び出してしまいます。 ファイル名を引数に取れば良いのではないでしょうか? |
No.17281![]() |
Re:次のプログラムを関数を使って簡略化(追記) 投稿者---新米(2004/10/13 14:38:34) |
||
>ファイル名を引数に取れば良いのではないでしょうか? なるほど、ファイル名を引数ですか・・・思いつきもしませんでした^^; 一応、かずまさんのアドバイスのもとやってなんとか完成することができました。 (完成と言えるのかわかりませんが--;) そのプログラムを載せときます。もし、まだ「ここはこうした方がいいのではないか?」とか、「ここはおかしいだろ」という場所があれば、どうかご指摘ご指導のほどよろしくお願いします。 /* データファイルとリソースファイルを読み込みリソースファイルの型に合った形で出力する */ #include<stdio.h> #include<string.h> #include<stdlib.h> typedef struct DATA{ char name[100]; /* リソースファイルのデータの種類を入れる */ int size; /* リソースファイルのバイト数を入れる */ char kata[100]; /* リソースファイルのそれぞれの型を入れる */ }DATA; int resource_k(struct DATA *data, int i, int j ) { FILE *r_fp; char temp[100],temp1[100]; /* リソースファイルオープン */ if((r_fp = fopen("resorcsfile4.txt","r"))==NULL){ printf("リソースファイルオープンエラー\n"); exit(1); } temp1[0]=0x00; for(i=0;;i++){ fscanf(r_fp,"%s ",&temp[0]); if(temp[0] == temp1[0]){ /* 新しい読み込みなしでfor文終了 */ break; } strcpy(temp1 ,temp); /* リソースファイルが no = d name = 6s addr = 8s だった場合に 読み込んだ順に 1 2 3 4 5 6 7 8 9 となるので以下のようにした */ if((i+2+1)%3==0){ /* ↑でいう1,4,7番目(データ項目)を取得 */ strcpy(data[j].name ,temp); } if((i+1)%3==0){ /* ↑でいう3,6,9番目(バイト数)を取得 */ strcpy(data[j].kata ,temp); if(temp[0] == 'd'){ /* dの場合int型(4バイト)取得 */ data[j].size = 4; strcpy(data[j].kata ,"int"); }else if(strcmp(&temp[0], "s" )==0){ printf("リソースファイルのchar型にサイズを指定してください。\n"); break; }else{ /* sの場合それぞれのbit取得 */ data[j].size = atoi(data[j].kata); strcpy(data[j].kata ,"char"); } j++; } } /* 名前・サイズ・型名をそれぞれ表示 */ for(i=0;i<j;i++){ printf("data[%d].mame = %s \n",i,data[i].name); printf("data[%d].size = %d \n",i,data[i].size); printf("data[%d].kata = %s \n",i,data[i].kata); } fclose(r_fp); return (j-1); } int data_k(struct DATA *data, int n) { FILE *d_fp; char inbuf[100]; int i,j; int nRead; int num; /* データファイルオープン */ if((d_fp = fopen("TEST4.DAT","rb"))==NULL){ printf("データファイルオープンエラー\n"); exit(1); } for(i=0;;i++){ /* 型がint型の場合 */ if(strcmp(data[i].kata ,"int")==0){ nRead = fread(&num,sizeof(char), sizeof(int),d_fp); if(nRead != sizeof(int)) { break; } printf(" %s: %d \n",data[i].name,num); /* 型がchar型の場合 */ }else{ /* 指定された文字でバッファを初期化 */ memset(inbuf, 0x00, sizeof(inbuf)); nRead = fread(&inbuf,sizeof(char),data[i].size,d_fp); if(nRead != data[i].size) { break; } printf(" %s: %s \n",data[i].name,inbuf); } if(i==n){ i = -1; } } fclose(d_fp); return 0; } int main(void) { struct DATA data[20]; int i=0,j=0,n; n = resource_k(data, i, j); data_k(data, n); return 0; } |
No.17288![]() |
次のプログラムで指定した行のみ出力、(変更)するには? 投稿者---新米(2004/10/14 11:32:19) |
||
なんかいもすいません。新米です。おかげさまで関数化に成功しました。で、次なる問題なのですが、出力を指定した、行のみ出力もしくは変更しなければなりません。この場合、どのようにすればいいでしょうか? すいません、まったく方法が思いつかないもので・・・ ヒントでいいのでよろしくお願いします。 /* データファイルとリソースファイルを読み込みリソースファイルの型に合った形で出力する */ #include<stdio.h> #include<string.h> #include<stdlib.h> typedef struct DATA{ char name[100]; /* リソースファイルのデータの種類を入れる */ int size; /* リソースファイルのバイト数を入れる */ char kata[100]; /* リソースファイルのそれぞれの型を入れる */ }DATA; int resource_k(struct DATA *data ,char *R_file) { FILE *r_fp; char temp[100],temp1[100]; int i,j=0; /* リソースファイルオープン */ if((r_fp = fopen(R_file,"r"))==NULL){ printf("リソースファイルオープンエラー\n"); exit(1); } temp1[0]=0x00; for(i=0;;i++){ fscanf(r_fp,"%s ",&temp[0]); if(strcmp(temp,temp1)==0){ /* 新しい読み込みなしでfor文終了 */ break; } strcpy(temp1 ,temp); /* リソースファイルが no = d name = 6s addr = 8s だった場合に 読み込んだ順に 1 2 3 4 5 6 7 8 9 となるので以下のようにした */ if((i+2+1)%3==0){ /* ↑でいう1,4,7番目(データ項目)を取得 */ strcpy(data[j].name ,temp); } if((i+1)%3==0){ /* ↑でいう3,6,9番目(バイト数)を取得 */ strcpy(data[j].kata ,temp); if(temp[0] == 'd'){ /* dの場合int型(4バイト)取得 */ data[j].size = 4; strcpy(data[j].kata ,"int"); }else if(strcmp(&temp[0], "s" )==0){ printf("リソースファイルのchar型にサイズを指定してください。\n"); break; }else{ /* sの場合それぞれのbit取得 */ data[j].size = atoi(data[j].kata); strcpy(data[j].kata ,"char"); } j++; } } /* 名前・サイズ・型名をそれぞれ表示 */ for(i=0;i<j;i++){ printf("data[%d].mame = %s \n",i,data[i].name); printf("data[%d].size = %d \n",i,data[i].size); printf("data[%d].kata = %s \n",i,data[i].kata); } fclose(r_fp); return (j-1); } int data_k(struct DATA *data, char *D_file, int n) { FILE *d_fp; char inbuf[100]; int i,j; int nRead; int num; /* データファイルオープン */ if((d_fp = fopen(D_file,"rb"))==NULL){ printf("データファイルオープンエラー\n"); exit(1); } for(i=0;;i++){ /* 型がint型の場合 */ if(strcmp(data[i].kata ,"int")==0){ nRead = fread(&num,sizeof(char), sizeof(int),d_fp); if(nRead != sizeof(int)) { break; } printf(" %s: %d \n",data[i].name,num); /* 型がchar型の場合 */ }else{ /* 指定された文字でバッファを初期化 */ memset(inbuf, 0x00, sizeof(inbuf)); nRead = fread(&inbuf,sizeof(char),data[i].size,d_fp); if(nRead != data[i].size) { break; } printf(" %s: %s \n",data[i].name,inbuf); } if(i==n){ i = -1; } } fclose(d_fp); return 0; } int main(void) { struct DATA data[20]; char str_r[50]={0},str_d[50]={0}; int n; printf("読み込むリソースファイルを入力してください。\n"); scanf("%s",str_r); printf("読み込むリデータファイルを入力してください。\n"); scanf("%s",str_d); n = resource_k(data,str_r); data_k(data,str_d, n); return 0; } |
No.17292![]() |
Re:次のプログラムで指定した行のみ出力、変更するにあたって 投稿者---新米(2004/10/14 16:17:37) |
||
何回もすいません。新米です。現在指定した行の出力、変更を行っているのですが、以下のプログラムで出力する行を変更する行より後にすると表示されません。あと、全表示で変更する行を指定した場合変更する行以降の表示が行われません。なにが悪いのかわかりません。できればどこがおかしいのか教えていただきたいのですが。よろしくお願いします。 /* データファイルとリソースファイルを読み込みリソースファイルの型に合った形で出力する */ #include<stdio.h> #include<string.h> #include<stdlib.h> typedef struct DATA{ char name[100]; /* リソースファイルのデータの種類を入れる */ int size; /* リソースファイルのバイト数を入れる */ char kata[100]; /* リソースファイルのそれぞれの型を入れる */ }DATA; int resource_k(struct DATA *data ,char *R_file) { FILE *r_fp; char temp[100],temp1[100]; int i,j=0; /* リソースファイルオープン */ if((r_fp = fopen(R_file,"r"))==NULL){ printf("リソースファイルオープンエラー\n"); exit(1); } temp1[0]=0x00; for(i=0;;i++){ fscanf(r_fp,"%s ",&temp[0]); if(strcmp(temp,temp1)==0){ /* 新しい読み込みなしでfor文終了 */ break; } strcpy(temp1 ,temp); /* リソースファイルが no = d name = 6s addr = 8s だった場合に 読み込んだ順に 1 2 3 4 5 6 7 8 9 となるので以下のようにした */ if((i+2+1)%3==0){ /* ↑でいう1,4,7番目(データ項目)を取得 */ strcpy(data[j].name ,temp); } if((i+1)%3==0){ /* ↑でいう3,6,9番目(バイト数)を取得 */ strcpy(data[j].kata ,temp); if(temp[0] == 'd'){ /* dの場合int型(4バイト)取得 */ data[j].size = 4; strcpy(data[j].kata ,"int"); }else if(strcmp(&temp[0], "s" )==0){ printf("リソースファイルのchar型にサイズを指定してください。\n"); break; }else{ /* sの場合それぞれのbit取得 */ data[j].size = atoi(data[j].kata); strcpy(data[j].kata ,"char"); } j++; } } /* 名前・サイズ・型名をそれぞれ表示 */ for(i=0;i<j;i++){ printf("data[%d].mame = %s \n",i,data[i].name); printf("data[%d].size = %d \n",i,data[i].size); printf("data[%d].kata = %s \n",i,data[i].kata); } fclose(r_fp); return (j-1); } int data_k(struct DATA *data, char *D_file, int n ,int line ,int chenge) { FILE *d_fp; char inbuf[100]; int i,j; int nRead; int num; int after_d; char after_s[10]={0}; int count=0; /* データファイルオープン */ if((d_fp = fopen(D_file,"rb"))==NULL){ printf("データファイルオープンエラー\n"); exit(1); } for(i=0;;i++){ count++; /* 型がint型の場合 */ if(strcmp(data[i].kata ,"int")==0){ nRead = fread(&num,sizeof(char), sizeof(int),d_fp); if(nRead != sizeof(int)) { break; } if(line == count || chenge == count){ if(chenge == count){ printf("(変更前)[%d] %s: %d \n",count,data[i].name,num); printf("変更後の数字の入力\n"); scanf("%d",&after_d); num = after_d; printf("(変更後)[%d] %s: %d \n",count,data[i].name,num); break; }else{ printf("[%d] %s: %d \n",count,data[i].name,num); } }else if(line == 0){ printf("[%d] %s: %d \n",count,data[i].name,num); } /* 型がchar型の場合 */ }else{ /* 指定された文字でバッファを初期化 */ memset(inbuf, 0x00, sizeof(inbuf)); nRead = fread(&inbuf,sizeof(char),data[i].size,d_fp); if(nRead != data[i].size) { break; } if(line == count || chenge == count){ if(chenge == count){ printf("(変更前)[%d] %s: %s \n",count,data[i].name,inbuf); printf("変更後の文字列の入力\n"); scanf("%s",after_s); strcpy(inbuf , after_s); printf("(変更後)[%d] %s: %s \n",count,data[i].name,inbuf); break; }else{ printf("[%d] %s: %s \n",count,data[i].name,inbuf); } }else if(line == 0){ printf("[%d] %s: %s \n",count,data[i].name,inbuf); } } if(i==n){ i = -1; } } if(line > count){ printf("指定した行は存在しないため表示されませんでした。\n"); } fclose(d_fp); return 0; } int main(void) { struct DATA data[20]; char str_r[50]={0},str_d[50]={0}; int n; int line; int chenge; printf("読み込むリソースファイルを入力してください。\n"); scanf("%s",str_r); printf("読み込むリデータファイルを入力してください。\n"); scanf("%s",str_d); printf("表示したい行番号を入力してください。(全行表示の場合は0)\n"); scanf("%d",&line); printf("内容を変更したい行を入力してください。(ない場合は0)\n"); scanf("%d",&chenge); n = resource_k(data,str_r); data_k(data,str_d, n ,line ,chenge); return 0; } |
No.17293![]() |
Re:次のプログラムで指定した行のみ出力、変更するにあたって 投稿者---REE(2004/10/14 16:39:52) |
||
変更後にbreakしているからでは? |
No.17294![]() |
Re:次のプログラムで指定した行のみ出力、変更するにあたって 投稿者---新米(2004/10/14 16:44:51) |
||
>変更後にbreakしているからでは? はい、そのとうりでした。ご指摘ありがとうございました。 |
No.17295![]() |
Re:次のプログラムで指定した行を変更し保存するにあたって 投稿者---新米(2004/10/14 16:54:54) |
||
またまたすいません。新米です。現在ファイルをrbモードで開いているのですが、ファイルの内容変更後、それを保存することはwbモードでなくても出来るのでしょうか? |
No.17296![]() |
Re:次のプログラムで指定した行を変更し保存するにあたって 投稿者---επιστημη(2004/10/14 17:16:30) |
||
>またまたすいません。新米です。現在ファイルをrbモードで開いているのですが、ファイルの内容変更後、それを保存することはwbモードでなくても出来るのでしょうか? なんだかなぁ… やってみたらええでしょうに。 |
No.17311![]() |
Re:次のプログラムで指定した行を変更し保存するにあたって 投稿者---新米(2004/10/15 09:50:17) |
||
>なんだかなぁ… やってみたらええでしょうに。 大変失礼しました。やってみました。 で、以下のようにしたのですが、思うように行きません。変更したい行が追加という形になってしまします。私にはなにが悪いのかわかりません。 どうかご指摘お願いいたします。 /* データファイルとリソースファイルを読み込みリソースファイルの型に合った形で出力する */ #include<stdio.h> #include<string.h> #include<stdlib.h> typedef struct DATA{ char name[100]; /* リソースファイルのデータの種類を入れる */ int size; /* リソースファイルのバイト数を入れる */ char kata[100]; /* リソースファイルのそれぞれの型を入れる */ }DATA; int resource_k(struct DATA *data ,char *R_file) { FILE *r_fp; char temp[100],temp1[100]; int i,j=0; /* リソースファイルオープン */ if((r_fp = fopen(R_file,"r"))==NULL){ printf("リソースファイルオープンエラー\n"); exit(1); } temp1[0]=0x00; for(i=0;;i++){ fscanf(r_fp,"%s ",&temp[0]); if(strcmp(temp,temp1)==0){ /* 新しい読み込みなしでfor文終了 */ break; } strcpy(temp1 ,temp); /* リソースファイルが no = d name = 6s addr = 8s だった場合に 読み込んだ順に 1 2 3 4 5 6 7 8 9 となるので以下のようにした */ if((i+2+1)%3==0){ /* ↑でいう1,4,7番目(データ項目)を取得 */ strcpy(data[j].name ,temp); } if((i+1)%3==0){ /* ↑でいう3,6,9番目(バイト数)を取得 */ strcpy(data[j].kata ,temp); if(temp[0] == 'd'){ /* dの場合int型(4バイト)取得 */ data[j].size = 4; strcpy(data[j].kata ,"int"); }else if(strcmp(&temp[0], "s" )==0){ printf("リソースファイルのchar型にサイズを指定してください。\n"); break; }else{ /* sの場合それぞれのbit取得 */ data[j].size = atoi(data[j].kata); strcpy(data[j].kata ,"char"); } j++; } } /* 名前・サイズ・型名をそれぞれ表示 */ for(i=0;i<j;i++){ printf("data[%d].mame = %s \n",i,data[i].name); printf("data[%d].size = %d \n",i,data[i].size); printf("data[%d].kata = %s \n",i,data[i].kata); } fclose(r_fp); return (j-1); } int data_k(struct DATA *data, char *D_file, int n ,int line ,int chenge) { FILE *d_fp; char inbuf[100],buf[100][100]={0}; int i,j; int nRead; int num; int after_d; char after_s[10]={0}; int count=0; /* データファイルオープン */ if((d_fp = fopen(D_file,"r+b"))==NULL){ printf("データファイルオープンエラー\n"); exit(1); } for(i=0;;i++){ count++; /* 型がint型の場合 */ if(strcmp(data[i].kata ,"int")==0){ nRead = fread(&num,sizeof(char), sizeof(int),d_fp); if(nRead != sizeof(int)) { break; } if(line == count || chenge == count){ if(chenge == count){ printf("(変更前)[%d] %s: %d \n",count,data[i].name,num); printf("変更後の数字の入力\n"); scanf("%d",&after_d); num = after_d; printf("(変更後)[%d] %s: %d \n",count,data[i].name,num); buf[i][0]=num; }else{ printf("[%d] %s: %d \n",count,data[i].name,num); buf[i][0]=num; } }else if(line == 0){ printf("[%d] %s: %d \n",count,data[i].name,num); } /* 型がchar型の場合 */ }else{ /* 指定された文字でバッファを初期化 */ memset(inbuf, 0x00, sizeof(inbuf)); nRead = fread(&inbuf,sizeof(char),data[i].size,d_fp); if(nRead != data[i].size) { break; } // strcpy(&buf[i], &inbuf[0]); if(line == count || chenge == count){ if(chenge == count){ printf("(変更前)[%d] %s: %s \n",count,data[i].name,inbuf); printf("変更後の文字列の入力\n"); scanf("%s",after_s); strcpy(inbuf , after_s); printf("(変更後)[%d] %s: %s \n",count,data[i].name,inbuf); strcpy(&buf[i][0], &inbuf[0]); }else{ strcpy(&buf[i][0], &inbuf[0]); printf(":[%d] %s: %s \n",count,data[i].name,inbuf); } }else if(line == 0){ printf("[%d]: %s: %s \n",count,data[i].name,inbuf); } } if(i==n){ i = -1; } } if(line > count){ printf("指定した行は存在しないため表示されませんでした。\n"); } for(i=0;buf[i][0]!='\0';i++){ fprintf(d_fp,"%s\n",buf); } fclose(d_fp); return 0; } int main(void) { struct DATA data[20]; char str_r[50]={0},str_d[50]={0}; int n; int line; int chenge; printf("読み込むリソースファイルの入力\n"); scanf("%s",str_r); printf("読み込むリデータファイルの入力\n"); scanf("%s",str_d); printf("表示したい行番号の入力(全行表示の場合は0)\n"); scanf("%d",&line); printf("内容を変更したい行の入力(ない場合は0)\n"); scanf("%d",&chenge); n = resource_k(data,str_r); data_k(data,str_d, n ,line ,chenge); return 0; } |
No.17312![]() |
Re:次のプログラムで指定した行を変更し保存するにあたって 投稿者---REE(2004/10/15 10:19:03) |
||
>で、以下のようにしたのですが、思うように行きません。変更したい行が追加という形になってしまします。私にはなにが悪いのかわかりません。 fprintfなどでは、ファイルポインタの位置に書き込まれます。 データが全て読まれた段階では、ファイルポインタは、ファイルの末尾にありますので、そのままでは、末尾に追加されます。 fseek関数を調べてみてください。 |
No.17313![]() |
Re:次のプログラムで指定した行を変更し保存するにあたって 投稿者---新米(2004/10/15 10:27:42) |
||
>fseek関数を調べてみてください。 ありがとうございます。さっそく調べてやってみます。 |
No.17322![]() |
Re:次のプログラムで指定した行を変更し保存するにあたって 投稿者---新米(2004/10/15 17:46:44) |
||
fseekを調べてやってみたのですが、いまいちよくわかりません。今現在こういう状態なんですが、なにがおかしいか指摘してもらえないでしょうか。自分なりに色々考えて試したのですが、わかりません(出来ません)。現在は強制終了されてしまう状態です。お願いいたします。 /* データファイルとリソースファイルを読み込みリソースファイルの型に合った形で出力する */ #include<stdio.h> #include<string.h> #include<stdlib.h> typedef struct DATA{ char name[100]; /* リソースファイルのデータの種類を入れる */ int size; /* リソースファイルのバイト数を入れる */ char kata[100]; /* リソースファイルのそれぞれの型を入れる */ }DATA; int resource_k(struct DATA *data ,char *R_file) { FILE *r_fp; char temp[100],temp1[100]; int i,j=0; /* リソースファイルオープン */ if((r_fp = fopen(R_file,"r"))==NULL){ printf("リソースファイルオープンエラー\n"); exit(1); } temp1[0]=0x00; for(i=0;;i++){ fscanf(r_fp,"%s ",&temp[0]); if(strcmp(temp,temp1)==0){ /* 新しい読み込みなしでfor文終了 */ break; } strcpy(temp1 ,temp); /* リソースファイルが no = d name = 6s addr = 8s だった場合に 読み込んだ順に 1 2 3 4 5 6 7 8 9 となるので以下のようにした */ if((i+2+1)%3==0){ /* ↑でいう1,4,7番目(データ項目)を取得 */ strcpy(data[j].name ,temp); } if((i+1)%3==0){ /* ↑でいう3,6,9番目(バイト数)を取得 */ strcpy(data[j].kata ,temp); if(temp[0] == 'd'){ /* dの場合int型(4バイト)取得 */ data[j].size = 4; strcpy(data[j].kata ,"int"); }else if(strcmp(&temp[0], "s" )==0){ printf("リソースファイルのchar型にサイズを指定してください。\n"); break; }else{ /* sの場合それぞれのbit取得 */ data[j].size = atoi(data[j].kata); strcpy(data[j].kata ,"char"); } j++; } } /* 名前・サイズ・型名をそれぞれ表示 */ for(i=0;i<j;i++){ printf("data[%d].mame = %s \n",i,data[i].name); printf("data[%d].size = %d \n",i,data[i].size); printf("data[%d].kata = %s \n",i,data[i].kata); } fclose(r_fp); return (j-1); } int data_k(struct DATA *data, char *D_file, int n ,int line ,int change) { FILE *d_fp; char inbuf[100],buf[100][100]={0}; int i,j; int nRead; int num; int after_d; char after_s[10]={0}; int count=0; /* データファイルオープン */ if((d_fp = fopen(D_file,"r+b"))==NULL){ printf("データファイルオープンエラー\n"); exit(1); } for(i=0;;i++){ count++; /* 型がint型の場合 */ if(strcmp(data[i].kata ,"int")==0){ nRead = fread(&num,sizeof(char), sizeof(int),d_fp); if(nRead != sizeof(int)) { break; } if(line == count || change == count){ if(change == count){ printf("(変更前)[%d] %s: %d \n",count,data[i].name,num); printf("変更後の数字の入力\n"); scanf("%d",&after_d); num = after_d; printf("(変更後)[%d] %s: %d \n",count,data[i].name,num); buf[i][0]=num; fseek(d_fp ,i,SEEK_CUR); fwrite(&buf,sizeof(char), sizeof(int) ,d_fp); }else{ printf("[%d] %s: %d \n",count,data[i].name,num); buf[i][0]=num; } }else if(line == 0){ printf("[%d] %s: %d \n",count ,data[i].name ,num); } /* 型がchar型の場合 */ }else{ /* 指定された文字でバッファを初期化 */ memset(inbuf, 0x00, sizeof(inbuf)); nRead = fread(&inbuf,sizeof(char),data[i].size,d_fp); if(nRead != data[i].size) { break; } if(line == count || change == count){ if(change == count){ printf("(変更前)[%d] %s: %s \n",count,data[i].name,inbuf); printf("変更後の文字列の入力\n"); scanf("%s",after_s); strcpy(inbuf , after_s); printf("(変更後)[%d] %s: %s \n",count,data[i].name,inbuf); strcpy(&buf[i][0], &inbuf[0]); printf("buf[0] = %s\n",buf[0]); /* fwrite(&buf,sizeof(char),data[i].size,d_fp);*/ }else{ strcpy(&buf[i][0], &inbuf[0]); printf(":[%d] %s: %s \n",count,data[i].name,inbuf); } }else if(line == 0){ printf("[%d]: %s: %s \n",count,data[i].name,inbuf); } } if(i==n){ i = -1; } } if(line > count){ printf("指定した行は存在しないため表示されませんでした。\n"); } fclose(d_fp); return 0; } int main(void) { struct DATA data[20]; char str_r[50]={0},str_d[50]={0}; int n; int line; int change; printf("読み込むリソースファイルの入力\n"); scanf("%s",str_r); printf("読み込むリデータファイルの入力\n"); scanf("%s",str_d); printf("表示したい行番号の入力(全行表示の場合は0)\n"); scanf("%d",&line); printf("内容を変更したい行の入力(ない場合は0)\n"); scanf("%d",&change); n = resource_k(data,str_r); data_k(data,str_d, n ,line ,change); return 0; } |
No.17323![]() |
Re:次のプログラムで指定した行を変更し保存するにあたって 投稿者---REE(2004/10/15 18:21:49) |
||
>fseekを調べてやってみたのですが、いまいちよくわかりません。 よく分からないだけでは、どこが分からないのかわかりません。 理解のために、一度小さなテストプログラムで試してみるとよいでしょう。 例:abcdefg と言う内容のファイルの、dだけ大文字にする |
No.17367![]() |
Re:次のプログラムで指定した行を変更し保存するにあたって 投稿者---新米(2004/10/18 13:15:35) |
||
>よく分からないだけでは、どこが分からないのかわかりません。 >理解のために、一度小さなテストプログラムで試してみるとよいでしょう。 > >例:abcdefg と言う内容のファイルの、dだけ大文字にする 一応、いつも新しいライブラリ関数を使う時は、それだけを使うような、プログラムテストは作ってます。今回も「初心者のためのポイントC言語」その他をみて作っているのですが・・・ で、関係ないですが、このやりかたならできるんです。 #include<stdio.h> #include<string.h> #include<stdlib.h> #include <ctype.h> void main(){ FILE *fp; char temp[100]={0}; int i; if((fp = fopen("abcdef.txt","r"))==NULL){ printf("fileopen error \n"); exit(1); } for(i=0;;i++){ temp[i] = fgetc(fp); if(temp[i]=='d'){ temp[i] = toupper(temp[i]); } if(temp[i]=='0'){ break; } printf(" temp[%d] = %c\n",i,temp[i]); } fclose(fp); } で、fseekを使うと(まだ未完成です) #include<stdio.h> #include<string.h> #include<stdlib.h> #include<ctype.h> void main(){ FILE *fp; char temp[100]={0}; int i; if((fp = fopen("abcdef.txt","r"))==NULL){ printf("fileopen error \n"); exit(1); } for(i=0;i<10;i++){ fseek(fp,i,SEEK_SET); str = fgetc(fp); if(temp[i]=='d'){ temp[i] = toupper(temp[i]); } } fclose(fp); } という感じでいまやっているのですが、fseek関数自体がどうのような動きをするのかがわかりません。SEEK_SETでファイルの位置を動かすとかが、どういう動きをするのかがわからないのです。よろしければご教授お願いします。何度もすいません。 |
No.17388![]() |
Re:次のプログラムで指定した行を変更し保存するにあたって 投稿者---REE(2004/10/19 10:27:14) |
||
int str; while( (str = fgetc(fp)) != EOF){ if(str == 'd'){ fseek(fp, -1, SEEK_CUR); /* ファイルポインタを1文字戻す */ fputc('D', fp); /* Dを上書きする */ } } |
No.17426![]() |
Re:次のプログラムで指定した行を変更し保存するにあたって 投稿者---かずま(2004/10/21 00:58:13) |
||
> int str; > while( (str = fgetc(fp)) != EOF){ > if(str == 'd'){ > fseek(fp, -1, SEEK_CUR); /* ファイルポインタを1文字戻す */ > fputc('D', fp); /* Dを上書きする */ > } > } gcc では、思ったとおり、'd' を 'D' に変えてくれるようですが、 Visual C++ や Borland C++ では、ダメです。 fopen のマニュアルに書いてありますが、read/write ストリームでは、入力 と出力の間に fseek または fgetpos などを実行しなければなりません。 上記のプログラムでは、fputs('D', fp); の後に fseek(fp, 0, SEEK_CUR); を 追加するとよいでしょう。 |
No.17457![]() |
Re:次のプログラムで指定した行を変更し保存するにあたって 投稿者---かずま(2004/10/22 17:28:37) |
||
元の質問に対する回答がないようなので、参考となるプログラムを書いてみました。 #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { char *name; int size; char type; } DATA; int resource_k(DATA *data, FILE *fp) { char name[256], type[256]; int i, n; for (n = 0; fscanf(fp, "%s =%s", name, type) == 2; n++) { data[n].name = strdup(name); if (data[n].name == NULL) puts("out of memory"), exit(1); if (type[0] == 'd') data[n].size = sizeof(int), data[n].type = 'd'; else if (sscanf(type, "%d%c", &data[n].size, &data[n].type) != 2 || data[n].size <= 0 || data[n].type != 's') puts("resource format error"), exit(1); } for (i = 0; i < n; i++) { printf("data[%d].name = %s\n", i, data[i].name); printf("data[%d].size = %d\n", i, data[i].size); printf("data[%d].type = %s\n", i, data[i].type=='d' ? "int" : "char"); } return n; } int data_k(const DATA *data, FILE *fp, int n, int line, int change) { int i, j = 0, size, len, num; char str[256]; for (i = 1; ; i++) { size = data[j].size; if (data[j].type == 'd') { if (fread(&num, size, 1, fp) != 1) break; if (i == change) { printf("(変更前)[%d] %s: %d \n", i, data[j].name, num); printf("変更後の数字の入力\n"); if (scanf("%d", &num) != 1) exit(1); printf("(変更後)[%d] %s: %d \n", i, data[j].name, num); fseek(fp, -size, SEEK_CUR); fwrite(&num, size, 1, fp); fseek(fp, 0, SEEK_CUR); } else if (i == line || line == 0) printf("[%d] %s: %d \n", i, data[j].name, num); } else { if (fread(str, size, 1, fp) != 1) break; if (i == change) { printf("(変更前)[%d] %s: %.*s\n", i, data[j].name, size, str); printf("変更後の文字列の入力\n"); if (scanf("%s", str) != 1) exit(1); len = strlen(str); if (len < size) memset(str + len, ' ', size - len); printf("(変更後)[%d] %s: %.*s\n", i, data[j].name, size, str); fseek(fp, -size, SEEK_CUR); fwrite(str, size, 1, fp); fseek(fp, 0, SEEK_CUR); } else if (i == line || line == 0) printf("[%d] %s: %.*s \n", i, data[j].name, size, str); } if (++j >= n) j = 0; } if (line > i) puts("指定した行は存在しないため表示されませんでした。"); return 0; } int main(void) { FILE *fp; DATA data[20]; char res_file[256], data_file[256]; int n, line, change; printf("読み込むリソースファイルの入力\n"); if (scanf("%s", res_file) != 1) return 1; printf("読み込むリデータファイルの入力\n"); if (scanf("%s", data_file) != 1) return 1; printf("表示したい行番号の入力(全行表示の場合は0)\n"); if (scanf("%d", &line) != 1) return 1; printf("内容を変更したい行の入力(ない場合は0)\n"); if (scanf("%d", &change) != 1) return 1; fp = fopen(res_file, "r"); if (fp == NULL) puts("リソースファイルオープンエラー"), exit(1); n = resource_k(data, fp); fclose(fp); fp = fopen(data_file, "r+b"); if (fp == NULL) puts("データファイルオープンエラー"), exit(1); data_k(data, fp, n, line, change); fclose(fp); return 0; } |