/* C言語研修(初級)演習課題7.4   仮想CVSの販売管理システム */
/*345678901234567890123456789M123456789012345678901234567890123456789012345678*/
/*----- FILE DESCRIPTION -----------------------------------------------------*/
/*      FILENAME : Ssms_all.c                                                 */
/*      FUNCTION : virtual convenience store Sale Management System           */
/*      REMARKS  : main                 : メイン                              */
/*                 Ssms_start           : システム開始前処理                  */
/*                 Ssms_add             : 商品データ登録処理                  */
/*                 Ssms_del             : 商品データ削除処理                  */
/*                 Ssms_view            : 商品データ一覧表示処理              */
/*                 Ssms_end             : 終了処理                            */
/*                 ssms_search          : 商品データ検索処理(内部関数)        */
/*      REVISION : 1.0        2000/03/08          by S.Ikenami                */
/*----------------------------------------------------------------------------*/

/*----- INCLUDE DEFINITION ---------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Fsms.h"                       /* 個別ヘッダ */

/*----- FUNCTION DESCRIPTION -------------------------------------------------*/
/*      FUNCTION   : main                                                     */
/*      RETURN     : int                                                      */
/*      PARAMETERS : void                                                     */
/*      REMAERK    :                                                          */
/*----------------------------------------------------------------------------*/
main()
{
    struct syohin_data *a_root=NULL;     /* 商品データ先頭アドレス     */
    int    n_menu;                       /* 入力メニュー番号           */
    int    n_endflg = OFF;               /* システム終了フラグ         */

    Ssms_start(&a_root);                 /* システム開始前処理 */

    /* メニュー画面表示 */
    while(n_endflg == OFF)
    {
        printf("\n +--------------------------+\n");
        printf(  " | [コマンド一覧]           |\n");
        printf(  " +--------------------------+\n");
        printf(  " | 商品データ登録('A'dd)    |\n");
        printf(  " | 商品データ削除('D'elete) |\n");
        printf(  " | 商品データ一覧('V'iew)   |\n");
        printf(  " | 終了          ('E'nd)    |\n");
        printf(  " +--------------------------+\n");
        printf(  " どの処理を行いますか？>");

        fflush(stdin);
        n_menu = getchar();

        switch(n_menu)
        {
        case 'a':
        case 'A':
            Ssms_add(&a_root);          /* 商品データ登録処理 */
            break;

        case 'd':
        case 'D':
            Ssms_del(&a_root);          /* 商品データ削除処理 */
            break;

        case 'v':
        case 'V':
            Ssms_view(a_root);          /* 商品データ一覧表示処理 */
            break;

        case 'e':
        case 'E':
            n_endflg = Ssms_end(a_root);/* 終了処理 */
            break;

        default:
            printf("\n**** 正しい記号を入力して下さい。****\n\n");
        }
    }
    exit(0);
}

/*----- FUNCTION DESCRIPTION -------------------------------------------------*/
/*      FUNCTION   : Ssms_start                                               */
/*      RETURN     : void                                                     */
/*      PARAMETERS :                                                          */
/*        I/O : struct syohin_data ** ; 商品データ先頭アドレスへのポインタ    */
/*      REMAERK    : システム開始前処理                                       */
/*----------------------------------------------------------------------------*/
void Ssms_start(struct syohin_data **aa_root)
{
    FILE  *gdfp;                        /* 商品データファイルポインタ */
    int    n_code;                      /* 商品コード格納用           */
    char   a_name[31];                  /* 商品名格納用               */
    int    n_price;                     /* 商品価格格納用             */
    struct syohin_data *a_wk;           /* データ領域確保用           */
    struct syohin_data *a_current;      /* 商品データ構築用           */

    CLEAR;                              /* 画面クリア */

    if( (gdfp=fopen("syohin.dat","r")) == NULL )
    {                                   /* 在庫ファイルを開けない場合 */
        printf("\n**** 在庫ファイルが無いか、開けません。****\n\n");
    }
    else
    {
        a_current = *aa_root;
        /* 商品データファイルからファイル終端迄1行ずつ読み込み */
        while( fscanf(gdfp,"%d %s %d",&n_code,a_name,&n_price) != EOF )
        {
            a_wk = (struct syohin_data *)malloc(sizeof(struct syohin_data));
                                        /* 1商品データ用メモリ確保 */
            a_wk->code = n_code;
            strcpy(a_wk->name, a_name);
            a_wk->price = n_price;
            
            if(*aa_root==NULL)          /* 商品データ未作成の場合 */
            {
                *aa_root = a_wk;        /* 先頭商品データに設定 */
            }
            else{                       /* 商品データがある場合 */
                a_current->ptr = a_wk;
            }
            a_current = a_wk;           /* カレント商品データの更新 */
            a_wk->ptr = NULL;
        }
        fclose(gdfp);
    }

    return;
}

/*----- FUNCTION DESCRIPTION -------------------------------------------------*/
/*      FUNCTION   : Ssms_add                                                 */
/*      RETURN     : void                                                     */
/*      PARAMETERS :                                                          */
/*        I/O : struct syohin_data ** ; 商品データ先頭アドレスへのポインタ    */
/*      REMAERK    : 商品データ登録処理                                       */
/*----------------------------------------------------------------------------*/
void Ssms_add(struct syohin_data **aa_root)
{
    int    n_endflg = OFF;                  /* 終了フラグ */
    char   a_array[10];                     /* 入力文字列格納用 */
    int    n_code;                          /* 入力商品コード(int) */
    char   a_name[31];                      /* 入力商品名 */
    int    n_price;                         /* 入力商品価格 */
    int    n_yn;                            /* YESorNO */
    int    n_retval = 0;                    /* return value */
    struct syohin_data *a_current;          /* 検索の際の現在位置のポインタ */
    struct syohin_data *a_before;           /* 直前ポインタ */
    struct syohin_data *a_wk;               /* データ領域確保用           */

    CLEAR;
    printf("  ######################  \n");
    printf("  # 商品データ登録処理 #  \n");
    printf("  ######################  \n\n");

do
{
    /* 商品コード入力用無限ループ */
    while(1)
    {
        printf("登録する商品コードを入力して戴けますか？(1000〜9999):");
        fflush(stdin);
        gets(a_array);
        n_code = atoi(a_array);

        a_current= *aa_root;            /* 検索の際の現在位置のポインタ */
        a_before = NULL;                /* 直前ポインタ */

        if(n_code<MINCODE || n_code>MAXCODE)
        {                               /* 商品コード範囲外の時 */
            printf("\n**** 商品コードは%d〜%dの範囲です。****\n",MINCODE,MAXCODE);
        }
        /* 以下、商品コード範囲チェックOKの場合 */
        else if(*aa_root == NULL)       /* 商品データ未作成の時 */
        {
            break;                      /* 商品コード入力用無限ループから抜ける*/
        }
        else                            /* 商品データ作成済み */
        {
            n_retval = ssms_search(*aa_root,&a_current,&a_before,n_code);
                                        /* 検索処理call */

            if(n_retval == EXIST)       /* 該当商品コードが登録済みの時 */
            {
                printf("\n**** あなたが入力した商品コード%dは登録済みです。****\n\n"
                       ,n_code);
            }
            else                        /* 該当商品コード未登録の時 */
            {
                break;                  /* 商品コード入力用無限ループから抜ける*/
            }
        }

        printf("商品コードを再入力致しますか？(Yes;'y'/'Y'  メニューへ戻る;その他):");
        fflush(stdin);
        if( !( (n_yn = getchar()) == 'y' || n_yn == 'Y') )
        {                               /* yes以外の時 */
            return;
        }
    }

    /* 商品名入力 */
    printf("登録する商品名を入力して戴けますか？(半角30文字以内):");
    fflush(stdin);
/*    fgets(a_name, 30, stdin);*/
    gets(a_name);

    /* 商品単価入力用無限ループ */
    while(1)
    {
        printf("登録する商品単価を入力して戴けますか？(\\1〜\\10,000):");
        fflush(stdin);
        gets(a_array);
        n_price = atoi(a_array);

        if(n_price<MINPRICE || n_price>MAXPRICE)
        {                               /* 商品単価範囲外の時 */
            printf("\n**** 商品単価は%d〜%dの範囲です。****\n\n",MINPRICE,MAXPRICE);
            printf("商品単価を再入力致しますか？(Yes;'y'/'Y'  メニューへ戻る;その他):");
            fflush(stdin);
            if( !( (n_yn = getchar()) == 'y' || n_yn == 'Y') )
            {
                return;
            }
        }
        else                            /* 商品単価範囲チェックOKの時 */
        {
            break;                      /* 商品単価入力用無限ループから抜ける*/
        }
    }

    printf("+----------+------------------------------+--------+\n");
    printf("|商品コード|            商品名            |商品価格|\n");
    printf("+----------+------------------------------+--------+\n");
    printf("| %8d |%30s| %6d |\n", n_code, a_name, n_price);
    printf("+----------+------------------------------+--------+\n");
    printf("以上の商品を登録して宜しいですか？(Yes;'y'/'Y'  No;その他):");
    fflush(stdin);

    if( (n_yn = getchar()) == 'y' || n_yn == 'Y')
    {
        a_wk = (struct syohin_data *)malloc(sizeof(struct syohin_data));
                                        /* 登録商品データ用メモリ確保 */
        a_wk->code = n_code;
        strcpy(a_wk->name,a_name);
        a_wk->price = n_price;
        a_wk->ptr = a_current;          /* 確保エリアのnext pointerに */
                                        /* 現在位置アドレスを設定     */

Lprintf("$$ DEBUG $$ 1*aa_root=%d\n",*aa_root);
Lprintf("$$ DEBUG $$ 1a_current=%d\n",a_current);
Lprintf("$$ DEBUG $$ 1a_before=%d\n",a_before);
        if(a_current == *aa_root)       /* 追加先が先頭商品データの時 */
        {                               /*(最初の商品データの時も含む)*/
Lprintf("$$ DEBUG $$ 2*aa_root=%d\n",*aa_root);
            *aa_root = a_wk;            /* 商品データ先頭アドレスに */
                                        /* 確保エリアアドレスを設定 */
        }
        else                            /* 追加先がその他(終端も含む)の時 */
        {
            a_before->ptr = a_wk;       /* 直前ポインタのnext pointerに */
                                        /* 確保エリアアドレスを設定     */ 
        }
Lprintf("$$ DEBUG $$ 3*aa_root=%d\n",*aa_root);
Lprintf("$$ DEBUG $$ 3a_current=%d\n",a_current);
Lprintf("$$ DEBUG $$ 3a_before=%d\n",a_before);
        printf("\n==== 登録致しました。====\n\n");
    }

    fflush(stdin);
    printf("登録処理を終了致しますか？(Yes;'y'/'Y'  No;その他):");
    if( (n_yn = getchar()) == 'y' || n_yn == 'Y')
    {
        n_endflg = ON;
    }
}while(n_endflg != ON);

    return;
}

