// 例題4.2 名簿処理 #include #include #include // 1人分のデータ格納用構造体 typedef struct member { char name[20]; char comment[40]; struct member *next; } Member; // データ入力 // 引数 *mp:入力されたデータを格納する領域 inline int read_member(Member *mp, FILE *ifp) { return fscanf(ifp, "%s %s", mp->name, mp->comment ); } // データ出力 // 引数 *mp:リストの先頭 // n:行番号(標準出力の場合のみ表示) inline int write_member(Member *mp,int n,FILE *ofp) { if (ofp==stdout) printf("%4d:", n); return fprintf(ofp, "%-20s%-40s\n", mp->name, mp->comment ); } // ファイルから読み込み(低速版) // 引数 *mp:リストの先頭(第1要素はダミー) // 局所変数 *mp2:1行分の入力データ格納 // 戻り値 読み込んだ行数 int read_file(Member *mp, FILE *ifp) { int cnt = 0; Member m,*mp2; while (read_member(&m,ifp) != EOF) { mp2 = (Member*)malloc(sizeof(Member)); if (mp2 == 0) break; *mp2 = m; mp2->next = 0; mp->next = mp2; mp = mp->next; cnt++; } return cnt; } // ファイルへの書き出し // 引数 *mp:リストの先頭 // 戻り値: 常に0 int write_file(Member *mp, FILE *ofp) { int n=0; mp = mp->next; // ダミー要素を飛ばす while (mp) { write_member(mp,n++,ofp); mp = mp->next; } return 0; } // リストへの要素の挿入 // 引数 *mp:リストの先頭 // k:挿入位置(0..n) kの直後に挿入, k==0なら先頭 // 戻り値 成功すれば0, 失敗すれば-1 int insert_member(Member *mp, int k, Member *p) { Member *p2; if (k<0) return -1; while (mp && k-- > 0) mp=mp->next; if (mp==0) return -1; p2 = (Member*)malloc(sizeof(Member)); if (p2==0) return -1; *p2 = *p; p2->next = mp->next; mp->next = p2; return 0; } // リストからの削除 // 引数 *mp:リストの先頭 // k:削除位置(0..n-1) // 戻り値 成功すれば0, 失敗すれば-1 int delete_member(Member *mp, int k) { Member *p; if (k<0) return -1; while (mp && k-- > 0) mp=mp->next; if (mp==0 || mp->next==0) return -1; p = mp->next; if (p) mp->next = p->next; else mp->next = 0; free(p); // pを解放 return 0; } // メニュー表示 void show_menu() { printf(" 1: read from file\n"); printf(" 2: write to file\n"); printf(" 3: insert member\n"); printf(" 4: delete member\n"); printf(" q: quit\n\n"); } // 作業用変数 Member mem; char com[20]; char prompt[] = "command:" ; char buf[80]; // ファイル名入力 void input_filename(char *buf) { do { printf("filename:"); scanf("%s",buf); } while (buf[0] == 0); } // 位置入力 void input_position(char *buf) { do { printf("position:"); scanf("%s",buf); } while (buf[0] == 0); } // メインプログラム int main() { FILE *ifp, *ofp; Member m; int k; while (1) { printf(prompt); scanf("%s", com); switch (com[0]) { case '1': input_filename(buf); ifp = fopen(buf,"r"); if (ifp==0) { exit(1); } // 要エラーメッセージ if (read_file(&mem,ifp) < 0) { exit(1); } fclose(ifp); break; case '2': input_filename(buf); ofp = fopen(buf,"w"); if (ofp==0) { exit(1); } // 要エラーメッセージ if (write_file(&mem,ofp) < 0) { exit(1); } fclose(ofp); break; case '3': input_position(buf); k = atoi(buf); printf("member:"); read_member(&m, stdin); if (insert_member(&mem, k, &m) < 0) { exit(1); } break; case '4': input_position(buf); k = atoi(buf); if (delete_member(&mem, k) < 0) { exit(1); } break; case 'q': // 終了 return 0; default: // エラー show_menu(); break; } // 画面出力(確認用) write_file(&mem, stdout); }; return 0; }