質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Cygwin

Cygwinは、Unixのような環境を、Windows上で構築させるコマンドラインインターフェースです。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

Q&A

3回答

5473閲覧

C言語で成績評価システムを作成しています。

退会済みユーザー

退会済みユーザー

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Cygwin

Cygwinは、Unixのような環境を、Windows上で構築させるコマンドラインインターフェースです。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

0グッド

0クリップ

投稿2015/12/13 17:44

編集2022/01/12 10:55

###前提・実現したいこと
C言語を使用して成績評価システムを作成しています。
学生情報の追加、検索、表示、変更、削除の5つの機能を実装したいと考えています。

###発生している問題・エラーメッセージ
コンパイルは通るのですが、変更、削除機能がうまく動かず質問しました。

###ソースコード

c

1#include<stdio.h> 2#include<stdlib.h> 3#include<string.h> 4 5struct student{ 6 int id, command; 7 char name[25]; 8 int shiken, enshu, kadai, tsuishi; 9}; 10 11void add(char *, struct student); 12int search(char *, struct student *); 13void list(char *); 14void change(char *, struct student, int); 15void delete(char *, int); 16 17main(int argc,char *argv[]) { 18 FILE *fp; 19 int i = 0; 20 int num; 21 struct student student; 22 23 if(argc == 1){ 24 printf("set filename\n"); 25 exit(1); 26 } 27 28 while(1) { 29 printf("1)add 2)search 3)list 4)change 5)delete 0)quit "); 30 scanf("%d",&num); 31 32 if(num == 0) 33 break; 34 35 /*--- 追加 ---*/ 36 if(num == 1) { 37 printf("id name shiken enshu kadai tsuishi ? "); 38 scanf("%d %s %d %d %d %d", &student.id, student.name, &student.shiken, &student.enshu,&student.kadai, &student.tsuishi); 39 add(argv[1], student); 40 } 41 42 /*--- 検索 ---*/ 43 if(num == 2) { 44 printf("id ? "); 45 scanf("%d", &student.id); 46 if(search(argv[1],&student)){ 47 printf("%d %s %d %d %d %d\n", student.id, student.name, student.shiken, student.enshu, student.kadai, student.tsuishi); 48 } else { 49 printf("ID %d Not Found.\n",student.id); 50 } 51 } 52 53 /* 表示 */ 54 if(num == 3){ 55 list(argv[1]); 56 } 57 58 /*--- 変更 ---*/ 59 if(num == 4){ 60 printf("1)shiken 2)enshu 3)kadai 4)tsuishi 5)all "); 61 scanf("%d", &student.command); 62 if(student.command == 1) { 63 printf("id shiken ?"); 64 scanf("%d %d", &student.id, &student.shiken); 65 change(argv[1], student, student.command); 66 } 67 } 68 69 /*--- 削除 ---*/ 70 if(num == 5){ 71 printf("id ? "); 72 scanf("%d", &student.id); 73 delete(argv[1],student.id); 74 } 75 } 76} 77 78/*--- 追加ルーチン ---*/ 79void add(char *filename, struct student student) { 80 FILE *fp; 81 82 if((fp = fopen(filename, "a")) == NULL){ 83 printf("can't open %s\n", filename); 84 exit(1); 85 } 86 87 fprintf(fp,"%d %s %d %d %d %d\n", student.id, student.name, student.shiken, student.enshu, student.kadai, student.tsuishi); 88 fclose(fp); 89} 90 91/*--- 検索ルーチン ---*/ 92int search(char *filename, struct student *student) { 93 FILE *fp; 94 int id; 95 char name[25]; 96 int shiken, enshu, kadai, tsuishi; 97 98 if((fp = fopen(filename, "r")) == NULL){ 99 printf("can't open %s\n", filename); 100 exit(1); 101 } 102 while(fscanf(fp,"%d %s %d %d %d %d", &id, name, &shiken, &enshu, &kadai, &tsuishi) != EOF) { 103 if(id == student->id){ 104 student->id = id; 105 strcpy(student->name ,name); 106 student->shiken = shiken; 107 student->enshu = enshu; 108 student->kadai = kadai; 109 student->tsuishi = tsuishi; 110 fclose(fp); 111 return 1; 112 } 113 } 114 fclose(fp); 115 return 0; 116} 117 118/*--- 表示ルーチン ---*/ 119void list(char *filename){ 120 FILE *fp; 121 struct student s; 122 if((fp=fopen(filename,"r")) == NULL){ 123 printf("can't open %s\n", filename); 124 exit(1); 125 } 126 while(fscanf(fp,"%d %s %d %d %d %d", &s.id, s.name, &s.shiken, &s.enshu, &s.kadai, &s.tsuishi) != EOF) { 127 printf("%d %s %d %d %d %d\n", s.id, s.name, s.shiken, s.enshu, s.kadai, s.tsuishi); 128 } 129 fclose(fp); 130} 131 132/*--- 変更ルーチン ---*/ 133void change(char *filename, struct student student, int command){ 134 FILE *fp; 135 struct student s[100]; 136 int i, n = 0; 137 if((fp=fopen(filename, "r")) == NULL) { 138 printf("file open error\n"); 139 exit(1); 140 } 141 while(fscanf(fp, "%d %s %d %d %d %d", &s[n].id, s[n].name, &s[n].shiken, &s[n].enshu, &s[n].kadai, &s[n].tsuishi) != EOF) { 142 if(s[n].id == student.id) { 143 if(command == 1) { 144 s[n].shiken = student.shiken; 145 } else if(command == 2) { 146 s[n].enshu = student.enshu; 147 } else if(command == 3) { 148 s[n].kadai = student.kadai; 149 } else if(command == 4) { 150 s[n].tsuishi = student.tsuishi; 151 } else if (command == 5) { 152 strcpy(s[n].name, student.name); 153 s[n].shiken = student.shiken; 154 s[n].enshu = student.enshu; 155 s[n].kadai = student.kadai; 156 s[n].tsuishi = student.tsuishi; 157 } 158 } 159 } 160 fclose(fp); 161} 162 163/*--- 削除ルーチン ---*/ 164void delete(char *filename, int id){ 165 FILE *fp; 166 struct student s[25]; 167 int i,j; 168 if((fp=fopen(filename,"r")) == NULL){ 169 printf("can't open %s\n", filename); 170 exit(1); 171 } 172 for(i=0;fscanf(fp,"%d %s %d %d", &s[i].id, s[i].name, &s[i].shiken, &s[i].enshu) != EOF;i++); 173 fclose(fp); 174 if((fp=fopen(filename,"w")) == NULL){ 175 printf("can't open %s\n", filename); 176 exit(1); 177 } 178 for(j=0;j<i;j++){ 179 if(s[j].id!=id){ 180 fprintf(fp,"%d %s %d %d\r\n", s[j].id, s[j].name, s[j].shiken, s[j].enshu); 181 } 182 } 183 fclose(fp); 184}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