/*----- FUNCTION DESCRIPTION -------------------------------------------------*/
/*      FUNCTION   : Ssms_del                                                 */
/*      RETURN     : void                                                     */
/*      PARAMETERS :                                                          */
/*        I/O : struct syohin_data ** ; 商品データ先頭アドレスへのポインタ    */
/*      REMAERK    : 商品データ削除処理                                       */
/*----------------------------------------------------------------------------*/
void Ssms_del(struct syohin_data **aa_root)
{
    int    n_endflg = OFF;                  /* 終了フラグ */
    char   a_array[5];                      /* 入力商品コード(文字列) */
    int    n_code;                          /* 入力商品コード(int) */
    int    n_yn;                            /* YESorNO */
    int    n_retval = 0;                    /* return value */
    struct syohin_data *a_current;          /* 検索の際の現在位置のポインタ */
    struct syohin_data *a_before;           /* 直前ポインタ */

    CLEAR;
    printf("  ######################  \n");
    printf("  # 商品データ削除処理 #  \n");
    printf("  ######################  \n\n");

    if(*aa_root == NULL)
    {
        printf("\n\n**** 商品データが存在しません。****\n\n");
        return;
    }

    /* 商品コード入力用無限ループ */
    do
    {
        fflush(stdin);
        printf("削除する商品コードを入力して戴けますか？(1000〜9999):");
        fgets(a_array, 5, stdin);
        n_code = atoi(a_array);

        a_current= *aa_root;            /* 検索の際の現在位置のポインタ */
        a_before = NULL;                /* 直前ポインタ */

        if(n_code<MINCODE || n_code>MAXCODE)
        {                               /* 商品コード範囲外の時 */
            printf("\n**** 商品コードは%d〜%dの範囲です。****\n\n",
                   MINCODE,MAXCODE);
        }
        else                            /* 商品コード範囲チェックOKの時 */
        {
            n_retval = ssms_search(*aa_root,&a_current,&a_before,n_code);
                                        /* 検索処理call */

            if(n_retval == EXIST)       /* 該当商品コードがある時 */
            {
                printf("+----------+------------------------------+--------+\n");
                printf("|商品コード|            商品名            |商品価格|\n");
                printf("+----------+------------------------------+--------+\n");
                printf("| %8d |%30s| %6d |\n",
                        a_current->code, a_current->name, a_current->price);
                printf("+----------+------------------------------+--------+\n");

                fflush(stdin);
                printf("以上の商品を削除して宜しいですか？(Yes;'Y'/'y'  No;その他):");
                if( !( (n_yn = getchar()) == 'y' || n_yn == 'Y') )
                {
                   printf("\n==== 削除を中止致しました。====\n");
                }
                else                         /* 削除実行 */
                {
Lprintf("$$ DEBUG $$ 4*aa_root=%d\n",*aa_root);
Lprintf("$$ DEBUG $$ 4a_current=%d\n",a_current);
Lprintf("$$ DEBUG $$ 4a_before=%d\n",a_before);
                    if(a_current == *aa_root)/* 削除対象が先頭商品データの時 */
                    {
                        *aa_root = a_current->ptr;
                    }
                    else
                    {
                        a_before->ptr = a_current->ptr;
                    }
Lprintf("$$ DEBUG $$ 5*aa_root=%d\n",*aa_root);
Lprintf("$$ DEBUG $$ 5a_current=%d\n",a_current);
Lprintf("$$ DEBUG $$ 5a_before=%d\n",a_before);
                    printf("削除しました。\n");
                    free(a_current);        /* 削除商品データの領域解放 */
                }
            }
            else
            {
                printf("\n**** あなたが入力した商品コード%dは存在致しません。****\n\n"
                       ,n_code);
            }
        }

        fflush(stdin);
        printf("削除処理を終了致しますか？(Yes;'Y'/'y'  削除処理続行;その他):");
        if( (n_yn = getchar()) == 'y' || n_yn == 'Y')
        {
            n_endflg = ON;
        }
    }while(n_endflg != ON);

    return;
}

