C 語言初學教材 - 第五章 使用區域變數的帳號管理程式

現在我們採用另一個把帳號管理程式模組化的方式,這個版本將採區域變數的設計方式,也就是說,會把兩個二維字元陣列宣告在所有函數 main() 的定義之中

// 在所有函數外宣告預設的帳號及密碼
char userID[SIZE][LEN];
char userCODE[SIZE][LEN];


同樣的,我們會定義如下各個函數
// 函數原型的宣告
int manage(int counter, char id[][LEN], char code[][LEN]);
void printList(char id[][LEN], char code[][LEN]);
void si(char id[][LEN], char code[][LEN]);
int ssearch(char array[][LEN], int size, char *target);
int di(int counter, char id[][LEN], char code[][LEN]);
int so(char id[][LEN], char code[][LEN]);
void ssort(char array[][LEN], char code[][LEN], int size);


函數 main() 處理最外層的登入,而 manage() 處理帳號管理的部份,這是說一旦比對使用者輸入的帳號為 administrator ,密碼也與預設的 0000 相符, main() 便呼叫 manage() 進行帳號管理工作
if (i == 0 && !strcmp(inputCode, userCODE[i])) {
    counter = manage(counter, userID, userCODE);
    printf("\n\n");
    state = RUN;
    break;
}


簡單說, counter 作為參數也是回傳值,此外多了兩個參數,分別是儲存使用者帳號的 userID 及 userCODE 。定義如下
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;
        }
    }               
}


printList() 、 si() 、 di() 及 so() 都增加兩個參數,分別是使用者帳號的 id 及使用者密碼的 code ,這也是 manage() 所接收的參數。


函數 printList() 用為印出所有使用者帳號,定義如下
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]);
    }
}


函數 si() 為查詢使用者帳號與管理者互動的介面,實際搜尋演算法寫在函數 ssearch() 之中。
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;
}


函數 di() 為刪除帳號指令的與管理者互動介面,定義如下
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;
    }
}


di() 同樣以 ssearch() 為核心的搜尋演算法,若搜尋成功便可取得所要刪除陣列元素的索引值,然後才進行刪除的工作。


函數 so() 為排序指令的與管理者互動介面,而 ssort() 為實際核心的排序演算法,定義如下
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);
            }
        }
    }
}


so() 最後回傳 1 這是因為排序完之後,我們把 counter 重新設為 1 。這裡我們同樣沿用已經開發好的 ssort() ,但是多增加一個二維字元陣列的參數,因為需要同時搬移兩個二維字元陣列的資料。


完整的範例程式碼及編譯執行,請繼續參考




沒有留言: