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

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

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


同樣的,我們會定義如下各個函數
9
10
11
12
13
14
15
16
// 函數原型的宣告
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() 進行帳號管理工作
86
87
88
89
90
91
if (i == 0 && !strcmp(inputCode, userCODE[i])) {
    counter = manage(counter, userID, userCODE);
    printf("\n\n");
    state = RUN;
    break;
}


簡單說, counter 作為參數也是回傳值,此外多了兩個參數,分別是儲存使用者帳號的 userID 及 userCODE 。定義如下
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
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() 用為印出所有使用者帳號,定義如下
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
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() 之中。
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
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() 為刪除帳號指令的與管理者互動介面,定義如下
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
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() 為實際核心的排序演算法,定義如下
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
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() ,但是多增加一個二維字元陣列的參數,因為需要同時搬移兩個二維字元陣列的資料。


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




沒有留言: