みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

ファイル操作やポインタ、構造体について(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);
となっていて、どうやるのかまったく見当もつきません。

稚拙な文で伝わりにくいかもしれませんが、
変更のやり方についてご教授願います。
見難くて申し訳ありません。
どうか宜しくお願いします。

投稿日時 - 2007-12-04 21:51:30

QNo.3571376

困ってます

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

>指定したIDの内容を書き換えるにはポインタを2つ使う方法しか思いつかないのですが、...

要は、既に存在するファイル中に書き込まれている、誰か(検索ヒットした人)のIDを書き換えたい、ということだよね。
だとしたらポインタを2つどころか、一つもいらないと思うよ。

No.1さんが回答を書かれているので、詳細はNo.1さんのを参考にしてください。

---
あとこれは回答じゃないけど、なんつーのかな、悪いけどアナだらけのプログラムだぞ。いくら学生さんの課題とはいえ。

例えば、
scanf("%d %s %d %d", &students.id, students.name, &students.gp, &students.credit);
で、25文字以上の学生名を入力された場合の処置(ガード)が無いよね。
もしそれやられたら一発でアウトだよ。その後に続くgpとかcreditを壊しちゃうからね。

それに、argv[1]はファイル名であることが前提とされてるけど、
せめてそれが本当に存在するファイルかどうかを確認するコードは入れた方がいいよ。

あと、小姑のようで悪いが、(argc == 1)のときに、set filename とモニタに表示されても、何だかイマイチわからんと思うがな..

投稿日時 - 2007-12-06 14:16:14

ANo.3

^^;
スペルミスしてます。
ftellです。

投稿日時 - 2007-12-04 23:45:55

ANo.2

>fteel
ftell ?

投稿日時 - 2007-12-04 23:37:11

ANo.1

"r+"でfopenすれば書き換え可能になりますよ。
current = fteel(fp);
でファイル位置が分かります。

例)fseekでfscanfを行う前の位置に戻る。
current = fteel(fp);
fscanf(fp,"%d %s %d %d", &id, name, &gp, &credit);
fseek(fp, current, SEEK_SET);

ただ、直接書き換える場合、色々と決まり事を作っておかないと、データを破壊する恐れがあります。
あとは試行錯誤してみてください。

※ 細かいことは関数リファレンスを参照してください。

投稿日時 - 2007-12-04 22:49:53

あなたにオススメの質問