#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* コマンドの読み込みの最大値 */
#define BUFFER_SIZE 256
/* 患者の最大数 */
#define MAX_NUM_PATIENTS 101
/* 患者の状態の数 */
#define NUM_STATUS_LEVELS 5
/* 名前の長さの最大 */
#define MAX_NAME_LENGTH 51
/* 患者の状態を表す構造体 */
typedef struct patient{
/* 受付時刻(時) */
int hour;
/* 受付時刻(分) */
int minute;
/* 名前 */
char name[MAX_NAME_LENGTH];
/* 状態 */
int status;
} patient;
/* 患者のポインタの配列の型 */
typedef patient** patients;
/* 状態別の患者のリスト */
typedef patients* patient_list;
/********************************/
/* 患者・患者リストの作成・削除 */
/********************************/
/* 患者のエントリを作成する */
void create_patient(patient** ppat){
(*ppat) = malloc(sizeof(patient));
}
/* 患者のエントリを削除する */
void release_patient(patient* pat){
free(pat);
}
/* 患者のリストを作成する */
void craete_patient_list(patient_list* plist){
int i,j;
(*plist) = malloc(NUM_STATUS_LEVELS * sizeof(patients));
for(i = 0; i < NUM_STATUS_LEVELS; i++){
(*plist)[i] = malloc(MAX_NUM_PATIENTS * sizeof(patient*));
for(j = 0; j < MAX_NUM_PATIENTS; j++){
(*plist)[i][j] = NULL;
}
}
}
/* 患者のリストを削除する */
void release_patient_list(patient_list list){
int i,j;
for(i = 0; i < NUM_STATUS_LEVELS; i++){
for(j = 0; j < MAX_NUM_PATIENTS; j++){
if(list[i][j] != NULL){
release_patient(list[i][j]);
}else{
break;
}
}
free(list[i]);
}
free(list);
}
/**************************/
/* 操作 */
/**************************/
/* 待ち行列に追加 */
void insert_patient(patient_list list, patient* p){
patient** it = list[p->status-1];
while((*it) != NULL){ it++; }
(*it) = p;
}
/* 待ち行列から削除 */
void remove_patient(patient_list list, patient* p){
int i,j;
for(i = 0; i < NUM_STATUS_LEVELS; i++){
for(j = 0; j < MAX_NUM_PATIENTS; j++){
if(list[i][j] == NULL) break;
if(list[i][j] != p) continue;
for(; j < MAX_NUM_PATIENTS; j++){
list[i][j] = list[i][j+1];
if(list[i][j] == NULL) return;
}
}
}
}
/* 次に呼ばれる患者を取得 */
patient* next_pateint(patient_list list){
int i;
for(i = NUM_STATUS_LEVELS-1; i >= 0; i--){
if(list[i][0] != NULL){
return list[i][0];
}
}
return NULL;
}
/* 名前の一致する患者を探す */
patient* find_patient(patient_list list, char* name){
int i,j;
for(i = 0; i < NUM_STATUS_LEVELS; i++){
for(j = 0; j < MAX_NUM_PATIENTS; j++){
if(list[i][j] == NULL) break;
if(strcmp(name, list[i][j]->name) != 0) continue;
return list[i][j];
}
}
return NULL;
}
/* 待ち行列の内容を全て表示する */
void print_list(patient_list list){
int i,j;
printf("Patients:\n");
for(i = NUM_STATUS_LEVELS-1; i >= 0; i--){
for(j = 0; j < MAX_NUM_PATIENTS; j++){
patient* p = list[i][j];
if(p == NULL) break;
printf(" %d %02d:%02d %s\n", p->status, p->hour, p->minute, p->name);
}
}
}
/**************************/
/* コマンドファイルの実行 */
/**************************/
/* ファイルから1行バッファに読み込む */
int read_line(FILE* fp, char* buff){
int ret = fscanf(fp, "%[^\n]%*c", buff);
return ret;
}
/*
* ファイルに書いてあるコマンドを解釈して実行
* 実行したコマンドの数を返します。
* @param fp ファイルポインタ
* @param list 患者リスト
*/
int interpret_command(FILE* fp, patient_list list){
char buff[BUFFER_SIZE];
int command_count = 0;
patient* pat;
int hour,minute,status;
if(fp == NULL) return -1;
while(feof(fp) == 0){
/* 1行読む */
read_line(fp, buff);
if(feof(fp) != 0){
break;
}
else if(buff[0] == 'i'){
/* 患者の受付 */
create_patient(&pat);
read_line(fp, buff);
sscanf(buff, "%d:%d", &pat->hour, &pat->minute);
read_line(fp, &pat->name[0]);
read_line(fp, buff);
sscanf(buff, "%d", &pat->status);
insert_patient(list, pat);
}
else if(buff[0] == 'r'){
/* 次の患者の参照 */
read_line(fp, buff);
sscanf(buff, "%d:%d", &hour, &minute);
pat = next_pateint(list);
if(pat != NULL){
printf("Next patient:\n");
printf(" %d %02d:%02d %s\n", pat->status, pat->hour, pat->minute, pat->name);
}
}
else if(buff[0] == 'c'){
/* 次の患者の呼び出し */
read_line(fp, buff);
sscanf(buff, "%d:%d", &hour, &minute);
pat = next_pateint(list);
if(pat != NULL){
remove_patient(list, pat);
printf("Called patient:\n");
printf(" %d %02d:%02d %s\n", pat->status, pat->hour, pat->minute, pat->name);
}
}
else if(buff[0] == 'u'){
/* 指定患者の状態変更 */
read_line(fp, buff);
sscanf(buff, "%d:%d", &hour, &minute);
read_line(fp, buff);
pat = find_patient(list, buff);
read_line(fp, buff);
sscanf(buff, "%d", &status);
if(pat != NULL && status > pat->status){
remove_patient(list, pat);
pat->hour = hour;
pat->minute = minute;
pat->status = status;
insert_patient(list, pat);
}
}
else if(buff[0] == 'd'){
/* 患者の削除 */
read_line(fp, buff);
sscanf(buff, "%d:%d", &hour, &minute);
read_line(fp, buff);
pat = find_patient(list, buff);
if(pat != NULL){
/* リストから除外 */
remove_patient(list, pat);
/* メモリの解放 */
release_patient(pat);
}
}
else if(buff[0] == 't'){
/* 患者の一覧表示 */
read_line(fp, buff);
sscanf(buff, "%d:%d", &hour, &minute);
print_list(list);
}
else if(buff[0] == '*'){
/* 終わり */
break;
}
command_count++;
}
return command_count;
}
/*************************/
/* main関数 */
/*************************/
int main(int argc, char* argv[]){
/* コマンドファイルのファイルポインタ */
FILE* fp;
/* 患者リスト */
patient_list list;
/* 引数が渡されていなければ異常終了する */
if(argc != 2) return 1;
/* コマンドファイルを開く */
fp = fopen(argv[1], "r");
if(fp == NULL) return 2;
/* 患者リストを作成 */
craete_patient_list(&list);
/* コマンドファイルを実行 */
interpret_command(fp, list);
/* 患者リストを削除 */
release_patient_list(list);
/* コマンドファイルを閉じる */
fclose(fp);
return 0;
}