C 語言初學教材 - 第六章 實作檔

實作檔是將函數定義放在另一個 .c 的檔案,注意,實作檔不需要定義函數 main() ,因此我們另外還需要規劃一個實際執行的執行檔。



實作檔的開頭需要引入自己定義的標頭檔,以下為實作檔的內容
#include "itm.h"

void login(void)
{
    // 宣告預設的帳號及密碼
    char userID[SIZE][LEN];
    char userCODE[SIZE][LEN];
    
    // 宣告暫存使用者輸入的帳號及密碼
    char inputName[LEN];
    char inputCode[LEN];
    
    // 宣告暫存新註冊的帳號及密碼
    char newName[LEN];
    char newCode[LEN];
    
    // 宣告暫存成功登入的帳號及密碼
    char whoName[LEN];
    char whoCode[LEN];
    
    // 宣告狀態變數、迴圈變數及陣列索引值變數
    int state, i, j, k;
    int counter;
    My_Time mytime;
    
    // administrator 為預設的管理者帳號, 0000 為其密碼
    strcpy(userID[0], "administrator");
    strcpy(userCODE[0], "0000");
    
    for (i = 1; i < SIZE; i++) {
        strcpy(userID[i], "");
        strcpy(userCODE[i], "");
    }
    
    counter = 1;
    while (1) {
        state = WRONG_NAME;
        
        printf("login: ");
        scanf("%s", inputName);
        
        // "exit" 為內建指令,用來離開迴圈
        if (!strcmp(inputName, "exit")) {
            state = EXIT;
            printf("\n\n您將要離開本登入程式....\n\n");
            break;
        }
        
        // "new" 為內建指令,用來新建帳號密碼
        if (!strcmp(inputName, "new")) {
            state = RUN;
            
            printf("\n請輸入新的註冊帳號: ");
            scanf("%s", newName);
            printf("請輸入新的登入密碼: ");
            scanf("%s", newCode);
            
            strcpy(userID[counter], newName);
            strcpy(userCODE[counter], newCode);
            counter++;
            
            printf("\n新的帳號、密碼已建立,請重新登入....\n");
            continue;
        }

        // 從陣列中判斷是否有使用者輸入的帳號,若有才再繼續要求輸入密碼
        for (i = 0; i < SIZE; i++) {
            if (!strcmp(inputName, userID[i])) {
                printf("password: ");
                scanf("%s", inputCode);
                
                if (i == 0 && !strcmp(inputCode, userCODE[i])) {
                    counter = manage(counter, userID, userCODE);
                    printf("\n\n");
                    state = RUN;
                    break;
                }
                
                if (!strcmp(inputCode, userCODE[i])) {
                    strcpy(whoName, inputName);
                    strcpy(whoCode, inputCode);
                    
                    state = RUN;
                    break;
                }
                else {
                    state = WRONG_CODE;
                    break;
                }
            }
        }
        
        // 判斷目前狀態,顯示提示訊息
        if (state == RUN) {
            mytime = myTimeS(time(NULL));
            sayHello(&mytime, whoName);
            frienddata(whoName);
            continue;
        }
        else if (state == WRONG_NAME) {
            printf("\n\n沒有這名使用者喔!請重新登入....\n\n");
            continue;
        }
        else if (state == WRONG_CODE) {
            printf("\n\n密碼錯誤,請重新登入....\n\n");
            continue;
        }
    }
    
    printf("\n\n程式即將關閉,所有建立的資料都會消失....\n\n");
}

My_Time myTimeS(time_t seconds)
{
    struct tm *tmPtr = localtime(&seconds);
    My_Time mt;
    
    mt.year = tmPtr->tm_year + 1900;
    mt.month = tmPtr->tm_mon + 1;
    mt.day = tmPtr->tm_mday;
    mt.hour = tmPtr->tm_hour;
    if (mt.hour <= 12) {
        mt.isam = 1;
        mt.hourt = tmPtr->tm_hour;
    }
    else {
        mt.isam = 0;
        mt.hourt = tmPtr->tm_hour - 12;
    }
    mt.min = tmPtr->tm_min;
    mt.sec = tmPtr->tm_sec;
    
    return mt;   
}

void sayHello(My_Time *tPtr, char *name)
{
    printf("\n\n今天是 %d 月 %d 日\n", tPtr->month, tPtr->day);
    printf("現在%s %d:%d\n", tPtr->isam ? "上午" : "下午", tPtr->hourt, tPtr->min);
    printf("哈囉, %s, 歡迎使用本通訊錄程式\n\n", name);
}

int manage(int counter, char id[][LEN], char code[][LEN])
{
    // 宣告接收管理模式指令
    char instruction[LEN];
    
    printf("\n\n您成功以管理員模式登入....\n");
    printf("將入帳號管理模式,請在提示符號 # 後輸入指令\n");
                    
    while (1) {
        printf("\n# ");
        scanf("%s", instruction);
                        
        // exit 為離開管理模式的指令
        if (!strcmp(instruction, "exit")) {
            return counter;
        }
                        
        // list 為列印使用者列表的指令
        if (!strcmp(instruction, "list")) {
            printList(id, code);
            continue;
        }
                        
        // search 為查詢帳號指令
        if (!strcmp(instruction, "search")) {
            si(id, code);
            continue;
        }
                        
        // delete 為刪除帳號指令
        if (!strcmp(instruction, "delete")) {
            counter = di(counter, id, code);
            continue;
        }
                        
        // sort 為排序指令
        if (!strcmp(instruction, "sort")) {
            counter = so(id, code);
            continue;
        }
    }               
}

void printList(char id[][LEN], char code[][LEN])
{
    int i;
    
    printf("\n以下為所有註冊使用者的帳號及密碼\n");
    printf("\n帳號 - 密碼\n");
    
    for (i = 0; i < SIZE; i++) {
        if (id[i][0] == '\0') {
            continue;
        }
                                
        printf("%s - %s\n", id[i], code[i]);
    }
}

void si(char id[][LEN], char code[][LEN])
{
    char searchname[LEN];
    int index;
                            
    printf("\n請輸入要查找的帳號: ");
    scanf("%s", searchname);
    index = ssearch(id, SIZE, searchname);                        
                            
    if (index != -1) {
        printf("\n帳號 %s 已經註冊,密碼是 %s\n", id[index], code[index]);
    }
    else {
        printf("\n還沒有 %s 的帳號註冊唷!\n", searchname);
    }
}

int ssearch(char array[][LEN], int size, char *target)
{
    int i;
    
    for (i = 0; i < size; i++) {
        if (!strcmp(array[i], target)) {
            return i;
        }
    }
    
    return -1;
}

int di(int counter, char id[][LEN], char code[][LEN])
{
    char deletename[LEN];
    int index;
                            
    printf("\n請輸入要刪除的帳號: ");
    scanf("%s", deletename);
    index = ssearch(id, SIZE, deletename);
                            
    if (index != -1) {
        for (index; index < SIZE; index++) {
            strcpy(id[index], id[index + 1]);
            strcpy(code[index], code[index + 1]);
        }
                                
        printf("\n%s 的帳號資料已刪除\n", deletename);
        return counter--;
    }
    else {
        printf("\n%s 的帳號資料不存在,無法刪除\n", deletename);
        return counter;
    }
}

int so(char id[][LEN], char code[][LEN])
{
    ssort(id, code, SIZE);
    printf("\n資料已排序完成\n");
    return 1;
}

void ssort(char array[][LEN], char code[][LEN], int size)
{
    int i, j;
    char tempa[LEN], tempb[LEN];
    
    for (i = 0; i < size - 1; i++) {
        for (j = 1; j < size; j++) {
            if (array[j - 1][0] > array[j][0]) {
                strcpy(tempa, array[j - 1]);
                strcpy(tempb, code[j - 1]);
                strcpy(array[j - 1], array[j]);
                strcpy(code[j - 1], code[j]);
                strcpy(array[j], tempa);
                strcpy(code[j], tempb);
            }
        }
    }
}

int prompt(void)
{
    int choice;
    char whoinput[1];
    
    printf("\n\n1. 增加好友\n");
    printf("2. 刪除好友\n");
    printf("3. 查詢好友\n");
    printf("4. 印出列表\n");
    printf("5. 排序列表\n");
    printf("6. 存檔後登出\n");
    printf("7. 不存檔登出\n");
    printf("8. 存檔後離開\n");
    printf("9. 不存檔離開\n");
    
    printf("請輸入 1-9 功能選項: ");
    scanf("%s", whoinput);
    
    choice = atoi(whoinput);
    
    return choice;
}

void frienddata(char *name)
{
    int STATE;
    int choice;
    LinkedListNode *startPtr = NULL;
    
    while (1) {
        STATE = RUN;
        choice = prompt();
        printf("\n\nyour choice is %d\n\n", choice);
        
        switch (choice) {
            case 1:
                printf("\n\n您即將開啟增加好友的功能.....\n\n");
                addfriend(&startPtr);
                break;
                
            case 2:
                printf("\n\n您即將開啟刪除好友的功能.....\n\n");
                break;
                
            case 3:
                printf("\n\n您即將開啟查詢好友的功能.....\n\n");
                break;

            case 4:
                printf("\n\n您即將開啟印出列表的功能.....\n\n");
                printList2(startPtr);
                break;
            
            case 5:
                printf("\n\n您即將開啟排序列表的功能.....\n\n");
                break;
            
            case 6:
                printf("\n\n您即將開啟存檔後登出的功能.....\n\n");
                STATE = EXIT;
                break;
            
            case 7:
                printf("\n\n您即將開啟不存檔登出的功能.....\n\n");
                STATE = EXIT;
                break;
            
            case 8:
                printf("\n\n您即將開啟存檔後離開的功能.....\n\n");
                exit(1);
                break;
            
            case 9:
                printf("\n\n您即將開啟不存檔離開的功能.....\n\n");
                exit(1);
                break;
            
            default:
                printf("\n\nWRONG CHOICE!\n\n");
        }
        
        if (STATE == EXIT) {
            break;
        }
    }
}

void addfriend(LinkedListNode **startPtr)
{
    LinkedListNode *newPtr, *currentPtr;
    char fname[NAME_SIZE];
    int fage, fsex, frelation;

    // 向作業系統要求新的記憶體空間
    newPtr = malloc(sizeof(LinkedListNode));
        
    // 依序輸入好友資料
    printf("\n好友暱稱: ");
    scanf("%s", fname);
    printf("好友年齡: ");
    scanf("%d", &fage);
    printf("好友性別 - 0.女 1.男: ");
    scanf("%d", &fsex);
    printf("好友關係 - 0.家人 1.同學 2.朋友: ");
    scanf("%d", &frelation); 
        
    // 將好友資料拷貝到剛才取得的記憶體空間之中
    strcpy(newPtr->data.name, fname);
    newPtr->data.age = fage;
    newPtr->data.sex = fsex;
    newPtr->data.relation = frelation;
    newPtr->nextPtr = NULL;
        
    // 將資料加入鏈結串列
    if (*startPtr == NULL) {
        *startPtr = newPtr;
    }
    else {
        currentPtr = *startPtr;
           
        while (currentPtr != NULL) {
           if (currentPtr->nextPtr == NULL) {
               currentPtr->nextPtr = newPtr;
               break;
           }
                       
           currentPtr = currentPtr->nextPtr;
        }
    }
}

void printList2(LinkedListNode *currentPtr)
{
    if (currentPtr == NULL) {
        printf("\n\n還沒有建立任何好友資料唷...\n\n");
    }
    else {
        // 依序由鏈結串獵取出資料,然後印在螢幕上
        printf("\n\n以下依好友名錄的儲存順序印出好友資料\n");
        printf("  好友暱稱 - 年 齡 - 性 別 - 關 係\n");
        while (currentPtr != NULL) {
            printf("%10s - ", currentPtr->data.name);
            printf("%5d - ", currentPtr->data.age);
            printf("%5s  - ", currentPtr->data.sex ? "男" : "女");
            printf("%s \n", currentPtr->data.relation ? "同學或朋友" : "家人");
        
            currentPtr = currentPtr->nextPtr;
        }
    }
        
}

/* 《程式語言教學誌》的範例程式
    http://pydoing.blogspot.com/
    檔名:itmf.c
    功能:實作 itm.h 所宣告的函數原型
    作者:張凱慶
    時間:西元2010年7月 */


標頭檔及執行檔,請繼續參考




1 則留言:

whitelittldog 提到...
作者已經移除這則留言。