• 締切済み

C言語:ファイル操作

ファイル操作がよくわかりません。 struct music{ char *artist[256]; char *title[256]; int year; }list[100]; という構造体に格納されたデータをファイルに書き込みたいのですが、 fwrite((struct music *)list,sizeof(struct list),100,fp); とするとyearが表示されません。 また、ファイルへの出力形式は Artist: list[0].artist Title: list[0].title Year: list[0].year のようにしたいのですが「Artist:」などの部分はどのようにファイルへ書き込めばいいのでしょうか。 ファイル操作が全くわかっていない状況です。 参考サイトなど ありましたら教えてください。 よろしくお願いします。

みんなの回答

回答No.5

#1です。 >Artist: list[0].artist >Title: list[0].title >Year: list[0].year ↑の書式にこだわりますか? 私だったら↓のようにします。 int i; fputs("Artist, Title, Year\n", fp); /* 項目名 */ for(i = 0; i < 100; i++) { fprintf(fp, "\"%s\", \"%s\", %d\n", list[i].artist, list[i].title, list[i].year); /* 各データを1行で出力 */ } こうやって出力するファイル名の拡張子を .CSV とします。もし、エクセルをお使いであれば、このファイル名をダブルクリックすると、エクセルで開けるかもしれません。

minato1985
質問者

お礼

実は宿題の一部分でして、出力形式、出力するファイルの種類、共に指定されています。 アドバイスありがとうございます。

回答No.4

> fprintf(fp, "Artist: %s\n Title: %s\n Year: %d\n\n", list[i].artist, list[i].title, year); > として保存されたファイル(txt)をみると2番目から > Artist: > list[i].artist とのことですが、考えられるのは、データの先頭に本当に改行が入っているということです。 このあたりは、データの入力方法がわからないと、何とも言えません。 特に、「2番目から」とのことなので、前のデータのゴミが残っているとか、そういう話なのかもしれません。

minato1985
質問者

お礼

ありがとうございます。 データはscanfで構造体へ格納してます。 これが原因でしょうか。

noname#16581
noname#16581
回答No.3

fwrite((struct music *)list,sizeof(struct list),100,fp); -> fwrite((struct music *)list,sizeof(struct list)*100,1,fp); ではないかと。

minato1985
質問者

お礼

回答ありがとうございます。 >fwrite((struct music *)list,sizeof(struct list)*100,1,fp); というのはlist 100個分のサイズということでしょうか。

noname#11843
noname#11843
回答No.2

第一印象からすると、 struct music{ char artist[256]; char title[256]; int year; }list[100]; で、 fwrite(list,sizeof(list[0]),100,fp); が正解だと思われます。 char *artist[256]; だと、アーティスト名を 256 人分保存出来ますよ。 char artist[256]; は、最大 256 文字のアーティスト名ひとり分です。 sizeof(struct list) は、エラーになりませでしたか?(チェックしていません) sizeof(struct music) か、sizeof(list[0]) かいずれかのはずですが。 あわせて、aritist や title への代入の仕方もおそらく間違っています。 (いや、文法的には間違っていないかも) > とするとyearが表示されません。 とのことなので、保存されたファイルをエディタなどで読みたいというところでしょうか? もしも、そういうことであれば、 int i; for(i = 0; i < 100; i++) { fprintf(fp, "Artist: %s\n Title: %s\n Year: %d\n\n", list[i].artist, list[i].title, year); } と別々に書き込む必要があります。

minato1985
質問者

お礼