/*----- FUNCTION DESCRIPTION -------------------------------------------------*/
/*      FUNCTION   : Ssms_view                                                */
/*      RETURN     : void                                                     */
/*      PARAMETERS :                                                          */
/*        I   : struct syohin_data *  ; 商品データ先頭アドレス                */
/*      REMAERK    : 商品データ一覧表示処理                                   */
/*----------------------------------------------------------------------------*/
void Ssms_view(struct syohin_data *a_root)
{
    int    n_count = 0;                 /* 商品データ表示数カウンタ */
    struct syohin_data *a_wk=a_root;    /* 商品データ表示用 */

    CLEAR;
    printf("  ######################  \n");
    printf("  # 商品データ一覧表示 #  \n");
    printf("  ######################  \n\n");

    if(a_root == NULL)
    {
        printf("\n**** 商品データが存在しません。****\n");
        return;
    }
    
    /* 以下、商品データが存在する時 */
    do
    {
        if(n_count == 0|| n_count == 10)/* 起動直後と次ページがある時はヘッダ表示 */
        {
            if(n_count == 10)           /* 次ページを表示する時 */
            {
                fflush(stdin);
                printf("RETURNを押下すると次ページを表示します。>");
                getchar();
                CLEAR;
                printf("  ######################  \n");
                printf("  # 商品データ一覧表示 #  \n");
                printf("  ######################  \n\n");
            }

            printf("+----------+------------------------------+--------+\n");
            printf("|商品コード|            商品名            |商品価格|\n");
            printf("+----------+------------------------------+--------+\n");
            n_count = 0;
        }
        printf("| %8d |%30s| %6d |\n",a_wk->code,a_wk->name,a_wk->price);
                                        /* 1商品データ表示 */
        a_wk = a_wk->ptr;               /* 商品データアドレス更新 */
        n_count++;                      /* 表示カウンタ1up */

        if(n_count==10 || a_wk == NULL) /* 10件表示又は商品データ終端迄表示 */
        {                               /* した時はフッタ表示               */
            printf("+----------+------------------------------+--------+\n");
        }
    }while(a_wk != NULL);               /* 商品データ終端に達する迄ループ */

    return;
}

