dポイントプレゼントキャンペーン実施中!

作成したプログラムファイルの管理を行うプログラムというものを学校の課題で行っているのですが、
この課題の制作にあたって、手始めにファイルの保存と読み込みを行う関数を作ろうと思うのですが、ファイルを保存する関数(save)と読み込む関数(load)の作り方、ファイルポインタに格納する方法がわかりません。

現在の途中経過を示します。

#include <stdio.h>
#include <stdlib.h>
struct date {/*作成日付を格納*/
int year;/*年*/
int month;/*月*/
int day;/*日*/
};

struct record {/*レコード*/
char title[30];/*タイトル名*/
char stitle[50];/*副タイトル名*/
struct date adate;/*作成日付*/
char path[50];/*パス名(ファイルがどこのフォルダにあるか)*/
char category[30];/*分類*/
};

int save(struct record file)/*ファイルを保存する*/
{
FILE *fp;
int c;

fp = fopen("program.txt","w");
if (fp == NULL){
fprintf(stderr,"Cannot open file: composition.txt\n");
return -1;
}
fprintf("");
fclose(fp);

}

int load(struct record file)/*ファイルを読み込む*/
{

}

int main()
{
int num;
char file;

int sortnum;

printf("プログラムファイル管理プログラムへようこそ!\n");
do{
printf("何をしますか?\n");
printf("[0:終了、1:保存、2:読み込み]\n");
printf("入力してください: ");
scanf("%d",&num);
if(num==1 && num == 2){
printf("ファイル名を指定してください: ");
scanf("%s",&file);
if(num==1)
save(file);
if(num==2)
load(file);
}else printf("入力された数値が正しくありません。\n");
}while(num != 0)
return 0;
}

A 回答 (4件)

テキストで保存する方法を考えたけど、あまり良くない。

(スペースが含まれてるとfscanfはそこで区切ってしまい、以降は正常に読めなくなる)
これを防ぐにはそれなりの処理を考える必要があるけど、面倒ならバイナリで構造体ごと保存・読み込みをした方が楽。


それにしても、元のソースは誤りが多い。
main関数内をどう直したかぐらいはチェックしてほしい。


#include <stdio.h>

struct date {/*作成日付を格納*/
int year;/*年*/
int month;/*月*/
int day;/*日*/
};

struct record {/*レコード*/
char title[30];/*タイトル名*/
char stitle[50];/*副タイトル名*/
struct date adate;/*作成日付*/
char path[50];/*パス名(ファイルがどこのフォルダにあるか)*/
char category[30];/*分類*/
};

int save(struct record data, const char *fname)/*ファイルを保存する*/
{
FILE *fp;

fp = fopen(fname,"w");
if (fp == NULL){
fprintf(stderr,"Cannot open file: %s\n", fname);
return -1;
}
fprintf(fp, "title=%s\n", data.title);
fprintf(fp, "stitle=%s\n", data.stitle);
fprintf(fp, "date=%04d-%02d-%02d\n", data.adate.year, data.adate.month, data.adate.day);
fprintf(fp, "path=%s\n", data.path);
fprintf(fp, "category=%s\n", data.category);

fclose(fp);
return(0);
}

int load(struct record *pdata, const char *fname)/*ファイルを読み込む*/
{
FILE *fp;

fp = fopen(fname,"r");
if (fp == NULL){
fprintf(stderr,"Cannot open file: %s\n", fname);
return -1;
}
fscanf(fp, "title=%s\n", pdata->title);
fscanf(fp, "stitle=%s\n", pdata->stitle);
fscanf(fp, "date=%04d-%02d-%02d\n", &(pdata->adate.year), &(pdata->adate.month), &(pdata->adate.day));
fscanf(fp, "path=%s\n", pdata->path);
fscanf(fp, "category=%s\n", pdata->category);

fclose(fp);
return(0);
}


int main(void)
{
int num;
char file[256];

int sortnum;

struct record recdata;

printf("プログラムファイル管理プログラムへようこそ!\n");
do{
printf("何をしますか?\n");
printf("[0:終了、1:保存、2:読み込み]\n");
printf("入力してください: ");
scanf("%d",&num);
if(num==1 || num == 2){
printf("ファイル名を指定してください: ");
scanf("%s",&file);
if(num==1)
save(recdata, (const char *)file);
if(num==2)
load(&recdata, (const char *)file);
}else if (num != 0) {
printf("入力された数値が正しくありません。\n");
}
}while(num != 0);
return 0;
}

この回答への補足