こんにちは。いいところまでできている感じですね。

変更は、ファイルへの保存を忘れているようです。
削除は、kadaiとtsuishiのリード/ライトが漏れてますね。
ついでに、変更時のサブメニューの"2)enshu 3)kadai 4)tsuishi 5)all"についても処理が漏れているようです。


【蛇足かもしれませんが】
実用プログラムなら、入力ミスに対する対応をしておいた方が良いです。
scanf()で読み取れた数が想定外の時って入力ミスがあります。その時、そのまま処理するとほとんどの場合、起きてほしくないことが起きます。
あと、for (略);と記述すると";"を見落としやすいので、空っぽでも下記のように{}ブロックを設けるとバグり難くなるので良いですよ。

for (略) {
}

投稿2015/12/14 01:23

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

本質的なことはChironianさんが解説されているので、蛇足的をいくつか。

scanfについて: 実用プログラミングでは確かにエラーチェックを入れるべきなのですが、入門者であればあまり気にしないほうがいいと思います。木を見て森を見ず、という状態になりかねませんので。

「レコード」の読み込み、書き出しについて: 質問者さんの書き方は基本に忠実なのですが、例えば、受講態度も記録できるようにしたいと考えてみましょう。...全部のfprintfやfscanfの修正、面倒ですよね。間違えやすそうです。こういうときは、そこの部分だけ関数化してみるといいと思います。例えば

C

1int write_record( FILE* fp, const struct student* sp ) 2{ 3 return fprintf( fp, "%d %s %d %d %d %d\n", 4 sp->id, sp->name, sp->shiken, sp->enshu, sp->kadai, sp->tsuishi ); 5} 6 7int read_record( FILE* fp, struct student* sp ) 8{ 9 return fscanf( fp, "%d %s %d %d %d %d\n", 10 &sp->id, sp->name, &sp->shiken, &sp->enshu, &sp->kadai, &sp->tsuishi ); 11}

として、必要な部分で

C

1read_record( stdin, &s ); /* 標準入力(stdin)から取得 */

などとすれば、修正は1か所で済みますし、その部分で「何をしたいか」に集中できます。(スタイルの問題だと言われれば100%の反論はできませんが)

change関数について: 問題への対処法は2種類あります。1つは自前で保存コードを書くこと。もう1つ、分かりますか? 答えは、delete関数とadd関数を組み合わせること。楽ができますし、レコード数が100を超えた場合に暴走するという致命的な欠陥を簡単に修正できます。

まあ、私の話は半分ぐらい聞き流してもらえればいいので(半分では足りないかもしれませんが)。余裕があれば読む、程度でokです。

投稿2015/12/15 04:46

編集2015/12/15 05:57
majiponi

総合スコア1720

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

scanf("%d",&num);はバッファにごみが残ります。
fgets()→atoi()またはsscanf()を使ったほうがいいと思います。

投稿2015/12/13 21:49

編集2015/12/13 22:01
cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問