/*----- FUNCTION DESCRIPTION -------------------------------------------------*/
/*      FUNCTION   : Ssms_end                                                 */
/*      RETURN     : int              ; システム終了フラグ                    */
/*      PARAMETERS :                                                          */
/*        I   : struct syohin_data *  ; 商品データ先頭アドレス                */
/*      REMAERK    : 終了処理                                                 */
/*----------------------------------------------------------------------------*/
int Ssms_end(struct syohin_data *a_root)
{
    int    n_yn;                        /* YESorNO */
    FILE  *gdfp;                        /* 商品データファイルポインタ */
    struct syohin_data *a_wk=a_root;    /* 商品データ表示用 */

    printf("終了致しますか？(Yes;'Y'/'y'  No;その他):");
    fflush(stdin);
    if( !( (n_yn = getchar()) == 'y' || n_yn == 'Y') )
    {                                   /* 終了しない場合 */
        return OFF;
    }

    /* 以下、終了する場合 */
    if(a_root == NULL){                 /* 商品データがない場合 */
        remove("syohin.dat");           /* 商品データファイルを削除 */
        printf("\n==== 商品データが無い為ファイルを削除しました。終了します。====\n");
    }
    else if( (gdfp=fopen("syohin.dat","w")) == NULL )
    {                                   /* 在庫ファイルを開けない場合 */
        printf("\n**** 商品データファイルを開く事ができません。****\n\n");
        printf("それでも終了致しますか？(Yes;'Y'/'y'  No;その他):");
        fflush(stdin);
        if( (n_yn = getchar()) == 'y' || n_yn == 'Y')
        {
            return ON;
        }
    }
    else
    {
        do
        {
            fprintf(gdfp,"%d %s %d\n",a_wk->code,a_wk->name,a_wk->price);
            a_wk = a_wk->ptr;
        }while(a_wk != NULL);           /* 商品データ終端に達する迄ループ */

        printf("\n==== 商品データファイルに書き込みました。終了します。====\n");
        fclose(gdfp);
    }

    return ON;
}

/*----- FUNCTION DESCRIPTION -------------------------------------------------*/
/*      FUNCTION   : ssms_search                                              */
/*      RETURN     : int                                                      */
/*          EXIST       1                    ; 該当商品コード有り             */
/*          NOTEXIST    2                    ; 該当商品コード無し             */
/*          ENDOFDATA   3                    ; 商品データ終端迄検索           */
/*      PARAMETERS :                                                          */
/*        I   : struct syohin_data *  ; 商品データ先頭アドレス                */
/*        I/O : struct syohin_data ** ; (商品データ検索時)現在位置のポインタ  */
/*        I/O : struct syohin_data ** ; (商品データ検索時)直前ポインタ        */
/*        I   : int                   ; 入力商品コード                        */
/*      REMAERK    : 商品データ検索処理(内部関数)                             */
/*                   商品データ有りの時のみ呼ばれるものとする。               */
/*----------------------------------------------------------------------------*/
int ssms_search(struct syohin_data *a_root, struct syohin_data **aa_current,
                struct syohin_data **aa_before, int n_code)
{
Lprintf("$$ DEBUG $$ 6a_root=%d\n",a_root);
Lprintf("$$ DEBUG $$ 6aa_current=%d\n",*aa_current);
Lprintf("$$ DEBUG $$ 6aa_before=%d\n",*aa_before);
    do
    {
        if((*aa_current)->code < n_code)
        {
            *aa_before  = *aa_current;
            *aa_current = (*aa_current)->ptr;
        }
        else if((*aa_current)->code == n_code)
        {
            return EXIST;
        }
        else
        {
            return NOTEXIST;
        }

    }while(*aa_current != NULL);         /* 商品データ終端迄ループ */

    return ENDOFDATA;
}

/*** E n d   o f  F i l e ***/