回答ありがとうございます。参考にさせていただきましたが、
「collect2: ld はステータス 1 で終了しました」と出てコンパイルすることができません。いったいどうしてでしょうか。
使用しているOSはRED HAT ENTERPRISE LINUX 5、emacsで開発を行い、端末エミュレータを用いてコンパイルしています。

補足日時:2010/07/28 10:36
    • good
    • 0
この回答へのお礼

あの後にいろいろとご意見を参考にして、自分で調べたり人に聞いたりして解決することができました。ありがとうございます。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 128
#define DATASIZE 1000

typedef struct record {
char title[50];
char stitle[100];
char date[16];
char path[200];
char category[50];
} record;

record *head;
record header;
int record_counter = 0;

record ad[DATASIZE];

int main()
{
char dummy[BUFSIZE];
int i,cnt = 0;

puts("*Program Application*");
while(1){
puts("何をしますか?");
printf("0:終了\n1:検索\n2:追加\n3:修正\n4:削除\n5:全体\n6:ソート\n7:ファイルに書き込み\n8:ファイルから読み込み\n入力してください:");/*それぞれの関数をプロトタイプ宣言で呼び出す、省略*/
scanf("%d",&i);
gets(dummy);
if(1 <= i && i <= 8)
cnt = func[i - 1](ad,cnt);
else if(i != 0)
printf("Error!\n");
else if(i == 0)
break;
}
return 0;
}

int write(record *ap,int cnt)
{
FILE *fp;
record *t;
int check = 0;

fp = fopen("record_management.dat","w");
if(fp == NULL){
fprintf(stderr,"Cannot open file.");
return -1;
}

for(check = 0;check < cnt;check++)
{
fprintf(fp,"%d\n",check + 1);
fprintf(fp,"%s\t\n",ap[check].title);
fprintf(fp,"%s\t\n",ap[check].stitle);
fprintf(fp,"%s\t\n",ap[check].date);
fprintf(fp,"%s\t\n",ap[check].path);
fprintf(fp,"%s\t\n",ap[check].category);
t = ap + cnt;
}

fclose(fp);
puts("書き込みが完了しました。\n");
return cnt;
}

int read(record *ap,int cnt)
{
FILE *fp;
record *t = ap;

if((fp = fopen("record_management.dat","r"))==NULL){
fprintf(stderr,"Cannot open file.\n");
return -1;
}

while(fscanf(fp,"%d",&cnt) != EOF)
{
fscanf(fp,"%s\t",t->title);
fscanf(fp,"%s\t",t->stitle);
fscanf(fp,"%s\t",t->date);
fscanf(fp,"%s\t",t->path);
fscanf(fp,"%s\t",t->category);
t = ap + cnt;
}
fclose(fp);
return cnt;
}

お礼日時:2010/08/25 20:02

一応突っ込んでおくと,


scanf("%s",&file);

scanf("%s",file);
の方がよろしいかと>#2. あと, main にある const char * へのキャストはない方が自然でしょう.
後の大枠は #3 に同意. 「どのようにコンパイラを起動してどのようなメッセージが出たのか」を省略したりせず一字一句そのまま書いてください.
    • good
    • 0
この回答へのお礼

なるほど。回答ありがとうございます。

お礼日時:2010/08/25 18:18

記載のソースはWindows XP上のVisual C++ 2008で動作確認しています。


とくに機種依存するような部分は無いと思いますが、Linux上のGCCでは環境条件を整える必要があるのかも知れません。

>「collect2: ld はステータス 1 で終了しました」

これはリンカのエラーですね。エラーの本体(どこでどんなエラーが起きてるのかという情報)はその前に出ているはずなので、それを示してもらわないとちょっと原因がわかりません。
    • good
    • 0
この回答へのお礼

返事が遅れてすみません。この問題については、nkf --overwrite -wでUFT-8に変換することで解決できました。ありがとうございます。

お礼日時:2010/08/23 00:46

>ファイルを保存する関数(save)と読み込む関数(load)の作り方、ファイルポインタに格納する方法がわかりません。



バイナリファイルで構造体の中身を丸ごと読み書きする。
という方法もありましょう。
幸いにして構造体内にポインタはないようですので、それでも動作はするかと。
# ただし、書き出したファイルをテキストエディタなどで確認できませんが。
構造体のメンバを1行1メンバとして読み書きする(int型の日付に関しては数値<>数字変換を行う)という方法もあるでしょう。
「ファイルポインタに格納する」の意味が不明ですが。

あと、掲示されている例ではload()は期待する動作をできないでしょう。
呼び出し元からstruct recordのポインタを渡してもらって、そこに格納するべきです。
# scanf()で渡す場合と同様です。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

お礼日時:2010/07/28 10:29

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!