回答ありがとうございます。 >char *artist[256]; だと、アーティスト名を 256 人分保存出来ますよ。 char artist[256]; は、最大 256 文字のアーティスト名ひとり分です ポインタもイマイチわかってないです。 例のとおりにかいてみただけです……… >sizeof(struct list) は、エラーになりませでしたか?(チェックしていません) sizeof(struct music) か、sizeof(list[0]) かいずれかのはずですが。 間違えました、エラー出ますね(汗 >保存されたファイルをエディタなどで読みたいというところでしょうか? はい、そうです。 fprintf(fp, "Artist: %s\n Title: %s\n Year: %d\n\n", list[i].artist, list[i].title, year); として保存されたファイル(txt)をみると2番目から Artist: list[i].artist と改行が入ってしまうのですが、何故でしょうか。

回答No.1

こんにちは。 普通に fprintf() を使って1レコードずつ出力するのはダメですか?

minato1985
質問者

お礼

回答ありがとうございます。 fprintfで書き込もうとしましたが、「Artist:」などをどこにかけばいいのかわかりませんでした。

関連するQ&A

  • 構造体の文字列データをファイルへ書き込む方法は?

    構造体の文字列データをファイルへ書き込む方法として、構造体のデータを一気に書き込まずに、データ毎に書き込むことを勉強としてやってみようとしました。 数字の場合はうまくいったのですが、文字列の場合が分かりません。 ご存知の方、よろしくお願いいたします。 <数字の場合> typedef struct { int m1, m2; } Data; fwrite(&data[i].m1, sizeof(int), 1, fp); fwrite(&data[i].m2, sizeof(int), 1, fp); <文字列の場合> #include <stdio.h> typedef struct { char m1[10], m2[10]; } Data; int main() { static Data data[3] = { { "a1", "b1"}, { "c1", "d1"}, { "e1", "f1"}, }; Data data2[10]; FILE *fp; int i, n; fp = fopen("file.dat", "wb"); if (fp == NULL) return 1; for (i = 0; i < 3; i++) { fwrite(&data[i].m1, sizeof(Data.m1[10]), 1, fp); ← sizeofでエラーが出る fwrite(&data[i].m2, sizeof(Data.m2[10]), 1, fp); } fclose(fp); 以下省略

  • C言語の構造体参照について

    入力ファイルを読み込み、構造体に格納しています。 構造体の中の、char kumiai_kubun[1]が、'0'および'1'になっているかの参照方法を教えてください。 ファイル011100920001000001の部分の最後の数字(1)が組合区分になります。 ・入力ファイル 000000003820050507200504 011100920001000001 エス事業(協)     9999999999999999 ・プログラム #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <memory.h> #include <errno.h> void print(char* buf, int size); /* 組合情報構造体 */ typedef union kumiaiin_jyouhou { char rawdata[80]; struct hdr { char sikibetu_code[2]; char kensu[8]; char koushin_date[8]; char data_date_year[4]; char data_date_month[2]; char dummy[56]; } header; struct dat { char sikibetu_code[2]; char daicyo_bango[10]; char kumiaiin_bango[5]; char kumiai_kubun[1]; char kaisyamei[46]; char dattai_kaiyaku_ymd[8]; char sakujyo_ymd[8]; } data; } KUMIAIIN_JYOUHOU; int main(int argc, char* argv[]) { KUMIAIIN_JYOUHOU *bufp; FILE *fp; int sts, rtncd; /* 初期化 */ rtncd=0; /* 区切り文字設定 */ strncpy(fs, FS, sizeof(fs)); /* データファイルオープン */ fp = fopen(argv[1], "rb"); /* 組合員情報共用体領域読み込み用メモリの確保 */ bufp = malloc(sizeof(KUMIAIIN_JYOUHOU)); /* ファイル読込 */ while( 1 ) { /* 組合員情報読み込み */ memset(bufp, NULL, sizeof(KUMIAIIN_JYOUHOU)); sts = fread(bufp, sizeof(KUMIAIIN_JYOUHOU), 1, fp); ~組合区分の判定処理~ } fclose(fp); }

  • fwrite文について

    char型で宣言した配列の方はうまくいきましたが、構造体を用いたfwrite文がうまく出力されません。 どうしてでしょうか? #include <stdio.h> #include <string.h> #include <stdlib.h> struct ll{ char name[20]; int ten[3]; }list[3] = { {"aaa", 11}, {"bbb",22}, {"ccc",33} }; FILE *fpbin, *fpcsv; /*FILE構造体(グローバル変数)*/ void main(void) { char i[] = {'a','b'}; fpbin = fopen("data.txt","w"); //fwrite(&i,sizeof(char),2,fpbin); fwrite(&list[0].name,sizeof(struct ll),2,fpbin); fclose(fpbin); }

  • C言語でファイル読み書きを早くしたい。

    いつも利用させてもらって助かっています。 あるプログラムを作成しているのですが、ファイル入力の部分がネックとなってしまって、全体が使いものにならない状況に陥っています。 たくさんのデータをfread1回で読み込むことにより、読み込み速度はずいぶんと改善されましたが、まだ圧倒的に遅い状況です。システムコールを使いましたが、ほとんど改善されませんでした。 読み込み/書き込みの速度を改善する方法として,SSDメモリを使ったりする方法があると思いますが,プログラムの観点から改善できるところはないでしょうか? 下に、ファイル読み込みの部分だけ記述したコードを添付させて頂いたので、改善できる点があれば、御指摘頂けると助かります。 なお、前提として, (1)データはスタック領域だと不足するので、ヒープ領域に確保 (2)データファイルは改行無しの一連のデータ とします。 ちなみに、環境は OS   : CentOS5.3 memory   : 6GB コンパイラ : gcc です。 よろしくお願いします。 //----------------------------------------------------- //通常バージョン #include <stdio.h> #include <stdlib.h> #define SIZE (512*1024*1024) //500MB int main(void) { unsigned long int i; unsigned char *data; FILE *fp; data = (unsigned char *)malloc(SIZE); if(data == NULL) { printf("メモリが確保できません\n"); exit(EXIT_FAILURE); } fp = fopen("filein.dat", "rb"); fread( data, sizeof( unsigned char), (int)SIZE, fp ); fclose(fp); /* //表示 for( i=0; i<SIZE; i++ ){ printf("%2x", data[i]); } puts(""); */ fp = fopen("fileout.dat", "w"); fwrite( data, sizeof( unsigned char), (int)SIZE, fp); fclose(fp); free(data); return 0; } //----------------------------------------------------- //readシステムコールを使ったバージョン #include <stdio.h> #include <stdlib.h> #define SIZE (512*1024*1024) //500MB int main(void) { unsigned long int i; unsigned char *data; data = (unsigned char *)malloc(SIZE); if(data == NULL) { printf("メモリが確保できません\n"); exit(EXIT_FAILURE); } int fd; fd = open( "filein.dat" ); read( fd, data, sizeof(unsigned char)*SIZE); close(fd); /* //表示 for( i=0; i<SIZE; i++ ){ printf("%2x", data[i]); } puts(""); */ FILE *fp; fp = fopen("fileout.dat", "w"); fwrite( data, sizeof( unsigned char), (int)SIZE, fp); fclose(fp); free(data); return 0; }

  • ファイルから読みこんで構造体に格納する、

    shohinというファイルに RX-100 odango_tsumeawase 3000という のが 五行ならんでいるのですが、 これを読み込んで struct shohin{ char code[10]: char name[40]; int price; } にファイルから読みこんで構造体配列に 格納したいのですが、構造体配列に格納する やりかたがわかりません。 構造体配列は struct shohin list[];というのを宣言しています。 ファイルから一行読み込んで fprintf()を使おうと思うのですが、 それはできますか? メンバ毎に格納したいのですが、 それがわかりません お願いします。

  • C言語の構造体のファイルへの書き込みについて

    C言語を勉強しているものです。構造体を指定した番号の場所にファイルへ書き出し、その指定した番号の場所の構造体をファイルから読み込み表示というプログラムを作成したいのですが、うまくいかずどうしたらいいのかわかりません。説明不足ですがご教授お願いします。 ソフトはVisual C++ 2008 Express Editionを使ってます。 ↓↓↓作成ソースコード↓↓↓ #include<stdio.h> #include<stdlib.h> struct S_data{ char Name[10+1];/*名前*/ int Sex;/*性別*/ int Height;/*身長*/ float Weight;/*体重*/ }; void main(){ FILE *Fp; int pos; int Ret; struct S_data tag; memset(&tag,'\0',sizeof(tag)); Fp=fopen("aaa.dat","r+b"); if(Fp==NULL){ Fp=fopen("aaa.dat","w+b"); if(Fp==NULL){ printf("File not open\n"); exit(2); } } while(1){ scanf("%d",&pos); /*番号の入力*/ if (pos==0) break; scanf("%s",tag.Name);/*名前*/ scanf("%d",&tag.Sex);/*性別*/ scanf("%d",&tag.Height);/*身長*/ scanf("%d",&tag.Weight);/*体重*/ fseek(Fp,sizeof(tag)*(pos),SEEK_SET); fwrite(&tag,sizeof(tag),1,Fp); memset(&tag,'\0',sizeof(tag)); } while(1){ scanf("%d",&pos); if (pos==0) break; fseek(Fp,sizeof(tag)*(pos),SEEK_SET); fread(&tag,sizeof(tag),1,Fp); printf("%s\n",tag.Name); printf("%d\n",&tag.Sex); printf("%d\n",&tag.Height); printf("%d\n",&tag.Weight); memset(&tag,'\0',sizeof(tag)); } Ret=fclose(Fp); if (Ret!=0){ exit(2); } }

  • c/c++でのファイルの上書き保存について

     現在cを勉強中なのですがファイル入出力に関して質問があります。 たとえばint型の2つの要素を持つ構造体 typedef struct{ int first,second; }ex; のex型の変数 datをFILE *fpにfwriteで書き込むとすると fwrite(&dat,sizeof(ex),1,fp); と書きますよね。書き込まれる位置はr+モードならファイルポインタの位置から上書き、aなら末尾から追加です。今データは残しておきたいのでwモードは考えていません。  ここで質問なのですが末尾ではなく任意のファイルポインタの位置から追加で書き込んだり、ある特定のレコードを削除したりと言う操作は不可能なのでしょうか?  今のところ、削除については削除したマークをつける方法、レコードの追加についてはテンポラリファイルに追加する前までのレコードをコピーして追加したいレコードを書いてそのあとに残りのデータをコピーした後テンポラリファイルの名前を変える、ということが考えられるのですがもっと効率のよい方法はないのでしょうか? よろしくお願いします。cで無理ならc++でもかまいません。

  • プログラム(C)

    #include <stdio.h> #include <stdlib.h> #define FNAME "smp.bmp" #define WSIZE 256 #define HSIZE 256 #define BSIZE 1024 int main(void) { struct BMPFILEHEADER { ・   ・ }; struct BMPINFOHEADER { ・   ・ }; unsigned char img[HSIZE][WSIZE][3]; unsigned char buf[BSIZE]; struct BMPFILEHEADER lpHead; struct BMPINFOHEADER lpInfo; FILE *fp; int i; int j; int k; fp = fopen(FNAME,"rb"); if (fp==NULL) { printf("ファイルをオープンできません\n"); return 0; } fread(&lpHead.bfType, sizeof(unsigned short),1,fp); fread(&lpHead.bfSize, sizeof(unsigned int),1,fp); fread(&lpHead.bfReserved1, sizeof(unsigned short),1,fp); fread(&lpHead.bfReserved2, sizeof(unsigned short),1,fp); fread(&lpHead.bf0ffBits, sizeof(unsigned int),1,fp); fread(&lpInfo, sizeof(struct BMPINFOHEADER),1,fp); for(i=0;i<HSIZE;i++) { fread(buf,sizeof(unsigned char),WSIZE*3,fp); for(j=0;j<WSIZE;j++) { for(k=0;k<3;k++) { img[HSIZE-1-i][j][k]=buf[j*3+k]; } } } fclose; return 0; } このプログラムはBMP画像を読み込むプログラムなんですが このプログラムに画素値を出力するプログラムにしたいのですがうまくできません。 結果は(真っ白な画像の時)255255255・・・255255と出力したいのです。白黒画像なのでR=G=Bで1画素値は255だけでいいのですが。どうしても255255255や25500などとでてしまいます。 アドバイスお願いします。(800字までなので構造体の宣言は抜いてしましました) 。

  • ファイル操作

    あるファイルから長さの違った数字や文字を読み込んで配列に格納したいのですが数字などの長さが違うとなんかおかしくなってしまいます; 例えば 1 a 1 2 a 2 3 b 3 4 b 4 などのファイルはできるのですが 0 1 2 3 a 3 4 b 4 5 c 5 の場合5つの配列に格納したいのです。1行目で1つ2行目で1つ3行目の 左、真ん中、右の数字でそれぞれ1つづつ格納したいのです。 それで自分でやったのですが typedef struct path{ int left [100]; int right[100]; char center [100]; }Path; int main(int argc,char *argv[]) { FILE *fp; Path path; int i=0; int first; int second[100]; fp = fopen(argv[1],"r"); while(fscanf(fp,"%d %c %d",&path.left[i],&path.center[i],&path.right[i])==3){ i++; } fclose(fp); このようにやると3行目からはきちんとよみこむのですが1、2行目がうまくできません@@; firstとsecondのそれぞれ1、2行目を入れたいのです。 fscanfをもう1つ増やすしてもやってみましたがうまくいきませんでした。 ちなみにfscanf関数のところをならったばかりです。 fgetcとかそのようなのを使うのでしょうか?(よくわからないですけど) よろしくお願いします。ちなみにLinuxでgcc、C言語です。

  • ファイル操作やポインタ、構造体について(C言語)

    C言語の課題で詰まってしまいました。宜しければ助言を宜しくお願いします。 コマンド選択で,0) 終了,1) 追加,2) 検索(id),3)変更 が行える学生成績管理プログラムを作成する。 データは,学生の番号 名前 GP 総単位数 形で学生のデータを持っているファイルである。 #include<stdio.h> #include<stdlib.h> #include<string.h> struct student{ int id; char name[25]; int gp; int credit; }; void add(char *, struct student);//追加 int search(char *, struct student *);//検索 void change(char *, struct student);//指定したidの学生の情報を変更 main(int argc,char *argv[]) { FILE *fp; int i = 0; int num; struct student students; if(argc == 1){ printf("set filename\n"); return 1; } while(1) { printf("1)add 2)search 0)quit "); scanf("%d",&num); if(num == 0) break; /* 追加 */ if(num == 1) { printf("id name gp credit ? "); scanf("%d %s %d %d", &students.id, students.name, &students.gp, &students.credit); add(argv[1], students); } /* 検索 */ if(num == 2) { printf("id ? "); scanf("%d", &students.id); if(search(argv[1],&students)){ printf("%d %s %d %d\n", students.id, students.name, students.gp, students.credit); } else{ printf("ID %d Not Found.\n",students.id); } } if(num == 3){ //変更 } } } /* 追加ルーチン */ void add(char *filename, struct student students) { FILE *fp; if((fp = fopen(filename, "a")) == NULL){ printf("can't open %s\n", filename); exit(1); } fprintf(fp,"%d %s %d %d\n", students.id, students.name, students.gp, students.credit); fclose(fp); } /* 検索ルーチン */ int search(char *filename, struct student *students) { FILE *fp; int id; char name[25]; int gp; int credit; if((fp = fopen(filename, "r")) == NULL){ printf("can't open %s\n", filename); exit(1); } while(fscanf(fp,"%d %s %d %d", &id, name, &gp, &credit) != EOF) { if(id == students->id){ students->id = id; strcpy(students->name ,name); students->gp = gp; students->credit = credit; return 1; } } return 0; fclose(fp); } /* 変更ルーチン */ void add(char *filename, struct student students){ } ------------ここまで------------ ファイルの操作での入出力は"a"や"r"、また"w"を利用するのかとも思いましたが、 指定したIDの内容を書き換えるにはポインタを2つ使う方法しか思いつかないのですが、与えられた問題で、変更のプロトタイプは void change(char *, struct student); となっていて、どうやるのかまったく見当もつきません。 稚拙な文で伝わりにくいかもしれませんが、 変更のやり方についてご教授願います。 見難くて申し訳ありません。 どうか宜しくお願いします。